sl@0: // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // Performs some benchmarking of the LFFS media driver sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file bf_raw.cpp sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include "bf_raw.h" sl@0: #include "user_config.h" sl@0: sl@0: const TInt KAverageOverInSeconds=10; ///< Number of seconds to run tests for sl@0: sl@0: //TInt64 Count; ///< Global variable used to count number of operations completed sl@0: TUint32 Count; sl@0: sl@0: RTest test(_L("BF_RAW")); sl@0: sl@0: sl@0: TTestInfo TestInfo; ///< Data passed to exector thread sl@0: sl@0: TBusLocalDrive drive; sl@0: TLocalDriveCapsV2Buf driveInfo; sl@0: sl@0: GLDEF_D HBufC8* writeBuffer; ///< Buffer for transferring data sl@0: GLDEF_D HBufC8* readBuffer; ///< Buffer for transferring data sl@0: sl@0: GLDEF_D TBool StopTest; ///< set to ETrue to stop the test sl@0: sl@0: sl@0: GLREF_C TInt BmWrite(TAny*); sl@0: GLREF_C TInt BmWriteThread(TAny*); sl@0: GLREF_C TInt BmRead(TAny*); sl@0: GLREF_C TInt BmReadThread(TAny*); sl@0: sl@0: GLDEF_D TInt mainThreadHandle; sl@0: sl@0: TUint32 runTest(TThreadFunction aFunction) sl@0: /** sl@0: * Function which actually runs the test. sl@0: * sl@0: * It creates a new thread to exeute the operations and then waits sl@0: * for a pre-determined time. The executor thread increments a counter sl@0: * each time it completes one operation. After the time period expires sl@0: * the counter is averaged to get an "operations per second". This is sl@0: * then multiplied by the data size to obtain tranfer rate sl@0: */ sl@0: { sl@0: sl@0: RThread thread; sl@0: TInt r=thread.Create(_L("TESTER"),aFunction,KDefaultStackSize,&User::Heap(),NULL); sl@0: if(r!=KErrNone) sl@0: { sl@0: test.Printf(_L("Failed to create thread with error %d\n"),r); sl@0: return(r); sl@0: } sl@0: StopTest = EFalse; // allow the test to run sl@0: TRequestStatus deadStat; sl@0: thread.Logon( deadStat ); sl@0: sl@0: RThread().SetPriority( EPriorityMuchMore ); sl@0: sl@0: thread.Resume(); sl@0: User::After(1000000); sl@0: Count=0; sl@0: User::After(KAverageOverInSeconds*1000000); sl@0: TUint32 result=Count; sl@0: sl@0: // tell test to stop and wait for thread to exit. sl@0: StopTest = ETrue; sl@0: User::WaitForRequest( deadStat ); sl@0: sl@0: CLOSE_AND_WAIT(thread); sl@0: return(result); sl@0: } sl@0: sl@0: void PrintResult( TUint32 aCount, const TDesC& aTitle ) sl@0: /** sl@0: * Prints result of test sl@0: */ sl@0: { sl@0: TInt64 count(static_cast(aCount)); sl@0: TInt64 transferRate = (count * TestInfo.iLength) / KAverageOverInSeconds; sl@0: sl@0: test.Printf(_L("%S: %d bytes/second\n"), sl@0: &aTitle, sl@0: I64LOW(transferRate) ); sl@0: } sl@0: sl@0: sl@0: LOCAL_C TInt EraseSegment( TInt aSegmentNumber ) sl@0: /** sl@0: * Erases a segment on Flash sl@0: * sl@0: * @param aSegmentNumber index of segment to erase sl@0: * @return KErrNone or error code sl@0: */ sl@0: { sl@0: TInt offset = aSegmentNumber * driveInfo().iEraseBlockSize; sl@0: sl@0: TInt r = drive.Format( offset, driveInfo().iEraseBlockSize ); sl@0: return r; sl@0: } sl@0: sl@0: sl@0: /** sl@0: * Structure defining tests sl@0: */ sl@0: class TTestData sl@0: { sl@0: public: sl@0: TThreadFunction iFunction; ///< function to execute, NULL for end of list sl@0: TInt iLength; ///< data length sl@0: TInt iOffset; ///< Flash offset sl@0: const TDesC* iDescription; ///< descriptive text sl@0: }; sl@0: sl@0: sl@0: _LIT( KErasingSegment0, "Erasing segment 0" ); sl@0: sl@0: _LIT( KWrite1Start, "Write, 1 byte, 32-byte boundary, current thread" ); sl@0: _LIT( KWrite24Start, "Write, 24 bytes, 32-byte boundary, current thread" ); sl@0: _LIT( KWrite64Start, "Write, 64 bytes, 32-byte boundary, current thread" ); sl@0: _LIT( KWrite512Start, "Write, 512 bytes, 32-byte boundary, current thread" ); sl@0: sl@0: _LIT( KRead1Start, "Read, 1 byte, 32-byte boundary, current thread" ); sl@0: _LIT( KRead24Start, "Read, 24 bytes, 32-byte boundary, current thread" ); sl@0: _LIT( KRead64Start, "Read, 64 bytes, 32-byte boundary, current thread" ); sl@0: _LIT( KRead512Start, "Read, 512 bytes, 32-byte boundary, current thread" ); sl@0: sl@0: const TThreadFunction KEraseSegment = (TThreadFunction)0x000000F1; sl@0: sl@0: const TTestData testData[] = ///< the test data sl@0: { sl@0: { KEraseSegment, 0, 0, &KErasingSegment0 }, sl@0: sl@0: { BmWrite, 1, 0, &KWrite1Start }, sl@0: { BmWrite, 24, 32, &KWrite24Start }, sl@0: { BmWrite, 64, 64, &KWrite64Start }, sl@0: { BmWrite, 512, 128, &KWrite512Start }, sl@0: sl@0: { BmRead, 1, 0, &KRead1Start }, sl@0: { BmRead, 24, 0, &KRead24Start }, sl@0: { BmRead, 64, 0, &KRead64Start }, sl@0: { BmRead, 512, 0, &KRead512Start }, sl@0: sl@0: { NULL, 0, 0, NULL } sl@0: }; sl@0: sl@0: sl@0: sl@0: void Initialize() sl@0: /** sl@0: * Open channel to media driver sl@0: */ sl@0: { sl@0: // sl@0: // Load the media driver sl@0: // sl@0: #ifndef SKIP_PDD_LOAD sl@0: test.Printf( _L("Loading %S\n"), &KLfsDriverName ); sl@0: TInt r = User::LoadPhysicalDevice( KLfsDriverName ); sl@0: test( KErrNone == r || KErrAlreadyExists == r ); sl@0: #endif sl@0: sl@0: #ifdef UNMOUNT_DRIVE sl@0: RFs fs; sl@0: test( KErrNone == fs.Connect() ); sl@0: #if 0 sl@0: // XXX - not EKA2 sl@0: test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) ); sl@0: #endif sl@0: TFullName name; sl@0: fs.FileSystemName( name, KLffsLogicalDriveNumber ); sl@0: if( name.Length() > 0 ) sl@0: { sl@0: test.Printf( _L("Unmounting drive") ); sl@0: test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) ); sl@0: User::After( 2000000 ); sl@0: test.Printf( _L("Drive unmounted") ); sl@0: } sl@0: fs.Close(); sl@0: #endif sl@0: sl@0: // sl@0: // Open a TBusLogicalDevice to it sl@0: // sl@0: test.Printf( _L("Opening media channel\n") ); sl@0: TBool changedFlag = EFalse; sl@0: test( KErrNone == drive.Connect( KDriveNumber, changedFlag ) ); sl@0: sl@0: // sl@0: // Get size of Flash drive, block size, block count sl@0: // sl@0: drive.Caps(driveInfo); sl@0: sl@0: // sl@0: // Create data buffer sl@0: // sl@0: writeBuffer = HBufC8::New( 1024 ); sl@0: test( NULL != writeBuffer ); sl@0: writeBuffer->Des().FillZ(1024); sl@0: sl@0: readBuffer = HBufC8::New( 1024 ); sl@0: test( NULL != readBuffer ); sl@0: readBuffer->Des().FillZ(1024); sl@0: sl@0: mainThreadHandle = RThread().Handle(); sl@0: } sl@0: sl@0: sl@0: sl@0: TInt E32Main() sl@0: { sl@0: sl@0: test.Title(); sl@0: test.Start(_L("Benchmarks for media driver")); sl@0: sl@0: Initialize(); sl@0: sl@0: const TTestData* pTest = &testData[0]; sl@0: while( pTest->iFunction ) sl@0: { sl@0: if( KEraseSegment == pTest->iFunction ) sl@0: { sl@0: test.Printf( *pTest->iDescription ); sl@0: TInt r = EraseSegment( pTest->iOffset ); sl@0: test( KErrNone == r ); sl@0: test.Printf( _L("Segment erased") ); sl@0: } sl@0: else sl@0: { sl@0: TestInfo.iLength = pTest->iLength; sl@0: TestInfo.iOffset = pTest->iOffset; sl@0: PrintResult( runTest( pTest->iFunction ), *pTest->iDescription ); sl@0: } sl@0: ++pTest; sl@0: } sl@0: sl@0: drive.Disconnect(); sl@0: test.End(); sl@0: return(KErrNone); sl@0: } sl@0: