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