os/kernelhwsrv/kerneltest/e32test/lffs/t_lfsdrv2.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 the License "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
// e32test\lffs\t_lfsdrv2.cpp
sl@0
    15
// Test the LFFS Flash media driver
sl@0
    16
// 
sl@0
    17
//
sl@0
    18
sl@0
    19
#include <e32test.h>
sl@0
    20
#include <e32svr.h>
sl@0
    21
#include <e32hal.h>
sl@0
    22
#include <e32uid.h>
sl@0
    23
#include <hal.h>
sl@0
    24
#include "u32std.h"
sl@0
    25
#include "..\misc\prbs.h"
sl@0
    26
sl@0
    27
_LIT(KTestName,"T_LFSDRV");
sl@0
    28
_LIT(KMediaDriverName,"MEDLFS");
sl@0
    29
_LIT(KDot,".");
sl@0
    30
_LIT(KSemiColon,";");
sl@0
    31
sl@0
    32
RTest test(KTestName);
sl@0
    33
TBusLocalDrive Drive;
sl@0
    34
TInt DriveNumber;
sl@0
    35
TLocalDriveCapsV7 DriveCaps;	// Required for M18 devices
sl@0
    36
TBool ChangedFlag;
sl@0
    37
TUint32 EbSz;
sl@0
    38
TUint32 Size;
sl@0
    39
sl@0
    40
const TInt KBufferSize=4096;
sl@0
    41
const TInt KBigBufferSize=4096*4;
sl@0
    42
TUint8 Buffer[KBigBufferSize];
sl@0
    43
sl@0
    44
#ifdef _DEBUG
sl@0
    45
/***************************************************
sl@0
    46
 * ControlIO command types - for debug builds, only
sl@0
    47
 ***************************************************/
sl@0
    48
enum TCtrlIoTypes
sl@0
    49
	{
sl@0
    50
	ECtrlIoRww=0,
sl@0
    51
	ECtrlIoTimeout=1
sl@0
    52
	};
sl@0
    53
// Used only for the ControlIO tests
sl@0
    54
#define TYAX_PARTITION_SIZE	0x00200000 	// Partition size for TYAX is 1MB; 2 devices in parallel
sl@0
    55
#endif
sl@0
    56
sl@0
    57
sl@0
    58
/******************************************************************************
sl@0
    59
 * Extra thread for background erase
sl@0
    60
 ******************************************************************************/
sl@0
    61
struct SEraseInfo
sl@0
    62
	{
sl@0
    63
	TInt iFirstBlock;
sl@0
    64
	TInt iNumBlocks;
sl@0
    65
	};
sl@0
    66
sl@0
    67
volatile TInt Block;
sl@0
    68
TInt EraseThreadFn(TAny* aPtr)
sl@0
    69
	{
sl@0
    70
	SEraseInfo& e=*(SEraseInfo*)aPtr;
sl@0
    71
	TInt r=KErrNone;
sl@0
    72
	for (Block=e.iFirstBlock; Block<e.iFirstBlock+e.iNumBlocks; ++Block)
sl@0
    73
		{
sl@0
    74
		TInt64 pos64 = MAKE_TINT64(0, Block*EbSz);
sl@0
    75
		r=Drive.Format(pos64,EbSz);
sl@0
    76
		if (r!=KErrNone)
sl@0
    77
			return r;
sl@0
    78
		}
sl@0
    79
	return KErrNone;
sl@0
    80
	}
sl@0
    81
sl@0
    82
SEraseInfo EraseInfo;
sl@0
    83
RThread EraseThread;
sl@0
    84
TRequestStatus EraseStatus;
sl@0
    85
const TInt KHeapSize=0x4000;
sl@0
    86
sl@0
    87
_LIT(KEraseThreadName,"Eraser");
sl@0
    88
TInt StartAsyncErase(TInt aFirstBlock, TInt aNumBlocks)
sl@0
    89
	{
sl@0
    90
	EraseInfo.iFirstBlock=aFirstBlock;
sl@0
    91
	EraseInfo.iNumBlocks=aNumBlocks;
sl@0
    92
	TInt r=EraseThread.Create(KEraseThreadName,EraseThreadFn,0x4000,KHeapSize,KHeapSize,&EraseInfo,EOwnerThread);
sl@0
    93
	if (r!=KErrNone)
sl@0
    94
		return r;
sl@0
    95
	EraseThread.Logon(EraseStatus);
sl@0
    96
	EraseThread.Resume();
sl@0
    97
	return KErrNone;
sl@0
    98
	}
sl@0
    99
sl@0
   100
TInt WaitForAsyncErase()
sl@0
   101
	{
sl@0
   102
	User::WaitForRequest(EraseStatus);
sl@0
   103
	TInt exitType=EraseThread.ExitType();
sl@0
   104
	TInt exitReason=EraseThread.ExitReason();
sl@0
   105
	TBuf<16> exitCat=EraseThread.ExitCategory();
sl@0
   106
	if((exitType!= EExitKill)||(exitReason!=KErrNone))
sl@0
   107
		{
sl@0
   108
		test.Printf(_L("Async erase error: %d, block %d\n"),EraseStatus.Int(),Block);
sl@0
   109
		test.Printf(_L("Thread exit reason: %d,%d,%S\n"),exitType,exitReason,&exitCat);
sl@0
   110
		test(0);		
sl@0
   111
		}
sl@0
   112
	EraseThread.Close();
sl@0
   113
sl@0
   114
	TUint32 pos=EraseInfo.iFirstBlock*EbSz;
sl@0
   115
	TUint32 endpos=pos+EraseInfo.iNumBlocks*EbSz;
sl@0
   116
	test.Printf(_L("\nAsync erase completed; verifying...\n"));
sl@0
   117
	for (; pos<endpos; pos+=KBufferSize)
sl@0
   118
		{
sl@0
   119
		TInt64 pos64 = MAKE_TINT64(0, pos);
sl@0
   120
		TPtr8 ptr(Buffer,0,KBufferSize);
sl@0
   121
		Mem::FillZ(Buffer,KBufferSize);
sl@0
   122
		TInt r=Drive.Read(pos64,KBufferSize,ptr);
sl@0
   123
		test(r==KErrNone);
sl@0
   124
		test(ptr.Length()==KBufferSize);
sl@0
   125
		const TUint32* pB=(const TUint32*)Buffer;
sl@0
   126
		const TUint32* pE=(const TUint32*)(Buffer+KBufferSize);
sl@0
   127
		while (pB<pE && *pB==0xffffffff) ++pB;
sl@0
   128
		if (pB<pE)
sl@0
   129
			{
sl@0
   130
			test.Printf(_L("ERROR: pos %08x data %08x\n"),((TUint32)pB)-((TUint32)Buffer)+pos,*pB);
sl@0
   131
			test(0);
sl@0
   132
			}
sl@0
   133
		test.Printf(KDot);
sl@0
   134
		}
sl@0
   135
	test.Printf(_L("\n"));
sl@0
   136
	return KErrNone;
sl@0
   137
	}
sl@0
   138
	
sl@0
   139
/******************************************************************************
sl@0
   140
 * Extra thread for background write, for use in the read-while-write tests
sl@0
   141
 ******************************************************************************/
sl@0
   142
TUint seed[2];
sl@0
   143
sl@0
   144
TInt WriteThreadFn(TAny* aPtr)
sl@0
   145
	{
sl@0
   146
	// re-use the struct created for the erase thread
sl@0
   147
	SEraseInfo& e=*(SEraseInfo*)aPtr;
sl@0
   148
	TInt r=KErrNone;
sl@0
   149
	
sl@0
   150
	TPtrC8 wptr(Buffer,KBufferSize);
sl@0
   151
	TUint32* pB=(TUint32*)Buffer;
sl@0
   152
	TUint32* pE=(TUint32*)(Buffer+KBufferSize);
sl@0
   153
	while (pB<pE)
sl@0
   154
		*pB++=Random(seed);
sl@0
   155
sl@0
   156
	for (Block=e.iFirstBlock; Block<e.iFirstBlock+e.iNumBlocks; ++Block)
sl@0
   157
		{
sl@0
   158
		TInt64 pos64 = MAKE_TINT64(0, Block*EbSz);
sl@0
   159
		r=Drive.Write(pos64,wptr);
sl@0
   160
		if (r!=KErrNone)
sl@0
   161
			return r;
sl@0
   162
		}
sl@0
   163
	return KErrNone;
sl@0
   164
	}
sl@0
   165
sl@0
   166
RThread WriteThread;
sl@0
   167
TRequestStatus WriteStatus;
sl@0
   168
sl@0
   169
_LIT(KWriteThreadName,"Writer");
sl@0
   170
TInt StartAsyncWrite(TInt aFirstBlock, TInt aNumBlocks)
sl@0
   171
	{
sl@0
   172
	// re-use the struct created for the erase thread
sl@0
   173
	EraseInfo.iFirstBlock=aFirstBlock;
sl@0
   174
	EraseInfo.iNumBlocks=aNumBlocks;
sl@0
   175
	TInt r=WriteThread.Create(KWriteThreadName,WriteThreadFn,0x4000,KHeapSize,KHeapSize,&EraseInfo,EOwnerThread);
sl@0
   176
	if (r!=KErrNone)
sl@0
   177
		return r;
sl@0
   178
	WriteThread.Logon(WriteStatus);
sl@0
   179
	WriteThread.Resume();
sl@0
   180
	return KErrNone;
sl@0
   181
	}
sl@0
   182
sl@0
   183
TInt WaitForAsyncWrite()
sl@0
   184
	{
sl@0
   185
	User::WaitForRequest(WriteStatus);
sl@0
   186
	TInt exitType=WriteThread.ExitType();
sl@0
   187
	TInt exitReason=WriteThread.ExitReason();
sl@0
   188
	TBuf<16> exitCat=WriteThread.ExitCategory();
sl@0
   189
	if((exitType!= EExitKill)||(exitReason!=KErrNone))
sl@0
   190
		{
sl@0
   191
		test.Printf(_L("Async Write error: %d, block %d\n"),WriteStatus.Int(),Block);
sl@0
   192
		test.Printf(_L("Thread exit reason: %d,%d,%S\n"),exitType,exitReason,&exitCat);
sl@0
   193
		test(0);
sl@0
   194
		}
sl@0
   195
	WriteThread.Close();
sl@0
   196
	// No verification performed
sl@0
   197
	test.Printf(_L("\n"));
sl@0
   198
	return KErrNone;
sl@0
   199
	}
sl@0
   200
sl@0
   201
/******************************************************************************
sl@0
   202
 * Control mode and Object mode test functions
sl@0
   203
 ******************************************************************************/
sl@0
   204
TInt DoControlModeWriteAndVerify(TUint32 aPattern, TUint32 aStartOffset)
sl@0
   205
	{
sl@0
   206
	// Writes 4K bytes of a given pattern to the "A" half of programming regions, 
sl@0
   207
	// starting at the specified offset, then reads the data back to verify it
sl@0
   208
sl@0
   209
		TUint32* pB=(TUint32*)(Buffer);
sl@0
   210
		TUint32* pE=(TUint32*)(Buffer + KBufferSize);
sl@0
   211
		TInt r=KErrNone;
sl@0
   212
sl@0
   213
		// Fill the entire buffer with an initial value
sl@0
   214
		while (pB<pE)
sl@0
   215
			*pB++= aPattern;
sl@0
   216
sl@0
   217
		// In this mode, half the device is available for writing, the other half is reserved;
sl@0
   218
		// the available half appears as the first DriveCaps.iControlModeSize bytes, the reserved 
sl@0
   219
		// half as the following DriveCaps.iControlModeSize, and this alternating continues.
sl@0
   220
		// To perform this discrete-write test, therefore, the data held in Buffer that corresponds
sl@0
   221
		// to the reserved area is overwritten with 0xFF; 'writing' this value to the reserved area
sl@0
   222
		// has no detrimental effect.
sl@0
   223
		TInt i;
sl@0
   224
		TUint32 b;
sl@0
   225
		pB=(TUint32*)Buffer;
sl@0
   226
		for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
sl@0
   227
		{
sl@0
   228
			pB = (TUint32 *)((TUint32)pB + DriveCaps.iControlModeSize);
sl@0
   229
			for (b=0; b < DriveCaps.iControlModeSize; b+=4)
sl@0
   230
			{
sl@0
   231
				*pB = 0xFFFFFFFF;
sl@0
   232
				pB++;	
sl@0
   233
			}
sl@0
   234
		}
sl@0
   235
		// Write the data
sl@0
   236
		for (i=0; i<KBufferSize; i+=(4*DriveCaps.iControlModeSize))
sl@0
   237
			{
sl@0
   238
			TInt64 pos64(i + aStartOffset);
sl@0
   239
			TPtrC8 ptr(Buffer+i,(4*DriveCaps.iControlModeSize));
sl@0
   240
			r=Drive.Write(pos64,ptr);
sl@0
   241
			test(r==KErrNone);
sl@0
   242
			}
sl@0
   243
		// Check what has been written
sl@0
   244
		Mem::FillZ(Buffer,KBigBufferSize);
sl@0
   245
		TPtr8 buf(Buffer,0,KBufferSize);
sl@0
   246
		r=Drive.Read(aStartOffset,KBufferSize,buf);
sl@0
   247
		test(r==KErrNone);
sl@0
   248
		pB=(TUint32*)Buffer;
sl@0
   249
		for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
sl@0
   250
			{
sl@0
   251
			for (b=0; b< DriveCaps.iControlModeSize; b+=4)
sl@0
   252
				{
sl@0
   253
				if(*pB++ != aPattern)
sl@0
   254
					{ 
sl@0
   255
					test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,aPattern);
sl@0
   256
					r=KErrCorrupt;
sl@0
   257
					break;
sl@0
   258
					}
sl@0
   259
				}
sl@0
   260
			for (b=0; b< DriveCaps.iControlModeSize; b+=4)
sl@0
   261
				{
sl@0
   262
				if(*pB++ != 0xFFFFFFFF)
sl@0
   263
					{ 
sl@0
   264
					test.Printf(_L("ERROR: addr %08x data %08x expected 0xFFFFFFFF\n"),pB,*pB);
sl@0
   265
					r=KErrCorrupt;
sl@0
   266
					break;
sl@0
   267
					}
sl@0
   268
				}
sl@0
   269
			}
sl@0
   270
		return r;
sl@0
   271
	}
sl@0
   272
sl@0
   273
TInt DoObjectModeWriteAndVerify(TUint32 aOffset, TUint32 aSize)
sl@0
   274
	{
sl@0
   275
	// Writes 'aSize' bytes of a 'random' pattern to the specified offset
sl@0
   276
	// then read back and verify
sl@0
   277
	TInt r=KErrNone;
sl@0
   278
sl@0
   279
	// Check that aSize is valid
sl@0
   280
	if(aSize>DriveCaps.iObjectModeSize)
sl@0
   281
		{
sl@0
   282
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - aSize=%x is greater than max (%x)\n"),aSize,DriveCaps.iObjectModeSize);
sl@0
   283
		return KErrArgument;
sl@0
   284
		}
sl@0
   285
	// write the data
sl@0
   286
	TUint seed[2];
sl@0
   287
	seed[0]=0xb17217f8;
sl@0
   288
	seed[1]=0;
sl@0
   289
	TInt64 pos64 = MAKE_TINT64(0, aOffset);
sl@0
   290
	TPtrC8 ptr(Buffer,aSize);
sl@0
   291
	TUint32* pB=(TUint32*)Buffer;
sl@0
   292
	TUint32* pE=(TUint32*)(Buffer+aSize);
sl@0
   293
	while (pB<pE)
sl@0
   294
		*pB++=Random(seed);
sl@0
   295
	r=Drive.Write(pos64,ptr);
sl@0
   296
	if(r!=KErrNone)
sl@0
   297
		{
sl@0
   298
		return r;
sl@0
   299
		}
sl@0
   300
	
sl@0
   301
	// Read the data back
sl@0
   302
	seed[0]=0xb17217f8;
sl@0
   303
	seed[1]=0;
sl@0
   304
	TPtr8 rptr(Buffer,0,aSize);
sl@0
   305
	Mem::FillZ(Buffer,aSize);
sl@0
   306
	r=Drive.Read(pos64,aSize,rptr);
sl@0
   307
	if(r!=KErrNone)
sl@0
   308
		{
sl@0
   309
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
sl@0
   310
		return r;
sl@0
   311
		}
sl@0
   312
	test((TUint32)(rptr.Length())==aSize);
sl@0
   313
sl@0
   314
	// Verify the content
sl@0
   315
	pB=(TUint32*)Buffer;
sl@0
   316
	pE=(TUint32*)(Buffer+aSize);
sl@0
   317
	TUint32 ex=0;
sl@0
   318
	while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
sl@0
   319
	if (pB<pE)
sl@0
   320
		{
sl@0
   321
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   322
		r=KErrCorrupt;
sl@0
   323
		}
sl@0
   324
	return r;
sl@0
   325
	}
sl@0
   326
sl@0
   327
sl@0
   328
TInt DoControlModeBoundaryWriteAndVerify()
sl@0
   329
	{
sl@0
   330
	// 
sl@0
   331
	
sl@0
   332
	TInt r=KErrNone;
sl@0
   333
	//test.Printf(_L("Entering: DoControlModeBoundaryWriteAndVerify - Start Test\n"));
sl@0
   334
sl@0
   335
	r=Drive.Format(0,DriveCaps.iEraseBlockSize);
sl@0
   336
	test(r==KErrNone);
sl@0
   337
	
sl@0
   338
	// Program into the last Control mode region in the programming region.
sl@0
   339
	TInt64 pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - (DriveCaps.iControlModeSize*2)));
sl@0
   340
	TPtrC8 ptr(Buffer,DriveCaps.iControlModeSize);
sl@0
   341
	TUint32* pB=(TUint32*)Buffer;
sl@0
   342
	TUint32* pE=(TUint32*)(Buffer+DriveCaps.iControlModeSize);
sl@0
   343
	while (pB<pE)
sl@0
   344
		*pB++=0xb4b4a5a5;
sl@0
   345
	r=Drive.Write(pos64,ptr);
sl@0
   346
	if(r!=KErrNone)
sl@0
   347
		{
sl@0
   348
		test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 1\n"));
sl@0
   349
		return r;
sl@0
   350
		}
sl@0
   351
sl@0
   352
	// Program into the next programming region starting at the first byte up to the size of the Control Mode Size.
sl@0
   353
	pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
sl@0
   354
	r=Drive.Write(pos64,ptr);
sl@0
   355
	if(r!=KErrNone)
sl@0
   356
		{
sl@0
   357
		test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 2\n"));
sl@0
   358
		return r;
sl@0
   359
		}
sl@0
   360
	
sl@0
   361
	// Read the data back from the first program
sl@0
   362
	pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - (DriveCaps.iControlModeSize*2)));
sl@0
   363
	TPtr8 rptr(Buffer,0,(TInt)DriveCaps.iControlModeSize);
sl@0
   364
	Mem::FillZ(Buffer,DriveCaps.iControlModeSize);
sl@0
   365
	r=Drive.Read(pos64,DriveCaps.iControlModeSize,rptr);
sl@0
   366
	if(r!=KErrNone)
sl@0
   367
		{
sl@0
   368
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
sl@0
   369
		return r;
sl@0
   370
		}
sl@0
   371
	test((TUint32)(rptr.Length())==DriveCaps.iControlModeSize);
sl@0
   372
sl@0
   373
	// Verify the content
sl@0
   374
	pB=(TUint32*)Buffer;
sl@0
   375
	pE=(TUint32*)(Buffer+DriveCaps.iControlModeSize);
sl@0
   376
	TUint32 ex=0xb4b4a5a5;
sl@0
   377
	while (pB<pE && (*pB==ex)) ++pB;
sl@0
   378
	if (pB<pE)
sl@0
   379
		{
sl@0
   380
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   381
		r=KErrCorrupt;
sl@0
   382
		}
sl@0
   383
sl@0
   384
   // Read the data back from the second program
sl@0
   385
   	pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
sl@0
   386
	TPtr8 rptr2(Buffer,0,((TInt)DriveCaps.iControlModeSize));
sl@0
   387
	Mem::FillZ(Buffer,DriveCaps.iControlModeSize);
sl@0
   388
	r=Drive.Read(pos64,DriveCaps.iControlModeSize,rptr2);
sl@0
   389
	if(r!=KErrNone)
sl@0
   390
		{
sl@0
   391
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
sl@0
   392
		return r;
sl@0
   393
		}
sl@0
   394
	test((TUint32)(rptr2.Length())==DriveCaps.iControlModeSize);
sl@0
   395
sl@0
   396
	// Verify the content
sl@0
   397
	pB=(TUint32*)Buffer;
sl@0
   398
	pE=(TUint32*)(Buffer+DriveCaps.iControlModeSize);
sl@0
   399
	ex=0xb4b4a5a5;
sl@0
   400
	while (pB<pE && (*pB==ex)) ++pB;
sl@0
   401
	if (pB<pE)
sl@0
   402
		{
sl@0
   403
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   404
		r=KErrCorrupt;
sl@0
   405
		}
sl@0
   406
sl@0
   407
	// Bit Twiddle the last bit of the last Control Mode Region 
sl@0
   408
	// Then bit twiddle the first bit of the first control Mode region.
sl@0
   409
sl@0
   410
	// Program into the last Control mode region in the programming region.
sl@0
   411
	pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - DriveCaps.iControlModeSize - 4));
sl@0
   412
	TPtrC8 ptr2(Buffer,4);
sl@0
   413
	TUint32* pC=(TUint32*)Buffer;
sl@0
   414
	*pC = 0xFFFFFFFE;
sl@0
   415
	r=Drive.Write(pos64,ptr2);
sl@0
   416
	if(r!=KErrNone)
sl@0
   417
		{
sl@0
   418
				test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 3\n"));
sl@0
   419
sl@0
   420
		return r;
sl@0
   421
		}
sl@0
   422
	
sl@0
   423
	// Read the data back from the first program
sl@0
   424
	pos64 = MAKE_TINT64(0, (DriveCaps.iObjectModeSize - DriveCaps.iControlModeSize - 4));
sl@0
   425
	TPtr8 rptr3(Buffer,0,4);
sl@0
   426
	Mem::FillZ(Buffer,4);
sl@0
   427
	r=Drive.Read(pos64,4,rptr3);
sl@0
   428
	if(r!=KErrNone)
sl@0
   429
		{
sl@0
   430
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
sl@0
   431
		return r;
sl@0
   432
		}
sl@0
   433
	test(rptr3.Length()==4);
sl@0
   434
sl@0
   435
	// Verify the content
sl@0
   436
	pB=(TUint32*)Buffer;
sl@0
   437
	if (*pB != 0xb4b4a5a4)
sl@0
   438
		{
sl@0
   439
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected 0xb4b4a5a4\n"),pB,*pB);
sl@0
   440
		r=KErrCorrupt;
sl@0
   441
		}
sl@0
   442
sl@0
   443
	// Program into the last Control mode region in the programming region.
sl@0
   444
	pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
sl@0
   445
	TPtrC8 ptr3(Buffer,4);
sl@0
   446
	pC=(TUint32*)Buffer;
sl@0
   447
	*pC = 0x7FFFFFFF;
sl@0
   448
	r=Drive.Write(pos64,ptr3);
sl@0
   449
	if(r!=KErrNone)
sl@0
   450
		{
sl@0
   451
				test.Printf(_L("ERROR: DoControlModeBoundaryWriteAndVerify - Write 4\n"));
sl@0
   452
sl@0
   453
		return r;
sl@0
   454
		}
sl@0
   455
	
sl@0
   456
	// Read the data back from the first program
sl@0
   457
	pos64 = MAKE_TINT64(0, DriveCaps.iObjectModeSize);
sl@0
   458
	TPtr8 rptr4(Buffer,0,4);
sl@0
   459
	Mem::FillZ(Buffer,4);
sl@0
   460
	r=Drive.Read(pos64,4,rptr4);
sl@0
   461
	if(r!=KErrNone)
sl@0
   462
		{
sl@0
   463
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - Read returned %d\n"),r);
sl@0
   464
		return r;
sl@0
   465
		}
sl@0
   466
	test(rptr4.Length()==4);
sl@0
   467
sl@0
   468
	// Verify the content
sl@0
   469
	pB=(TUint32*)Buffer;
sl@0
   470
	if (*pB != 0x34b4a5a5)
sl@0
   471
		{
sl@0
   472
		test.Printf(_L("ERROR: DoObjectModeWriteAndVerify - addr %08x data %08x expected 0x34b4a5a5\n"),pB,*pB);
sl@0
   473
		r=KErrCorrupt;
sl@0
   474
		}
sl@0
   475
		
sl@0
   476
	return r;
sl@0
   477
	}
sl@0
   478
sl@0
   479
sl@0
   480
sl@0
   481
sl@0
   482
/******************************************************************************
sl@0
   483
 * Main test program
sl@0
   484
 ******************************************************************************/
sl@0
   485
GLDEF_C TInt E32Main()
sl@0
   486
	{
sl@0
   487
	test.Title();
sl@0
   488
sl@0
   489
/******************************************************************************
sl@0
   490
 * Initialisation
sl@0
   491
 ******************************************************************************/
sl@0
   492
	TDriveInfoV1Buf diBuf;
sl@0
   493
	UserHal::DriveInfo(diBuf);
sl@0
   494
	TDriveInfoV1 &di=diBuf();
sl@0
   495
	test.Start(_L("Test the LFFS media driver"));
sl@0
   496
	test.Printf(_L("DRIVES PRESENT  :%d\r\n"),di.iTotalSupportedDrives);
sl@0
   497
	test.Printf(_L("C:(1ST) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[0]);
sl@0
   498
	test.Printf(_L("D:(2ND) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[1]);
sl@0
   499
	test.Printf(_L("E:(3RD) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[2]);
sl@0
   500
	test.Printf(_L("F:(4TH) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[3]);
sl@0
   501
	test.Printf(_L("G:(5TH) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[4]);
sl@0
   502
	test.Printf(_L("H:(6TH) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[5]);
sl@0
   503
	test.Printf(_L("I:(7TH) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[6]);
sl@0
   504
	test.Printf(_L("J:(8TH) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[7]);
sl@0
   505
	test.Printf(_L("K:(9TH) DRIVE NAME  :%- 16S\r\n"),&di.iDriveName[8]);
sl@0
   506
sl@0
   507
	test.Printf(_L("\r\nWarning - all data on LFFS drive will be lost.\r\n"));
sl@0
   508
	test.Printf(_L("<<<Select drive to continue>>>\r\n"));
sl@0
   509
	FOREVER
sl@0
   510
		{
sl@0
   511
		TChar c=(TUint)test.Getch();
sl@0
   512
		c.UpperCase();
sl@0
   513
		DriveNumber=((TUint)c)-'C';
sl@0
   514
		if (DriveNumber>=0&&DriveNumber<='C'+ 8)
sl@0
   515
			break;
sl@0
   516
		}
sl@0
   517
sl@0
   518
	test.Next(_L("Load media driver"));
sl@0
   519
	TInt r=User::LoadPhysicalDevice(KMediaDriverName);
sl@0
   520
	test(r==KErrNone || r==KErrAlreadyExists);
sl@0
   521
sl@0
   522
	test.Next(_L("Connect to drive"));
sl@0
   523
	r=Drive.Connect(DriveNumber,ChangedFlag);
sl@0
   524
	test(r==KErrNone);
sl@0
   525
	test.Next(_L("Get capabilities"));
sl@0
   526
sl@0
   527
	DriveCaps.iControlModeSize=0;	// If test invoked for a chip other than Sibley then this element will not be updated
sl@0
   528
	DriveCaps.iObjectModeSize=0;	// If test invoked for a chip other than Sibley then this element will not be updated 
sl@0
   529
	TPckg<TLocalDriveCapsV7> capsPckg(DriveCaps);
sl@0
   530
  	r=Drive.Caps(capsPckg);
sl@0
   531
sl@0
   532
	test(r==KErrNone);
sl@0
   533
	test.Printf(_L("Size            : %08x\n"),I64LOW(DriveCaps.iSize));
sl@0
   534
	test.Printf(_L("Type            : %d\n"),DriveCaps.iType);
sl@0
   535
	test.Printf(_L("Connection Bus  : %d\n"),DriveCaps.iConnectionBusType);
sl@0
   536
	test.Printf(_L("DriveAtt        : %02x\n"),DriveCaps.iDriveAtt);
sl@0
   537
	test.Printf(_L("MediaAtt        : %02x\n"),DriveCaps.iMediaAtt);
sl@0
   538
	test.Printf(_L("BaseAddress     : %08x\n"),DriveCaps.iBaseAddress);
sl@0
   539
	test.Printf(_L("FileSysID       : %d\n"),DriveCaps.iFileSystemId);
sl@0
   540
	test.Printf(_L("Hidden sectors  : %d\n"),DriveCaps.iHiddenSectors);
sl@0
   541
	test.Printf(_L("Erase block size: %d\n"),DriveCaps.iEraseBlockSize);
sl@0
   542
sl@0
   543
	test.Printf(_L("Partition size: %d\n"),DriveCaps.iPartitionSize);
sl@0
   544
	test.Printf(_L("Control Mode size: %d\n"),DriveCaps.iControlModeSize);
sl@0
   545
	test.Printf(_L("Object Mode size: %d\n"),DriveCaps.iObjectModeSize);
sl@0
   546
	test.Printf(_L("Press any key...\n\n"));
sl@0
   547
	test.Getch();
sl@0
   548
sl@0
   549
	test(DriveCaps.iDriveAtt==(KDriveAttLocal|KDriveAttInternal));
sl@0
   550
	test((DriveCaps.iMediaAtt&KMediaAttFormattable)==(KMediaAttFormattable)); // Apply mask since other flags may be set
sl@0
   551
sl@0
   552
#if defined(_DEBUG) && defined(_WINS)
sl@0
   553
/******************************************************************************
sl@0
   554
 * Simulate device timeout
sl@0
   555
 ******************************************************************************/
sl@0
   556
	test.Next(_L("Timeout"));
sl@0
   557
	EbSz=DriveCaps.iEraseBlockSize;
sl@0
   558
	r=Drive.Format(0,EbSz);
sl@0
   559
	test(r==KErrNone);
sl@0
   560
	r=Drive.ControlIO(ECtrlIoTimeout, NULL, NULL);
sl@0
   561
sl@0
   562
	if(r!=KErrNotSupported)
sl@0
   563
		{
sl@0
   564
		if(r==KErrNone)
sl@0
   565
			{
sl@0
   566
			// Test timeout behaviour for Write operation
sl@0
   567
			TPtrC8 ptr(Buffer,1);
sl@0
   568
			r=Drive.Write(0,ptr);
sl@0
   569
			test(r==KErrNotReady);
sl@0
   570
			// Test condition now cleared, ensure normal operation is OK
sl@0
   571
			r=Drive.Write(0,ptr);
sl@0
   572
			test(r==KErrNone);
sl@0
   573
			// Test timeout behaviour for Format operation
sl@0
   574
			r=Drive.ControlIO(ECtrlIoTimeout, NULL, NULL);
sl@0
   575
			test(r==KErrNone);
sl@0
   576
			r=Drive.Format(0,EbSz);
sl@0
   577
			test(r==KErrNotReady);
sl@0
   578
			// Cleanup
sl@0
   579
			r=Drive.Format(0,EbSz);
sl@0
   580
			test(r==KErrNone);
sl@0
   581
			}
sl@0
   582
		else
sl@0
   583
			{
sl@0
   584
			test.Printf(_L("Timeout ControlIO failed initialisation\n"));
sl@0
   585
			test(0);	// Cannot proceed with this test
sl@0
   586
			}
sl@0
   587
		}
sl@0
   588
	else 
sl@0
   589
		{
sl@0
   590
		test.Printf(_L("Timeout ControlIO not supported\n"));
sl@0
   591
		}
sl@0
   592
sl@0
   593
	test.Printf(_L("Press any key...\n"));
sl@0
   594
	test.Getch();
sl@0
   595
#endif
sl@0
   596
sl@0
   597
 /******************************************************************************
sl@0
   598
 * Formatting
sl@0
   599
 ******************************************************************************/
sl@0
   600
	test.Next(_L("Format"));
sl@0
   601
	TUint32 pos;
sl@0
   602
	EbSz=DriveCaps.iEraseBlockSize;
sl@0
   603
	Size=I64LOW(DriveCaps.iSize);
sl@0
   604
// Reduce size so test doesn't take forever
sl@0
   605
	if (Size>8*EbSz)
sl@0
   606
		Size=8*EbSz;
sl@0
   607
sl@0
   608
	for (pos=0; pos<Size; pos+=EbSz)
sl@0
   609
		{
sl@0
   610
		TInt64 pos64 = MAKE_TINT64(0, pos);
sl@0
   611
		r=Drive.Format(pos64,EbSz);
sl@0
   612
		test(r==KErrNone);
sl@0
   613
		test.Printf(KDot);
sl@0
   614
		}
sl@0
   615
	test.Next(_L("\nVerify"));
sl@0
   616
	for (pos=0; pos<Size; pos+=KBufferSize)
sl@0
   617
		{
sl@0
   618
		TInt64 pos64 = MAKE_TINT64(0, pos);
sl@0
   619
		TPtr8 ptr(Buffer,0,KBufferSize);
sl@0
   620
		Mem::FillZ(Buffer,KBigBufferSize);
sl@0
   621
		r=Drive.Read(pos64,KBufferSize,ptr);
sl@0
   622
		test(r==KErrNone);
sl@0
   623
		test(ptr.Length()==KBufferSize);
sl@0
   624
		const TUint32* pB=(const TUint32*)Buffer;
sl@0
   625
		const TUint32* pE=(const TUint32*)(Buffer+KBufferSize);
sl@0
   626
		while (pB<pE && *pB==0xffffffff) ++pB;
sl@0
   627
		if (pB<pE)
sl@0
   628
			{
sl@0
   629
			test.Printf(_L("ERROR: addr %08x data %08x\n"),pB,*pB);
sl@0
   630
			test(0);
sl@0
   631
			}
sl@0
   632
		test.Printf(KDot);
sl@0
   633
		}
sl@0
   634
	test.Printf(_L("\nPress any key...\n\n"));
sl@0
   635
	test.Getch();
sl@0
   636
sl@0
   637
/******************************************************************************
sl@0
   638
 * Large block writes
sl@0
   639
 ******************************************************************************/
sl@0
   640
	test.Next(_L("Write"));
sl@0
   641
	TUint seed[2];
sl@0
   642
	seed[0]=0xb17217f8;
sl@0
   643
	seed[1]=0;
sl@0
   644
	for (pos=0; pos<Size; pos+=KBufferSize)
sl@0
   645
		{
sl@0
   646
		TInt64 pos64 = MAKE_TINT64(0, pos);
sl@0
   647
		TPtrC8 ptr(Buffer,KBufferSize);
sl@0
   648
		TUint32* pB=(TUint32*)Buffer;
sl@0
   649
		TUint32* pE=(TUint32*)(Buffer+KBufferSize);
sl@0
   650
		while (pB<pE)
sl@0
   651
			*pB++=Random(seed);
sl@0
   652
		r=Drive.Write(pos64,ptr);
sl@0
   653
		test(r==KErrNone);
sl@0
   654
		test.Printf(KDot);
sl@0
   655
		}
sl@0
   656
	test.Printf(_L("\n"));
sl@0
   657
	test.Next(_L("Verify"));
sl@0
   658
	seed[0]=0xb17217f8;
sl@0
   659
	seed[1]=0;
sl@0
   660
	for (pos=0; pos<Size; pos+=KBufferSize)
sl@0
   661
		{
sl@0
   662
		TInt64 pos64 = MAKE_TINT64(0, pos);
sl@0
   663
		TPtr8 ptr(Buffer,0,KBufferSize);
sl@0
   664
		Mem::FillZ(Buffer,KBigBufferSize);
sl@0
   665
		r=Drive.Read(pos64,KBufferSize,ptr);
sl@0
   666
		test(r==KErrNone);
sl@0
   667
		test(ptr.Length()==KBufferSize);
sl@0
   668
		const TUint32* pB=(const TUint32*)Buffer;
sl@0
   669
		const TUint32* pE=(const TUint32*)(Buffer+KBufferSize);
sl@0
   670
		TUint32 ex=0;
sl@0
   671
		while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
sl@0
   672
		if (pB<pE)
sl@0
   673
			{
sl@0
   674
			test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   675
			test(0);
sl@0
   676
			}
sl@0
   677
		test.Printf(KDot);
sl@0
   678
		}
sl@0
   679
sl@0
   680
	test.Printf(_L("\nPress any key...\n\n"));
sl@0
   681
	test.Getch();
sl@0
   682
sl@0
   683
/******************************************************************************
sl@0
   684
 * Single byte writes
sl@0
   685
 ******************************************************************************/
sl@0
   686
	test.Next(_L("Format first block"));
sl@0
   687
	r=Drive.Format(0,EbSz);
sl@0
   688
	test(r==KErrNone);
sl@0
   689
	test.Next(_L("Single byte writes"));
sl@0
   690
	seed[0]=0x317b106f;
sl@0
   691
	seed[1]=0;
sl@0
   692
	TUint32* pB=(TUint32*)Buffer;
sl@0
   693
	TUint32* pE=(TUint32*)(Buffer+KBufferSize);
sl@0
   694
	while (pB<pE)
sl@0
   695
		*pB++= Random(seed);
sl@0
   696
	
sl@0
   697
	// For M18 devices, this test requires control mode operation.
sl@0
   698
	// In this mode, half the device is available for writing, the other half is reserved;
sl@0
   699
	// the available half appears as the first DriveCaps.iControlModeSize bytes, the reserved 
sl@0
   700
	// half as the following DriveCaps.iControlModeSize, and this alternating continues.
sl@0
   701
	// To perform this discrete-write test, therefore, the data held in Buffer that corresponds
sl@0
   702
	// to the reserved area is overwritten with 0xFF; 'writing' this value to the reserved area
sl@0
   703
	// has no detrimental effect.
sl@0
   704
	TInt i;
sl@0
   705
	TUint32 b;
sl@0
   706
	if (DriveCaps.iControlModeSize > 0)
sl@0
   707
	{
sl@0
   708
		pB=(TUint32*)Buffer;
sl@0
   709
		for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
sl@0
   710
		{
sl@0
   711
			pB = (TUint32 *)((TUint32)pB + DriveCaps.iControlModeSize);
sl@0
   712
			for (b=0; b < DriveCaps.iControlModeSize; b+=4)
sl@0
   713
			{
sl@0
   714
				*pB = 0xFFFFFFFF;
sl@0
   715
				pB++;	
sl@0
   716
			}
sl@0
   717
		}
sl@0
   718
	} 
sl@0
   719
	
sl@0
   720
#if 0
sl@0
   721
	// Debug - print content of buffer
sl@0
   722
	test.Printf(_L("Content of buffer after inserting 0xFFFFFFFFs follows\n"));
sl@0
   723
	i=0;
sl@0
   724
	TUint32* verifyPtr=(TUint32*)Buffer;
sl@0
   725
	while(i<KBufferSize)
sl@0
   726
		{
sl@0
   727
		test.Printf(_L("%8x %8X %8X\n"),i+=8,*verifyPtr++,*verifyPtr++);
sl@0
   728
		}
sl@0
   729
#endif
sl@0
   730
	
sl@0
   731
	for (i=0; i<KBufferSize; ++i)
sl@0
   732
		{
sl@0
   733
		TInt64 pos64(i);
sl@0
   734
		TPtrC8 ptr(Buffer+i,1);
sl@0
   735
		r=Drive.Write(pos64,ptr);
sl@0
   736
		test(r==KErrNone);
sl@0
   737
		if (!(i%16))
sl@0
   738
			test.Printf(KDot);
sl@0
   739
		}
sl@0
   740
	test.Printf(_L("\n"));
sl@0
   741
	test.Next(_L("Verify"));
sl@0
   742
	Mem::FillZ(Buffer,KBigBufferSize);
sl@0
   743
	TPtr8 buf(Buffer,0,KBufferSize);
sl@0
   744
	r=Drive.Read(0,KBufferSize,buf);
sl@0
   745
	test(r==KErrNone);
sl@0
   746
	seed[0]=0x317b106f;
sl@0
   747
	seed[1]=0;
sl@0
   748
	pB=(TUint32*)Buffer;
sl@0
   749
	TUint32 ex=0;
sl@0
   750
	if (DriveCaps.iControlModeSize > 0)
sl@0
   751
		{
sl@0
   752
		pB=(TUint32*)Buffer;
sl@0
   753
		for(i=0; i< KBufferSize; i+=(DriveCaps.iControlModeSize*2))
sl@0
   754
			{
sl@0
   755
			for (b=0; b< DriveCaps.iControlModeSize; b+=4)
sl@0
   756
				{
sl@0
   757
				ex=Random(seed);
sl@0
   758
				if(*pB++ != ex)
sl@0
   759
					{ 
sl@0
   760
					test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   761
					break;
sl@0
   762
					}
sl@0
   763
				}
sl@0
   764
			for (b=0; b< DriveCaps.iControlModeSize; b+=4)
sl@0
   765
				{
sl@0
   766
				ex=Random(seed);
sl@0
   767
				if(*pB++ != 0xFFFFFFFF)
sl@0
   768
					{ 
sl@0
   769
					test.Printf(_L("ERROR: addr %08x data %08x expected 0xFF\n"),pB,*pB);
sl@0
   770
					break;
sl@0
   771
					}
sl@0
   772
				}
sl@0
   773
			if (!((i+1)%64))
sl@0
   774
				test.Printf(KDot);
sl@0
   775
sl@0
   776
			}
sl@0
   777
		}
sl@0
   778
	else
sl@0
   779
		{	
sl@0
   780
		while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
sl@0
   781
		}
sl@0
   782
	if (pB<pE)
sl@0
   783
		{
sl@0
   784
		test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   785
		test(0);
sl@0
   786
		}
sl@0
   787
sl@0
   788
	test.Printf(_L("Single byte writes OK\n"));
sl@0
   789
	
sl@0
   790
	test.Printf(_L("Press any key...\n\n"));
sl@0
   791
	test.Getch();
sl@0
   792
sl@0
   793
/******************************************************************************
sl@0
   794
 * Random length writes
sl@0
   795
 ******************************************************************************/
sl@0
   796
	test.Next(_L("Random length writes"));
sl@0
   797
	// Prepare the device (required if control mode is used for M18 devices)
sl@0
   798
	// assume that a maximum of 2 blocks is required
sl@0
   799
	r=Drive.Format(0,EbSz);
sl@0
   800
	r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
sl@0
   801
sl@0
   802
	seed[0]=0xdeadbeef;
sl@0
   803
	seed[1]=0;
sl@0
   804
	pB=(TUint32*)Buffer;
sl@0
   805
	pE=(TUint32*)(Buffer+KBigBufferSize);
sl@0
   806
	while (pB<pE)
sl@0
   807
		*pB++=Random(seed);
sl@0
   808
	TInt remain=KBigBufferSize;
sl@0
   809
	TInt objectModeOffset=0;
sl@0
   810
	TUint32 writeCount=0;
sl@0
   811
	seed[0]=0xdeadbeef;
sl@0
   812
	seed[1]=0;
sl@0
   813
	for(writeCount=0; remain && (writeCount<512); writeCount++)
sl@0
   814
		{
sl@0
   815
		TInt l=1+(Random(seed)&255);	 // random length between 1 and 256
sl@0
   816
		if (l>remain)
sl@0
   817
			l=remain;
sl@0
   818
		TInt pos=0;
sl@0
   819
		if(DriveCaps.iObjectModeSize == 0)
sl@0
   820
			{
sl@0
   821
			pos=KBigBufferSize-remain;
sl@0
   822
			}
sl@0
   823
		
sl@0
   824
		TPtrC8 ptr(Buffer+(KBigBufferSize-remain),l);
sl@0
   825
		TInt64 pos64(pos+objectModeOffset);  // Start writes in a new programming region if object mode supported
sl@0
   826
		r=Drive.Write(pos64,ptr);
sl@0
   827
		test(r==KErrNone);
sl@0
   828
		objectModeOffset+=DriveCaps.iObjectModeSize;
sl@0
   829
		remain-=l;
sl@0
   830
		test.Printf(KDot);
sl@0
   831
		}
sl@0
   832
	test.Printf(_L("\n"));
sl@0
   833
	test.Next(_L("Verify"));
sl@0
   834
	Mem::FillZ(Buffer,KBigBufferSize);
sl@0
   835
	new (&buf) TPtr8(Buffer,0,KBigBufferSize);
sl@0
   836
	if(DriveCaps.iObjectModeSize==0)
sl@0
   837
	{
sl@0
   838
		r=Drive.Read(0,KBigBufferSize,buf);
sl@0
   839
		test(r==KErrNone);
sl@0
   840
sl@0
   841
	}
sl@0
   842
	else
sl@0
   843
	{
sl@0
   844
		remain=KBigBufferSize;
sl@0
   845
		objectModeOffset=0;
sl@0
   846
		
sl@0
   847
		while(remain && writeCount)
sl@0
   848
			{
sl@0
   849
			TInt totalLength=0;
sl@0
   850
			TInt l=1+(Random(seed)&255);	 // random length between 1 and 256
sl@0
   851
			if (l>remain)
sl@0
   852
				l=remain;
sl@0
   853
			TPtr8 ptr(Buffer+(totalLength),l);
sl@0
   854
			r=Drive.Read(objectModeOffset,l,ptr);
sl@0
   855
			test(r==KErrNone);
sl@0
   856
			totalLength +=l;
sl@0
   857
			remain-=l;
sl@0
   858
			writeCount--;
sl@0
   859
			test.Printf(KDot);
sl@0
   860
			}
sl@0
   861
	}
sl@0
   862
sl@0
   863
	seed[0]=0xdeadbeef;
sl@0
   864
	seed[1]=0;
sl@0
   865
	pB=(TUint32*)Buffer;
sl@0
   866
	ex=0;
sl@0
   867
	if(DriveCaps.iObjectModeSize==0)
sl@0
   868
	{
sl@0
   869
		while (pB<pE && (ex=Random(seed),*pB==ex)) ++pB;
sl@0
   870
		if (pB<pE)
sl@0
   871
			{
sl@0
   872
			test.Printf(_L("ERROR: addr %08x data %08x expected %08x\n"),pB,*pB,ex);
sl@0
   873
	//		test.Getch();
sl@0
   874
			test(0);
sl@0
   875
			}
sl@0
   876
	}
sl@0
   877
	
sl@0
   878
	r=Drive.Format(0,EbSz);
sl@0
   879
	r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
sl@0
   880
	test.Printf(_L("\nPress any key...\n\n"));
sl@0
   881
	test.Getch();
sl@0
   882
sl@0
   883
/******************************************************************************
sl@0
   884
 * Concurrent read/write/erase
sl@0
   885
 ******************************************************************************/
sl@0
   886
	test.Printf(_L("Foreground R/W\n"));
sl@0
   887
	r=StartAsyncErase(1,Size/EbSz-1);
sl@0
   888
	test(r==KErrNone);
sl@0
   889
sl@0
   890
	seed[0]=0xb17217f8;
sl@0
   891
	seed[1]=0;
sl@0
   892
	for (pos=KBufferSize+KBigBufferSize; pos<EbSz; pos+=KBufferSize)
sl@0
   893
		{
sl@0
   894
		TInt64 pos64 = MAKE_TINT64(0, pos);
sl@0
   895
		TPtrC8 wptr(Buffer,KBufferSize);
sl@0
   896
		TUint32* pB=(TUint32*)Buffer;
sl@0
   897
		TUint32* pE=(TUint32*)(Buffer+KBufferSize);
sl@0
   898
		while (pB<pE)
sl@0
   899
			*pB++=Random(seed);
sl@0
   900
		r=Drive.Write(pos64,wptr);
sl@0
   901
		test(r==KErrNone);
sl@0
   902
		test.Printf(KDot);
sl@0
   903
		Mem::FillZ(Buffer+KBufferSize,KBufferSize);
sl@0
   904
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
   905
		r=Drive.Read(pos64,KBufferSize,rptr);
sl@0
   906
		test(r==KErrNone);
sl@0
   907
		test(rptr.Length()==KBufferSize);
sl@0
   908
		//test(Mem::Compare(Buffer,KBufferSize,Buffer+KBufferSize,KBufferSize)==0);
sl@0
   909
		r = Mem::Compare(Buffer,KBufferSize,Buffer+KBufferSize,KBufferSize);
sl@0
   910
#if 0
sl@0
   911
		if (r!=KErrNone)
sl@0
   912
		{
sl@0
   913
			pB=(TUint32*)Buffer;
sl@0
   914
			pE=(TUint32*)(Buffer+KBufferSize);
sl@0
   915
			for(TInt i=0; i < (KBufferSize>>2); i++)
sl@0
   916
			{
sl@0
   917
			  test.Printf(_L("%d Buffer Content %08x   %08x Flash Content\n"),i, pB[i], pE[i]);			
sl@0
   918
			} 
sl@0
   919
		}
sl@0
   920
#endif
sl@0
   921
		test (r==KErrNone);
sl@0
   922
		test.Printf(KSemiColon);
sl@0
   923
		}
sl@0
   924
sl@0
   925
	r=WaitForAsyncErase();
sl@0
   926
	test(r==KErrNone);
sl@0
   927
sl@0
   928
    r=Drive.Format(0,EbSz);
sl@0
   929
	r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
sl@0
   930
	test.Printf(_L("Press any key...\n\n"));
sl@0
   931
	test.Getch();
sl@0
   932
sl@0
   933
// Perform the following tests for debug builds, only
sl@0
   934
sl@0
   935
#ifdef _DEBUG
sl@0
   936
sl@0
   937
/******************************************************************************
sl@0
   938
 * Concurrent operations to exercise TYAX Read-While-Write capability
sl@0
   939
 * First, show read while write denied when attempting to read from a partition 
sl@0
   940
 * that is being written to
sl@0
   941
 * Second, show read while write proceeding when reading from a partition other
sl@0
   942
 * than that which is being written to
sl@0
   943
 ******************************************************************************/
sl@0
   944
sl@0
   945
	// Do not perform these tests unless read-while-write is supported
sl@0
   946
	if(DriveCaps.iMediaAtt&KMediaAttReadWhileWrite)
sl@0
   947
		{	
sl@0
   948
		test.Next(_L("Denied read while write"));
sl@0
   949
		r=Drive.ControlIO(ECtrlIoRww, NULL, NULL);
sl@0
   950
		if(r!=KErrNone)
sl@0
   951
			{
sl@0
   952
			test.Printf(_L("ControlIO not ready, returned %d\n"), r);
sl@0
   953
			test(0);	// Cannot proceed with this test
sl@0
   954
			}
sl@0
   955
		test.Printf(_L("Press any key...\n"));
sl@0
   956
		test.Getch();
sl@0
   957
sl@0
   958
		test.Printf(_L("Starting async write for the first RWE/RWW test"));
sl@0
   959
		r=StartAsyncWrite(1,3); // Write to the first three blocks, only, to limit duration
sl@0
   960
		test(r==KErrNone);
sl@0
   961
	
sl@0
   962
		// Allow the write thread to be created and ready to run
sl@0
   963
		// This will ensure that the driver will have received a write request before the second of the read
sl@0
   964
		// requests, below. Following the issue of the ControlIO command, above, the driver will not instigate
sl@0
   965
		// the write request until the next (second) read request is received. This is done so that the high priority
sl@0
   966
		// driver thread recognises the existence of a read request (from a lower priority test / user thread)
sl@0
   967
		// before it executes a sequence of writes to the FLASH device. This is necessary because, although
sl@0
   968
		// each write takes a finite amount of time, the poll timer expires so quickly that the driver thread
sl@0
   969
		// would not be blocked for a sufficiently long period to allow the read request to be processed. Adopting
sl@0
   970
		// the contrived, and artificial, approach of using ControlIO to 'stage' the write allows the read-while-write
sl@0
   971
		// capability of the device to be execrised.
sl@0
   972
		User::After(1000);	
sl@0
   973
sl@0
   974
		test.Printf(_L("Starting concurrent loop for background write\n"));
sl@0
   975
		{
sl@0
   976
		// First read - this will be performed before the write thread is run, so does
sl@0
   977
		// not exercise read while write.
sl@0
   978
		TInt64 pos64 = MAKE_TINT64(0,0);
sl@0
   979
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
   980
		test.Printf(_L("Issuing Drive.Read 1\n"));
sl@0
   981
		r=Drive.Read(pos64,KBufferSize,rptr); 
sl@0
   982
		test(r==KErrNone);
sl@0
   983
		test.Printf(KSemiColon);		
sl@0
   984
		}
sl@0
   985
		{
sl@0
   986
		// Second read - to same partition (and block) as the active write
sl@0
   987
		// This read should be deferred by the driver
sl@0
   988
		TInt64 pos64 = MAKE_TINT64(0, 2*EbSz);
sl@0
   989
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
   990
		test.Printf(_L("Issuing Drive.Read 2\n"));
sl@0
   991
		r=Drive.Read(pos64,KBufferSize,rptr); // Should collide with second write
sl@0
   992
		test(r==KErrNone);
sl@0
   993
		test.Printf(KSemiColon);		
sl@0
   994
		}
sl@0
   995
		{
sl@0
   996
		// Third read - due to the tight poll timer period, this will not be scheduled 
sl@0
   997
		// until the write request has completed - so does not exercise read while write.
sl@0
   998
		TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
sl@0
   999
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
  1000
		test.Printf(_L("Issuing Drive.Read 3\n"));
sl@0
  1001
		r=Drive.Read(pos64,KBufferSize,rptr);
sl@0
  1002
		test(r==KErrNone);
sl@0
  1003
		test.Printf(KSemiColon);		
sl@0
  1004
		}
sl@0
  1005
sl@0
  1006
		r=WaitForAsyncWrite();
sl@0
  1007
		test(r==KErrNone);
sl@0
  1008
	
sl@0
  1009
	///////////////////////////////////////////////////////////////////////////////
sl@0
  1010
		r=Drive.Format(0,EbSz);
sl@0
  1011
		r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
sl@0
  1012
		r=Drive.Format((DriveCaps.iEraseBlockSize*2),EbSz);
sl@0
  1013
		r=Drive.Format((DriveCaps.iEraseBlockSize*3),EbSz);
sl@0
  1014
		test.Printf(_L("Press any key...\n"));
sl@0
  1015
		test.Getch();
sl@0
  1016
		test.Next(_L("Supported read while write"));
sl@0
  1017
		r=Drive.ControlIO(ECtrlIoRww, NULL, NULL);
sl@0
  1018
		if(r!=KErrNone)
sl@0
  1019
			{
sl@0
  1020
			test.Printf(_L("ControlIO not ready\n"));
sl@0
  1021
			return r;
sl@0
  1022
			}
sl@0
  1023
		test.Printf(_L("Press any key...\n"));
sl@0
  1024
		test.Getch();
sl@0
  1025
sl@0
  1026
		test.Printf(_L("Starting async write for the second RWE/RWW test"));
sl@0
  1027
		r=StartAsyncWrite(1,3); // Write to the first three blocks, only, to limit duration
sl@0
  1028
		test(r==KErrNone);
sl@0
  1029
sl@0
  1030
		// Allow the write thread to be created and ready to run
sl@0
  1031
		User::After(1000);	
sl@0
  1032
sl@0
  1033
		test.Printf(_L("Starting concurrent loop for background write\n"));
sl@0
  1034
		{
sl@0
  1035
		// First read - this will be performed before the write thread is run, so does
sl@0
  1036
		// not exercise read while write.
sl@0
  1037
		TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
sl@0
  1038
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
  1039
		test.Printf(_L("Issuing Drive.Read 1\n"));
sl@0
  1040
		r=Drive.Read(pos64,KBufferSize,rptr); 
sl@0
  1041
		test(r==KErrNone);
sl@0
  1042
		test.Printf(KSemiColon);		
sl@0
  1043
		}
sl@0
  1044
		{
sl@0
  1045
		// Second read - to different partition than that targeted by the active write
sl@0
  1046
		// This read should check the overlap and proceed without being deferred
sl@0
  1047
		TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
sl@0
  1048
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
  1049
		test.Printf(_L("Issuing Drive.Read 2\n"));
sl@0
  1050
		r=Drive.Read(pos64,KBufferSize,rptr); // Should collide with second write
sl@0
  1051
		test(r==KErrNone);
sl@0
  1052
		test.Printf(KSemiColon);		
sl@0
  1053
		}
sl@0
  1054
		{
sl@0
  1055
		// Third read - due to the tight poll timer period, this will not be scheduled 
sl@0
  1056
		// until the write request has completed - so does not exercise read while write.
sl@0
  1057
		TInt64 pos64 = MAKE_TINT64(0, DriveCaps.iPartitionSize);
sl@0
  1058
		TPtr8 rptr(Buffer+KBufferSize,0,KBufferSize);
sl@0
  1059
		test.Printf(_L("Issuing Drive.Read 3\n"));
sl@0
  1060
		r=Drive.Read(pos64,KBufferSize,rptr);
sl@0
  1061
		test(r==KErrNone);
sl@0
  1062
		test.Printf(KSemiColon);		
sl@0
  1063
		}
sl@0
  1064
sl@0
  1065
		test.Printf(_L("\nForeground Read OK\n"));
sl@0
  1066
		r=WaitForAsyncWrite();
sl@0
  1067
		test(r==KErrNone);
sl@0
  1068
		}
sl@0
  1069
#endif		
sl@0
  1070
sl@0
  1071
	// Clean up
sl@0
  1072
	r=Drive.Format(0,EbSz);
sl@0
  1073
	r=Drive.Format(DriveCaps.iEraseBlockSize,EbSz);
sl@0
  1074
	r=Drive.Format((DriveCaps.iEraseBlockSize*2),EbSz);
sl@0
  1075
	r=Drive.Format((DriveCaps.iEraseBlockSize*3),EbSz);
sl@0
  1076
sl@0
  1077
/*****************************************************************************************************
sl@0
  1078
	Tests for M18 NOR Flash devices
sl@0
  1079
sl@0
  1080
	These tests assume that object mode and control mode is supported
sl@0
  1081
 *****************************************************************************************************/
sl@0
  1082
	if((DriveCaps.iControlModeSize !=0) && (DriveCaps.iObjectModeSize != 0))
sl@0
  1083
		{
sl@0
  1084
		// Control mode writes
sl@0
  1085
		// Prove that control mode writes are supported
sl@0
  1086
		// This requires that data is formatted such that areas coinciding with the "B" Half of a
sl@0
  1087
		// programming region are set to all 0xFFs
sl@0
  1088
		// Write to programming region zero
sl@0
  1089
		test.Next(_L("\nControl mode writes"));
sl@0
  1090
sl@0
  1091
		r=DoControlModeWriteAndVerify(0xa5a5a5a5, 0);
sl@0
  1092
		test(r==KErrNone);
sl@0
  1093
		// Now verify that data written in control mode can be further modified
sl@0
  1094
		// Do this by ANDing the read-back pattern with a mask that clears particular bits
sl@0
  1095
		// then write the resulting pattern back to the region
sl@0
  1096
		r=DoControlModeWriteAndVerify(0x84848484, 0);
sl@0
  1097
		test(r==KErrNone);
sl@0
  1098
		// Now verify that data written in control mode can be further modified to all 0x00s
sl@0
  1099
		// Do this by ANDing the read-back pattern with a mask that clears the remaining bits
sl@0
  1100
		// then write the resulting pattern back to the region
sl@0
  1101
		r=DoControlModeWriteAndVerify(0x00000000, 0);
sl@0
  1102
		test(r==KErrNone);
sl@0
  1103
		// Erase the block before attempting to re-use the programming region for object mode writing
sl@0
  1104
		test.Printf(_L("\nErase block 0 before object mode write"));
sl@0
  1105
		r=Drive.Format(0,EbSz);
sl@0
  1106
		test(r==KErrNone);
sl@0
  1107
sl@0
  1108
		test.Next(_L("\n(Subsequent) Object mode writes"));
sl@0
  1109
sl@0
  1110
		// Control mode writes
sl@0
  1111
		// Prove that object mode writes are allowd to an erased block that was previously
sl@0
  1112
		// used in control mode
sl@0
  1113
		// Use offset zero and length equal to one-quarter of the allowed object mode size (i.e. one-
sl@0
  1114
		// quarter of the lengh of the programming region) (The write test, above, wrote an entire region
sl@0
  1115
		// in object mode)
sl@0
  1116
		test.Printf(_L("\nObject mode write, object mode size=%d"),DriveCaps.iObjectModeSize);
sl@0
  1117
		r=DoObjectModeWriteAndVerify(0, (DriveCaps.iObjectModeSize>>2));
sl@0
  1118
		test(r==KErrNone);
sl@0
  1119
		// Prove that an attempt to append data to an object mode region fails
sl@0
  1120
		test.Printf(_L("\nAttempt append to object mode region"));
sl@0
  1121
		r=DoObjectModeWriteAndVerify((DriveCaps.iObjectModeSize>>2),(DriveCaps.iObjectModeSize>>2));
sl@0
  1122
		test(r==KErrGeneral);
sl@0
  1123
		// Erase the block after a failed write and before attempting to re-use for programming
sl@0
  1124
		test.Printf(_L("\nErase block 0 after failed object mode write"));
sl@0
  1125
		r=Drive.Format(0,EbSz);
sl@0
  1126
		test(r==KErrNone);
sl@0
  1127
sl@0
  1128
		test.Next(_L("\n(Subsequent) Object mode writes following an error"));
sl@0
  1129
sl@0
  1130
		// write to a new object mode region after a failed write and before attempting to erase the block
sl@0
  1131
		// Prove that erase block can be re-written to
sl@0
  1132
		test.Printf(_L("\nObject mode write following failed write and erase"));
sl@0
  1133
		r=DoObjectModeWriteAndVerify(0, (DriveCaps.iObjectModeSize>>2));
sl@0
  1134
		test(r==KErrNone);
sl@0
  1135
		// Cause a failed object mode write
sl@0
  1136
		r=DoObjectModeWriteAndVerify(0, (DriveCaps.iObjectModeSize>>2));
sl@0
  1137
		test(r==KErrGeneral);
sl@0
  1138
		// the status register has an error.  Attempt to write in a new region and ensure that it succeeds
sl@0
  1139
		r=DoObjectModeWriteAndVerify(DriveCaps.iObjectModeSize, DriveCaps.iObjectModeSize);
sl@0
  1140
		test(r==KErrNone);
sl@0
  1141
sl@0
  1142
		test.Next(_L("\n(Subsequent) Control mode writes following previous use in object mode"));
sl@0
  1143
sl@0
  1144
		// Re-use a former object mode region for control mode writes
sl@0
  1145
		// Erase the block after a failed write and before attempting to re-use for programming
sl@0
  1146
		r=Drive.Format(0,EbSz);
sl@0
  1147
		test(r==KErrNone);
sl@0
  1148
		r=DoControlModeWriteAndVerify(0xa5a5a5a5, 0);
sl@0
  1149
		test(r==KErrNone);
sl@0
  1150
		// Verify that data written in control mode can be further modified
sl@0
  1151
		r=DoControlModeWriteAndVerify(0x84848484, 0);
sl@0
  1152
		test(r==KErrNone);
sl@0
  1153
sl@0
  1154
		test.Next(_L("\n(Subsequent) Control mode writes following an error"));
sl@0
  1155
sl@0
  1156
		// Test that a control mode write can succeed after a previous error
sl@0
  1157
		// Use a failed object mode write attempt to the "B" half of a control mode region
sl@0
  1158
		// to cause the error
sl@0
  1159
		r=DoObjectModeWriteAndVerify(DriveCaps.iControlModeSize,(DriveCaps.iObjectModeSize>>2));
sl@0
  1160
		test(r==KErrGeneral);
sl@0
  1161
		r=DoControlModeWriteAndVerify(0x00000000, 0);
sl@0
  1162
		test(r==KErrNone);
sl@0
  1163
sl@0
  1164
		test.Next(_L("\nControl mode boundary write test"));
sl@0
  1165
sl@0
  1166
		r=DoControlModeBoundaryWriteAndVerify();
sl@0
  1167
		test(r==KErrNone);
sl@0
  1168
sl@0
  1169
	}
sl@0
  1170
sl@0
  1171
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
sl@0
  1172
sl@0
  1173
	test.Printf(_L("Press any key...\n"));
sl@0
  1174
	test.Getch();
sl@0
  1175
	test.End();
sl@0
  1176
	return KErrNone;
sl@0
  1177
	}