sl@0: // Copyright (c) 2007-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: // e32test\pccd\t_nandbm.cpp sl@0: // Test read/write performance for NAND drives accessed directly sl@0: // through the Local Media Sub-System sl@0: // When no command parameter is supplied search for first sl@0: // writeable NAND drive that can be found sl@0: // If a drive number parameter in the range 0 - F is provided, sl@0: // interpret this as a local drive number in the range 0 - 15 sl@0: // and test the drive if it is a writeable NAND drive sl@0: // Please note that local drive numbers at the Local Media Sub-System sl@0: // level are not the same as drive numbers / drive letters at the sl@0: // File Server level. File Server drive numbers / drive letters fall sl@0: // in the range 0 - 25 / a - z. The mapping between local drive numbers sl@0: // and File Server drive numbers / drive letters is defined in sl@0: // estart.txt or its equivalent sl@0: // Use TBusLocalDrive directly and bypass the File Server sl@0: // Fill NAND user data drive with data prior to executing actual sl@0: // performance tests. TBusLocalDrive should read from areas that have sl@0: // been written to and are therefore assigned. Where areas are sl@0: // unassigned, XSR FTL returns FFs without accessing the NAND flash sl@0: // hardware. This type of behaviour generates misleadingly quick sl@0: // performance figures sl@0: // Test various block sizes in the range 16 - 65536 bytes sl@0: // sl@0: // sl@0: sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: LOCAL_D TBuf<1048576> DataBuf; sl@0: LOCAL_D TBusLocalDrive TheDrive; sl@0: LOCAL_D TBool ChangedFlag; sl@0: LOCAL_D RFs TheFs; sl@0: sl@0: RTest test(_L("Local NAND Drive BenchMark Test")); sl@0: sl@0: LOCAL_C void DoRead(TInt aReadBlockSize) sl@0: // sl@0: // Do Read benchmark sl@0: // sl@0: { sl@0: TInt msgHandle = KLocalMessageHandle; sl@0: TLocalDriveCapsV2 info; sl@0: TPckg infoPckg(info); sl@0: TInt maxSize; sl@0: TheDrive.Caps(infoPckg); sl@0: maxSize=I64LOW(info.iSize); sl@0: TInt count,pos,err; sl@0: count=pos=err=0; sl@0: sl@0: RTimer timer; sl@0: timer.CreateLocal(); sl@0: TRequestStatus reqStat; sl@0: timer.After(reqStat,10000000); // After 10 secs sl@0: while(reqStat==KRequestPending) sl@0: { sl@0: if (TheDrive.Read(pos,aReadBlockSize,&DataBuf,msgHandle,0)==KErrNone) sl@0: count++; sl@0: else sl@0: err++; sl@0: pos+=aReadBlockSize; sl@0: if (pos>=(maxSize-aReadBlockSize)) sl@0: pos=0; sl@0: } sl@0: #if defined (__WINS__) sl@0: test.Printf(_L("Read %d %d byte blocks in 10 secs\n"),count,aReadBlockSize); sl@0: #else sl@0: TBuf<60> buf; sl@0: TReal32 rate=((TReal32)(count*aReadBlockSize))/10240.0F; sl@0: TRealFormat rf(10,2); sl@0: buf.Format(_L("Read %d %d byte blocks in 10 secs ("),count,aReadBlockSize); sl@0: buf.AppendNum(rate,rf); sl@0: buf.Append(_L("Kb/s)\n")); sl@0: test.Printf(buf); sl@0: #endif sl@0: test.Printf(_L("Errors:%d\n"),err); sl@0: } sl@0: sl@0: LOCAL_C void DoWrite(TInt aWriteBlockSize) sl@0: // sl@0: // Do write benchmark sl@0: // sl@0: { sl@0: TInt msgHandle = KLocalMessageHandle; sl@0: TLocalDriveCapsV2 info; sl@0: TPckg infoPckg(info); sl@0: TInt maxSize; sl@0: TheDrive.Caps(infoPckg); sl@0: maxSize=I64LOW(info.iSize); sl@0: TInt count,pos,err; sl@0: count=pos=err=0; sl@0: sl@0: RTimer timer; sl@0: timer.CreateLocal(); sl@0: TRequestStatus reqStat; sl@0: timer.After(reqStat,10000000); // After 10 secs sl@0: while(reqStat==KRequestPending) sl@0: { sl@0: if (TheDrive.Write(pos,aWriteBlockSize,&DataBuf,msgHandle,0)==KErrNone) sl@0: count++; sl@0: else sl@0: err++; sl@0: pos+=aWriteBlockSize; sl@0: if (pos>=(maxSize-aWriteBlockSize)) sl@0: pos=0; sl@0: } sl@0: #if defined (__WINS__) sl@0: test.Printf(_L("Write %d %d byte blocks in 10 secs\n"),count,aWriteBlockSize); sl@0: #else sl@0: TBuf<60> buf; sl@0: TReal32 rate=((TReal32)(count*aWriteBlockSize))/10240.0F; sl@0: TRealFormat rf(10,2); sl@0: buf.Format(_L("Write %d %d byte blocks in 10 secs ("),count,aWriteBlockSize); sl@0: buf.AppendNum(rate,rf); sl@0: buf.Append(_L("Kb/s)\n")); sl@0: test.Printf(buf); sl@0: #endif sl@0: test.Printf(_L("Errors:%d\n"),err); sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: test.Title(); sl@0: sl@0: TBuf<0x100> cmd; sl@0: User::CommandLine(cmd); // put command line into decriptor sl@0: TLex lex(cmd); sl@0: TPtrC param=lex.NextToken(); // point token at local drive number if any sl@0: test.Printf(_L("Local Drive = %S\r\n"),¶m); sl@0: sl@0: TChar localDrv; sl@0: TInt localDrvNum; sl@0: TBusLocalDrive drive; sl@0: TBool changeFlag; sl@0: TLocalDriveCapsV4 driveCaps; sl@0: TPckg capsPckg(driveCaps); sl@0: TInt r; sl@0: sl@0: if (param.Length()==0) sl@0: { sl@0: // locate writeable NAND drive sl@0: for (localDrvNum=0; localDrvNum='0'&&localDrv<='9') sl@0: { sl@0: localDrvNum=((TInt)localDrv-'0'); sl@0: } sl@0: else if (localDrv>='A'&&localDrv<='F') sl@0: { sl@0: localDrvNum=((TInt)localDrv-'A'+10); sl@0: } sl@0: else sl@0: { sl@0: test.Printf(_L("Commandline %S invalid\r\n"), &cmd); sl@0: test.Printf(_L("Usage:\r\n")); sl@0: test.Printf(_L("t_nandbm with no arguments, test first suitable NAND drive \r\n")); sl@0: test.Printf(_L("t_nandbm x, where x = 0-F test local drive number 0-15\r\n")); sl@0: return(KErrGeneral); sl@0: } sl@0: // is selected drive suitable for test sl@0: r = drive.Connect(localDrvNum,changeFlag); sl@0: if(r!=KErrNone) sl@0: { sl@0: test.Printf(_L("Can't connect to drive %d\r\n"), localDrvNum); sl@0: return(KErrGeneral); sl@0: } sl@0: r = drive.Caps(capsPckg); sl@0: if(r!=KErrNone) sl@0: { sl@0: test.Printf(_L("Drive %d caps method error\r\n"), localDrvNum); sl@0: return(KErrGeneral); sl@0: } sl@0: drive.Disconnect(); sl@0: if ((driveCaps.iType!=EMediaNANDFlash) sl@0: ||(driveCaps.iMediaAtt&KMediaAttWriteProtected) sl@0: ||(driveCaps.iPartitionType==KPartitionTypeSymbianCrashLog)) sl@0: { sl@0: test.Printf(_L("Drive %d has unsuitable capabilities\r\n"), localDrvNum); sl@0: test.Printf(_L("Writeable NAND drive required for test\r\n")); sl@0: return(KErrGeneral); sl@0: } sl@0: sl@0: } sl@0: sl@0: // Fill the nand user data drive with data so TBusLocalDrive reads sl@0: // from areas that have been written to and are therefore assigned. sl@0: // Where areas are unassigned, XSR FTL returns FFs without accessing sl@0: // the NAND flash hardware. This type of behaviour generates misleadingly sl@0: // quick performance figures. sl@0: TInt writesize=1048576; sl@0: TInt pos = 0; sl@0: TInt msgHandle = KLocalMessageHandle; sl@0: sl@0: TheDrive.Connect(localDrvNum,ChangedFlag); sl@0: test.Printf( _L("Fill up NAND drive %d\r\n"),localDrvNum); sl@0: while(writesize>=1) sl@0: { sl@0: test.Printf( _L("%d byte write to pos %d of NAND drive\r\n"),writesize,pos); sl@0: if (TheDrive.Write(pos,writesize,&DataBuf,msgHandle,0)!=KErrNone) sl@0: { sl@0: writesize/=16; sl@0: } sl@0: else sl@0: { sl@0: pos += writesize; sl@0: } sl@0: } sl@0: sl@0: test.Start(_L("Start Benchmarking ...")); sl@0: sl@0: DoRead(16); sl@0: DoRead(256); sl@0: DoRead(512); sl@0: DoRead(513); sl@0: DoRead(2048); sl@0: DoRead(4096); sl@0: DoRead(16384); sl@0: DoRead(32768); sl@0: DoRead(65536); sl@0: sl@0: DoWrite(16); sl@0: DoWrite(256); sl@0: DoWrite(512); sl@0: DoWrite(513); sl@0: DoWrite(2048); sl@0: DoWrite(4096); sl@0: DoWrite(16384); sl@0: DoWrite(32768); sl@0: DoWrite(65536); sl@0: sl@0: test.End(); sl@0: sl@0: TheFs.Close(); sl@0: sl@0: return(KErrNone); sl@0: } sl@0: