diff -r 48e57fb1237e -r ddfd5aa0d58f kerneltest/f32test/bench/t_trimbm.cpp --- /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 +#include +#include +#include +#include +#include +#include +#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 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); + }