os/boardsupport/emulator/emulatorbsp/specific/nanddev.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// D_MEDNAND.CPP
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#define _MEDIA_DRIVER
sl@0
    19
#include <nand_media.h>
sl@0
    20
#include <emulator.h>
sl@0
    21
#include <property.h>
sl@0
    22
sl@0
    23
/********************************************
sl@0
    24
 * Driver definitions
sl@0
    25
 ********************************************/
sl@0
    26
const TInt KSimulatedDeviceId = 0xEC73;
sl@0
    27
const CHAR KNandFileName[] = "NANDDRV.BIN";
sl@0
    28
sl@0
    29
//
sl@0
    30
// Platform dependent media driver class
sl@0
    31
//
sl@0
    32
class DMediaDriverNandWin32 : public DMediaDriverNand
sl@0
    33
	{
sl@0
    34
public:
sl@0
    35
	DMediaDriverNandWin32(TMediaDevice aDevice);
sl@0
    36
sl@0
    37
	// replacing pure virtual - NAND device specific stuff
sl@0
    38
	virtual TInt Initialise();
sl@0
    39
	virtual TInt GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId);
sl@0
    40
	virtual TInt DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength);
sl@0
    41
	virtual TInt DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength);
sl@0
    42
	virtual TInt DeviceErase(const TUint aBlockAddress);
sl@0
    43
	virtual TInt DeviceClose();
sl@0
    44
sl@0
    45
public:
sl@0
    46
	HANDLE iFile;
sl@0
    47
	HANDLE iMapping;
sl@0
    48
	TUint8* iBase;
sl@0
    49
	};
sl@0
    50
sl@0
    51
LOCAL_C TInt MapLastError()
sl@0
    52
//
sl@0
    53
// Map an NT error to an Epoc/32 error.
sl@0
    54
//
sl@0
    55
	{
sl@0
    56
	__PATH_NOT_YET_TESTED;
sl@0
    57
	DWORD r=GetLastError();
sl@0
    58
	TInt res;
sl@0
    59
	switch (r)
sl@0
    60
		{
sl@0
    61
	    case ERROR_SHARING_VIOLATION : res=KErrAccessDenied; break;
sl@0
    62
	    case ERROR_LOCK_VIOLATION : res=KErrLocked; break;
sl@0
    63
	    case ERROR_FILE_NOT_FOUND: res=KErrNotFound; break;
sl@0
    64
	    case ERROR_PATH_NOT_FOUND: res=KErrPathNotFound; break;
sl@0
    65
	    case ERROR_ALREADY_EXISTS:
sl@0
    66
	    case ERROR_FILE_EXISTS:
sl@0
    67
            res=KErrAlreadyExists;
sl@0
    68
		    break;
sl@0
    69
	    case ERROR_NOT_READY: res=KErrNotReady; break;
sl@0
    70
	    case ERROR_UNRECOGNIZED_VOLUME:
sl@0
    71
	    case ERROR_NOT_DOS_DISK:
sl@0
    72
		    res=KErrUnknown;
sl@0
    73
		    break;
sl@0
    74
	    case ERROR_UNRECOGNIZED_MEDIA: res=KErrCorrupt; break;
sl@0
    75
	    case ERROR_INVALID_NAME: res=KErrBadName; break;
sl@0
    76
	    case ERROR_NO_MORE_FILES: res=KErrEof; break;
sl@0
    77
		case ERROR_DISK_FULL: res=KErrDiskFull; break;
sl@0
    78
		default: res=KErrGeneral;
sl@0
    79
		}
sl@0
    80
	return(res);
sl@0
    81
	}
sl@0
    82
sl@0
    83
TInt DMediaDriverNandWin32::Initialise()
sl@0
    84
//
sl@0
    85
// Create the simulated NAND file if necessary and
sl@0
    86
// map it into memory.
sl@0
    87
//
sl@0
    88
	{
sl@0
    89
	__PATH_TESTED;
sl@0
    90
sl@0
    91
	// locate/open the file that models the flash
sl@0
    92
	CHAR filename[MAX_PATH];
sl@0
    93
	strcpy(filename, Property::GetString("EmulatorMediaPath"));
sl@0
    94
	if (!Emulator::CreateAllDirectories(filename))
sl@0
    95
		{
sl@0
    96
		__PATH_NOT_YET_TESTED;
sl@0
    97
		return Emulator::LastError();
sl@0
    98
		}
sl@0
    99
	strcat(filename, KNandFileName);
sl@0
   100
	iFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
sl@0
   101
sl@0
   102
	if (iFile == INVALID_HANDLE_VALUE)
sl@0
   103
		{
sl@0
   104
		__PATH_NOT_YET_TESTED;
sl@0
   105
		return Emulator::LastError();
sl@0
   106
		}
sl@0
   107
sl@0
   108
	const TUint32 flashSizeInBytes = iNumBlocks * iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare);
sl@0
   109
sl@0
   110
	SetFilePointer(iFile, flashSizeInBytes, NULL, FILE_BEGIN);
sl@0
   111
	SetEndOfFile(iFile);
sl@0
   112
	
sl@0
   113
	iMapping = CreateFileMappingA(iFile, NULL, PAGE_READWRITE, 0, flashSizeInBytes, NULL);
sl@0
   114
	if (iMapping == NULL)
sl@0
   115
		{
sl@0
   116
		__PATH_NOT_YET_TESTED;
sl@0
   117
		return Emulator::LastError();
sl@0
   118
		}
sl@0
   119
sl@0
   120
	iBase = (TUint8*)MapViewOfFile(iMapping, FILE_MAP_WRITE, 0, 0, flashSizeInBytes);
sl@0
   121
	if (iBase == NULL)
sl@0
   122
		{
sl@0
   123
		__PATH_NOT_YET_TESTED;
sl@0
   124
		return Emulator::LastError();
sl@0
   125
		}
sl@0
   126
sl@0
   127
	return KErrNone;
sl@0
   128
	}
sl@0
   129
sl@0
   130
TInt DMediaDriverNandWin32::GetDeviceId(TUint8& aDeviceId, TUint8& aManufacturerId)
sl@0
   131
	{
sl@0
   132
	__PATH_TESTED;
sl@0
   133
	
sl@0
   134
	aManufacturerId = (KSimulatedDeviceId & 0xFF00) >> 8;
sl@0
   135
	aDeviceId       = (KSimulatedDeviceId & 0xFF);
sl@0
   136
	return KErrNone;
sl@0
   137
	}
sl@0
   138
sl@0
   139
TInt DMediaDriverNandWin32::DeviceRead(const TUint aPageAddress, TAny* aBuf, const TUint aLength)
sl@0
   140
	{
sl@0
   141
	__PATH_TESTED;
sl@0
   142
sl@0
   143
	__NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock));
sl@0
   144
	__NAND_ASSERT(   (aLength == iNumBytesMain)
sl@0
   145
				  || (aLength == iNumBytesMain + iNumBytesSpare)
sl@0
   146
				  || (aLength == iNumBytesSpare)				 );
sl@0
   147
	
sl@0
   148
#ifdef __TEST_MEDIA_DRIVER__
sl@0
   149
		extern TBool gNoPower;
sl@0
   150
		if(gNoPower)
sl@0
   151
			return KErrBadPower;
sl@0
   152
#endif
sl@0
   153
sl@0
   154
	TUint8* readPoint;
sl@0
   155
	if (aLength == iNumBytesMain)
sl@0
   156
		{
sl@0
   157
		__PATH_TESTED;
sl@0
   158
		readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
sl@0
   159
		}
sl@0
   160
	else if (aLength == iNumBytesSpare)
sl@0
   161
		{
sl@0
   162
		__PATH_TESTED;
sl@0
   163
		readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain;
sl@0
   164
		}
sl@0
   165
	else if (aLength == (iNumBytesMain + iNumBytesSpare))
sl@0
   166
		{
sl@0
   167
		__PATH_TESTED;
sl@0
   168
		readPoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
sl@0
   169
		}
sl@0
   170
	else
sl@0
   171
		{
sl@0
   172
		__PATH_NOT_YET_TESTED;
sl@0
   173
		return KErrArgument;
sl@0
   174
		}
sl@0
   175
sl@0
   176
	for (TUint i = 0; i < aLength; i++)
sl@0
   177
		{
sl@0
   178
		((TUint8*)aBuf)[i] = readPoint[i];
sl@0
   179
		}
sl@0
   180
sl@0
   181
#ifdef __TEST_MEDIA_DRIVER__
sl@0
   182
	extern TBool gECCFail;
sl@0
   183
		if(gECCFail)
sl@0
   184
		{
sl@0
   185
			//introduce a random one bit error
sl@0
   186
			TUint8* p=(TUint8*)aBuf;
sl@0
   187
			TUint32 key=Kern::Random() % aLength;
sl@0
   188
			TUint32 shift=1<<(Kern::Random() % 8);
sl@0
   189
			p[key]=(TUint8)(p[key]&shift?p[key]-shift:p[key]+shift);
sl@0
   190
			gECCFail=EFalse;
sl@0
   191
		}
sl@0
   192
#endif
sl@0
   193
sl@0
   194
	return KErrNone;
sl@0
   195
	}
sl@0
   196
sl@0
   197
#ifdef __TEST_MEDIA_DRIVER__
sl@0
   198
extern "C" TUint32 gbbm_get_sphy_blknum(TUint32, TUint32);
sl@0
   199
#endif
sl@0
   200
TInt DMediaDriverNandWin32::DeviceWrite(const TUint aPageAddress, TAny* aBuf, const TUint aLength)
sl@0
   201
	{
sl@0
   202
	__PATH_TESTED;
sl@0
   203
sl@0
   204
	__NAND_ASSERT(aPageAddress < (iNumBlocks * iNumPagesPerBlock));
sl@0
   205
	__NAND_ASSERT(   (aLength == iNumBytesMain)
sl@0
   206
				  || (aLength == iNumBytesMain + iNumBytesSpare)
sl@0
   207
				  || (aLength == iNumBytesSpare)				 );
sl@0
   208
sl@0
   209
#ifdef __TEST_MEDIA_DRIVER__
sl@0
   210
		extern TBool gNoPower;
sl@0
   211
		extern TBool gPowerFail;
sl@0
   212
		extern TUint32 gPowerFailAfter;
sl@0
   213
		if(gNoPower)
sl@0
   214
			return KErrBadPower;
sl@0
   215
		if(gPowerFail)
sl@0
   216
			{
sl@0
   217
			if(gPowerFailAfter)
sl@0
   218
				--gPowerFailAfter;
sl@0
   219
			else
sl@0
   220
				{
sl@0
   221
				gPowerFail=EFalse;
sl@0
   222
				gNoPower=ETrue;
sl@0
   223
				extern TUint32 gNotificationType;
sl@0
   224
				extern TUint32 KNandDbgNotifyPowerDown;
sl@0
   225
				extern TInt NotifyThread();
sl@0
   226
				if(gNotificationType==KNandDbgNotifyPowerDown)
sl@0
   227
					NotifyThread();
sl@0
   228
				return KErrBadPower;
sl@0
   229
				}
sl@0
   230
			}
sl@0
   231
#endif
sl@0
   232
	
sl@0
   233
	TUint8* writePoint;
sl@0
   234
	
sl@0
   235
	if (aLength == iNumBytesMain)
sl@0
   236
		{
sl@0
   237
		__PATH_TESTED;
sl@0
   238
		writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
sl@0
   239
		}
sl@0
   240
	else if (aLength == iNumBytesSpare)
sl@0
   241
		{
sl@0
   242
		__PATH_TESTED;
sl@0
   243
		writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare)) + iNumBytesMain;
sl@0
   244
		}
sl@0
   245
	else if (aLength == (iNumBytesMain + iNumBytesSpare))
sl@0
   246
		{
sl@0
   247
		__PATH_TESTED;
sl@0
   248
		writePoint = iBase + (aPageAddress * (iNumBytesMain + iNumBytesSpare));
sl@0
   249
		}
sl@0
   250
	else
sl@0
   251
		{
sl@0
   252
		__PATH_NOT_YET_TESTED;
sl@0
   253
		return KErrArgument;
sl@0
   254
		}
sl@0
   255
	
sl@0
   256
	for (TUint i = 0; i < aLength; i++)
sl@0
   257
		{
sl@0
   258
		writePoint[i] &= ((TUint8*)aBuf)[i];
sl@0
   259
		}
sl@0
   260
sl@0
   261
#ifdef __TEST_MEDIA_DRIVER__
sl@0
   262
		extern TUint32 gFailAfter;
sl@0
   263
		extern TUint32 gFailAfterCnt;
sl@0
   264
		extern TBool gFailureType; //true-WriteFail, false-EraseFail
sl@0
   265
		extern TBool gFailON;
sl@0
   266
		if(gFailON && gFailureType)
sl@0
   267
			{
sl@0
   268
			if(gFailAfterCnt)
sl@0
   269
				--gFailAfterCnt;
sl@0
   270
			else
sl@0
   271
				{
sl@0
   272
				extern TUint32 FirstReadPUN;
sl@0
   273
				extern DMediaDriverNand* gMediaDriverPtr;		
sl@0
   274
				if(gbbm_get_sphy_blknum(0,aPageAddress/gMediaDriverPtr->iNumPagesPerBlock)==FirstReadPUN)
sl@0
   275
					{
sl@0
   276
					gFailAfterCnt=gFailAfter;
sl@0
   277
					//notify failure
sl@0
   278
					extern TUint32 gNotificationType;
sl@0
   279
					extern TUint32 KNandDbgNotifyWriteFail;
sl@0
   280
					extern TInt NotifyThread();
sl@0
   281
					if(gNotificationType==KNandDbgNotifyWriteFail)
sl@0
   282
						NotifyThread();
sl@0
   283
sl@0
   284
					return KErrCorrupt;
sl@0
   285
					}
sl@0
   286
				}
sl@0
   287
			}
sl@0
   288
#endif
sl@0
   289
sl@0
   290
	return KErrNone;
sl@0
   291
	}
sl@0
   292
sl@0
   293
TInt DMediaDriverNandWin32::DeviceErase(const TUint aBlockAddress)
sl@0
   294
	{
sl@0
   295
	__PATH_TESTED;
sl@0
   296
	
sl@0
   297
	__NAND_ASSERT(aBlockAddress < iNumBlocks);
sl@0
   298
#ifdef __TEST_MEDIA_DRIVER__
sl@0
   299
		extern TBool gNoPower;
sl@0
   300
		extern TBool gPowerFail;
sl@0
   301
		extern TUint32 gPowerFailAfter;
sl@0
   302
		if(gNoPower)
sl@0
   303
			return KErrBadPower;
sl@0
   304
		if(gPowerFail)
sl@0
   305
			{
sl@0
   306
			if(gPowerFailAfter)
sl@0
   307
				--gPowerFailAfter;
sl@0
   308
			else
sl@0
   309
				{
sl@0
   310
				gPowerFail=EFalse;
sl@0
   311
				gNoPower=ETrue;
sl@0
   312
				extern TUint32 gNotificationType;
sl@0
   313
				extern TUint32 KNandDbgNotifyPowerDown;
sl@0
   314
				extern TInt NotifyThread();
sl@0
   315
				if(gNotificationType==KNandDbgNotifyPowerDown)
sl@0
   316
					NotifyThread();
sl@0
   317
				return KErrBadPower;
sl@0
   318
				}
sl@0
   319
			}
sl@0
   320
#endif
sl@0
   321
	
sl@0
   322
	const TUint bytesPerEraseBlock = iNumPagesPerBlock * (iNumBytesMain + iNumBytesSpare);
sl@0
   323
	const TUint erasePos = aBlockAddress * bytesPerEraseBlock;
sl@0
   324
	
sl@0
   325
	TUint8* temp = iBase + erasePos;
sl@0
   326
	for (TUint i=0; i < bytesPerEraseBlock; i++)
sl@0
   327
		{
sl@0
   328
		temp[i]=0xFF;
sl@0
   329
		}
sl@0
   330
	return KErrNone;
sl@0
   331
	}
sl@0
   332
sl@0
   333
TInt DMediaDriverNandWin32::DeviceClose()
sl@0
   334
	{
sl@0
   335
	__PATH_NOT_YET_TESTED;
sl@0
   336
	TBool bRtn=UnmapViewOfFile(iBase);
sl@0
   337
	if(!bRtn)
sl@0
   338
		{
sl@0
   339
		__PATH_NOT_YET_TESTED;
sl@0
   340
		return(MapLastError());
sl@0
   341
		}
sl@0
   342
sl@0
   343
	bRtn=CloseHandle(iMapping);
sl@0
   344
	if (!bRtn)
sl@0
   345
		{
sl@0
   346
		__PATH_NOT_YET_TESTED;
sl@0
   347
		return(MapLastError());
sl@0
   348
		}
sl@0
   349
sl@0
   350
	bRtn=CloseHandle(iFile);
sl@0
   351
	if (!bRtn)
sl@0
   352
		{
sl@0
   353
		__PATH_NOT_YET_TESTED;
sl@0
   354
		return(MapLastError());
sl@0
   355
		}
sl@0
   356
sl@0
   357
	return KErrNone;
sl@0
   358
	}
sl@0
   359
sl@0
   360
DMediaDriverNandWin32::DMediaDriverNandWin32(TMediaDevice aDevice)
sl@0
   361
	:	DMediaDriverNand(aDevice)
sl@0
   362
	{
sl@0
   363
	__PATH_TESTED;
sl@0
   364
	}
sl@0
   365
sl@0
   366
DMediaDriverNand* DMediaDriverNand::New(TMediaDevice aDevice)
sl@0
   367
	{
sl@0
   368
	__PATH_TESTED;
sl@0
   369
	return new DMediaDriverNandWin32(aDevice);
sl@0
   370
	}
sl@0
   371
sl@0
   372
#ifdef __USE_CUSTOM_ALLOCATOR
sl@0
   373
/**	
sl@0
   374
	Concrete implementation of the NAND buffer allocator class
sl@0
   375
		- Uses Kern::Alloc based allocation
sl@0
   376
sl@0
   377
	@internalTechnology
sl@0
   378
 */
sl@0
   379
class TNandAllocatorWins : public TNandAllocatorBase
sl@0
   380
	{
sl@0
   381
public:
sl@0
   382
	virtual TInt AllocateBuffers(SBufferInfo& aBufferInfo);	// Initialise the allocator
sl@0
   383
	};
sl@0
   384
sl@0
   385
/**	Concrete implementation of the NAND buffer allocator class
sl@0
   386
	Creates a customallocator (using Kern::Alloc)
sl@0
   387
sl@0
   388
	@param aBufferInfo A reference to a SBufferInfo containing the details of the PSL allocated buffer
sl@0
   389
	@return Standard Symbian OS error code
sl@0
   390
	@see TNandAllocatorBase::SCellInfo
sl@0
   391
 */
sl@0
   392
TInt TNandAllocatorWins::AllocateBuffers(SBufferInfo& aBufferInfo)
sl@0
   393
	{
sl@0
   394
	const TUint32 KNumBuffers		= 4;
sl@0
   395
	const TUint32 KMaxNumBytesSpare = 16;
sl@0
   396
	const TUint32 KMaxNumBytesMain	= 512;
sl@0
   397
	const TUint32 KMaxNumBytesPage	= KMaxNumBytesSpare + KMaxNumBytesMain;
sl@0
   398
sl@0
   399
	aBufferInfo.iBytesPerSpareArray = KMaxNumBytesSpare;
sl@0
   400
	aBufferInfo.iBytesPerMainArray = KMaxNumBytesMain;
sl@0
   401
	aBufferInfo.iBufferCount = KNumBuffers;
sl@0
   402
sl@0
   403
	aBufferInfo.iBufferP = reinterpret_cast<TUint8*>(Kern::Alloc(KMaxNumBytesPage * KNumBuffers));
sl@0
   404
sl@0
   405
	return(aBufferInfo.iBufferP ? KErrNone : KErrNoMemory);
sl@0
   406
	}
sl@0
   407
sl@0
   408
/**
sl@0
   409
Create an allocator suitable for use on this target
sl@0
   410
@internalComponent
sl@0
   411
*/
sl@0
   412
TNandAllocatorBase* DMediaDriverNand::ExtensionInitAllocator()
sl@0
   413
	{
sl@0
   414
	return new TNandAllocatorWins;
sl@0
   415
	}
sl@0
   416
#endif