os/boardsupport/emulator/emulatorbsp/specific/lffsdev.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
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
// wins\specific\lffsdev.cpp
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <flash_media.h>
sl@0
    19
#include <emulator.h>
sl@0
    20
#include <property.h>
sl@0
    21
sl@0
    22
#define FLASH_FAULT()	Kern::Fault("LFFSDEV",__LINE__)
sl@0
    23
sl@0
    24
//#define M18_EMULATION // Test for Control Mode operation
sl@0
    25
sl@0
    26
/********************************************
sl@0
    27
 * Driver definitions
sl@0
    28
 ********************************************/
sl@0
    29
sl@0
    30
/** LFFS image name */
sl@0
    31
const CHAR KLfsFileName[] = "LFSLDRV.BIN";
sl@0
    32
sl@0
    33
sl@0
    34
//-- default values for LFFS related entries in "epoc.ini" file
sl@0
    35
const TInt      KDefaultFlashSize = 0x400000;   //-- "FlashSize"        entry, default 4MB
sl@0
    36
const TInt      KEraseBlockSize   = 0x20000;	//-- "FlashEraseSize"   entry, default 128KB
sl@0
    37
const TUint32   KFlashEraseTime   =	1000000;	//-- "FlashEraseTime"   entry, default 1s
sl@0
    38
const TInt      KWriteBlockSize   = 64;         //-- "FlashWriteSize"   entry
sl@0
    39
const TInt      KFlashWriteTime   = 406;		//-- "FlashWriteTime"   entry, default 406us
sl@0
    40
const TInt      KResumeTime       = 5000;		//-- "FlashResumeTime"  entry, default 5ms
sl@0
    41
sl@0
    42
//-- other possible LFFS related entries in "epoc.ini" file:
sl@0
    43
//-- "FlashHoldOffTime"   default value = iEraseTime/10
sl@0
    44
sl@0
    45
//-- "FlashForceImgMount" default value = 0. If not 0 LFFS image will be mounted as it is, even if it doesn't have TLfsParams structure in the end.
sl@0
    46
//-- Moreover, it won't be zero filled and TLfsParams structure won't be written at the end of the image file.
sl@0
    47
//-- shall be useful for dealing with real images from the real devices
sl@0
    48
sl@0
    49
sl@0
    50
/** 
sl@0
    51
    This cunning structure is supposed to be at the very end of the LFFS image file. If it is not foung there, 
sl@0
    52
    the image gets zero-filled (depends on "FlashForceImgMount" flag in epoc.ini). 
sl@0
    53
*/
sl@0
    54
sl@0
    55
struct TLfsParams
sl@0
    56
	{
sl@0
    57
	TInt iEraseSize;
sl@0
    58
	};
sl@0
    59
sl@0
    60
#ifdef _DEBUG
sl@0
    61
/***************************************************
sl@0
    62
 * ControlIO command types - for debug builds, only
sl@0
    63
 ***************************************************/
sl@0
    64
sl@0
    65
enum TCtrlIoTypes
sl@0
    66
	{
sl@0
    67
	//KCtrlIoRww=0,
sl@0
    68
	KCtrlIoTimeout=1
sl@0
    69
	};
sl@0
    70
#endif
sl@0
    71
sl@0
    72
sl@0
    73
const TInt KDataBufSize=1024;
sl@0
    74
sl@0
    75
/********************************************
sl@0
    76
 * Media driver class
sl@0
    77
 ********************************************/
sl@0
    78
class DMediaDriverFlashWin32 : public DMediaDriverFlash
sl@0
    79
	{
sl@0
    80
public:
sl@0
    81
	enum TState
sl@0
    82
		{
sl@0
    83
		EIdle=0,
sl@0
    84
		EWriting=1,
sl@0
    85
		EEraseNoSuspend=2,
sl@0
    86
		EErase=3,
sl@0
    87
		ESuspendPending=4,
sl@0
    88
		ESuspending=5,
sl@0
    89
		ESuspended=6,
sl@0
    90
		EErasePending=7
sl@0
    91
		};
sl@0
    92
public:
sl@0
    93
	DMediaDriverFlashWin32(TInt aMediaId);
sl@0
    94
public:
sl@0
    95
	// replacing pure virtual - FLASH device specific stuff
sl@0
    96
	virtual TInt Initialise();
sl@0
    97
	virtual TUint32 EraseBlockSize();
sl@0
    98
	virtual TUint32 TotalSize();
sl@0
    99
	virtual TInt DoRead();
sl@0
   100
	virtual TInt DoWrite();
sl@0
   101
	virtual TInt DoErase();
sl@0
   102
	virtual TInt Caps(TLocalDriveCapsV2& caps);
sl@0
   103
public:
sl@0
   104
	void HandleEvent();
sl@0
   105
	void StartTimer(TInt aMicros);
sl@0
   106
	void StartErase();
sl@0
   107
	void SuspendErase();
sl@0
   108
	void CompleteErase();
sl@0
   109
	void CompleteWrite();
sl@0
   110
	void CompleteSuspend();
sl@0
   111
	void StartPendingRW();
sl@0
   112
	void ReadFlashParameters();
sl@0
   113
public:
sl@0
   114
	static void TimerFn(TAny* aPtr);
sl@0
   115
	static void EventDfc(TAny* aPtr);
sl@0
   116
#ifdef _DEBUG
sl@0
   117
public:
sl@0
   118
    enum TCtrlIoState {/*EIdle=0,ECtrlIoWaitWr=1,ECtrlIoWaitRd=2,ECtrlIoWrActive=3,*/ECtrlIoTimeOutPrep=4};
sl@0
   119
    TInt ControlIO(TInt aCommand,TAny* aParam1,TAny* /*aParam2*/);
sl@0
   120
	TInt Request(TLocDrvRequest& m);
sl@0
   121
#endif
sl@0
   122
public:
sl@0
   123
	TState iState;
sl@0
   124
	
sl@0
   125
	TInt iSize;
sl@0
   126
	TInt iEraseBlockSize;
sl@0
   127
	TInt iEraseTime;
sl@0
   128
	TInt iSuspendHoldOffTime;
sl@0
   129
	TInt iResumeTime;
sl@0
   130
	TInt iWriteBlockSize;
sl@0
   131
	TInt iWriteTime;
sl@0
   132
    
sl@0
   133
	HANDLE iFile;
sl@0
   134
	HANDLE iMapping;
sl@0
   135
	TUint8* iBase;
sl@0
   136
	TUint8* iData;		// data being written
sl@0
   137
	
sl@0
   138
	NTimer iTimer;
sl@0
   139
	TDfc iEventDfc;
sl@0
   140
	TUint32 iTickPeriod;
sl@0
   141
	TUint32 iEraseCounter;
sl@0
   142
	TUint32 iErasePos;
sl@0
   143
	TInt iTimerExtra;
sl@0
   144
sl@0
   145
#ifdef _DEBUG
sl@0
   146
public:
sl@0
   147
    TUint8 iCtrlIoState;
sl@0
   148
#endif
sl@0
   149
	};
sl@0
   150
sl@0
   151
DMediaDriverFlashWin32::DMediaDriverFlashWin32(TInt aMediaId)
sl@0
   152
	:	DMediaDriverFlash(aMediaId),
sl@0
   153
		iTimer(&TimerFn,this),
sl@0
   154
		iEventDfc(&EventDfc,this,NULL,2),
sl@0
   155
		iTickPeriod(NKern::TickPeriod())
sl@0
   156
	{
sl@0
   157
	// iState=EIdle;
sl@0
   158
#ifdef _DEBUG
sl@0
   159
    //iCtrlIoState=EIdle;
sl@0
   160
#endif
sl@0
   161
sl@0
   162
	}
sl@0
   163
sl@0
   164
void DMediaDriverFlashWin32::ReadFlashParameters()
sl@0
   165
//
sl@0
   166
// Read the flash parameters from the ini file, or use defaults
sl@0
   167
//
sl@0
   168
	{
sl@0
   169
   
sl@0
   170
	iSize = Property::GetInt("FlashSize", KDefaultFlashSize);
sl@0
   171
sl@0
   172
	TInt nblocks = Property::GetInt("FlashEraseBlocks", 0);
sl@0
   173
	if (nblocks == 0)
sl@0
   174
		nblocks = iSize/Property::GetInt("FlashEraseSize", KEraseBlockSize);
sl@0
   175
sl@0
   176
	iEraseBlockSize = iSize / nblocks;
sl@0
   177
	__ASSERT_ALWAYS(iEraseBlockSize * nblocks == iSize, FLASH_FAULT());
sl@0
   178
	__ASSERT_ALWAYS((iEraseBlockSize & (iEraseBlockSize-1)) == 0, FLASH_FAULT());
sl@0
   179
sl@0
   180
	iEraseTime = Property::GetInt("FlashEraseTime", KFlashEraseTime);
sl@0
   181
	
sl@0
   182
	iSuspendHoldOffTime = Property::GetInt("FlashHoldOffTime", iEraseTime/10);
sl@0
   183
	iResumeTime = Property::GetInt("FlashResumeTime", KResumeTime);
sl@0
   184
	iWriteBlockSize = Property::GetInt("FlashWriteSize", KWriteBlockSize);
sl@0
   185
	__ASSERT_ALWAYS((iWriteBlockSize & (iWriteBlockSize-1)) == 0, FLASH_FAULT());
sl@0
   186
sl@0
   187
	iWriteTime = Property::GetInt("FlashWriteTime", KFlashWriteTime);
sl@0
   188
	
sl@0
   189
	}
sl@0
   190
sl@0
   191
TInt DMediaDriverFlashWin32::Initialise()
sl@0
   192
	{
sl@0
   193
	iEventDfc.SetDfcQ(iPrimaryMedia->iDfcQ);
sl@0
   194
	iData=(TUint8*)Kern::Alloc(KDataBufSize);
sl@0
   195
	if (!iData)
sl@0
   196
		return KErrNoMemory;
sl@0
   197
sl@0
   198
	ReadFlashParameters();
sl@0
   199
sl@0
   200
	// locate/open the file that models the flash
sl@0
   201
	CHAR filename[MAX_PATH];
sl@0
   202
	strcpy(filename, Property::GetString("EmulatorMediaPath"));
sl@0
   203
	if (!Emulator::CreateAllDirectories(filename))
sl@0
   204
		return Emulator::LastError();
sl@0
   205
	strcat(filename, KLfsFileName);
sl@0
   206
	
sl@0
   207
	iFile = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_RANDOM_ACCESS, NULL);
sl@0
   208
	if (iFile == INVALID_HANDLE_VALUE)
sl@0
   209
		return Emulator::LastError();
sl@0
   210
sl@0
   211
	TLfsParams p;
sl@0
   212
	p.iEraseSize = -1;
sl@0
   213
	DWORD bytes;
sl@0
   214
	TBool valid;
sl@0
   215
	
sl@0
   216
    //-- try to read TLfsParams structure from the end of the image file.
sl@0
   217
	if (SetFilePointer(iFile, iSize, NULL, FILE_BEGIN) != -1
sl@0
   218
		&& ReadFile(iFile, &p, sizeof(TLfsParams), &bytes, NULL)
sl@0
   219
		&& p.iEraseSize == iEraseBlockSize)
sl@0
   220
	{
sl@0
   221
        valid = ETrue; //-- read it OK.
sl@0
   222
	}
sl@0
   223
	else
sl@0
   224
	{//-- couldn't read TLfsParams structure from the end of the image file.
sl@0
   225
     //-- if "FlashForceImgMount" parameter from epoc.ini is 0 or not present,
sl@0
   226
     //-- zero-fill the lffs image file and write TLfsParams structure at the end of the file.
sl@0
   227
sl@0
   228
		const TInt forceImgMount = Property::GetInt("FlashForceImgMount", 0);
sl@0
   229
        if(!forceImgMount)
sl@0
   230
		{
sl@0
   231
		p.iEraseSize = iEraseBlockSize;
sl@0
   232
		if (SetFilePointer(iFile,iSize, NULL, FILE_BEGIN) == -1
sl@0
   233
			|| !WriteFile(iFile, &p, sizeof(p), &bytes, NULL)
sl@0
   234
			|| !SetEndOfFile(iFile))
sl@0
   235
			return Emulator::LastError();
sl@0
   236
		    
sl@0
   237
		valid = EFalse;
sl@0
   238
		}
sl@0
   239
        else
sl@0
   240
        {//-- mount LFFS image forcingly.
sl@0
   241
            valid = ETrue;
sl@0
   242
        }
sl@0
   243
	}
sl@0
   244
sl@0
   245
	iMapping = CreateFileMappingA(iFile, NULL, PAGE_READWRITE, 0, iSize, NULL);
sl@0
   246
	if (iMapping == NULL)
sl@0
   247
		return Emulator::LastError();
sl@0
   248
sl@0
   249
	iBase = (TUint8*)MapViewOfFile(iMapping, FILE_MAP_WRITE, 0, 0, iSize);
sl@0
   250
	if (iBase == NULL)
sl@0
   251
		return Emulator::LastError();
sl@0
   252
sl@0
   253
	//-- zero-fill media image it doesn't contain TLfsParams data at the very end.
sl@0
   254
	if (!valid)
sl@0
   255
	    {
sl@0
   256
		memclr(iBase, iSize);
sl@0
   257
        }
sl@0
   258
sl@0
   259
	return KErrNone;
sl@0
   260
	}
sl@0
   261
sl@0
   262
TUint32 DMediaDriverFlashWin32::EraseBlockSize()
sl@0
   263
	{
sl@0
   264
	return iEraseBlockSize;
sl@0
   265
	}
sl@0
   266
sl@0
   267
TUint32 DMediaDriverFlashWin32::TotalSize()
sl@0
   268
	{
sl@0
   269
	return iSize;
sl@0
   270
	}
sl@0
   271
sl@0
   272
TInt DMediaDriverFlashWin32::DoRead()
sl@0
   273
	{
sl@0
   274
	if (iWriteReq)
sl@0
   275
		return 1;	// write in progress so defer read
sl@0
   276
	
sl@0
   277
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:DoRead"));
sl@0
   278
sl@0
   279
	if (iState==EErasePending)
sl@0
   280
		{
sl@0
   281
		iTimer.Cancel();
sl@0
   282
		iState = ESuspended;
sl@0
   283
		}
sl@0
   284
	if (iState==EIdle || iState==ESuspended)
sl@0
   285
		{
sl@0
   286
		// can do the read now
sl@0
   287
		TInt pos=(TInt)iReadReq->Pos();
sl@0
   288
		TInt len=(TInt)iReadReq->Length();
sl@0
   289
sl@0
   290
		TPtrC8 des(iBase+pos,len);
sl@0
   291
		TInt r=iReadReq->WriteRemote(&des,0);
sl@0
   292
		Complete(EReqRead,r);
sl@0
   293
		if (iState==ESuspended)
sl@0
   294
			StartErase();
sl@0
   295
		}
sl@0
   296
	else if (iState==EErase)
sl@0
   297
		{
sl@0
   298
		// erase in progress - suspend it
sl@0
   299
		SuspendErase();
sl@0
   300
		}
sl@0
   301
	else if (iState==EEraseNoSuspend)
sl@0
   302
		iState=ESuspendPending;
sl@0
   303
	// wait for suspend to complete
sl@0
   304
	return KErrNone;
sl@0
   305
	}
sl@0
   306
sl@0
   307
TInt DMediaDriverFlashWin32::DoWrite()
sl@0
   308
	{
sl@0
   309
	if (iReadReq)
sl@0
   310
		return 1;	// read in progress so defer write
sl@0
   311
sl@0
   312
	if (iState==EErasePending)
sl@0
   313
		{
sl@0
   314
		iTimer.Cancel();
sl@0
   315
		iState = ESuspended;
sl@0
   316
		}
sl@0
   317
	if (iState==EIdle || iState==ESuspended)
sl@0
   318
		{
sl@0
   319
		// can start the write now
sl@0
   320
		__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:Write Pos=%08x Length=%08x RemDesOff=%08x",
sl@0
   321
											(TInt)iWriteReq->Pos(),(TInt)iWriteReq->Length(),iWriteReq->RemoteDesOffset()));
sl@0
   322
		if (iState==EIdle)
sl@0
   323
			iState=EWriting;
sl@0
   324
		TInt pos = (TInt)iWriteReq->Pos();
sl@0
   325
		TInt end = pos + (TInt)iWriteReq->Length();
sl@0
   326
		pos &= ~(iWriteBlockSize-1);
sl@0
   327
		end = (end + iWriteBlockSize-1) & ~(iWriteBlockSize-1);
sl@0
   328
		StartTimer(((end-pos)/iWriteBlockSize) * iWriteTime);
sl@0
   329
		}
sl@0
   330
	else if (iState==EErase)
sl@0
   331
		{
sl@0
   332
		// erase in progress - suspend it
sl@0
   333
		SuspendErase();
sl@0
   334
		}
sl@0
   335
	else if (iState==EEraseNoSuspend)
sl@0
   336
		iState=ESuspendPending;
sl@0
   337
	// wait for suspend to complete
sl@0
   338
	return KErrNone;
sl@0
   339
	}
sl@0
   340
sl@0
   341
void DMediaDriverFlashWin32::CompleteWrite()
sl@0
   342
//
sl@0
   343
// Do the actual write in the completion
sl@0
   344
// Transfer data in blocks from the client and AND it to the 'flash'
sl@0
   345
//
sl@0
   346
	{
sl@0
   347
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:WriteComplete"));
sl@0
   348
sl@0
   349
	TInt r = KErrNone;
sl@0
   350
	TUint8* flash = iBase + (TInt)iWriteReq->Pos();
sl@0
   351
	TInt len = (TInt)iWriteReq->Length();
sl@0
   352
	TInt offset = 0;
sl@0
   353
	while (len > 0)
sl@0
   354
		{
sl@0
   355
		TInt size = Min(len, KDataBufSize);
sl@0
   356
		TPtr8 des(iData,size);
sl@0
   357
		r = iWriteReq->ReadRemote(&des, offset);
sl@0
   358
		if (r!=KErrNone)
sl@0
   359
			break;
sl@0
   360
		len -= size;
sl@0
   361
		offset += size;
sl@0
   362
		const TUint8* ptr = iData;
sl@0
   363
		do
sl@0
   364
			{
sl@0
   365
			*flash++ &= *ptr++;
sl@0
   366
			} while (--size > 0);
sl@0
   367
		}
sl@0
   368
sl@0
   369
	if (iState == EWriting)
sl@0
   370
		iState = EIdle;
sl@0
   371
	Complete(EReqWrite,r);
sl@0
   372
	if (iState == ESuspended)
sl@0
   373
		StartErase();
sl@0
   374
	}
sl@0
   375
sl@0
   376
TInt DMediaDriverFlashWin32::DoErase()
sl@0
   377
	{
sl@0
   378
	if (iReadReq || iWriteReq)
sl@0
   379
		return 1;		// read or write in progress so defer this request
sl@0
   380
	TInt pos=(TUint32)iEraseReq->Pos();
sl@0
   381
	TInt len=(TUint32)iEraseReq->Length();
sl@0
   382
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:DoErase %d@%08x",len,pos));
sl@0
   383
	if (len!=iEraseBlockSize)
sl@0
   384
		return KErrArgument;	// only allow single-block erase
sl@0
   385
	if (pos & (iEraseBlockSize-1))
sl@0
   386
		return KErrArgument;	// start position must be on erase block boundary
sl@0
   387
	__ASSERT_ALWAYS(iState==EIdle,FLASH_FAULT());
sl@0
   388
	iErasePos=pos;
sl@0
   389
	StartErase();
sl@0
   390
	return KErrNone;
sl@0
   391
	}
sl@0
   392
sl@0
   393
void DMediaDriverFlashWin32::StartTimer(TInt aMicros)
sl@0
   394
	{
sl@0
   395
	aMicros += iTimerExtra - (iTickPeriod>>1);
sl@0
   396
	if (aMicros < 0)
sl@0
   397
		{
sl@0
   398
		iTimerExtra = aMicros + (iTickPeriod>>1);
sl@0
   399
		iEventDfc.Enque();		// go off 'immediately'
sl@0
   400
		}
sl@0
   401
	else
sl@0
   402
		{
sl@0
   403
		iTimerExtra = 0;
sl@0
   404
		iTimer.OneShot(aMicros / iTickPeriod);
sl@0
   405
		}
sl@0
   406
	}
sl@0
   407
sl@0
   408
void DMediaDriverFlashWin32::TimerFn(TAny* aPtr)
sl@0
   409
	{
sl@0
   410
	((DMediaDriverFlashWin32*)aPtr)->iEventDfc.Add();
sl@0
   411
	}
sl@0
   412
sl@0
   413
void DMediaDriverFlashWin32::EventDfc(TAny* aPtr)
sl@0
   414
	{
sl@0
   415
	((DMediaDriverFlashWin32*)aPtr)->HandleEvent();
sl@0
   416
	}
sl@0
   417
sl@0
   418
void DMediaDriverFlashWin32::HandleEvent()
sl@0
   419
	{
sl@0
   420
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:Event %d", iState));
sl@0
   421
	switch (iState)
sl@0
   422
		{
sl@0
   423
	case ESuspended:
sl@0
   424
	case EWriting:	// write completed
sl@0
   425
		{
sl@0
   426
#ifdef _DEBUG
sl@0
   427
		if(iCtrlIoState==ECtrlIoTimeOutPrep)
sl@0
   428
			{
sl@0
   429
			iState=EIdle;
sl@0
   430
			iCtrlIoState=EIdle;
sl@0
   431
			Complete(EReqWrite,KErrNotReady);
sl@0
   432
			}
sl@0
   433
		else
sl@0
   434
#endif
sl@0
   435
			CompleteWrite();
sl@0
   436
		break;
sl@0
   437
		}
sl@0
   438
	case EEraseNoSuspend:
sl@0
   439
		{
sl@0
   440
#ifdef _DEBUG
sl@0
   441
		if(iCtrlIoState==ECtrlIoTimeOutPrep)
sl@0
   442
			{
sl@0
   443
			iState=EIdle;
sl@0
   444
			iCtrlIoState=EIdle;
sl@0
   445
			Complete(EReqErase,KErrNotReady);
sl@0
   446
			}
sl@0
   447
		else
sl@0
   448
			{
sl@0
   449
#endif
sl@0
   450
		TInt remain = iEraseCounter - NKern::TickCount();
sl@0
   451
		if (remain <= 0)
sl@0
   452
			CompleteErase();
sl@0
   453
		else
sl@0
   454
			{
sl@0
   455
			iState=EErase;
sl@0
   456
			StartTimer(remain * iTickPeriod);
sl@0
   457
			}
sl@0
   458
#ifdef _DEBUG
sl@0
   459
			}
sl@0
   460
#endif
sl@0
   461
		break;
sl@0
   462
		}
sl@0
   463
	case EErasePending:
sl@0
   464
		StartErase();
sl@0
   465
		break;
sl@0
   466
	case EErase:	// erase completed
sl@0
   467
		CompleteErase();
sl@0
   468
		break;
sl@0
   469
	case ESuspendPending:
sl@0
   470
		if (TInt(iEraseCounter - NKern::TickCount()) <= 0)
sl@0
   471
			CompleteErase();
sl@0
   472
		else
sl@0
   473
			SuspendErase();
sl@0
   474
		break;
sl@0
   475
	case ESuspending:
sl@0
   476
		CompleteSuspend();
sl@0
   477
		break;
sl@0
   478
	default:
sl@0
   479
		__KTRACE_OPT(KPANIC,Kern::Printf("iState=%d",iState));
sl@0
   480
		FLASH_FAULT();
sl@0
   481
		}
sl@0
   482
	}
sl@0
   483
sl@0
   484
void DMediaDriverFlashWin32::StartErase()
sl@0
   485
//
sl@0
   486
// Continue an erase - iEraseCounter has the remaining time for the erase
sl@0
   487
//
sl@0
   488
	{
sl@0
   489
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:StartErase %08x",iBase+iErasePos));
sl@0
   490
	switch (iState)
sl@0
   491
		{
sl@0
   492
	case ESuspended:
sl@0
   493
		iState = EErasePending;
sl@0
   494
		StartTimer(iResumeTime);
sl@0
   495
		break;
sl@0
   496
	case EIdle:	// starting to erase
sl@0
   497
		iEraseCounter = iEraseTime;
sl@0
   498
	case EErasePending:
sl@0
   499
		{
sl@0
   500
		iState = EEraseNoSuspend;
sl@0
   501
		TUint32 remain = iEraseCounter;
sl@0
   502
		iEraseCounter = NKern::TickCount() + remain/iTickPeriod;
sl@0
   503
		StartTimer(Min(remain, iSuspendHoldOffTime));
sl@0
   504
		}
sl@0
   505
		break;
sl@0
   506
	default:
sl@0
   507
		__KTRACE_OPT(KPANIC,Kern::Printf("iState=%d",iState));
sl@0
   508
		FLASH_FAULT();
sl@0
   509
		}
sl@0
   510
	}
sl@0
   511
sl@0
   512
void DMediaDriverFlashWin32::SuspendErase()
sl@0
   513
	{
sl@0
   514
	__ASSERT_ALWAYS(iState==EErase || iState==ESuspendPending,FLASH_FAULT());
sl@0
   515
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:SuspendErase %08x",iBase+iErasePos));
sl@0
   516
	iTimer.Cancel();
sl@0
   517
	TInt remain = Max(0, TInt(iEraseCounter - NKern::TickCount()));
sl@0
   518
	iEraseCounter = remain * iTickPeriod;
sl@0
   519
	iState = ESuspending;
sl@0
   520
	StartTimer(0);
sl@0
   521
	}
sl@0
   522
sl@0
   523
void DMediaDriverFlashWin32::CompleteSuspend()
sl@0
   524
	{
sl@0
   525
	// erase suspend completion
sl@0
   526
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:SuspendComplete"));
sl@0
   527
sl@0
   528
	iState = ESuspended;
sl@0
   529
	// start any pending read or write requests
sl@0
   530
	StartPendingRW();
sl@0
   531
	}
sl@0
   532
sl@0
   533
void DMediaDriverFlashWin32::CompleteErase()
sl@0
   534
//
sl@0
   535
// Do the actual erase in the completion
sl@0
   536
//
sl@0
   537
	{
sl@0
   538
	// erase completion
sl@0
   539
	__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:EraseComplete"));
sl@0
   540
sl@0
   541
	memset(iBase + iErasePos, 0xff, iEraseBlockSize);
sl@0
   542
sl@0
   543
	// complete the erase request
sl@0
   544
	iState = EIdle;
sl@0
   545
	Complete(EReqErase,KErrNone);
sl@0
   546
sl@0
   547
	// start any pending read or write requests
sl@0
   548
	StartPendingRW();
sl@0
   549
	}
sl@0
   550
sl@0
   551
sl@0
   552
void DMediaDriverFlashWin32::StartPendingRW()
sl@0
   553
	{
sl@0
   554
	// start any pending read or write requests
sl@0
   555
	if (iReadReq)
sl@0
   556
		DoRead();
sl@0
   557
	if (iWriteReq)
sl@0
   558
		DoWrite();
sl@0
   559
	}
sl@0
   560
sl@0
   561
#ifdef _DEBUG
sl@0
   562
// Override the base class version in order to provide access to ControlIO
sl@0
   563
//
sl@0
   564
TInt DMediaDriverFlashWin32::Request(TLocDrvRequest& m)
sl@0
   565
	{
sl@0
   566
	TInt r;
sl@0
   567
	TInt id=m.Id();
sl@0
   568
	__KTRACE_OPT(KLOCDRV,Kern::Printf(">DMediaDriverFlashWin32::Request %d",id));
sl@0
   569
	if (id!=DLocalDrive::EControlIO)
sl@0
   570
		{
sl@0
   571
		r=DMediaDriverFlash::Request(m);
sl@0
   572
		return r;
sl@0
   573
		}
sl@0
   574
	r=ControlIO((TInt)m.iArg[0],m.iArg[1],m.iArg[2]);
sl@0
   575
	DMediaDriver::Complete(m,r);
sl@0
   576
	return r;
sl@0
   577
	}
sl@0
   578
sl@0
   579
TInt DMediaDriverFlashWin32::ControlIO(TInt aCommand,TAny* /*aParam1*/,TAny* /*aParam2*/)
sl@0
   580
	{
sl@0
   581
	switch (aCommand)
sl@0
   582
		{
sl@0
   583
		case(KCtrlIoTimeout):
sl@0
   584
			{
sl@0
   585
			__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash:DoControlIO invoked for KCtrlIoTimeout"));
sl@0
   586
			// The aim of this test is simulate a flash timeout (and so exercise the consequent
sl@0
   587
			// actions of the software that initiated the request)				
sl@0
   588
			if(iCtrlIoState!=EIdle)
sl@0
   589
				{
sl@0
   590
				__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash: ControlIO request before previous completed"));
sl@0
   591
				return KErrServerBusy;
sl@0
   592
				}
sl@0
   593
			else
sl@0
   594
				{
sl@0
   595
				__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash: ControlIO timeout initiated"));
sl@0
   596
				iCtrlIoState=ECtrlIoTimeOutPrep;
sl@0
   597
				}
sl@0
   598
			break;
sl@0
   599
			}
sl@0
   600
		
sl@0
   601
		default:
sl@0
   602
			{
sl@0
   603
			__KTRACE_OPT(KLOCDRV,Kern::Printf("Flash: ERROR - unrecognised ControlIO command %d",aCommand));
sl@0
   604
			FLASH_FAULT();
sl@0
   605
			break;
sl@0
   606
			}
sl@0
   607
		}
sl@0
   608
	return KErrNone;
sl@0
   609
	}
sl@0
   610
	
sl@0
   611
#endif
sl@0
   612
sl@0
   613
TInt DMediaDriverFlashWin32::Caps(TLocalDriveCapsV2& aCaps)
sl@0
   614
// On return, aCaps data contains capability information about the 
sl@0
   615
// flash device, in the form of a class derived from TLocalDriveCapsV2. 
sl@0
   616
// The size of the derived class should not exceed KMaxLocalDriveCapsLength 
sl@0
   617
// which is defined and used in e32\drivers\locmedia\locmedia.cpp. If a 
sl@0
   618
// larger sized capabilities class is used, and this code is modified to 
sl@0
   619
// write to member data beyond KMaxLocalDriveCapsLength this will cause a 
sl@0
   620
// fault.
sl@0
   621
	{
sl@0
   622
	// Invoke the base class method then update the sizes for
sl@0
   623
	// Control Mode and Object Mode as required.
sl@0
   624
	DMediaDriverFlash::Caps(aCaps);
sl@0
   625
#if defined (M18_EMULATION)
sl@0
   626
	TLocalDriveCapsV7* caps = &((TLocalDriveCapsV7&)(aCaps));
sl@0
   627
	caps->iControlModeSize=16;
sl@0
   628
	caps->iObjectModeSize=1024;
sl@0
   629
    __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) ControlModeSize UPDATED as=0x%x", caps->iControlModeSize) );
sl@0
   630
    __KTRACE_OPT( KLOCDRV, Kern::Printf("MLFS: ) ObjectModeSize UPDATED as=0x%x", caps->iObjectModeSize) );
sl@0
   631
#endif
sl@0
   632
	return KErrCompletion;	// synchronous completion
sl@0
   633
	}
sl@0
   634
sl@0
   635
DMediaDriverFlash* DMediaDriverFlash::New(TInt aDevice)
sl@0
   636
	{
sl@0
   637
	return new DMediaDriverFlashWin32(aDevice);
sl@0
   638
	}
sl@0
   639
sl@0
   640
sl@0
   641
sl@0
   642