sl@0: // Copyright (c) 1997-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_pccdsk.cpp sl@0: // Soak test the Compact Flash card (ATA). sl@0: // sl@0: // sl@0: sl@0: sl@0: // One of these sl@0: #define USE_MEDIA_CHANGE sl@0: //#define USE_POWER_OFF_ON sl@0: sl@0: #include <e32test.h> sl@0: #include <e32svr.h> sl@0: #include <e32hal.h> sl@0: #include <e32uid.h> sl@0: #include <hal.h> sl@0: sl@0: #define ATA_PDD_NAME _L("MEDATA") sl@0: sl@0: const TInt KAtaSectorSize=512; sl@0: const TInt KMaxSectors=16; sl@0: const TInt KMaxRdWrBufLen=(KAtaSectorSize*KMaxSectors); // 8K sl@0: const TInt KMaxErrPos=5; sl@0: sl@0: LOCAL_D TBusLocalDrive TheDrive; sl@0: LOCAL_D TBool ChangedFlag; sl@0: RTest test(_L("Local Drive Soak Test")); sl@0: LOCAL_D TBuf8<KMaxRdWrBufLen> wrBuf1,wrBuf2,rdBuf; sl@0: sl@0: class TResult sl@0: { sl@0: public: sl@0: enum TResTest {EWrite,ERead,ECompare,EFormat,EReMount}; sl@0: TResult(); sl@0: void Display(CConsoleBase *aConsole, TInt aCycles); sl@0: void Add(TResTest aTst,TInt anErr,TInt anErrPos); sl@0: inline void SetMemStillFree(TInt aVal) sl@0: {iFreeMem=aVal;} sl@0: inline void WriteAborted() sl@0: {iAbortedWrites++;} sl@0: inline TInt WriteFails() sl@0: {return(iWriteTimeoutFails+iWriteWriteFails+iWriteGeneralFails+iWriteCorruptFails+iWriteBatLowFails+iWriteOtherFails);} sl@0: inline TInt ReadFails() sl@0: {return(iReadTimeoutFails+iReadCorruptFails+iReadOtherFails);} sl@0: inline TInt CompareFails() sl@0: {return(iCompareFails);} sl@0: inline TInt FormatFails() sl@0: {return(iFormatTimeoutFails+iFormatEmergencyFails+iFormatBatLowFails+iFormatOtherFails);} sl@0: inline TInt ReMountFails() sl@0: {return(iReMountFails);} sl@0: public: sl@0: TInt iWriteTimeoutFails; sl@0: TInt iWriteWriteFails; sl@0: TInt iWriteGeneralFails; sl@0: TInt iWriteCorruptFails; sl@0: TInt iWriteBatLowFails; sl@0: TInt iWriteOtherFails; sl@0: TInt iReadTimeoutFails; sl@0: TInt iReadCorruptFails; sl@0: TInt iReadOtherFails; sl@0: TInt iCompareFails; sl@0: TInt iFormatTimeoutFails; sl@0: TInt iFormatEmergencyFails; sl@0: TInt iFormatBatLowFails; sl@0: TInt iFormatOtherFails; sl@0: TInt iReMountFails; sl@0: TInt iLastErrorPos[KMaxErrPos]; sl@0: TInt iLastErrorPtr; sl@0: TInt iFreeMem; sl@0: TInt iAbortedWrites; sl@0: }; sl@0: sl@0: sl@0: LOCAL_C void StatusBar(TInt aPos,TInt anEndPos,TInt aYPos,const TPtrC &aTitle) sl@0: // sl@0: // Display progress of local drive operation on screen (1-16 dots) sl@0: // sl@0: { sl@0: static TInt prev; sl@0: TInt curr; sl@0: if ((curr=(aPos-1)/(anEndPos>>4))>prev) sl@0: { // Update progress bar sl@0: test.Console()->SetPos(0,aYPos); sl@0: test.Printf(_L(" ")); sl@0: test.Console()->SetPos(2); sl@0: test.Printf(_L("%S "),&aTitle); sl@0: for (TInt i=curr;i>=0;i--) sl@0: test.Printf(_L(".")); sl@0: } sl@0: prev=curr; sl@0: } sl@0: sl@0: TResult::TResult() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: sl@0: iWriteTimeoutFails=0; sl@0: iWriteWriteFails=0; sl@0: iWriteGeneralFails=0; sl@0: iWriteCorruptFails=0; sl@0: iWriteBatLowFails=0; sl@0: iWriteOtherFails=0; sl@0: iReadTimeoutFails=0; sl@0: iReadCorruptFails=0; sl@0: iReadOtherFails=0; sl@0: iCompareFails=0; sl@0: iFormatTimeoutFails=0; sl@0: iFormatEmergencyFails=0; sl@0: iFormatBatLowFails=0; sl@0: iFormatOtherFails=0; sl@0: iReMountFails=0; sl@0: for (TInt i=0;i<KMaxErrPos;i++) sl@0: iLastErrorPos[i]=0; sl@0: iLastErrorPtr=0; sl@0: iFreeMem=0; sl@0: iAbortedWrites=0; sl@0: } sl@0: sl@0: void TResult::Display(CConsoleBase *aConsole, TInt aCycles) sl@0: // sl@0: // Display test results sl@0: // sl@0: { sl@0: sl@0: TInt xStartPos=3; sl@0: TInt yStartPos=8; sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos); sl@0: test.Printf(_L("Cycles(%08xH) : %d"),iFreeMem,aCycles); sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos+1); sl@0: if (WriteFails()) sl@0: test.Printf(_L("Write Fails : %d (TO:%d BT:%d WR:%d GE:%d CU:%d OT:%d)"),WriteFails(),iWriteTimeoutFails,\ sl@0: iWriteBatLowFails,iWriteWriteFails,iWriteGeneralFails,iWriteCorruptFails,iWriteOtherFails); sl@0: else sl@0: test.Printf(_L("Write Fails : 0")); sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos+2); sl@0: if (ReadFails()) sl@0: test.Printf(_L("Read Fails : %d (TO:%d CU:%d OT:%d)"),ReadFails(),iReadTimeoutFails,iReadCorruptFails,iReadOtherFails); sl@0: else sl@0: test.Printf(_L("Read Fails : 0")); sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos+3); sl@0: test.Printf(_L("Compare Fails : %d"),CompareFails()); sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos+4); sl@0: if (FormatFails()) sl@0: test.Printf(_L("Format Fails : %d (TO:%d EM:%d BT:%d OT:%d)"),FormatFails(),iFormatTimeoutFails,iFormatEmergencyFails,iFormatBatLowFails,iFormatOtherFails); sl@0: else sl@0: test.Printf(_L("Format Fails : 0")); sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos+5); sl@0: #if defined (USE_MEDIA_CHANGE) sl@0: test.Printf(_L("MediaChange Fails : %d"),ReMountFails()); sl@0: #else sl@0: test.Printf(_L("Pwr off/on Fails : %d"),ReMountFails()); sl@0: #endif sl@0: sl@0: aConsole->SetPos(xStartPos,yStartPos+6); sl@0: test.Printf(_L("Last failures at : ")); sl@0: for (TInt i=iLastErrorPtr;i>0;i--) sl@0: test.Printf(_L("%xH "),iLastErrorPos[i-1]); sl@0: aConsole->SetPos(xStartPos,yStartPos+7); sl@0: test.Printf(_L("Writes aborted : %d"),iAbortedWrites); sl@0: test.Printf(_L("\r\n")); sl@0: } sl@0: sl@0: void TResult::Add(TResTest aTst,TInt anErr,TInt anErrPos) sl@0: // sl@0: // Add a test result sl@0: // sl@0: { sl@0: sl@0: if (anErr!=KErrNone) sl@0: { sl@0: RDebug::Print(_L("%d) %d(%x)"),aTst,anErr,anErrPos); sl@0: // Save start sector involved in operation which failed sl@0: if (anErrPos>=0) sl@0: { sl@0: if (iLastErrorPtr>=KMaxErrPos) sl@0: { sl@0: TInt i; sl@0: for (i=0;i<(KMaxErrPos-1);i++) sl@0: iLastErrorPos[i]=iLastErrorPos[i+1]; sl@0: iLastErrorPos[i]=anErrPos; sl@0: } sl@0: else sl@0: { sl@0: iLastErrorPtr++; sl@0: iLastErrorPos[iLastErrorPtr-1]=anErrPos; sl@0: } sl@0: } sl@0: sl@0: // Save error type sl@0: switch (aTst) sl@0: { sl@0: case EWrite: sl@0: if (anErr==KErrTimedOut) sl@0: iWriteTimeoutFails++; sl@0: else if (anErr==KErrWrite) sl@0: iWriteWriteFails++; sl@0: else if (anErr==KErrGeneral) sl@0: iWriteGeneralFails++; sl@0: else if (anErr==KErrCorrupt) sl@0: iWriteCorruptFails++; sl@0: else if (anErr==KErrBadPower) sl@0: iWriteBatLowFails++; sl@0: else sl@0: iWriteOtherFails++; sl@0: break; sl@0: case ERead: sl@0: if (anErr==KErrTimedOut) sl@0: iReadTimeoutFails++; sl@0: else if (anErr==KErrCorrupt) sl@0: iReadCorruptFails++; sl@0: else sl@0: iReadOtherFails++; sl@0: break; sl@0: case ECompare: sl@0: iCompareFails++; sl@0: break; sl@0: case EFormat: sl@0: if (anErr==KErrTimedOut) sl@0: iFormatTimeoutFails++; sl@0: else if (anErr==KErrAbort) sl@0: iFormatEmergencyFails++; sl@0: else if (anErr==KErrBadPower) sl@0: iFormatBatLowFails++; sl@0: else sl@0: iFormatOtherFails++; sl@0: break; sl@0: case EReMount: sl@0: iReMountFails++; sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: LOCAL_C TUint GetTUintFromConsole(const TDesC &aText) sl@0: // sl@0: // Get a TUint value from the console sl@0: // sl@0: { sl@0: sl@0: TBuf<10> buf(0); sl@0: TKeyCode kc; sl@0: TUint pos=0; sl@0: test.Printf(aText); sl@0: TUint linePos=(aText.Length()+2); sl@0: test.Console()->SetPos(linePos); sl@0: FOREVER sl@0: { sl@0: switch((kc=test.Getch())) sl@0: { sl@0: case EKeyEscape: case EKeyEnter: sl@0: { sl@0: TLex lex(buf); sl@0: TUint v; sl@0: if (lex.Val(v,EDecimal)==KErrNone) sl@0: return(v); sl@0: return(0); sl@0: } sl@0: case EKeyBackspace: case EKeyDelete: sl@0: pos--; sl@0: buf.Delete(pos,1); sl@0: linePos--; sl@0: test.Console()->SetPos(linePos); sl@0: test.Printf(_L(" ")); sl@0: test.Console()->SetPos(linePos); sl@0: break; sl@0: default: sl@0: TChar ch=(TUint)kc; sl@0: if (ch.IsDigit() && pos<9) sl@0: { sl@0: buf.Append(ch); sl@0: pos++; sl@0: test.Printf(_L("%c"),(TUint)ch); sl@0: linePos++; sl@0: } sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: TBuf<64> b; sl@0: sl@0: test.Title(); sl@0: TDriveInfoV1Buf diBuf; sl@0: UserHal::DriveInfo(diBuf); sl@0: TDriveInfoV1 &di=diBuf(); sl@0: test.Printf(_L("Select Local Drive (C-%c): "),'C'+(di.iTotalSupportedDrives-1)); sl@0: TChar c; sl@0: TInt drv; sl@0: FOREVER sl@0: { sl@0: c=(TUint)test.Getch(); sl@0: c.UpperCase(); sl@0: drv=((TUint)c)-'C'; sl@0: if (drv>=0&&drv<di.iTotalSupportedDrives) sl@0: break; sl@0: } sl@0: test.Printf(_L("%c:\r\n"),'C'+drv); sl@0: sl@0: test.Printf(_L("Select Test Sequence (Sector 1-R,2-WR,3-WRF)/(SubSector 4-R,5-WR,6-WRF): ")); sl@0: TInt testSeq; sl@0: FOREVER sl@0: { sl@0: c=(TUint)test.Getch(); sl@0: testSeq=((TUint)c)-'0'; sl@0: if (testSeq>=0&&testSeq<=6) sl@0: break; sl@0: } sl@0: test.Printf(_L("%d\r\n"),testSeq); sl@0: sl@0: TInt RdWrLen=(TInt)GetTUintFromConsole(_L("Select Buffer Size In Sectors: ")); sl@0: RdWrLen*=KAtaSectorSize; sl@0: sl@0: test.Start(_L("Load Ata Media Driver")); sl@0: TInt r; sl@0: r=User::LoadPhysicalDevice(ATA_PDD_NAME); sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: #if defined (USE_POWER_OFF_ON) sl@0: RTimer timer; sl@0: test(timer.CreateLocal()==KErrNone); sl@0: TRequestStatus prs; sl@0: TTime tim; sl@0: #endif sl@0: TInt muid=0; sl@0: r=HAL::Get(HAL::EMachineUid, muid); sl@0: test(r==KErrNone); sl@0: TBool reMountTestSupported=ETrue; sl@0: // if (machineName.MatchF(_L("SNOWBALL*"))>=0) // snowball is ancient history sl@0: // reMountTestSupported=EFalse; sl@0: sl@0: b.Format(_L("Connect to drive %c:"),'C'+drv); sl@0: test.Next(b); sl@0: ChangedFlag=EFalse; sl@0: TheDrive.Connect(drv,ChangedFlag); sl@0: sl@0: test.Next(_L("ATA drive: Capabilities")); sl@0: TLocalDriveCapsV2Buf info; sl@0: test(TheDrive.Caps(info)==KErrNone); sl@0: test(info().iType==EMediaHardDisk); sl@0: TInt diskSize=I64LOW(info().iSize); sl@0: sl@0: wrBuf1.SetLength(RdWrLen); sl@0: TInt j; sl@0: for (j=0;j<RdWrLen;j++) sl@0: wrBuf1[j]=(TUint8)j; sl@0: wrBuf2.SetLength(RdWrLen); sl@0: for (j=0;j<RdWrLen;j++) sl@0: wrBuf2[j]=(TUint8)((RdWrLen-1)-j); sl@0: sl@0: TUint *p; sl@0: TDes8* wrBuf; sl@0: TInt cycles=0; sl@0: TResult results; sl@0: TBool decendPat=EFalse; sl@0: sl@0: TRequestStatus kStat; sl@0: test.Console()->Read(kStat); sl@0: FOREVER sl@0: { sl@0: wrBuf=(decendPat)?&wrBuf2:&wrBuf1; sl@0: p=(decendPat)?(TUint*)&wrBuf2[0]:(TUint*)&wrBuf1[0]; sl@0: TInt i,j,len,res; sl@0: sl@0: // Recalculate amount of free memory sl@0: TMemoryInfoV1Buf membuf; sl@0: UserHal::MemoryInfo(membuf); sl@0: TMemoryInfoV1 &memoryInfo=membuf(); sl@0: results.SetMemStillFree(memoryInfo.iFreeRamInBytes); sl@0: results.Display(test.Console(),cycles); sl@0: sl@0: // Write test sl@0: RDebug::Print(_L("0")); sl@0: if (testSeq==2||testSeq==3||testSeq==5||testSeq==6) sl@0: { sl@0: for (i=0,j=0;i<diskSize;i+=len,j++) sl@0: { sl@0: StatusBar(i,diskSize,16,_L("WRITING ")); sl@0: if (testSeq>3) sl@0: len=Min(RdWrLen-3,(diskSize-i)); // Not on sector boundary sl@0: else sl@0: len=Min(RdWrLen,(diskSize-i)); sl@0: (*p)=j; sl@0: wrBuf->SetLength(len); sl@0: do sl@0: { sl@0: res=TheDrive.Write(i,*wrBuf); sl@0: if (res==KErrAbort) sl@0: { sl@0: results.WriteAborted(); sl@0: results.Display(test.Console(),cycles); sl@0: } sl@0: } while (res==KErrNotReady||res==KErrAbort); sl@0: results.Add(TResult::EWrite,res,i); sl@0: if (res!=KErrNone) sl@0: break; sl@0: } sl@0: results.Display(test.Console(),cycles); sl@0: } sl@0: sl@0: // Read test sl@0: RDebug::Print(_L("1")); sl@0: if (testSeq>=1) sl@0: { sl@0: for (i=0,j=0;i<diskSize;i+=len,j++) sl@0: { sl@0: StatusBar(i,diskSize,16,_L("READING ")); sl@0: if (testSeq>3) sl@0: len=Min(RdWrLen-3,(diskSize-i)); // Not on sector boundary sl@0: else sl@0: len=Min(RdWrLen,(diskSize-i)); sl@0: rdBuf.Fill(0,len); sl@0: do sl@0: { sl@0: res=TheDrive.Read(i,len,rdBuf); sl@0: } while (res==KErrNotReady); sl@0: sl@0: results.Add(TResult::ERead,res,i); sl@0: if (res!=KErrNone) sl@0: break; sl@0: if (testSeq==2||testSeq==3||testSeq==5||testSeq==6) sl@0: { sl@0: (*p)=j; sl@0: wrBuf->SetLength(len); sl@0: if (rdBuf.Compare(*wrBuf)!=0) sl@0: { sl@0: results.Add(TResult::ECompare,KErrGeneral,-1); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: results.Display(test.Console(),cycles); sl@0: } sl@0: sl@0: // Format test sl@0: RDebug::Print(_L("3")); sl@0: if (testSeq==3||testSeq==6) sl@0: { sl@0: TFormatInfo fi; sl@0: FOREVER sl@0: { sl@0: StatusBar((fi.i512ByteSectorsFormatted<<9),diskSize,16,_L("FORMATTING")); sl@0: do sl@0: { sl@0: res=TheDrive.Format(fi); sl@0: } while (res==KErrNotReady); sl@0: if (res==KErrEof) sl@0: break; sl@0: results.Add(TResult::EFormat,res,(fi.i512ByteSectorsFormatted<<9)); sl@0: if (res!=KErrNone) sl@0: break; sl@0: } sl@0: results.Display(test.Console(),cycles); sl@0: } sl@0: sl@0: RDebug::Print(_L("4")); sl@0: if (reMountTestSupported) sl@0: { sl@0: // Media change test / power off-on test sl@0: #if defined (USE_MEDIA_CHANGE) sl@0: TheDrive.ForceMediaChange(); sl@0: if (ChangedFlag==EFalse) sl@0: results.Add(TResult::EReMount,KErrGeneral,-1); sl@0: #else sl@0: tim.HomeTime(); sl@0: tim+=TTimeIntervalSeconds(8); sl@0: timer.At(prs,tim); sl@0: UserHal::SwitchOff(); // Switch off sl@0: User::WaitForRequest(prs); // Switch back on sl@0: if (prs.Int()!=KErrNone) sl@0: results.Add(TResult::EReMount,KErrGeneral,-1); sl@0: #endif sl@0: else sl@0: { sl@0: do sl@0: { sl@0: res=TheDrive.Caps(info); sl@0: } while (res==KErrNotReady); sl@0: if (res==KErrNone) sl@0: { sl@0: if (info().iType!=EMediaHardDisk) sl@0: results.Add(TResult::EReMount,KErrGeneral,-1); sl@0: } sl@0: else sl@0: results.Add(TResult::EReMount,res,-1); sl@0: } sl@0: ChangedFlag=EFalse; sl@0: } sl@0: sl@0: cycles++; sl@0: decendPat^=0x01; sl@0: sl@0: if (kStat!=KRequestPending) sl@0: { sl@0: TKeyCode c=test.Console()->KeyCode(); sl@0: if (c==EKeySpace) sl@0: break; sl@0: test.Console()->Read(kStat); sl@0: } sl@0: RDebug::Print(_L("<<")); sl@0: } sl@0: sl@0: b.Format(_L("Disconnect from local drive (%c:)"),'C'+drv); sl@0: test.Next(b); sl@0: TheDrive.Disconnect(); sl@0: sl@0: test.End(); sl@0: return(0); sl@0: } sl@0: