--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/f32test/bench/t_trimbm.cpp Mon Oct 11 19:11:06 2010 +0100
@@ -0,0 +1,875 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// f32test/bench/t_fsysbm.cpp
+//
+//
+
+#define __E32TEST_EXTENSION__
+
+#include <f32file.h>
+#include <e32test.h>
+#include <e32hal.h>
+#include <hal.h>
+#include <e32math.h>
+#include <e32ldr.h>
+#include <e32ldr_private.h>
+#include "t_server.h"
+#include "../../e32test/mmu/d_sharedchunk.h"
+#include "../../e32utils/pccd/d_mmcif.h"
+
+#define SYMBIAN_TEST_EXTENDED_BUFFER_SIZES // test using a greater number of buffer sizes
+
+RTest test(_L("eMMC 4.4 TRIM Benchmark"));
+
+static const TUint K1K = 1024; // 1K
+static const TUint K1M = K1K * K1K ; // 1M
+static const TUint K2M = 2 * K1M; // 2M
+
+
+#if defined(__WINS__)
+static TInt KMaxFileSize = 256 * K1K; // 256K
+#else
+static TInt KMaxFileSize = K2M; // 2M
+#endif
+
+const TTimeIntervalMicroSeconds32 KFloatingPointTestTime = 10000000; // 10 seconds
+
+static TPtr8 DataBuf(NULL, KMaxFileSize,KMaxFileSize);
+
+static RSharedChunkLdd Ldd;
+static RChunk TheChunk;
+
+GLDEF_D RFs TheFs;
+GLDEF_D TFileName gSessionPath;
+GLDEF_D TChar gDriveToTest;
+
+static RMmcCntrlIf iDriver;
+static TInt iStack = 0;
+static TInt iCard = 0;
+static TBool iDriverOpen = EFalse;
+
+enum TPanic {ECreatingConsole,ELoaderCheck,ELoadingMmcDriver,EStartingMmcDriver};
+
+LOCAL_C void Panic(TPanic aPanic)
+//
+// Panic
+//
+ {
+ User::Panic(_L("MMCTEST"),aPanic);
+ }
+
+
+static RFile File;
+
+static TInt gFastCounterFreq;
+
+const TUint KMMCExtendedCSDLength=512;
+class TExtendedCSD
+ {
+public:
+ enum TExtCSDAccessBits {ECmdSet, ESetBits, EClearBits, EWriteByte};
+ enum TExtCSDModesFieldIndex
+ {
+ ECmdSetIndex = 191,
+ ECmdSetRevIndex = 189,
+ EPowerClassIndex = 187,
+ EHighSpeedInterfaceTimingIndex = 185,
+ EBusWidthModeIndex = 183
+ };
+ enum TExtCSDBusWidths
+ {
+ EExtCsdBusWidth1 = 0x00,
+ EExtCsdBusWidth4 = 0x01,
+ EExtCsdBusWidth8 = 0x02
+ };
+ enum TCardTypes
+ {
+ EHighSpeedCard26Mhz = 0x01,
+ EHighSpeedCard52Mhz = 0x02
+ };
+public:
+ inline TExtendedCSD(); // Default constructor
+ inline TExtendedCSD(const TUint8*);
+ inline TExtendedCSD& operator=(const TExtendedCSD&);
+ inline TExtendedCSD& operator=(const TUint8*);
+ inline TUint8 At(TUint anIndex) const; // Byte from CSD at anIndex
+public:
+ inline TUint SupportedCmdSet() const;
+ inline TUint MinPerfWrite8Bit52Mhz() const;
+ inline TUint MinPerfRead8Bit52Mhz() const;
+ inline TUint MinPerfWrite8Bit26Mhz_4Bit52Mhz() const;
+ inline TUint MinPerfRead8Bit26Mhz_4Bit52Mhz() const;
+ inline TUint MinPerfWrite4Bit26Mhz() const;
+ inline TUint MinPerfRead4Bit26Mhz() const;
+ inline TUint PowerClass26Mhz360V() const;
+ inline TUint PowerClass52Mhz360V() const;
+ inline TUint PowerClass26Mhz195V() const;
+ inline TUint PowerClass52Mhz195V() const;
+ inline TUint CardType() const;
+ inline TUint CSDStructureVer() const;
+ inline TUint ExtendedCSDRev() const;
+ inline TUint CmdSet() const;
+ inline TUint CmdSetRev() const;
+ inline TUint PowerClass() const;
+ inline TUint HighSpeedTiming() const;
+ inline TUint BusWidth() const;
+
+ inline TUint TrimMultiplier() const;
+ inline TUint SecureFeatureSupport() const;
+ inline TUint SecureEraseMultiplier() const;
+ inline TUint SecureTrimMultiplier() const;
+
+private:
+ /**< @internalComponent little endian 512 byte field representing extended CSD */
+ TUint8 iData[KMMCExtendedCSDLength];
+ };
+
+inline TExtendedCSD::TExtendedCSD() // Default constructor
+ {}
+inline TExtendedCSD::TExtendedCSD(const TUint8* aPtr)
+ {memcpy(&iData[0], aPtr, KMMCExtendedCSDLength);}
+inline TExtendedCSD& TExtendedCSD::operator=(const TExtendedCSD& aCSD)
+ {memcpy(&iData[0], &aCSD.iData[0], KMMCExtendedCSDLength); return(*this);}
+inline TExtendedCSD& TExtendedCSD::operator=(const TUint8* aPtr)
+ {memcpy(&iData[0], aPtr, KMMCExtendedCSDLength); return(*this);}
+// field accessors.
+// "Properties Segment" of Extended CSD - i.e. read-only fields
+inline TUint TExtendedCSD::SupportedCmdSet() const {return iData[504];}
+inline TUint TExtendedCSD::MinPerfWrite8Bit52Mhz() const {return iData[210];}
+inline TUint TExtendedCSD::MinPerfRead8Bit52Mhz() const {return iData[209];}
+inline TUint TExtendedCSD::MinPerfWrite8Bit26Mhz_4Bit52Mhz() const {return iData[208];}
+inline TUint TExtendedCSD::MinPerfRead8Bit26Mhz_4Bit52Mhz() const {return iData[207];}
+inline TUint TExtendedCSD::MinPerfWrite4Bit26Mhz() const {return iData[206];}
+inline TUint TExtendedCSD::MinPerfRead4Bit26Mhz() const {return iData[205];}
+inline TUint TExtendedCSD::PowerClass26Mhz360V() const {return iData[203];}
+inline TUint TExtendedCSD::PowerClass52Mhz360V() const {return iData[202];}
+inline TUint TExtendedCSD::PowerClass26Mhz195V() const {return iData[201];}
+inline TUint TExtendedCSD::PowerClass52Mhz195V() const {return iData[200];}
+inline TUint TExtendedCSD::CardType() const {return iData[196];}
+inline TUint TExtendedCSD::CSDStructureVer() const {return iData[194];}
+inline TUint TExtendedCSD::ExtendedCSDRev() const {return iData[192];}
+
+inline TUint TExtendedCSD::TrimMultiplier() const {return iData[232]; }
+inline TUint TExtendedCSD::SecureFeatureSupport() const {return iData[231]; }
+inline TUint TExtendedCSD::SecureEraseMultiplier() const {return iData[230]; }
+inline TUint TExtendedCSD::SecureTrimMultiplier() const {return iData[229]; }
+
+
+// "Modes Segment" of Extended CSD - i.e. modifiable fields
+inline TUint TExtendedCSD::CmdSet() const {return iData[191];}
+inline TUint TExtendedCSD::CmdSetRev() const {return iData[189];}
+inline TUint TExtendedCSD::PowerClass() const {return iData[187];}
+inline TUint TExtendedCSD::HighSpeedTiming() const {return iData[185];}
+typedef TPckg<TExtendedCSD> TExtendedCSDPckg;
+
+static TExtendedCSD extCSD;
+
+GLDEF_C TInt CurrentDrive()
+//
+// Return the current drive number
+//
+ {
+
+ TInt driveNum;
+ TInt r=TheFs.CharToDrive(gSessionPath[0],driveNum);
+ test_KErrNone(r);
+ return(driveNum);
+ }
+
+GLDEF_C void Format(TInt aDrive)
+//
+// Format current drive
+//
+ {
+
+ TUint initTicks = User::FastCounter();
+ TUint finalTicks = 0;
+
+ TBuf<4> driveBuf=_L("?:\\");
+ driveBuf[0]=(TText)(aDrive+'A');
+ RFormat format;
+ TInt count;
+
+ TInt r=format.Open(TheFs,driveBuf, EFullFormat,count); // EQuickFormat
+ test_KErrNone(r);
+ while(count)
+ {
+ TInt r=format.Next(count);
+ test_KErrNone(r);
+ }
+ format.Close();
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to format %d ms)\n"), timeTakenInMs);
+ }
+
+
+
+static TInt getExtendedCSD()
+ {
+
+ if (!iDriverOpen)
+ return(KErrNotSupported);
+
+
+ // Power the stack down & up to make sure the CardInfo is up to date
+ iDriver.Reset();
+ User::After(1000);
+ iDriver.PwrDownStack();
+ User::After(1000);
+ TRequestStatus status;
+ iDriver.PwrUpAndInitStack(status);
+ User::WaitForRequest(status);
+ TInt err;
+ if ((err=status.Int())!=KErrNone)
+ {
+ test.Printf(_L("Error Powering Stack"),err);
+ return(err);
+ }
+ iDriver.SelectCard(iCard);
+
+ // Get the CSD first to check whether the ExtCSD is supported
+ TMmcCardInfo ci;
+ if ((err = iDriver.CardInfo(ci))!=KErrNone)
+ {
+ test.Printf(_L("Error getting card info"),err);
+ return(err);
+ }
+ //test.Printf(_L("CSD Spec version: %u\n"), ci.iSpecVers);
+
+ if (ci.iSpecVers < 4)
+ {
+ test.Printf(_L("Error: Extended CSD not supported\n"));
+ return KErrNotSupported;
+ }
+
+ TExtendedCSDPckg extCSDPckg(extCSD);
+
+ iDriver.ReadExtCSD(status, extCSDPckg);
+
+ User::WaitForRequest(status);
+
+ if (status.Int() != KErrNone)
+ {
+ test.Printf(_L("Error getting Extended CSD\n"));
+ return(KErrGeneral);
+ }
+ return err;
+ }
+
+
+static TUint GetSecEraseMultValue(void)
+ {
+ TUint retVal = 0;
+
+ getExtendedCSD();
+ retVal = extCSD.SecureEraseMultiplier();
+
+ return retVal;
+ }
+
+static TUint GetSecTrimMultValue(void)
+ {
+ TUint retVal = 0;
+
+ getExtendedCSD();
+ retVal = extCSD.SecureTrimMultiplier();
+
+ return retVal;
+ }
+
+static TUint GetTrimMultValue(void)
+ {
+ TUint retVal = 0;
+
+ getExtendedCSD();
+ retVal = extCSD.TrimMultiplier();
+
+ return retVal;
+ }
+
+static TInt64 DiskSize(TInt aDrive)
+//
+//
+//
+ {
+ TVolumeInfo v;
+ TInt r=TheFs.Volume(v,aDrive);
+ test_KErrNone(r);
+ return(v.iSize);
+ }
+
+static TInt CalcEntries(TInt64 aDiskSize, TUint& aEntrySize)
+ {
+
+ aEntrySize = KMaxFileSize;
+ TInt numFiles = (TInt)(aDiskSize / aEntrySize);
+
+ while ( numFiles > 1000 )
+ {
+ aEntrySize = aEntrySize << 2 ;
+ numFiles = (TUint)(aDiskSize / aEntrySize);
+ }
+ return numFiles;
+
+ }
+
+static void WriteFull(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ RFile f;
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+ TBuf8<8> WriteData =_L8("Wibbleuy");
+
+ r=TheFs.MkDirAll(gSessionPath);
+
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Create %d entries\n"),numFiles);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ initTicks = User::FastCounter();
+
+ for( TInt i = 0; i < numFiles; ++i)
+ {
+
+ test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName= gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ r=f.Replace(TheFs,baseName,EFileWrite);
+ test_KErrNone(r);
+ r = f.SetSize(entrySize);
+ if( r == KErrDiskFull)
+ {
+ numFiles = i;
+ break;
+ }
+ test_Value(r, r == KErrNone || r==KErrDiskFull);
+ r=f.Write((entrySize-30),WriteData);
+ test_KErrNone(r);
+ f.Flush();
+ f.Close();
+ }
+
+ test.Printf(_L("\nTRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ test.Printf(_L("Test all entries have been created successfully\n"));
+ TBuf8<8> ReadData;
+ TInt Size=0;
+ for (TInt j=0; j < numFiles; j++)
+ {
+
+ test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(j);
+
+ TInt r=f.Open(TheFs,baseName,EFileRead);
+ if (r!=KErrNone)
+ {
+ test_Value(r, r == KErrNotFound && j==numFiles);
+ return;
+ }
+ ReadData.FillZ();
+ r=f.Read((entrySize-30),ReadData);
+ test_KErrNone(r);
+ test(f.Size(Size)==KErrNone);
+ test(entrySize == (TUint)Size);
+ test(ReadData==WriteData);
+ f.Close();
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles );
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+static void ReWriteHalf(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ RFile f;
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+ TBuf8<8> WriteData =_L8("Wibbleuy");
+
+ r=TheFs.MkDirAll(gSessionPath);
+
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Create %d entries\n"),numFiles/2);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ initTicks = User::FastCounter();
+
+ for( TInt i = 0; i < numFiles; i += 2)
+ {
+
+ test.Printf(_L("Create FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName= gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ r=f.Replace(TheFs,baseName,EFileWrite);
+ test_KErrNone(r);
+ r = f.SetSize(entrySize);
+ if( r == KErrDiskFull)
+ {
+ numFiles = i;
+ break;
+ }
+ test_Value(r, r == KErrNone || r==KErrDiskFull);
+ r=f.Write((entrySize-30),WriteData);
+ test_KErrNone(r);
+ f.Flush();
+ f.Close();
+ }
+
+ test.Printf(_L("\nTRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ test.Printf(_L("Test all entries have been created successfully\n"));
+ TBuf8<8> ReadData;
+ TInt Size=0;
+ for (TInt j=0; j < numFiles; j += 2)
+ {
+
+ test.Printf(_L("Check FILE%d\t(%3d%%)\r"), j, (100*j/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(j);
+
+ TInt r=f.Open(TheFs,baseName,EFileRead);
+ if (r!=KErrNone)
+ {
+ test_Value(r, r == KErrNotFound && j==numFiles);
+ return;
+ }
+ ReadData.FillZ();
+ r=f.Read((entrySize-30),ReadData);
+ test_KErrNone(r);
+ test(f.Size(Size)==KErrNone);
+ test(entrySize == (TUint)Size);
+ test(ReadData==WriteData);
+ f.Close();
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to create %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2 );
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+
+
+static void DeleteAll(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Delete %d entries\n"),numFiles);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ initTicks = User::FastCounter();
+
+ for( TInt i = 2; i < numFiles; ++i)
+ {
+ test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ TInt r=TheFs.Delete(baseName);
+ test_Value(r, r == KErrNotFound || r == KErrNone);
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles, timeTakenInMs, timeTakenInMs/numFiles);
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+static void DeleteHalf(TInt aDrive)
+ {
+ TInt64 diskSize = DiskSize(aDrive);
+
+ TUint initTicks = 0;
+ TUint finalTicks = 0;
+
+ TFileName sessionPath;
+ TInt r=TheFs.SessionPath(sessionPath);
+ test_KErrNone(r);
+
+ TUint entrySize = KMaxFileSize;
+ TInt numFiles = CalcEntries(diskSize, entrySize);
+ test.Printf(_L("Disk size:%ld bytes, file size: %d bytes \n"), diskSize, entrySize) ;
+ test.Printf(_L("Delete %d entries\n"),numFiles/2);
+
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+
+ initTicks = User::FastCounter();
+
+ for( TInt i = 0; i < numFiles; i +=2)
+ {
+ test.Printf(_L("Delete FILE%d\t(%3d%%)\r"), i, (100*i/numFiles) );
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE"));
+ baseName.AppendNum(i);
+ TInt r=TheFs.Delete(baseName);
+ test_Value(r, r == KErrNotFound || r == KErrNone);
+ }
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to delete %d entries = %d ms (%d ms/entry)\n"), numFiles/2, timeTakenInMs, timeTakenInMs/numFiles/2);
+ test.Printf(_L("TRIM_MULT :%d\n"), GetTrimMultValue());
+ test.Printf(_L("SEC_TRIM_MULT :%d\n"), GetSecTrimMultValue());
+ test.Printf(_L("SEC_ERASE_MULT:%d\n"), GetSecEraseMultValue());
+ }
+
+
+static void WaitUntilTrimDone()
+ {
+
+ TUint initTicks = User::FastCounter();
+ TUint finalTicks = 0;
+
+#define READ_TO_KEEP_CARD_ON
+#ifdef READ_TO_KEEP_CARD_ON
+
+ const TInt readSize = 4096;
+ const TInt timeToRead = 30;
+
+ test.Printf(_L("Read a file for %d sec to keep card power on\n"), timeToRead );
+ TBuf8<4096> ReadData;
+
+ RTimer timer;
+ timer.CreateLocal();
+ TRequestStatus reqStat;
+
+ //test.Printf(_L("Timer started.\n"));
+
+ TFileName baseName = gSessionPath;
+ baseName.Append(_L("FILE1"));
+
+ RFile f;
+ TInt r=f.Open(TheFs,baseName,EFileRead);
+ if (r!=KErrNone)
+ {
+ return;
+ }
+ TInt alreadyRead = 0;
+ TInt fileSize;
+ test(f.Size(fileSize)==KErrNone);
+
+ //test.Printf(_L("File size:%d.\n"), fileSize);
+
+ timer.After(reqStat, timeToRead*1000000); // After 30 secs
+
+ while( reqStat==KRequestPending )
+ {
+
+ test.Printf(_L("Read pos:%d\r"), alreadyRead );
+ ReadData.FillZ();
+ r=f.Read(readSize,ReadData);
+
+ test_KErrNone(r);
+ alreadyRead += readSize;
+ if( alreadyRead == fileSize)
+ {
+ alreadyRead = 0;
+ f.Seek(ESeekStart, alreadyRead);
+ }
+ User::After(1000); // 1 ms
+ }
+
+ timer.Close();
+
+ f.Close();
+
+ test.Printf(_L("\n"));
+
+#else
+
+ TInt trimMult = GetTrimMultValue(); // Get TRIM_MULT value from eMMC Extended CSD
+ test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
+ while( trimMult-- > 0 )
+ {
+ // Wait for a while
+ User::After(300000); // TRIM Timeout = 300ms x TRIM_MULT
+ test.Printf(_L("TRIM_MULT:%d\r"), trimMult);
+ TInt trim = GetTrimMultValue();
+ }
+
+#endif
+
+ finalTicks = User::FastCounter();
+ TTimeIntervalMicroSeconds duration = TInt64(finalTicks - initTicks) * TInt64(1000000) / TInt64(gFastCounterFreq) ;
+
+ TInt timeTakenInMs = I64LOW(duration.Int64() / 1000);
+ test.Printf(_L("Time taken to TRIM done = %d ms\n"), timeTakenInMs);
+ }
+
+
+
+void doExit()
+ {
+ iDriver.Close();
+
+ User::FreeLogicalDevice(_L("MmcIf"));
+
+ test.End();
+ test.Close();
+
+ }
+
+GLDEF_C void CallTestsL(void)
+//
+// Call all tests
+//
+ {
+
+ test.Next(gSessionPath);
+
+ TInt err;
+ err=User::LoadLogicalDevice(_L("D_MMCIF"));
+ __ASSERT_ALWAYS((err==KErrNone||err==KErrAlreadyExists),Panic(ELoadingMmcDriver));
+ test.Printf(_L("MMCIF driver loaded\n"));
+
+
+ iDriver.Close();
+ TInt r=iDriver.Open(iStack,iDriver.VersionRequired());
+ iDriverOpen=(r==KErrNone)?(TBool)ETrue:(TBool)EFalse;
+ test.Printf(_L("iDriverOpen %d\n"), iDriverOpen);
+ if( !iDriverOpen )
+ {
+ doExit();
+ return;
+ }
+
+ test.Next(_L("Get extended CSD"));
+ r = getExtendedCSD();
+
+ if( r != KErrNone )
+ {
+ test.Next(_L("Extended CSD doesn't exists. Exit."));
+ doExit();
+ return;
+ }
+
+ if( extCSD.ExtendedCSDRev() < 5 )
+ {
+ test.Next(_L("TRIM feature doesn't exists. Exit!"));
+ }
+
+
+ r = HAL::Get(HAL::EFastCounterFrequency, gFastCounterFreq);
+ test_KErrNone(r);
+ test.Printf(_L("HAL::EFastCounterFrequency %d\n"), gFastCounterFreq);
+
+
+ TInt currentDrive = CurrentDrive();
+
+ // 1. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 2. Set TRIM off
+ //test.Next(_L("Set TRIM off"));
+
+
+ // 3. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 4. Delete all files and measure elapsed time
+ test.Next(_L("Delete all files"));
+ DeleteAll(currentDrive);
+
+ // 5. Rewrite all (or a set of) files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 6. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 7. Set TRIM on
+ //test.Next(_L("Set TRIM on"));
+
+ // 8. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 9. Delete all files and measure elapsed time
+ test.Next(_L("Delete all files"));
+ DeleteAll(currentDrive);
+
+ // 10. Wait for a while (give time to eMMC to do its TRIM job)
+ test.Next(_L("Wait for TRIM done"));
+ WaitUntilTrimDone();
+
+ // 11. Rewrite all (or same set of) files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 12. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 13. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 14. Delete half of files and measure elapsed time
+ test.Next(_L("Delete half of files"));
+ DeleteHalf(currentDrive);
+
+ // 15. Re-write half of files and measure elapsed time
+ test.Next(_L("Re-write half"));
+ ReWriteHalf(currentDrive);
+
+
+ // 16. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ // 17. Write full with files and measure elapsed time
+ test.Next(_L("Write full"));
+ WriteFull(currentDrive);
+
+ // 18. Delete half of files and measure elapsed time
+ test.Next(_L("Delete half of files"));
+ DeleteHalf(currentDrive);
+
+ // 19. Wait for a while (give time to eMMC to do its TRIM job)
+ test.Next(_L("Wait for TRIM done"));
+ WaitUntilTrimDone();
+
+ // 20. Re-write half of files and measure elapsed time
+ test.Next(_L("Re-write half"));
+ ReWriteHalf(currentDrive);
+
+ // 21. Format drive
+ test.Next(_L("Format drive"));
+ Format(currentDrive);
+
+ doExit();
+
+ return;
+ }
+
+GLDEF_C TInt E32Main()
+ {
+ TInt r=TheFs.Connect();
+ test_KErrNone(r);
+
+ test.Title();
+ test.Start(_L("Start Benchmarking ..."));
+
+ TInt theDrive;
+ gDriveToTest='E';
+ r=TheFs.CharToDrive(gDriveToTest,theDrive);
+ test_KErrNone(r);
+
+ gSessionPath=_L("?:\\TRIMTEST\\");
+ TChar driveLetter;
+ r=TheFs.DriveToChar(theDrive,driveLetter);
+ test_KErrNone(r);
+ gSessionPath[0]=(TText)driveLetter;
+ r=TheFs.SetSessionPath(gSessionPath);
+ test_KErrNone(r);
+
+ r=TheFs.MkDirAll(gSessionPath);
+ if(r == KErrCorrupt)
+ {
+ test.Printf(_L("Attempting to create directory \'%S\' failed, KErrCorrupt\n"), &gSessionPath);
+ test.Printf(_L("This could be caused by a previous failing test, or a test media defect\n"));
+ test.Printf(_L("Formatting drive, retrying MkDirall\nShould subsequent tests fail with KErrCorrupt (%d) as well, replace test medium !\n"),
+ r);
+ Format(theDrive);
+ r=TheFs.MkDirAll(gSessionPath);
+ test_KErrNone(r);
+ }
+ else if (r == KErrNotReady)
+ {
+ TDriveInfo d;
+ r=TheFs.Drive(d, theDrive);
+ test_KErrNone(r);
+ if (d.iType == EMediaNotPresent)
+ test.Printf(_L("%c: Medium not present - cannot perform test.\n"), (TUint)driveLetter);
+ else
+ test.Printf(_L("medium found (type %d) but drive %c: not ready\nPrevious test may have hung; else, check hardware.\n"), (TInt)d.iType, (TUint)driveLetter);
+ }
+ test_Value(r, r == KErrNone || r == KErrAlreadyExists);
+
+
+ CallTestsL();
+
+ TheFs.Close();
+
+ return(KErrNone);
+ }