| author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> | 
| Thu, 19 Aug 2010 11:14:22 +0300 | |
| branch | RCL_3 | 
| changeset 42 | a179b74831c9 | 
| parent 24 | 41f0cfe18c80 | 
| permissions | -rw-r--r-- | 
| 0 | 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_nandpaging.cpp | |
| 15 | // Suite of tests specifically to test the demand paging subsystem when | |
| 16 | // booted from NAND. | |
| 17 | // 002 Read/Write and Page test | |
| 18 | // 003 Defering test | |
| 19 | // | |
| 20 | // | |
| 21 | ||
| 22 | //! @SYMTestCaseID KBASE-T_NANDPAGING-0332 | |
| 23 | //! @SYMTestType UT | |
| 24 | //! @SYMPREQ PREQ1110 | |
| 25 | //! @SYMTestCaseDesc Demand Paging Nand Paging tests. | |
| 26 | //! @SYMTestActions 001 Check that the rom is paged | |
| 27 | //! @SYMTestExpectedResults All tests should pass. | |
| 28 | //! @SYMTestPriority High | |
| 29 | //! @SYMTestStatus Implemented | |
| 30 | ||
| 42 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 31 | #define __E32TEST_EXTENSION__ | 
| 0 | 32 | #include <e32test.h> | 
| 33 | RTest test(_L("T_NANDPAGING"));
 | |
| 34 | ||
| 35 | #include <e32rom.h> | |
| 6 
0173bcd7697c
Revision: 201001
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
0diff
changeset | 36 | #include <e32svr.h> | 
| 0 | 37 | #include <u32hal.h> | 
| 38 | #include <f32file.h> | |
| 39 | #include <f32dbg.h> | |
| 40 | #include "testdefs.h" | |
| 41 | #include <hal.h> | |
| 42 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 42 | #include "nfe.h" | 
| 0 | 43 | |
| 44 | ||
| 45 | TInt DriveNumber=-1; // Parameter - Which drive? -1 = autodetect. | |
| 46 | TInt locDriveNumber; | |
| 47 | ||
| 48 | TInt MaxDeferLoops=40; // Parameter - Defer test, for how long? | |
| 49 | TInt Maxloops=400; // Parameter - RW Soak, for how long? | |
| 50 | TBool Forever=EFalse; // Parameter - RW Soak forever? | |
| 51 | ||
| 52 | TBool Testing=ETrue; // Used to communicate when testing has finished between threads. | |
| 53 | ||
| 54 | RFs TheFs; | |
| 55 | TBusLocalDrive Drive; | |
| 56 | TLocalDriveCapsV4 DriveCaps; | |
| 57 | ||
| 58 | TInt PagedTrashCount=0; // Incremented by threads, is used to detect preemption. | |
| 59 | TInt GlobError=KErrNone; // To communicate an error between threads. | |
| 60 | TBool CtrlIoCollectGarbageSupported = ETrue; | |
| 61 | TBool CtrlIoGetDeferStatsSupported = ETrue; | |
| 62 | ||
| 63 | ||
| 64 | const TInt KDiskSectorShift=9; | |
| 65 | const TInt KBufSizeInSectors=8; | |
| 66 | const TInt KBufSizeInBytes=(KBufSizeInSectors<<KDiskSectorShift)*40; | |
| 67 | ||
| 68 | LOCAL_D TBuf8<KBufSizeInBytes> Buffer; | |
| 69 | ||
| 70 | ||
| 71 | ||
| 72 | // Three functions for the garbage test. | |
| 73 | // CreateFile creates a file, and sets up the buffer for WriteNumber. | |
| 74 | // After the code has finished writing numbers to the start, | |
| 75 | // CloseAndDestroy cleans up. | |
| 76 | ||
| 77 | void CreateFile(RFile &aFile,const TDesC& aFileName) | |
| 78 | 	{
 | |
| 79 | TBuf<256> fileName; | |
| 80 | 	fileName.Append((TChar)('A'+DriveNumber));
 | |
| 81 | 	fileName+=_L(":\\f32-tst\\");
 | |
| 82 | TInt r=TheFs.MkDirAll(fileName); | |
| 83 | test(r==KErrNone || r== KErrAlreadyExists); | |
| 84 | ||
| 85 | fileName += aFileName; | |
| 86 | ||
| 87 | r=aFile.Replace(TheFs,fileName,EFileWrite); | |
| 88 | if (r!=KErrNone) | |
| 89 | 		test.Printf(_L("Error %d: file '%S' could not be created\n"),r,&fileName);
 | |
| 90 | test(r==KErrNone); | |
| 91 | Buffer.SetLength(4); | |
| 92 | } | |
| 93 | ||
| 94 | void CloseAndDestroy(RFile &aFile) | |
| 95 | 	{
 | |
| 96 | TBuf<256> fileName; | |
| 97 | aFile.FullName(fileName); | |
| 98 | aFile.Close(); | |
| 99 | TheFs.Delete(fileName); | |
| 100 | } | |
| 101 | ||
| 102 | TInt WriteNumber(RFile &aFile) | |
| 103 | 	{
 | |
| 104 | TInt r; | |
| 105 | Buffer[0]++; | |
| 106 | r = aFile.Write(0,Buffer); | |
| 107 | if (r==KErrNone) | |
| 108 | return aFile.Flush(); | |
| 109 | else | |
| 110 | return r; | |
| 111 | } | |
| 112 | ||
| 113 | ||
| 114 | ||
| 115 | // The r/w soaktest leaves the drive in a mess. | |
| 116 | // Formatting is needed afterwards. | |
| 117 | ||
| 118 | void silentFormat(TInt driveNo) | |
| 119 | 	{    
 | |
| 120 |     TBuf<4> driveBuf=_L("?:\\");
 | |
| 121 | RFormat format; | |
| 122 | TInt count; | |
| 123 | ||
| 124 | driveBuf[0] = (TText)(driveNo + 'A'); | |
| 125 | ||
| 126 | TInt r = format.Open(TheFs, driveBuf, EHighDensity, count); | |
| 127 | test(r == KErrNone); | |
| 128 | ||
| 129 | while(count) | |
| 130 | 		{
 | |
| 131 | r=format.Next(count); | |
| 132 | test(r == KErrNone); | |
| 133 | } | |
| 134 | ||
| 135 | format.Close(); | |
| 136 | } | |
| 137 | ||
| 138 | // Finds the 1st r/w NAND drive, or checks the specified one fits requirements | |
| 139 | ||
| 140 | static TInt FindFsNANDDrive() | |
| 141 | 	{
 | |
| 142 | TDriveList driveList; | |
| 143 | TDriveInfo driveInfo; | |
| 144 | TInt r=TheFs.DriveList(driveList); | |
| 145 | test(r == KErrNone); | |
| 146 | ||
| 147 | for (TInt drvNum= (DriveNumber<0)?0:DriveNumber; drvNum<KMaxDrives; ++drvNum) | |
| 148 | 		{
 | |
| 149 | if(!driveList[drvNum]) | |
| 150 | continue; //-- skip unexisting drive | |
| 151 | ||
| 152 | test(TheFs.Drive(driveInfo, drvNum) == KErrNone); | |
| 153 | ||
| 154 | if ((driveInfo.iMediaAtt&KMediaAttPageable) && | |
| 155 | (driveInfo.iType == EMediaNANDFlash) && | |
| 156 | (driveInfo.iDriveAtt & KDriveAttInternal)) | |
| 157 | 			{
 | |
| 158 | TBool readOnly = driveInfo.iMediaAtt & KMediaAttWriteProtected; // skip ROFS partitions | |
| 159 | if(!readOnly) | |
| 160 | 				{
 | |
| 161 | if ((drvNum==DriveNumber) || (DriveNumber<0)) // only test if running on this drive | |
| 162 | 					{
 | |
| 163 | return (drvNum); | |
| 164 | } | |
| 165 | } | |
| 166 | } | |
| 167 | } | |
| 168 | return (-1); | |
| 169 | } | |
| 170 | ||
| 171 | ||
| 172 | // | |
| 173 | // Writes to main area for the entire disk and reads back to verify. | |
| 174 | // The function is called from TestNandAccuratcy, which will have also | |
| 175 | // started the background RepeatedPagingThread | |
| 176 | // | |
| 177 | void testWriteMain() | |
| 178 | 	{
 | |
| 179 | TInt i; | |
| 180 | TInt r; | |
| 181 | TInt changeCount=0; | |
| 182 | TInt totChangeCount=0; | |
| 183 | TInt cCount=0; | |
| 184 | TInt fullcCount=0; | |
| 185 | TInt oldPagedTrashCount=0; | |
| 186 | TInt delta=0; | |
| 187 | TInt high=0; | |
| 188 | TInt tot=0; | |
| 189 | TInt fullTot=0; | |
| 190 | TInt blockNo; | |
| 191 | ||
| 192 | // read size is 64K | |
| 193 | TInt readSize = (64*1024); | |
| 194 | TInt64 size = DriveCaps.iSize - (DriveCaps.iSize % readSize); | |
| 195 | ||
| 196 | // print position every 128K | |
| 197 | TInt64 printBlockPos = 128 * 1024; | |
| 198 | test (size > printBlockPos); | |
| 199 | ||
| 200 | // check for paging activity every 1MB | |
| 201 | TInt64 checkChangePos = 1024*1024; | |
| 202 | while (checkChangePos > size) | |
| 203 | checkChangePos>>= 1; | |
| 204 | ||
| 205 | ||
| 206 | SDeferStats stats; | |
| 207 | TInt pageGarbageCount=0; | |
| 208 | TInt pageOtherCount=0; | |
| 209 | TInt normalGarbageCount=0; | |
| 210 | TInt normalOtherCount=0; | |
| 211 | ||
| 212 | ||
| 213 | Buffer.SetLength(2*readSize); | |
| 214 | ||
| 215 | TPtr8 subBuf1(&Buffer[0],readSize); | |
| 216 | TPtrC8 subBuf2(&Buffer[readSize], readSize); | |
| 217 | ||
| 218 | 	test.Printf(_L("Page size = %d\n"), DriveCaps.iNumBytesMain);
 | |
| 219 | 	test.Printf(_L("Erase block size = %d\n"), DriveCaps.iEraseBlockSize);
 | |
| 220 | 	test.Printf(_L("Media size (rounded down) = %ld\n"), size);
 | |
| 221 | ||
| 222 | for(i = 0; i<readSize; i++) | |
| 223 | Buffer[readSize+i] = (char)(i%100); | |
| 224 | ||
| 225 | // Zero Stats | |
| 226 | if(CtrlIoGetDeferStatsSupported) | |
| 227 | 		{
 | |
| 228 | TPtr8 statsBuf((TUint8*) &stats, sizeof(stats)); | |
| 229 | test(Drive.ControlIO(KNandGetDeferStats,statsBuf,0)==KErrNone); | |
| 230 | } | |
| 231 | ||
| 232 | ||
| 233 | while (((totChangeCount<Maxloops) || Forever) && (GlobError==KErrNone)) | |
| 234 | 		{
 | |
| 235 | for(TInt64 pos=0; | |
| 236 | (pos<size) && ((totChangeCount<Maxloops) || Forever) && (GlobError==KErrNone); | |
| 237 | pos+=(TUint)(readSize)) | |
| 238 | 			{
 | |
| 239 | blockNo=I64LOW(pos / DriveCaps.iEraseBlockSize); | |
| 240 | if ((pos % printBlockPos) == 0) | |
| 241 | 				test.Printf(_L("Block %d at pos %lu \r"), blockNo, pos);
 | |
| 242 | ||
| 243 | //write the pattern | |
| 244 | r = Drive.Write(pos,subBuf2); | |
| 245 | test(r==KErrNone); | |
| 246 | ||
| 247 | //read back and verify | |
| 248 | r = Drive.Read(pos,readSize,subBuf1); | |
| 249 | test(r==KErrNone); | |
| 250 | ||
| 251 | for(i=0;i<readSize;i++) | |
| 252 | if(Buffer[i]!=Buffer[readSize+i]) | |
| 253 | 					{
 | |
| 254 | r = KErrCorrupt; | |
| 255 | break; | |
| 256 | } | |
| 257 | delta = PagedTrashCount-oldPagedTrashCount; | |
| 258 | cCount++; | |
| 259 | if (delta) | |
| 260 | 				{	
 | |
| 261 | if (delta>high) | |
| 262 | high=delta; | |
| 263 | tot+=delta; | |
| 264 | ||
| 265 | oldPagedTrashCount=PagedTrashCount; | |
| 266 | changeCount++; | |
| 267 | } | |
| 268 | ||
| 269 | if ((pos > 0) && (pos % checkChangePos) == 0) | |
| 270 | 				{
 | |
| 271 | totChangeCount+=changeCount; | |
| 272 | if(CtrlIoGetDeferStatsSupported) | |
| 273 | 					{
 | |
| 274 | 					test.Printf(_L("\nHigh%4d Avg%2d %d%% CC=%4d \n"), high, (TInt) (tot/cCount), (TInt)(changeCount*100)/cCount, totChangeCount);
 | |
| 275 | ||
| 276 | TPtr8 statsBuf((TUint8*) &stats, sizeof(stats)); | |
| 277 | Drive.ControlIO(KNandGetDeferStats,statsBuf,0); | |
| 278 | 					test.Printf(_L("PG %d PO %d(%d%%) NG %d NO %d\n"),stats.iPageGarbage,  stats.iPageOther, (TInt) ((stats.iPageOther*100)/cCount), stats.iNormalGarbage,  stats.iNormalOther);
 | |
| 279 | ||
| 280 | pageGarbageCount+=stats.iPageGarbage; | |
| 281 | pageOtherCount+=stats.iPageOther; | |
| 282 | normalGarbageCount+=stats.iNormalGarbage; | |
| 283 | normalOtherCount+=stats.iNormalOther; | |
| 284 | } | |
| 285 | ||
| 286 | high=0; | |
| 287 | ||
| 288 | fullTot+=tot; | |
| 289 | tot=0; | |
| 290 | ||
| 291 | fullcCount+=cCount; | |
| 292 | cCount=0; | |
| 293 | changeCount=0; | |
| 294 | } | |
| 295 | ||
| 296 | test(r==KErrNone); | |
| 297 | } // for loop | |
| 298 | ||
| 299 | if (CtrlIoGetDeferStatsSupported) | |
| 300 | 			{
 | |
| 301 | 			test.Printf(_L("\nTotals: Avg %2d %d%% CC=%4d \n"), fullTot/fullcCount, (TInt)(totChangeCount*100)/fullcCount, totChangeCount);
 | |
| 302 | 			test.Printf(_L("PG %d PO %d(%d%%) NG %d NO %d\n"),pageGarbageCount,  pageOtherCount,(TInt) (pageOtherCount*100/fullcCount), normalGarbageCount,  normalOtherCount );
 | |
| 24 
41f0cfe18c80
Revision: 201017
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
6diff
changeset | 303 | test(pageOtherCount > 0); // Ensure at least one paging conflict occurred during the test. | 
| 0 | 304 | } | 
| 305 | ||
| 306 | // If totChangeCount does not change, nand maybe busy waiting. | |
| 307 | test(totChangeCount>0); | |
| 308 | } // while () | |
| 309 | ||
| 310 | if (GlobError!=KErrNone) | |
| 311 | 		{
 | |
| 312 | 		test.Printf(_L("\nPaging failed with %x\n"), GlobError);
 | |
| 313 | test(0); | |
| 314 | } | |
| 315 | else | |
| 316 | 		test.Printf(_L("\ndone\n"));
 | |
| 317 | } | |
| 318 | ||
| 319 | ||
| 320 | TUint8 ReadByte(volatile TUint8* aPtr) | |
| 321 | 	{
 | |
| 322 | return *aPtr; | |
| 323 | } | |
| 324 | ||
| 325 | #define READ(a) ReadByte((volatile TUint8*)(a)) | |
| 326 | ||
| 327 | TUint32 RandomNo =0; | |
| 328 | ||
| 329 | TUint32 Random() | |
| 330 | 	{
 | |
| 331 | RandomNo = RandomNo*69069+1; | |
| 332 | return RandomNo; | |
| 333 | } | |
| 334 | ||
| 335 | ||
| 336 | // Many instances of this run while testWriteMain runs, | |
| 337 | // to cause random background paging. | |
| 338 | ||
| 339 | LOCAL_C TInt RepeatedPagingThread(TAny* aUseTb) | |
| 340 | 	{
 | |
| 341 | TBool trashBurst = EFalse; | |
| 342 | // This makes the paging system continually page stuff. | |
| 343 | // get info about a paged ROM... | |
| 344 | ||
| 345 | TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress(); | |
| 346 | TUint8* start = (TUint8*)romHeader+romHeader->iPageableRomStart; | |
| 347 | TUint size = romHeader->iPageableRomSize; | |
| 348 | TInt pageSize = 0; | |
| 349 | PagedTrashCount=1; | |
| 350 | ||
| 351 | UserSvr::HalFunction(EHalGroupKernel,EKernelHalPageSizeInBytes,&pageSize,0); | |
| 352 | RandomNo=123; | |
| 353 | PagedTrashCount++; | |
| 354 | ||
| 355 | while (Testing) | |
| 356 | 		{
 | |
| 357 | TInt r=UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0); | |
| 358 | if (Random() & 1) | |
| 359 | User::AfterHighRes(500+Random() & 2047); | |
| 360 | ||
| 361 | if (r<0) | |
| 362 | 			{
 | |
| 363 | GlobError=r; | |
| 364 | PagedTrashCount=99; | |
| 365 | return (KErrNone); | |
| 366 | } | |
| 367 | if (trashBurst) | |
| 368 | 			{
 | |
| 369 | if ((Random() & 0xf) == 0xf) | |
| 370 | trashBurst=EFalse; | |
| 371 | PagedTrashCount++; | |
| 372 | } | |
| 373 | else | |
| 374 | 			{
 | |
| 375 | ||
| 376 | for(TInt i=size/(pageSize); (i>0) && !trashBurst; --i) | |
| 377 | 				{
 | |
| 378 | READ(start+((TInt64(Random())*TInt64(size))>>32)); | |
| 379 | if ((RandomNo & 0x3f) == 0x3f) | |
| 380 | 					{
 | |
| 381 | trashBurst= (TBool) aUseTb; | |
| 382 | } | |
| 383 | PagedTrashCount++; | |
| 384 | if (RandomNo & 1) | |
| 385 | User::AfterHighRes(500+Random() & 2047); | |
| 386 | } | |
| 387 | } | |
| 388 | ||
| 389 | } | |
| 390 | return(KErrNone); | |
| 391 | } | |
| 392 | ||
| 393 | ||
| 394 | // This starts up multiple instances of repeatedPagingThread, and runs testWriteMain. | |
| 395 | // After its done, it calls format, to clean up the drive. | |
| 396 | ||
| 397 | void TestNandAccuratcy() | |
| 398 | 	{
 | |
| 399 | RThread thisThread; | |
| 400 | const TInt KNoThreads=10; | |
| 401 | TInt i; | |
| 402 | 	test.Printf(_L("Reset concurrency stats\n"));
 | |
| 403 | ||
| 404 | i=UserSvr::HalFunction(EHalGroupMedia,EMediaHalResetConcurrencyInfo,(TAny*)locDriveNumber,(TAny*)EMediaPagingStatsRom); | |
| 405 | test(i==KErrNone || i==KErrNotSupported); | |
| 406 | if(i==KErrNotSupported) | |
| 407 | 		test.Printf(_L("Concurrency stats not supported on this build\n"));
 | |
| 408 | i=UserSvr::HalFunction(EHalGroupMedia,EMediaHalResetPagingBenchmark,(TAny*)locDriveNumber,(TAny*)EMediaPagingStatsRom); | |
| 409 | test(i==KErrNone || i==KErrNotSupported); | |
| 410 | if(i==KErrNotSupported) | |
| 411 | 		test.Printf(_L("Benchmark stats not supported on this build\n"));
 | |
| 412 | ||
| 413 | if (Maxloops>0) | |
| 414 | 		{
 | |
| 415 | TRequestStatus stat[KNoThreads]; | |
| 416 | // Start Read Test | |
| 417 | RThread repeatedPagingThread[KNoThreads]; | |
| 418 | ||
| 419 | 		test.Next(_L("Read/Write and Page test"));
 | |
| 420 | ||
| 421 | Testing=ETrue; | |
| 422 | for (i=0; i<KNoThreads; i++) | |
| 423 | 			{
 | |
| 424 | ||
| 425 | 			test(repeatedPagingThread[i].Create(_L(""),RepeatedPagingThread,KDefaultStackSize,NULL,(TAny*) ETrue)==KErrNone);
 | |
| 426 | repeatedPagingThread[i].Logon(stat[i]); | |
| 427 | test(stat[i]==KRequestPending); | |
| 428 | repeatedPagingThread[i].Resume(); | |
| 429 | } | |
| 430 | // Start repeated paging. | |
| 431 | thisThread.SetPriority(EPriorityMore); | |
| 432 | testWriteMain(); | |
| 433 | Testing = 0; | |
| 434 | thisThread.SetPriority(EPriorityNormal); | |
| 435 | for (i=0; i<KNoThreads; i++) | |
| 436 | User::WaitForRequest(stat[i]); | |
| 437 | ||
| 438 | 		test.Printf(_L("Collect concurrency stats\n"));
 | |
| 439 | SMediaROMPagingConcurrencyInfo info; | |
| 440 | SPagingBenchmarkInfo infoBench; | |
| 441 | i=UserSvr::HalFunction(EHalGroupMedia,EMediaHalGetROMConcurrencyInfo,(TAny*)locDriveNumber,&info); | |
| 442 | test(i==KErrNone || i==KErrNotSupported); | |
| 443 | TInt r=UserSvr::HalFunction(EHalGroupMedia,EMediaHalGetROMPagingBenchmark,(TAny*)locDriveNumber,&infoBench); | |
| 444 | test(r==KErrNone || r==KErrNotSupported); | |
| 445 | if(i==KErrNone) | |
| 446 | 			{
 | |
| 447 | 			test.Printf(_L("Media concurrency stats:\n\n"));
 | |
| 448 | 			test.Printf(_L("The total number of page in requests issued whilst processing other page in requests: %d\n"),info.iTotalConcurrentReqs);
 | |
| 449 | 			test.Printf(_L("The total number of page in requests issued with at least one queue not empty: %d\n"),info.iTotalReqIssuedNonEmptyQ);
 | |
| 450 | 			test.Printf(_L("The maximum number of pending page in requests in the main queue any time during this session: %d\n"),info.iMaxReqsInPending);
 | |
| 451 | 			test.Printf(_L("The maximum number of pending page in requests in the deferred queue any time during this session: %d\n"),info.iMaxReqsInDeferred);
 | |
| 452 | 			test.Printf(_L("The total number of page in requests first-time deferred during this session: %d\n"),info.iTotalFirstTimeDeferrals);
 | |
| 453 | 			test.Printf(_L("The total number of page in requests re-deferred during this session: %d\n"),info.iTotalReDeferrals);
 | |
| 454 | 			test.Printf(_L("The maximum number of deferrals of any single page in request during this session: %d\n"),info.iMaxDeferrals);
 | |
| 455 | 			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);
 | |
| 456 | 			test.Printf(_L("The total number of page in requests serviced from main queue when completing an asynchronous request: %d\n"),info.iTotalSynchServicedFromMainQ);
 | |
| 457 | 			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);
 | |
| 458 | 			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);
 | |
| 459 | 			test.Printf(_L("The total number of dry runs of paging DFC avoided during this session: %d\n"),info.iTotalDryRunsAvoided);
 | |
| 460 | } | |
| 461 | ||
| 462 | if(r==KErrNone) | |
| 463 | 			{
 | |
| 464 | TInt freq = 0; | |
| 465 | r = HAL::Get(HAL::EFastCounterFrequency, freq); | |
| 466 | if (r==KErrNone) | |
| 467 | 				{
 | |
| 468 | TReal mult = 1000000.0 / freq; | |
| 469 | TReal min = 0.0; | |
| 470 | TReal max = 0.0; | |
| 471 | TReal avg = 0.0; | |
| 472 | if (infoBench.iCount != 0) | |
| 473 | 					{
 | |
| 474 | min = infoBench.iMinTime * mult; | |
| 475 | max = infoBench.iMaxTime * mult; | |
| 476 | avg = (infoBench.iTotalTime * mult) / infoBench.iCount; | |
| 477 | } | |
| 478 | 				test.Printf(_L("Media benchmarks:\n\n"));
 | |
| 479 | 				test.Printf(_L("The total number of page in requests issued: %d\n"),infoBench.iCount);
 | |
| 480 | 				test.Printf(_L("The average latency of any page in request in the Media subsystem: %9.1f(us)\n"),avg);
 | |
| 481 | 				test.Printf(_L("The maximum latency of any page in request in the Media subsystem: %9.1f(us)\n"),max);
 | |
| 482 | 				test.Printf(_L("The minimum latency of any page in request in the Media subsystem: %9.1f(us)\n"),min);
 | |
| 483 | } | |
| 484 | } | |
| 485 | ||
| 486 | 		test.Printf(_L("Formatting...\n"));
 | |
| 487 | silentFormat(DriveNumber); | |
| 488 | } | |
| 489 | else | |
| 490 | 			test.Next(_L("Read/Write test - Skipped!"));
 | |
| 491 | ||
| 492 | } | |
| 493 | ||
| 494 | ||
| 495 | // ************************************************************************************ | |
| 496 | ||
| 497 | ||
| 498 | // This code causes a flush | |
| 499 | // It is done in a second thread to see if you really do get just | |
| 500 | // one deferral, with the other page requests just waiting in line. | |
| 501 | // (Paging is not re-entrant) | |
| 502 | ||
| 503 | TInt PagesBeingPaged=0; | |
| 504 | RMutex PageMutex; | |
| 505 | RSemaphore PageSemaphore; | |
| 506 | RSemaphore PageDoneSemaphore; | |
| 507 | ||
| 508 | LOCAL_C TInt CausePage(TAny*) | |
| 509 | 	{	
 | |
| 510 | TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress(); | |
| 511 | TUint8* start = (TUint8*)romHeader+romHeader->iPageableRomStart; | |
| 512 | TUint size = romHeader->iPageableRomSize; | |
| 513 | TUint8* addr=NULL; | |
| 514 | while (Testing) | |
| 515 | 		{
 | |
| 516 | PageSemaphore.Wait(); // wait for main thread to want paging. | |
| 517 | addr=start+((TInt64(Random())*TInt64(size))>>32); | |
| 42 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 518 | PageDoneSemaphore.Signal(); // Acknowledge request. | 
| 0 | 519 | |
| 520 | PageMutex.Wait(); | |
| 42 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 521 | TBool flush = (PagesBeingPaged==0); // Ensure only one thread is flushing the cache at a time. | 
| 0 | 522 | PagesBeingPaged++; | 
| 523 | PageMutex.Signal(); | |
| 524 | ||
| 525 | if (flush) | |
| 526 | UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0); | |
| 527 | READ(addr); | |
| 528 | ||
| 529 | PageMutex.Wait(); | |
| 530 | PagesBeingPaged--; | |
| 531 | PageMutex.Signal(); | |
| 532 | } | |
| 533 | return 0; | |
| 534 | } | |
| 535 | ||
| 536 | ||
| 537 | // TestDefered causes garbage collection, and then triggers paging to happen, which should be defered. | |
| 538 | // One would only expect one defered request, as the paging system is not reentrant, but this is checked. | |
| 539 | ||
| 540 | void TestDefered() | |
| 541 | 	{
 | |
| 542 | if (MaxDeferLoops==0) | |
| 543 | 		{
 | |
| 544 | 		test.Next(_L("Defering test - Skipped!"));
 | |
| 545 | return; | |
| 546 | } | |
| 547 | ||
| 42 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 548 | // If the NFE test media driver extension is present, ALL the drive is encrypted; | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 549 | // this means that there will be very few free blocks in the free block reservoir: this effectively | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 550 | // disables background garbage collection and all block erasing needs to happen on the fly... | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 551 | TNfeDeviceInfo nfeDeviceinfo; | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 552 | TPtr8 nfeDeviceInfoBuf((TUint8*) &nfeDeviceinfo, sizeof(nfeDeviceinfo)); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 553 | nfeDeviceInfoBuf.FillZ(); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 554 | TInt r = Drive.QueryDevice((RLocalDrive::TQueryDevice) EQueryNfeDeviceInfo, nfeDeviceInfoBuf); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 555 | /* | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 556 | if (r == KErrNone) | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 557 | 		{
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 558 | 		test.Printf(_L("NFE device detected, aborting garbage collection test for now\n"));
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 559 | return; | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 560 | } | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 561 | */ | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 562 | // Create some free blocks by creating a huge file and then deleting it.... | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 563 | if (r == KErrNone) | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 564 | 		{
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 565 | 		test.Printf(_L("NFE device detected\n"));
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 566 | RFile file; | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 567 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 568 | 		TBuf<256> tempFileName = _L("?:\\f32-tst\\");
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 569 | tempFileName[0] = 'A'+DriveNumber; | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 570 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 571 | r = TheFs.MkDirAll(tempFileName); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 572 | test(r==KErrNone || r== KErrAlreadyExists); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 573 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 574 | 		tempFileName+= _L("TEMP.TXT");
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 575 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 576 | r = file.Replace(TheFs, tempFileName, EFileWrite); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 577 | test_KErrNone(r); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 578 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 579 | for (TInt fileSize = KMaxTInt; fileSize > 0; fileSize >>= 1) | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 580 | 			{
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 581 | r = file.SetSize(fileSize); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 582 | 			test.Printf(_L("Setting file size to %d, r %d\n"), fileSize, r);
 | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 583 | if (r == KErrNone) | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 584 | break; | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 585 | } | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 586 | file.Close(); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 587 | r = TheFs.Delete(tempFileName); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 588 | test_KErrNone(r); | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 589 | } | 
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 590 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 591 | |
| 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 592 | |
| 0 | 593 | TInt timeout; | 
| 594 | TInt writesNeeded=100; | |
| 595 | RFile tempFile; | |
| 596 | TInt i; | |
| 597 | TInt ii; | |
| 598 | TInt runs=0; | |
| 599 | ||
| 600 | SDeferStats stats; | |
| 601 | TInt pageGarbageCount=0; | |
| 602 | TInt pageOtherCount=0; | |
| 603 | TInt normalGarbageCount=0; | |
| 604 | TInt normalOtherCount=0; | |
| 605 | ||
| 606 | ||
| 607 | // Set up thread sync | |
| 608 | test(PageMutex.CreateLocal()==KErrNone); | |
| 609 | test(PageSemaphore.CreateLocal(0)==KErrNone); | |
| 610 | test(PageDoneSemaphore.CreateLocal(0)==KErrNone); | |
| 611 | ||
| 612 | ||
| 613 | ||
| 614 | const TInt KMaxPageThreads = 2; | |
| 615 | UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0); | |
| 616 | // Set up threads | |
| 617 | RThread pageThread[KMaxPageThreads]; | |
| 618 | TRequestStatus stat[KMaxPageThreads]; | |
| 619 | Testing=ETrue; | |
| 620 | for (i=0; i<KMaxPageThreads; i++) | |
| 621 | 		{
 | |
| 622 | 		test(pageThread[i].Create(_L(""),CausePage,KDefaultStackSize,NULL,NULL)==KErrNone);
 | |
| 623 | pageThread[i].Logon(stat[i]); | |
| 624 | test(stat[i]==KRequestPending); | |
| 625 | pageThread[i].SetPriority(EPriorityMore); | |
| 626 | pageThread[i].Resume(); | |
| 627 | } | |
| 628 | ||
| 629 | ||
| 630 | 	test.Next(_L("Defering test"));
 | |
| 631 | ||
| 632 | // clear counters | |
| 633 | TPtr8 statsBuf((TUint8*) &stats, sizeof(stats)); | |
| 634 | test(Drive.ControlIO(KNandGetDeferStats,statsBuf,0)==KErrNone); | |
| 635 | ||
| 636 | 	CreateFile(tempFile,_L("nandpage.txt"));
 | |
| 637 | ||
| 638 | ||
| 639 | for (ii=0; ii<MaxDeferLoops; ii++) // Repeat the test, 'MaxDeferLoops' number of times. This can be set on cammand line. | |
| 640 | 		{
 | |
| 42 
a179b74831c9
Revision: 201033
 Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> parents: 
24diff
changeset | 641 | writesNeeded=100; | 
| 0 | 642 | timeout=20; | 
| 643 | do // while ((pageGarbageCount==0) && (timeout>0)); | |
| 644 | // ie, while garbage collection hasn't happened, or timed out | |
| 645 | 			{
 | |
| 646 | timeout--; | |
| 647 | pageGarbageCount=0; | |
| 648 | pageOtherCount=0; | |
| 649 | normalGarbageCount=0; | |
| 650 | normalOtherCount=0; | |
| 651 | ||
| 652 | // Give somethng for garbage collector to collect | |
| 653 | for (i=0; i<writesNeeded; i++) | |
| 654 | test(WriteNumber(tempFile)==KErrNone); | |
| 655 | ||
| 656 | // Force Collection. (Normally only happens in Idle) | |
| 657 | r = Drive.ControlIO(KNandCollectGarbage,NULL,NULL); | |
| 658 | test(r==KErrNone); | |
| 659 | ||
| 660 | // Since garbage Colleciton should be going now, watch it, until its finished. | |
| 661 | do | |
| 662 | 		 		{
 | |
| 663 | runs = PagesBeingPaged; | |
| 664 | for (i=runs; i<KMaxPageThreads; i++) | |
| 665 | PageSemaphore.Signal(); // Trigger Paging. | |
| 666 | ||
| 667 | for (i=runs; i<KMaxPageThreads; i++) | |
| 668 | PageDoneSemaphore.Wait(); | |
| 669 | ||
| 670 | TInt tries = 10; | |
| 671 | 				do { // If we get zero hits, maybe the page hasnt hit yet.
 | |
| 672 | tries--; | |
| 673 | User::AfterHighRes(1000+Random() & 2047); // Throw some uncertainly into things | |
| 674 | ||
| 675 | TPtr8 statsBuf((TUint8*) &stats, sizeof(stats)); | |
| 676 | r = Drive.ControlIO(KNandGetDeferStats,statsBuf,0); | |
| 677 | test (r == KErrNone); | |
| 678 | pageGarbageCount+=stats.iPageGarbage; | |
| 679 | pageOtherCount+=stats.iPageOther; | |
| 680 | normalGarbageCount+=stats.iNormalGarbage; | |
| 681 | normalOtherCount+=stats.iNormalOther; | |
| 682 | } while ((pageGarbageCount==0) && (tries>0)); // If we get zero hits, maybe the page hasnt hit yet | |
| 683 | } | |
| 684 | while (stats.iPageGarbage>0); // Keep going until collection seems to have finished. | |
| 685 | ||
| 686 | // The paging system is not reentrant, so should never get more then one. | |
| 687 | test(stats.iPageGarbage<2); | |
| 688 | ||
| 689 | 			test.Printf(_L("%d: PG %d PO %d NG %d NO %d\n"),ii,pageGarbageCount,  pageOtherCount, normalGarbageCount,  normalOtherCount );
 | |
| 690 | // if no collection, probebly didnt write enough to trigger it, so up the quantity. | |
| 691 | if (pageGarbageCount==0) | |
| 692 | 				{		
 | |
| 693 | writesNeeded+=writesNeeded/2; | |
| 694 | 				test.Printf(_L("Writes needed = %d\n"),writesNeeded);
 | |
| 695 | } | |
| 696 | ||
| 697 | } | |
| 698 | while ((pageGarbageCount==0) && (timeout>0)); | |
| 699 | test(timeout>0); | |
| 700 | ||
| 701 | } // end for MaxDeferLoops. | |
| 702 | ||
| 703 | // Clean up. . . . . | |
| 704 | ||
| 705 | Testing=EFalse; // Setting this causes the CausePage threads to exit. | |
| 706 | ||
| 707 | // Wait for threads to exit, signaling the semaphore in case they where waiting on it. | |
| 708 | for (i=0; i<KMaxPageThreads; i++) | |
| 709 | PageSemaphore.Signal(); | |
| 710 | for (i=0; i<KMaxPageThreads; i++) | |
| 711 | User::WaitForRequest(stat[i]); | |
| 712 | ||
| 713 | PageMutex.Close(); | |
| 714 | PageSemaphore.Close(); | |
| 715 | PageDoneSemaphore.Close(); | |
| 716 | CloseAndDestroy(tempFile); | |
| 717 | } | |
| 718 | ||
| 719 | ||
| 720 | // ************************************************************************************ | |
| 721 | ||
| 722 | // | |
| 723 | // The gubbins that starts all the tests | |
| 724 | // | |
| 725 | // ParseCommandLine reads the arguments and sets globals accordingly. | |
| 726 | // | |
| 727 | ||
| 728 | void ParseCommandLine() | |
| 729 | 	{
 | |
| 730 | TBuf<32> args; | |
| 731 | User::CommandLine(args); | |
| 732 | TLex lex(args); | |
| 733 | ||
| 734 | FOREVER | |
| 735 | 		{
 | |
| 736 | ||
| 737 | TPtrC token=lex.NextToken(); | |
| 738 | if(token.Length()!=0) | |
| 739 | 			{
 | |
| 740 | if ((token.Length()==2) && (token[1]==':')) | |
| 741 | DriveNumber=User::UpperCase(token[0])-'A'; | |
| 742 | else if (token.Length()==1) | |
| 743 | 				{
 | |
| 744 | TChar driveLetter = User::UpperCase(token[0]); | |
| 745 | if ((driveLetter>='A') && (driveLetter<='Z')) | |
| 746 | DriveNumber=driveLetter - (TChar) 'A'; | |
| 747 | else | |
| 748 | 					test.Printf(_L("Unknown argument '%S' was ignored.\n"), &token);
 | |
| 749 | } | |
| 750 | 			else if ((token==_L("help")) || (token==_L("-h")) || (token==_L("-?")))
 | |
| 751 | 				{
 | |
| 752 | 				test.Printf(_L("\nUsage:  t_nandpaging <driveletter> [rwsoak <cc>] [defer <c>]\n'-' indicated infinity.\n\n"));
 | |
| 753 | test.Getch(); | |
| 754 | Maxloops=0; | |
| 755 | } | |
| 756 | 			else if (token==_L("rwsoak"))
 | |
| 757 | 				{
 | |
| 758 | TPtrC val=lex.NextToken(); | |
| 759 | TLex lexv(val); | |
| 760 | TInt v; | |
| 761 | ||
| 762 | 				if (val==_L("-"))
 | |
| 763 | Forever=ETrue; | |
| 764 | else | |
| 765 | if (lexv.Val(v)==KErrNone) | |
| 766 | Maxloops=v; | |
| 767 | else | |
| 768 | 						test.Printf(_L("Bad value for rwsoak '%S' was ignored.\n"), &val);
 | |
| 769 | } | |
| 770 | 			else if (token==_L("defer"))
 | |
| 771 | 				{
 | |
| 772 | TPtrC val=lex.NextToken(); | |
| 773 | TLex lexv(val); | |
| 774 | TInt v; | |
| 775 | ||
| 776 | 				if (val==_L("-"))
 | |
| 777 | MaxDeferLoops=KMaxTInt; | |
| 778 | else | |
| 779 | if (lexv.Val(v)==KErrNone) | |
| 780 | MaxDeferLoops=v; | |
| 781 | else | |
| 782 | 						test.Printf(_L("Bad value for defer '%S' was ignored.\n"), &val);
 | |
| 783 | } | |
| 784 | else | |
| 785 | 				test.Printf(_L("Unknown argument '%S' was ignored.\n"), &token);
 | |
| 786 | } | |
| 787 | else | |
| 788 | break; | |
| 789 | ||
| 790 | } | |
| 791 | } | |
| 792 | ||
| 793 | // | |
| 794 | // E32Main | |
| 795 | // | |
| 796 | ||
| 797 | TInt E32Main() | |
| 798 | 	{
 | |
| 799 | TInt r; | |
| 800 | test.Title(); | |
| 801 | ||
| 802 | 	test.Printf(_L("key\n---\n"));	
 | |
| 803 | 	test.Printf(_L("PG: Paging requests defered due to Garbage\n"));
 | |
| 804 | 	test.Printf(_L("PO: Paging requests defered due to other operations\n"));
 | |
| 805 | 	test.Printf(_L("NG: Normal requests defered due to Garbage\n"));
 | |
| 806 | 	test.Printf(_L("NO: Normal requests defered due to other operations\n\n"));
 | |
| 807 | ||
| 808 | ||
| 809 | 	test.Start(_L("Check that the rom is paged"));
 | |
| 810 | TRomHeader* romHeader = (TRomHeader*)UserSvr::RomHeaderAddress(); | |
| 811 | ||
| 812 | if (romHeader->iPageableRomStart==NULL) | |
| 813 | 		test.Printf(_L("Test ROM is not paged - test skipped!\r\n"));
 | |
| 814 | else | |
| 815 | 		{
 | |
| 816 | ParseCommandLine(); | |
| 817 | test(TheFs.Connect()==KErrNone); | |
| 818 | ||
| 819 | r=UserSvr::HalFunction(EHalGroupVM,EVMHalFlushCache,0,0); | |
| 820 | if(r<0) | |
| 821 | 			{
 | |
| 822 | 			test.Printf(_L("DemandPagingFlushPages Error = %d\n"),r);
 | |
| 823 | test(0); | |
| 824 | } | |
| 825 | ||
| 826 | DriveNumber = FindFsNANDDrive(); | |
| 827 | ||
| 828 | if(DriveNumber<0) | |
| 829 | 			test.Printf(_L("NAND Flash not found - test skipped!\r\n"));
 | |
| 830 | else | |
| 831 | 			{
 | |
| 832 | RFile file; | |
| 833 | TBuf<256> fileName; | |
| 834 | 			fileName.Append((TChar)('A'+DriveNumber));
 | |
| 835 | 			fileName+=_L(":\\f32-tst\\");
 | |
| 836 | TInt r=TheFs.MkDirAll(fileName); | |
| 837 | test(r==KErrNone || r== KErrAlreadyExists); | |
| 838 | 			fileName += _L("annoyingflies.txt");
 | |
| 839 | r=file.Replace(TheFs,fileName,EFileWrite); | |
| 840 | if (r!=KErrNone) | |
| 841 | 				test.Printf(_L("Error %d: file '%S' could not be created\n"),r,&fileName);
 | |
| 842 | test(r==KErrNone); | |
| 843 | 			r=file.Write(_L8("Flies as big as sparrows indoletly buzzing in the warm air, heavy with the stench of rotting carcasses"));
 | |
| 844 | if (r!=KErrNone) | |
| 845 | 				test.Printf(_L("Error %d: could not write to file\n"),r);
 | |
| 846 | test(r==KErrNone); | |
| 847 | ||
| 848 | test(file.Flush() == KErrNone); | |
| 849 | ||
| 850 | SBlockMapInfo info; | |
| 851 | TInt64 start=0; | |
| 852 | r=file.BlockMap(info,start, -1,ETestDebug); | |
| 853 | if (r!=KErrNone && r!=KErrCompletion) | |
| 854 | 				test.Printf(_L("Error %d: could not obtain block map\n"),r);
 | |
| 855 | test(r==KErrNone || r==KErrCompletion); | |
| 856 | locDriveNumber=info.iLocalDriveNumber; | |
| 857 | 			test.Printf(_L("Found drive: %c (NAND drive %d)\r\n"), DriveNumber+'A',locDriveNumber);
 | |
| 858 | file.Close(); | |
| 859 | ||
| 860 | // Connect to device driver | |
| 861 | TBool changeFlag = EFalse; | |
| 862 | r = Drive.Connect(locDriveNumber,changeFlag); | |
| 863 | TPckg<TLocalDriveCapsV4> capsPack(DriveCaps); | |
| 864 | Drive.Caps(capsPack); | |
| 865 | test(r == KErrNone); | |
| 866 | ||
| 867 | r = Drive.ControlIO(KNandCollectGarbage,NULL,NULL); | |
| 868 | if (r!=KErrNone) | |
| 869 | 				{
 | |
| 870 | 				test.Printf(_L("LocalDrive does not support the KNandCollectGarbage ControlIO request\n"));
 | |
| 871 | CtrlIoCollectGarbageSupported = EFalse; | |
| 872 | } | |
| 873 | ||
| 874 | SDeferStats stats; | |
| 875 | TPtr8 statsBuf((TUint8*) &stats, sizeof(stats)); | |
| 876 | r = Drive.ControlIO(KNandGetDeferStats,statsBuf,0); | |
| 877 | if (r == KErrNone) | |
| 878 | 				{
 | |
| 879 | if (stats.iSynchronousMediaDriver) | |
| 880 | 					{
 | |
| 881 | 					test.Printf(_L("Media drive is synchronous - test skipped!\r\n"));
 | |
| 882 | test.End(); | |
| 883 | return 0; | |
| 884 | } | |
| 885 | } | |
| 886 | else | |
| 887 | 				{
 | |
| 888 | 				test.Printf(_L("LocalDrive does not support the KNandGetDeferStats ControlIO request\n"));
 | |
| 889 | CtrlIoGetDeferStatsSupported = EFalse; | |
| 890 | } | |
| 891 | ||
| 892 | ||
| 893 | 			test.Printf(_L("LocalDrive Connected\n"));
 | |
| 894 | // | |
| 895 | // Run tests | |
| 896 | // | |
| 897 | TestNandAccuratcy(); | |
| 898 | if(CtrlIoCollectGarbageSupported && CtrlIoGetDeferStatsSupported) | |
| 899 | TestDefered(); | |
| 900 | // | |
| 901 | // Free device and end test program | |
| 902 | // | |
| 903 | Drive.Disconnect(); | |
| 904 | } | |
| 905 | } | |
| 906 | ||
| 907 | test.End(); | |
| 908 | return 0; | |
| 909 | } | |
| 910 | ||
| 911 |