1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/boardsupport/emulator/emulatorbsp/specific/nanddev.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,416 @@
1.4 +// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// D_MEDNAND.CPP
1.18 +//
1.19 +//
1.20 +
1.21 +#define _MEDIA_DRIVER
1.22 +#include <nand_media.h>
1.23 +#include <emulator.h>
1.24 +#include <property.h>
1.25 +
1.26 +/********************************************
1.27 + * Driver definitions
1.28 + ********************************************/
1.29 +const TInt KSimulatedDeviceId = 0xEC73;
1.30 +const CHAR KNandFileName[] = "NANDDRV.BIN";
1.31 +
1.32 +//
1.33 +// Platform dependent media driver class
1.34 +//
1.35 +class DMediaDriverNandWin32 : public DMediaDriverNand
1.36 + {
1.37 +public:
1.38 + DMediaDriverNandWin32(TMediaDevice aDevice);
1.39 +
1.40 + // replacing pure virtual - NAND device specific stuff
1.41 + virtual TInt Initialise();
1.42 + virtual TInt GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId);
1.43 + virtual TInt DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength);
1.44 + virtual TInt DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength);
1.45 + virtual TInt DeviceErase(const TUint aBlockAddress);
1.46 + virtual TInt DeviceClose();
1.47 +
1.48 +public:
1.49 + HANDLE iFile;
1.50 + HANDLE iMapping;
1.51 + TUint8* iBase;
1.52 + };
1.53 +
1.54 +LOCAL_C TInt MapLastError()
1.55 +//
1.56 +// Map an NT error to an Epoc/32 error.
1.57 +//
1.58 + {
1.59 + __PATH_NOT_YET_TESTED;
1.60 + DWORD r=GetLastError();
1.61 + TInt res;
1.62 + switch (r)
1.63 + {
1.64 + case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break;
1.65 + case ERROR_LOCK_VIOLATION : res=KErrLocked; break;
1.66 + case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break;
1.67 + case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break;
1.68 + case ERROR_ALREADY_EXISTS:
1.69 + case ERROR_FILE_EXISTS:
1.70 + res=KErrAlreadyExists;
1.71 + break;
1.72 + case ERROR_NOT_READY: res=KErrNotReady; break;
1.73 + case ERROR_UNRECOGNIZED_VOLUME:
1.74 + case ERROR_NOT_DOS_DISK:
1.75 + res=KErrUnknown;
1.76 + break;
1.77 + case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break;
1.78 + case ERROR_INVALID_NAME: res=KErrBadName; break;
1.79 + case ERROR_NO_MORE_FILES: res=KErrEof; break;
1.80 + case ERROR_DISK_FULL: res=KErrDiskFull; break;
1.81 + default: res=KErrGeneral;
1.82 + }
1.83 + return(res);
1.84 + }
1.85 +
1.86 +TInt DMediaDriverNandWin32::Initialise()
1.87 +//
1.88 +// Create the simulated NAND file if necessary and
1.89 +// map it into memory.
1.90 +//
1.91 + {
1.92 + __PATH_TESTED;
1.93 +
1.94 + // locate/open the file that models the flash
1.95 + CHAR filename[MAX_PATH];
1.96 + strcpy(filename, Property::GetString("EmulatorMediaPath"));
1.97 + if (!Emulator::CreateAllDirectories(filename))
1.98 + {
1.99 + __PATH_NOT_YET_TESTED;
1.100 + return Emulator::LastError();
1.101 + }
1.102 + strcat(filename, KNandFileName);
1.103 + iFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
1.104 +
1.105 + if (iFile == INVALID_HANDLE_VALUE)
1.106 + {
1.107 + __PATH_NOT_YET_TESTED;
1.108 + return Emulator::LastError();
1.109 + }
1.110 +
1.111 + const TUint32 flashSizeInBytes = iNumBlocks * iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare);
1.112 +
1.113 + SetFilePointer(iFile, flashSizeInBytes, NULL, FILE_BEGIN);
1.114 + SetEndOfFile(iFile);
1.115 +
1.116 + iMapping = CreateFileMappingA(iFile, NULL, PAGE_READWRITE, 0, flashSizeInBytes, NULL);
1.117 + if (iMapping == NULL)
1.118 + {
1.119 + __PATH_NOT_YET_TESTED;
1.120 + return Emulator::LastError();
1.121 + }
1.122 +
1.123 + iBase = (TUint8*)MapViewOfFile(iMapping, FILE_MAP_WRITE, 0, 0, flashSizeInBytes);
1.124 + if (iBase == NULL)
1.125 + {
1.126 + __PATH_NOT_YET_TESTED;
1.127 + return Emulator::LastError();
1.128 + }
1.129 +
1.130 + return KErrNone;
1.131 + }
1.132 +
1.133 +TInt DMediaDriverNandWin32::GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId)
1.134 + {
1.135 + __PATH_TESTED;
1.136 +
1.137 + aManufacturerId = (KSimulatedDeviceId & 0xFF00) >> 8;
1.138 + aDeviceId = (KSimulatedDeviceId & 0xFF);
1.139 + return KErrNone;
1.140 + }
1.141 +
1.142 +TInt DMediaDriverNandWin32::DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength)
1.143 + {
1.144 + __PATH_TESTED;
1.145 +
1.146 + __NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock));
1.147 + __NAND_ASSERT( (aLength == iNumBytesMain)
1.148 + || (aLength == iNumBytesMain + iNumBytesSpare)
1.149 + || (aLength == iNumBytesSpare) );
1.150 +
1.151 +#ifdef __TEST_MEDIA_DRIVER__
1.152 + extern TBool gNoPower;
1.153 + if(gNoPower)
1.154 + return KErrBadPower;
1.155 +#endif
1.156 +
1.157 + TUint8* readPoint;
1.158 + if (aLength == iNumBytesMain)
1.159 + {
1.160 + __PATH_TESTED;
1.161 + readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
1.162 + }
1.163 + else if (aLength == iNumBytesSpare)
1.164 + {
1.165 + __PATH_TESTED;
1.166 + readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain;
1.167 + }
1.168 + else if (aLength == (iNumBytesMain + iNumBytesSpare))
1.169 + {
1.170 + __PATH_TESTED;
1.171 + readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
1.172 + }
1.173 + else
1.174 + {
1.175 + __PATH_NOT_YET_TESTED;
1.176 + return KErrArgument;
1.177 + }
1.178 +
1.179 + for (TUint i = 0; i < aLength; i++)
1.180 + {
1.181 + ((TUint8*)aBuf)[i] = readPoint[i];
1.182 + }
1.183 +
1.184 +#ifdef __TEST_MEDIA_DRIVER__
1.185 + extern TBool gECCFail;
1.186 + if(gECCFail)
1.187 + {
1.188 + //introduce a random one bit error
1.189 + TUint8* p=(TUint8*)aBuf;
1.190 + TUint32 key=Kern::Random() % aLength;
1.191 + TUint32 shift=1<<(Kern::Random() % 8);
1.192 + p[key]=(TUint8)(p[key]&shift?p[key]-shift:p[key]+shift);
1.193 + gECCFail=EFalse;
1.194 + }
1.195 +#endif
1.196 +
1.197 + return KErrNone;
1.198 + }
1.199 +
1.200 +#ifdef __TEST_MEDIA_DRIVER__
1.201 +extern "C" TUint32 gbbm_get_sphy_blknum(TUint32, TUint32);
1.202 +#endif
1.203 +TInt DMediaDriverNandWin32::DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength)
1.204 + {
1.205 + __PATH_TESTED;
1.206 +
1.207 + __NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock));
1.208 + __NAND_ASSERT( (aLength == iNumBytesMain)
1.209 + || (aLength == iNumBytesMain + iNumBytesSpare)
1.210 + || (aLength == iNumBytesSpare) );
1.211 +
1.212 +#ifdef __TEST_MEDIA_DRIVER__
1.213 + extern TBool gNoPower;
1.214 + extern TBool gPowerFail;
1.215 + extern TUint32 gPowerFailAfter;
1.216 + if(gNoPower)
1.217 + return KErrBadPower;
1.218 + if(gPowerFail)
1.219 + {
1.220 + if(gPowerFailAfter)
1.221 + --gPowerFailAfter;
1.222 + else
1.223 + {
1.224 + gPowerFail=EFalse;
1.225 + gNoPower=ETrue;
1.226 + extern TUint32 gNotificationType;
1.227 + extern TUint32 KNandDbgNotifyPowerDown;
1.228 + extern TInt NotifyThread();
1.229 + if(gNotificationType==KNandDbgNotifyPowerDown)
1.230 + NotifyThread();
1.231 + return KErrBadPower;
1.232 + }
1.233 + }
1.234 +#endif
1.235 +
1.236 + TUint8* writePoint;
1.237 +
1.238 + if (aLength == iNumBytesMain)
1.239 + {
1.240 + __PATH_TESTED;
1.241 + writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
1.242 + }
1.243 + else if (aLength == iNumBytesSpare)
1.244 + {
1.245 + __PATH_TESTED;
1.246 + writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain;
1.247 + }
1.248 + else if (aLength == (iNumBytesMain + iNumBytesSpare))
1.249 + {
1.250 + __PATH_TESTED;
1.251 + writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
1.252 + }
1.253 + else
1.254 + {
1.255 + __PATH_NOT_YET_TESTED;
1.256 + return KErrArgument;
1.257 + }
1.258 +
1.259 + for (TUint i = 0; i < aLength; i++)
1.260 + {
1.261 + writePoint[i] &= ((TUint8*)aBuf)[i];
1.262 + }
1.263 +
1.264 +#ifdef __TEST_MEDIA_DRIVER__
1.265 + extern TUint32 gFailAfter;
1.266 + extern TUint32 gFailAfterCnt;
1.267 + extern TBool gFailureType; //true-WriteFail, false-EraseFail
1.268 + extern TBool gFailON;
1.269 + if(gFailON && gFailureType)
1.270 + {
1.271 + if(gFailAfterCnt)
1.272 + --gFailAfterCnt;
1.273 + else
1.274 + {
1.275 + extern TUint32 FirstReadPUN;
1.276 + extern DMediaDriverNand* gMediaDriverPtr;
1.277 + if(gbbm_get_sphy_blknum(0,aPageAddress/gMediaDriverPtr->iNumPagesPerBlock)==FirstReadPUN)
1.278 + {
1.279 + gFailAfterCnt=gFailAfter;
1.280 + //notify failure
1.281 + extern TUint32 gNotificationType;
1.282 + extern TUint32 KNandDbgNotifyWriteFail;
1.283 + extern TInt NotifyThread();
1.284 + if(gNotificationType==KNandDbgNotifyWriteFail)
1.285 + NotifyThread();
1.286 +
1.287 + return KErrCorrupt;
1.288 + }
1.289 + }
1.290 + }
1.291 +#endif
1.292 +
1.293 + return KErrNone;
1.294 + }
1.295 +
1.296 +TInt DMediaDriverNandWin32::DeviceErase(const TUint aBlockAddress)
1.297 + {
1.298 + __PATH_TESTED;
1.299 +
1.300 + __NAND_ASSERT(aBlockAddress < iNumBlocks);
1.301 +#ifdef __TEST_MEDIA_DRIVER__
1.302 + extern TBool gNoPower;
1.303 + extern TBool gPowerFail;
1.304 + extern TUint32 gPowerFailAfter;
1.305 + if(gNoPower)
1.306 + return KErrBadPower;
1.307 + if(gPowerFail)
1.308 + {
1.309 + if(gPowerFailAfter)
1.310 + --gPowerFailAfter;
1.311 + else
1.312 + {
1.313 + gPowerFail=EFalse;
1.314 + gNoPower=ETrue;
1.315 + extern TUint32 gNotificationType;
1.316 + extern TUint32 KNandDbgNotifyPowerDown;
1.317 + extern TInt NotifyThread();
1.318 + if(gNotificationType==KNandDbgNotifyPowerDown)
1.319 + NotifyThread();
1.320 + return KErrBadPower;
1.321 + }
1.322 + }
1.323 +#endif
1.324 +
1.325 + const TUint bytesPerEraseBlock = iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare);
1.326 + const TUint erasePos = aBlockAddress * bytesPerEraseBlock;
1.327 +
1.328 + TUint8* temp = iBase + erasePos;
1.329 + for (TUint i=0; i < bytesPerEraseBlock; i++)
1.330 + {
1.331 + temp[i]=0xFF;
1.332 + }
1.333 + return KErrNone;
1.334 + }
1.335 +
1.336 +TInt DMediaDriverNandWin32::DeviceClose()
1.337 + {
1.338 + __PATH_NOT_YET_TESTED;
1.339 + TBool bRtn=UnmapViewOfFile(iBase);
1.340 + if(!bRtn)
1.341 + {
1.342 + __PATH_NOT_YET_TESTED;
1.343 + return(MapLastError());
1.344 + }
1.345 +
1.346 + bRtn=CloseHandle(iMapping);
1.347 + if (!bRtn)
1.348 + {
1.349 + __PATH_NOT_YET_TESTED;
1.350 + return(MapLastError());
1.351 + }
1.352 +
1.353 + bRtn=CloseHandle(iFile);
1.354 + if (!bRtn)
1.355 + {
1.356 + __PATH_NOT_YET_TESTED;
1.357 + return(MapLastError());
1.358 + }
1.359 +
1.360 + return KErrNone;
1.361 + }
1.362 +
1.363 +DMediaDriverNandWin32::DMediaDriverNandWin32(TMediaDevice aDevice)
1.364 + : DMediaDriverNand(aDevice)
1.365 + {
1.366 + __PATH_TESTED;
1.367 + }
1.368 +
1.369 +DMediaDriverNand* DMediaDriverNand::New(TMediaDevice aDevice)
1.370 + {
1.371 + __PATH_TESTED;
1.372 + return new DMediaDriverNandWin32(aDevice);
1.373 + }
1.374 +
1.375 +#ifdef __USE_CUSTOM_ALLOCATOR
1.376 +/**
1.377 + Concrete implementation of the NAND buffer allocator class
1.378 + - Uses Kern::Alloc based allocation
1.379 +
1.380 + @internalTechnology
1.381 + */
1.382 +class TNandAllocatorWins : public TNandAllocatorBase
1.383 + {
1.384 +public:
1.385 + virtual TInt AllocateBuffers(SBufferInfo& aBufferInfo); // Initialise the allocator
1.386 + };
1.387 +
1.388 +/** Concrete implementation of the NAND buffer allocator class
1.389 + Creates a customallocator (using Kern::Alloc)
1.390 +
1.391 + @param aBufferInfo A reference to a SBufferInfo containing the details of the PSL allocated buffer
1.392 + @return Standard Symbian OS error code
1.393 + @see TNandAllocatorBase::SCellInfo
1.394 + */
1.395 +TInt TNandAllocatorWins::AllocateBuffers(SBufferInfo& aBufferInfo)
1.396 + {
1.397 + const TUint32 KNumBuffers = 4;
1.398 + const TUint32 KMaxNumBytesSpare = 16;
1.399 + const TUint32 KMaxNumBytesMain = 512;
1.400 + const TUint32 KMaxNumBytesPage = KMaxNumBytesSpare + KMaxNumBytesMain;
1.401 +
1.402 + aBufferInfo.iBytesPerSpareArray = KMaxNumBytesSpare;
1.403 + aBufferInfo.iBytesPerMainArray = KMaxNumBytesMain;
1.404 + aBufferInfo.iBufferCount = KNumBuffers;
1.405 +
1.406 + aBufferInfo.iBufferP = reinterpret_cast<TUint8*>(Kern::Alloc(KMaxNumBytesPage * KNumBuffers));
1.407 +
1.408 + return(aBufferInfo.iBufferP ? KErrNone : KErrNoMemory);
1.409 + }
1.410 +
1.411 +/**
1.412 +Create an allocator suitable for use on this target
1.413 +@internalComponent
1.414 +*/
1.415 +TNandAllocatorBase* DMediaDriverNand::ExtensionInitAllocator()
1.416 + {
1.417 + return new TNandAllocatorWins;
1.418 + }
1.419 +#endif