kerneltest/f32test/demandpaging/t_mmcpaging.cpp
changeset 43 96e5fb8b040d
child 33 0173bcd7697c
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     1 // Copyright (c) 2006-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\mmu\t_mmcpaging.cpp
       
    15 // Suite of tests specifically to test the demand paging subsystem when
       
    16 // booted from MMC rather than NAND.
       
    17 // 002 Read/Write and Page test
       
    18 // 
       
    19 //
       
    20 
       
    21 //! @SYMTestCaseID			KBASE-T_MMCPAGING-0331
       
    22 //! @SYMTestType			UT
       
    23 //! @SYMPREQ				PREQ1110
       
    24 //! @SYMTestCaseDesc		Demand Paging MMC Paging tests.
       
    25 //! @SYMTestActions			001 Check that the rom is paged
       
    26 //! @SYMTestExpectedResults All tests should pass.
       
    27 //! @SYMTestPriority        High
       
    28 //! @SYMTestStatus          Implemented
       
    29 
       
    30 #include <e32test.h>
       
    31 RTest test(_L("T_MMCPAGING"));
       
    32 
       
    33 #include <e32rom.h>
       
    34 #include <u32hal.h>
       
    35 #include <f32file.h>
       
    36 #include <f32dbg.h>
       
    37 #include <hal.h>
       
    38 #define __TEST_PAGING_MEDIA_DRIVER__
       
    39 #include "mmcdp.h"
       
    40 
       
    41 
       
    42 
       
    43 TInt DriveNumber=-1;   // Parameter - Which drive?  -1 = autodetect.
       
    44 TInt locDriveNumber;
       
    45 
       
    46 TInt MaxDeferLoops=40; // Parameter - Defer test, for how long?
       
    47 TInt Maxloops=400;	   // Parameter - RW Soak, for how long?
       
    48 TBool Forever=EFalse;  // Parameter - RW Soak forever?
       
    49 
       
    50 TBool Testing=ETrue;	// Used to communicate when testing has finished between threads.
       
    51 
       
    52 RFs TheFs;
       
    53 TBusLocalDrive Drive;
       
    54 TLocalDriveCapsV4 DriveCaps;
       
    55 
       
    56 TInt PagedTrashCount=0; // Incremented by threads, is used to detect preemption.
       
    57 TInt GlobError=KErrNone; // To communicate an error between threads.
       
    58 TBool CtrlIOSupported=ETrue;
       
    59 
       
    60 
       
    61 //const TInt KDiskSectorShift = 9;
       
    62 const TInt KBufSizeInBytes = (32 * 1024);
       
    63 
       
    64 LOCAL_D TBuf8<KBufSizeInBytes> Buffer;
       
    65 
       
    66 
       
    67 
       
    68 // Three functions for the garbage test.
       
    69 // CreateFile creates a file, and sets up the buffer for WriteNumber.
       
    70 // After the code has finished writing numbers to the start,
       
    71 // CloseAndDestroy cleans up.
       
    72 
       
    73 void CreateFile(RFile &aFile,const TDesC& aFileName)
       
    74 	{
       
    75 	TBuf<256> fileName;	
       
    76 	fileName.Append((TChar)('A'+DriveNumber));
       
    77 	fileName+=_L(":\\f32-tst\\");
       
    78 	TInt r=TheFs.MkDirAll(fileName);
       
    79 	test(r==KErrNone || r== KErrAlreadyExists);
       
    80 
       
    81 	fileName += aFileName;	
       
    82 
       
    83 	r=aFile.Replace(TheFs,fileName,EFileWrite);
       
    84 	if (r!=KErrNone)
       
    85 		test.Printf(_L("Error %d: file '%S' could not be created\n"),r,&fileName);
       
    86 	test(r==KErrNone);	
       
    87 	Buffer.SetLength(4);
       
    88 	}
       
    89 	
       
    90 void CloseAndDestroy(RFile &aFile)
       
    91 	{
       
    92 	TBuf<256> fileName;	
       
    93 	aFile.FullName(fileName);
       
    94 	aFile.Close();
       
    95 	TheFs.Delete(fileName);
       
    96 	}
       
    97 
       
    98 TInt WriteNumber(RFile &aFile)
       
    99 	{
       
   100 	TInt r;
       
   101 	Buffer[0]++;
       
   102 	r = aFile.Write(0,Buffer);
       
   103 	if (r==KErrNone)
       
   104 		return aFile.Flush();
       
   105 	else
       
   106 		return r; 
       
   107 	}
       
   108 
       
   109 
       
   110 
       
   111 // Finds the 1st MMC drive, or checks the specified one fits requirements  
       
   112 
       
   113 static TInt FindFsMMCDrive()
       
   114 	{
       
   115 	TDriveList driveList;
       
   116 	TDriveInfo driveInfo;
       
   117 	TInt r=TheFs.DriveList(driveList);
       
   118     test(r == KErrNone);
       
   119 
       
   120 	TInt drvNum = DriveNumber;
       
   121 	if (drvNum<0)
       
   122 		drvNum = 0;
       
   123 	do
       
   124 		{
       
   125 	    if(!driveList[drvNum])
       
   126 	        continue;   //-- skip unexisting drive
       
   127 
       
   128 	    test(TheFs.Drive(driveInfo, drvNum) == KErrNone);
       
   129 
       
   130 		if(driveInfo.iMediaAtt&KMediaAttPageable)
       
   131 			{
       
   132 			// Internal MMC ?
       
   133 			if (driveInfo.iType == EMediaHardDisk && 
       
   134 				(driveInfo.iDriveAtt & KDriveAttInternal) &&
       
   135 				(!(driveInfo.iDriveAtt & KDriveAttRemovable)))
       
   136 				return (drvNum);
       
   137 			}
       
   138 		}
       
   139 	while(DriveNumber<0 && ++drvNum<KMaxDrives);
       
   140 
       
   141 	return (-1);
       
   142 	}
       
   143 
       
   144 
       
   145 //
       
   146 // Writes to main area for the entire disk and reads back to verify.
       
   147 // The function is called from TestMmcAccuratcy, which will have also
       
   148 // started the background RepeatedPagingThread
       
   149 //
       
   150 void testWriteMain()
       
   151 	{
       
   152 	TInt i;
       
   153 	TInt r;
       
   154 	TInt changeCount=0;
       
   155 	TInt totChangeCount=0;
       
   156 	TInt cCount=0;
       
   157 	TInt fullcCount=0;
       
   158 	TInt oldPagedTrashCount=0;
       
   159 	TInt delta=0;
       
   160 	TInt high=0;
       
   161 	TInt tot=0;
       
   162 	TInt fullTot=0;
       
   163 	TInt blockNo;
       
   164 	
       
   165 	SMmcStats stats;
       
   166 	TInt reqPageCount=0;	
       
   167 	TInt reqNormalCount=0;
       
   168 
       
   169 	
       
   170 	TInt readSize = KBufSizeInBytes/2;
       
   171 	TInt writeSize = KBufSizeInBytes/2;
       
   172 
       
   173 	Buffer.SetLength(2*readSize);
       
   174 
       
   175 	TPtr8 subBuf1(&Buffer[0],readSize);
       
   176 	TPtrC8 subBuf2(&Buffer[readSize], readSize);
       
   177 	
       
   178 	test.Printf(_L("writeSize = %d\n"), writeSize);
       
   179 
       
   180 //	TInt64 size = DriveCaps.iSize - (DriveCaps.iSize % readSize);
       
   181 	
       
   182 	for(i = 0; i<readSize; i++)
       
   183 		Buffer[readSize+i] = (char)(i%100);
       
   184 
       
   185 	// Zero Stats
       
   186 	if(CtrlIOSupported)
       
   187 		{
       
   188 		TPtr8 statsBuf((TUint8*) &stats, sizeof(stats));
       
   189 	 	test(Drive.ControlIO(KMmcGetStats,statsBuf,0) == KErrNone);
       
   190 		}
       
   191 
       
   192 
       
   193 	TFileName fileName = _L("?:\\f32-tst\\mmcpage.txt");
       
   194 	fileName[0] = (TText) ('A'+DriveNumber);
       
   195 
       
   196 
       
   197 	r = TheFs.MkDirAll(fileName);
       
   198 	test(r==KErrNone || r== KErrAlreadyExists);
       
   199 //	fileName += KTempFileName;	
       
   200 	RFile tempFile;
       
   201 	r=tempFile.Replace(TheFs,fileName,EFileWrite);
       
   202 	if (r!=KErrNone)
       
   203 		test.Printf(_L("Error %d: file '%S' could not be created\n"),r,&fileName);
       
   204 	test(r==KErrNone);	
       
   205 
       
   206 	TVolumeInfo volInfo;
       
   207 	r = TheFs.Volume(volInfo, DriveNumber);
       
   208 	test (r == KErrNone);
       
   209 
       
   210 	
       
   211 	TInt64 size = volInfo.iFree - (volInfo.iFree % readSize);
       
   212 	TInt maxFileSize = (size > KMaxTInt) ? KMaxTInt : (TInt) size;
       
   213 	
       
   214 	test.Printf(_L("Volume size %ld, free %ld maxFileSize %d file '%S'\n"), volInfo.iSize, volInfo.iFree, maxFileSize, &fileName);
       
   215 	
       
   216 	while (((totChangeCount<Maxloops) || Forever) && (GlobError==KErrNone))
       
   217 		{
       
   218 		
       
   219 		for(TInt pos=0;
       
   220 			((pos+writeSize) < maxFileSize) && ((totChangeCount<Maxloops) || Forever) && (GlobError==KErrNone);
       
   221 			pos+=(TUint)(readSize))
       
   222 			{
       
   223 			blockNo=I64LOW(pos / writeSize);
       
   224 			if (pos % (writeSize) == 0)
       
   225 				test.Printf(_L("Block %d at %u \r"), blockNo, I64LOW(pos));
       
   226 
       
   227 			//write the pattern
       
   228 			r = tempFile.Write(pos,subBuf2);
       
   229 			if (r != KErrNone)
       
   230 				test.Printf(_L("Write failed %d"), r);
       
   231 			test(r==KErrNone);
       
   232 
       
   233 			//read back and verify
       
   234 			r = tempFile.Read(pos,subBuf1,readSize);
       
   235 			test(r==KErrNone);
       
   236 
       
   237 			for(i=0;i<readSize;i++)
       
   238 				if(Buffer[i]!=Buffer[readSize+i])
       
   239 					{
       
   240 					r = KErrCorrupt;
       
   241 					break;
       
   242 					}
       
   243 			delta = PagedTrashCount-oldPagedTrashCount;
       
   244 			cCount++;
       
   245 			if (delta)
       
   246 				{	
       
   247 				if (delta>high)
       
   248 					high=delta;
       
   249 				tot+=delta;
       
   250 				
       
   251 				oldPagedTrashCount=PagedTrashCount;
       
   252 				changeCount++;
       
   253 				}
       
   254 			if (pos % (writeSize) == 0)
       
   255 				{				
       
   256 
       
   257 				if ((blockNo%80==0) && (blockNo!=0))
       
   258 					{
       
   259 					totChangeCount+=changeCount;
       
   260 					if(CtrlIOSupported)
       
   261 						{
       
   262 						test.Printf(_L("High%4d Avg%2d %d%% CC=%4d \n"), high, (TInt) (tot/cCount), (TInt)(changeCount*100)/cCount, totChangeCount);
       
   263 						
       
   264 						TPtr8 statsBuf((TUint8*) &stats, sizeof(stats));
       
   265 						Drive.ControlIO(KMmcGetStats,statsBuf,0);
       
   266 						test.Printf(_L("PR %d(%d%%) NR %d\n"), stats.iReqPage, (TInt) ((stats.iReqPage*100)/cCount), stats.iReqNormal);
       
   267 
       
   268 						test(stats.iReqPage>0);
       
   269 				 		reqPageCount+=stats.iReqPage;			 	
       
   270 				 		reqNormalCount+=stats.iReqNormal;			 	
       
   271 						}
       
   272 
       
   273 					high=0;
       
   274 					
       
   275 					fullTot+=tot;
       
   276 					tot=0;
       
   277 					
       
   278 					fullcCount+=cCount;
       
   279 					cCount=0;
       
   280 					changeCount=0;
       
   281 					}
       
   282 						
       
   283 				}
       
   284 			test(r==KErrNone);
       
   285 			}
       
   286 		if(CtrlIOSupported)
       
   287 			{
       
   288 			test.Printf(_L("Totals: Avg %2d %d%% CC=%4d \n"), fullTot/fullcCount, (TInt)(totChangeCount*100)/fullcCount, totChangeCount);
       
   289 			test.Printf(_L("PR %d(%d%%) NR %d\n"), reqPageCount,(TInt) (reqPageCount*100/fullcCount), reqNormalCount );
       
   290 			}
       
   291 
       
   292 		// If totChangeCount does not change, mmc maybe busy waiting.
       
   293 		test(totChangeCount>0);
       
   294 		}
       
   295 
       
   296 
       
   297 	tempFile.Close();
       
   298 	r = TheFs.Delete(fileName);
       
   299 	test (r == KErrNone);
       
   300 	
       
   301 	if (GlobError!=KErrNone)
       
   302 		{
       
   303 		test.Printf(_L("\nPageing failed with %x\n"), GlobError);
       
   304 		test(0);
       
   305 		}
       
   306 	else
       
   307 		test.Printf(_L("\ndone\n"));
       
   308 	}
       
   309 
       
   310 
       
   311 TUint8 ReadByte(volatile TUint8* aPtr)
       
   312 	{
       
   313 	return *aPtr;
       
   314 	}
       
   315 
       
   316 #define READ(a) ReadByte((volatile TUint8*)(a))
       
   317 
       
   318 TUint32 RandomNo =0;
       
   319 
       
   320 TUint32 Random()
       
   321 	{
       
   322 	RandomNo = RandomNo*69069+1;
       
   323 	return RandomNo;
       
   324 	}
       
   325 
       
   326 
       
   327 // Many instances of this run while testWriteMain runs,
       
   328 // to cause random background paging.
       
   329 
       
   330 LOCAL_C TInt RepeatedPagingThread(TAny* aUseTb)
       
   331 	{
       
   332 //	RTest test(_L("RepeatedPagingThread"));
       
   333 	TBool trashBurst = EFalse;
       
   334 	// This makes the paging system continually page stuff.
       
   335 	// get info about a paged ROM...
       
   336 	
       
   337 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
       
   338 	TUint8* start = (TUint8*)romHeader+romHeader->iPageableRomStart;
       
   339 	TUint size = romHeader->iPageableRomSize;
       
   340 	TInt pageSize = 0;
       
   341 	PagedTrashCount=1;
       
   342 
       
   343 	UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0);
       
   344 	RandomNo=123;
       
   345 	PagedTrashCount++;
       
   346 
       
   347 	while (Testing)
       
   348 		{
       
   349 		TInt r=UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0);
       
   350 		if (Random() & 1)
       
   351 			User::AfterHighRes(500+Random() & 2047);
       
   352 
       
   353 		if (r<0)
       
   354 			{
       
   355 			GlobError=r;
       
   356 			PagedTrashCount=99;
       
   357 			return (KErrNone);
       
   358 			}
       
   359 		if (trashBurst)
       
   360 			{
       
   361 			if ((Random() & 0xf) == 0xf)
       
   362 				trashBurst=EFalse;
       
   363 			PagedTrashCount++;
       
   364 			}
       
   365 		else 
       
   366 			{
       
   367 			
       
   368 			for(TInt i=size/(pageSize); (i>0) && !trashBurst; --i)
       
   369 				{
       
   370 				READ(start+((TInt64(Random())*TInt64(size))>>32));
       
   371 				if ((RandomNo & 0x3f) == 0x3f)
       
   372 					{
       
   373 					trashBurst= (TBool) aUseTb;
       
   374 					}
       
   375 				PagedTrashCount++;
       
   376 				if (RandomNo & 1)
       
   377 					User::AfterHighRes(500+Random() & 2047);
       
   378 				}
       
   379 			}
       
   380 	
       
   381 		}
       
   382 	return(KErrNone);
       
   383 	}
       
   384 	
       
   385 
       
   386 // This starts up multiple instances of repeatedPagingThread, and runs testWriteMain.
       
   387 // After its done, it calls format, to clean up the drive.
       
   388 
       
   389 void TestMmcAccuratcy()
       
   390 	{
       
   391 	RThread thisThread;
       
   392 	const TInt KNoThreads=10;
       
   393 	TInt i;
       
   394 	test.Printf(_L("Reset stats\n"));
       
   395 
       
   396 	i=UserSvr::HalFunction(EHalGroupMedia,EMediaHalResetConcurrencyInfo,(TAny*)locDriveNumber,(TAny*)EMediaPagingStatsRom);
       
   397 	test(i==KErrNone || i==KErrNotSupported);
       
   398 	if(i==KErrNotSupported)
       
   399 		test.Printf(_L("Concurrency stats not supported on this build\n"));
       
   400 	i=UserSvr::HalFunction(EHalGroupMedia,EMediaHalResetPagingBenchmark,(TAny*)locDriveNumber,(TAny*)EMediaPagingStatsRom);
       
   401 	test(i==KErrNone || i==KErrNotSupported);
       
   402 	if(i==KErrNotSupported)
       
   403 		test.Printf(_L("Benchmark stats not supported on this build\n"));
       
   404 
       
   405 	if (Maxloops>0)
       
   406 		{
       
   407 		TRequestStatus stat[KNoThreads];
       
   408 		// Start Read Test
       
   409 		RThread repeatedPagingThread[KNoThreads];
       
   410 		
       
   411 		test.Next(_L("Read/Write and Page test"));
       
   412 
       
   413 		for (i=0; i<KNoThreads; i++)
       
   414 			{
       
   415 			test(repeatedPagingThread[i].Create(_L(""),RepeatedPagingThread,KDefaultStackSize,NULL,(TAny*) ETrue)==KErrNone);
       
   416 			repeatedPagingThread[i].Logon(stat[i]);
       
   417 			test(stat[i]==KRequestPending);	
       
   418 			repeatedPagingThread[i].Resume();
       
   419 			}
       
   420 		// Start repeated paging.
       
   421 		thisThread.SetPriority(EPriorityMore);
       
   422 		Testing=ETrue;
       
   423 		testWriteMain();
       
   424 		Testing = 0;
       
   425 		thisThread.SetPriority(EPriorityNormal);
       
   426 		for (i=0; i<KNoThreads; i++)
       
   427 	 		User::WaitForRequest(stat[i]);
       
   428 	 		
       
   429 		test.Printf(_L("Collect concurrency stats\n"));
       
   430 		SMediaROMPagingConcurrencyInfo info;
       
   431 		SPagingBenchmarkInfo infoBench;
       
   432 		i=UserSvr::HalFunction(EHalGroupMedia,EMediaHalGetROMConcurrencyInfo,(TAny*)locDriveNumber,&info);
       
   433 		test(i==KErrNone || i==KErrNotSupported);
       
   434 		TInt r=UserSvr::HalFunction(EHalGroupMedia,EMediaHalGetROMPagingBenchmark,(TAny*)locDriveNumber,&infoBench);
       
   435 		test(r==KErrNone || r==KErrNotSupported);
       
   436 		if(i==KErrNone)
       
   437 			{
       
   438 			test.Printf(_L("Media concurrency stats:\n\n"));
       
   439 			test.Printf(_L("The total number of page in requests issued whilst processing other page in requests: %d\n"),info.iTotalConcurrentReqs);
       
   440 			test.Printf(_L("The total number of page in requests issued with at least one queue not empty: %d\n"),info.iTotalReqIssuedNonEmptyQ);
       
   441 			test.Printf(_L("The maximum number of pending page in requests in the main queue any time during this session: %d\n"),info.iMaxReqsInPending);
       
   442 			test.Printf(_L("The maximum number of pending page in requests in the deferred queue any time during this session: %d\n"),info.iMaxReqsInDeferred);
       
   443 			test.Printf(_L("The total number of page in requests first-time deferred during this session: %d\n"),info.iTotalFirstTimeDeferrals);
       
   444 			test.Printf(_L("The total number of page in requests re-deferred during this session: %d\n"),info.iTotalReDeferrals);
       
   445 			test.Printf(_L("The maximum number of deferrals of any single page in request during this session: %d\n"),info.iMaxDeferrals);
       
   446 			test.Printf(_L("The total number of times the main queue was emptied when completing an asynchronous request during this session: %d\n"),info.iTotalSynchEmptiedMainQ);
       
   447 			test.Printf(_L("The total number of page in requests serviced from main queue when completing an asynchronous request: %d\n"),info.iTotalSynchServicedFromMainQ);
       
   448 			test.Printf(_L("The total number of page in requests deferred after being picked out of main queue when completing an asynchronous request: %d\n"),info.iTotalSynchDeferredFromMainQ);
       
   449 			test.Printf(_L("The total number of times the page in DFC run with an empty main queue during this session: %d\n"),info.iTotalRunDry);
       
   450 			test.Printf(_L("The total number of dry runs of paging DFC avoided during this session: %d\n"),info.iTotalDryRunsAvoided);
       
   451 			}
       
   452 
       
   453 		if(r==KErrNone)
       
   454 			{
       
   455 			TInt freq = 0;
       
   456 			r = HAL::Get(HAL::EFastCounterFrequency, freq);
       
   457 			if (r==KErrNone)
       
   458 				{
       
   459 				TReal mult = 1000000.0 / freq;
       
   460 				TReal min = 0.0;
       
   461 				TReal max = 0.0;
       
   462 				TReal avg = 0.0;
       
   463 				if (infoBench.iCount != 0)
       
   464 					{
       
   465 					min = infoBench.iMinTime * mult;
       
   466 					max = infoBench.iMaxTime * mult;
       
   467 					avg = (infoBench.iTotalTime * mult) / infoBench.iCount;
       
   468 					}
       
   469 				test.Printf(_L("Media benchmarks:\n\n"));
       
   470 				test.Printf(_L("The total number of page in requests issued: %d\n"),infoBench.iCount);
       
   471 				test.Printf(_L("The average latency of any page in request in the Media subsystem: %9.1f(us)\n"),avg);
       
   472 				test.Printf(_L("The maximum latency of any page in request in the Media subsystem: %9.1f(us)\n"),max);
       
   473 				test.Printf(_L("The minimum latency of any page in request in the Media subsystem: %9.1f(us)\n"),min);
       
   474 				}
       
   475 			}
       
   476 		}
       
   477 		else
       
   478 			test.Next(_L("Read/Write test - Skipped!"));
       
   479 
       
   480 	}
       
   481 	
       
   482 
       
   483 // ************************************************************************************
       
   484 	
       
   485 	
       
   486 /*
       
   487 // This code causes a flush
       
   488 // It is done in a second thread to see if you really do get just
       
   489 // one deferral, with the other page requests just waiting in line.
       
   490 // (Paging is not re-entrant)
       
   491 
       
   492 TInt PagesBeingPaged=0;
       
   493 RMutex PageMutex;
       
   494 RSemaphore PageSemaphore;
       
   495 RSemaphore PageDoneSemaphore;
       
   496  
       
   497 LOCAL_C TInt CausePage(TAny*)
       
   498 	{	
       
   499 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
       
   500 	TUint8* start = (TUint8*)romHeader+romHeader->iPageableRomStart;
       
   501 	TUint size = romHeader->iPageableRomSize;
       
   502 	TUint8* addr=NULL;
       
   503 	TBool flush;
       
   504 	while (Testing)
       
   505 		{
       
   506 		// Wait on semaphore
       
   507 		PageSemaphore.Wait();
       
   508 		flush = (PagesBeingPaged==0);
       
   509 		PagesBeingPaged++;
       
   510 		addr=start+((TInt64(Random())*TInt64(size))>>32);	
       
   511 		PageDoneSemaphore.Signal();
       
   512 		if (flush)
       
   513 			UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0);
       
   514 		READ(addr);
       
   515 		PageMutex.Wait();
       
   516 		PagesBeingPaged--;
       
   517 		PageMutex.Signal();
       
   518 		}
       
   519 	return 0;
       
   520 	}
       
   521 */
       
   522 
       
   523 // ************************************************************************************
       
   524 
       
   525 //
       
   526 // The gubbins that starts all the tests
       
   527 //
       
   528 // ParseCommandLine reads the arguments and sets globals accordingly.
       
   529 //
       
   530 
       
   531 void ParseCommandLine()
       
   532 	{
       
   533 	TBuf<32> args;
       
   534 	User::CommandLine(args);
       
   535 	TLex lex(args);
       
   536 	
       
   537 	FOREVER
       
   538 		{
       
   539 		
       
   540 		TPtrC token=lex.NextToken();
       
   541 		if(token.Length()!=0)
       
   542 			{
       
   543 			if ((token.Length()==2) && (token[1]==':'))
       
   544 				DriveNumber=User::UpperCase(token[0])-'A';
       
   545 			else if (token.Length()==1)
       
   546 				{
       
   547 				TChar driveLetter = User::UpperCase(token[0]); 
       
   548 				if ((driveLetter>='A') && (driveLetter<='Z'))
       
   549 					DriveNumber=driveLetter - (TChar) 'A';
       
   550 				else 
       
   551 					test.Printf(_L("Unknown argument '%S' was ignored.\n"), &token);
       
   552 				}
       
   553 			else if ((token==_L("help")) || (token==_L("-h")) || (token==_L("-?")))
       
   554 				{
       
   555 				test.Printf(_L("\nUsage:  t_mmcpaging <driveletter> [rwsoak <cc>] [defer <c>]\n'-' indicated infinity.\n\n"));
       
   556 				test.Getch();
       
   557 				Maxloops=0;
       
   558 				}
       
   559 			else if (token==_L("rwsoak"))
       
   560 				{
       
   561 				TPtrC val=lex.NextToken();
       
   562 				TLex lexv(val);
       
   563 				TInt v;
       
   564 
       
   565 				if (val==_L("-"))
       
   566 					Forever=ETrue;
       
   567 				else
       
   568 					if (lexv.Val(v)==KErrNone)
       
   569 						Maxloops=v;
       
   570 					else
       
   571 						test.Printf(_L("Bad value for rwsoak '%S' was ignored.\n"), &val);
       
   572 				}
       
   573 			else if (token==_L("defer"))
       
   574 				{
       
   575 				TPtrC val=lex.NextToken();
       
   576 				TLex lexv(val);
       
   577 				TInt v;
       
   578 
       
   579 				if (val==_L("-"))
       
   580 					MaxDeferLoops=KMaxTInt;
       
   581 				else
       
   582 					if (lexv.Val(v)==KErrNone)
       
   583 						MaxDeferLoops=v;
       
   584 					else
       
   585 						test.Printf(_L("Bad value for defer '%S' was ignored.\n"), &val);
       
   586 				}	
       
   587 			else
       
   588 				test.Printf(_L("Unknown argument '%S' was ignored.\n"), &token);
       
   589 			}
       
   590 		else
       
   591 			break;
       
   592 		
       
   593 		}
       
   594 	}
       
   595 
       
   596 //
       
   597 // E32Main
       
   598 //
       
   599 
       
   600 TInt E32Main()
       
   601 	{
       
   602 	TInt r;
       
   603 	test.Title();
       
   604 
       
   605 	test.Printf(_L("key\n---\n"));	
       
   606 	test.Printf(_L("PR: Paging requests\n"));
       
   607 	test.Printf(_L("NR: Normal requests\n\n"));
       
   608 
       
   609 	
       
   610 	test.Start(_L("Check that the rom is paged"));
       
   611 	TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress();
       
   612 	if (romHeader->iPageableRomStart==NULL)
       
   613 		test.Printf(_L("Test ROM is not paged - test skipped!\r\n"));
       
   614 	else
       
   615 		{
       
   616 		ParseCommandLine();	
       
   617 		test(TheFs.Connect()==KErrNone);
       
   618 
       
   619 		r=UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0);
       
   620 		if(r<0)
       
   621 			{
       
   622 			test.Printf(_L("DemandPagingFlushPages Error = %d\n"),r);
       
   623 			test(0);
       
   624 			}
       
   625 			
       
   626 		DriveNumber = FindFsMMCDrive();	
       
   627 		
       
   628 		if(DriveNumber<0)
       
   629 			test.Printf(_L("MMC Flash not found - test skipped!\r\n"));
       
   630 		else
       
   631 			{
       
   632 			RFile file;
       
   633 			TBuf<256> fileName;	
       
   634 			fileName.Append((TChar)('A'+DriveNumber));
       
   635 			fileName+=_L(":\\f32-tst\\");
       
   636 			TInt r=TheFs.MkDirAll(fileName);
       
   637 			test(r==KErrNone || r== KErrAlreadyExists);
       
   638 			fileName += _L("redglare.txt");
       
   639 			r=file.Replace(TheFs,fileName,EFileWrite);
       
   640 			if (r!=KErrNone)
       
   641 				test.Printf(_L("Error %d: file '%S' could not be created\n"),r,&fileName);
       
   642 			test(r==KErrNone);
       
   643 			r=file.Write(_L8("The red glare of an ancient sun reflecting on the leaden surface of a primeval soup of decomposing matter"));
       
   644 			if (r!=KErrNone)
       
   645 				test.Printf(_L("Error %d: could not write to file\n"),r);
       
   646 			test(r==KErrNone);
       
   647 
       
   648 			test(file.Flush() == KErrNone);
       
   649 
       
   650 			SBlockMapInfo info;
       
   651 			TInt64 start=0;
       
   652 			r=file.BlockMap(info,start, -1,ETestDebug);
       
   653 			if (r!=KErrNone && r!=KErrCompletion)
       
   654 				test.Printf(_L("Error %d: could not obtain block map\n"),r);
       
   655 			test(r==KErrNone || r==KErrCompletion);
       
   656 			locDriveNumber=info.iLocalDriveNumber;
       
   657 			test.Printf(_L("Found drive: %c (MMC drive %d)\r\n"), DriveNumber+'A',locDriveNumber);
       
   658 			file.Close();
       
   659 			
       
   660 			TDriveInfo driveInfo;
       
   661 			test(TheFs.Drive(driveInfo, DriveNumber) == KErrNone);
       
   662 
       
   663 			// Connect to device driver
       
   664 			TBool changeFlag = EFalse;
       
   665 			r = Drive.Connect(locDriveNumber,changeFlag);
       
   666 			TPckg<TLocalDriveCapsV4>	capsPack(DriveCaps);
       
   667 			Drive.Caps(capsPack);
       
   668 			test(r == KErrNone);
       
   669 
       
   670 			SMmcStats stats;
       
   671 			TPtr8 statsBuf((TUint8*) &stats, sizeof(stats));
       
   672 			r = Drive.ControlIO(KMmcGetStats,statsBuf,0);
       
   673 
       
   674 
       
   675 			if (r!=KErrNone)
       
   676 				{
       
   677 				test.Printf(_L("LocalDrive does not support testing IO Requests\n"));
       
   678 				CtrlIOSupported=EFalse;
       
   679 				}
       
   680 			test.Printf(_L("LocalDrive Connected\n"));
       
   681 			//
       
   682 			// Run tests	
       
   683 			//
       
   684 			TestMmcAccuratcy();
       
   685 			// 
       
   686 			// Free device and end test program
       
   687 			//
       
   688 			Drive.Disconnect();
       
   689 			}	
       
   690 		}
       
   691 		
       
   692 	test.End();
       
   693 	return 0;
       
   694 	}
       
   695