Update contrib.
1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // Tests erasing of Flash while forcing suspend-resume cycles
19 #include <e32std_private.h>
22 #include "user_config.h"
24 RTest test( _L("TF_SUSPEND") );
42 inline void WaitForDone()
45 iWaitingSignal.Signal(); // resignal, ready for next Start()
48 void EraseBlock( TUint32 aOffset, TUint aLength );
51 void Panic( TInt aPanicNum );
52 void Start( TFunction aFunction );
54 static TInt EraserThread( TAny* aParam );
62 // Shared between main & eraser thread
64 TFunction iRequestedFunction;
66 RSemaphore iWaitingSignal;
70 // These are local to the eraser thread
74 TBusLocalDrive iDrive;
81 iThread.Terminate( KErrNone );
84 iWaitingSignal.Close();
87 void CEraser::Panic( TInt aPanicNum )
89 _LIT( KPanicCat, "ERASE-T" );
90 User::Panic( KPanicCat, aPanicNum );
91 RProcess().Panic( KPanicCat, aPanicNum );
95 void CEraser::CreateL()
97 // Create new thread and wait for it to become ready
100 iGoSignal.CreateLocal( 0 ); // initially blocked
101 iWaitingSignal.CreateLocal( 0 ); // initially blocked
103 User::LeaveIfError( iThread.Create( _L("ERASER"), EraserThread, 2048, 2048, 65536, this ) );
104 test.Printf( _L("Eraser thread created\n") );
108 test.Printf( _L("Waiting for thread to become ready\n") );
110 iWaitingSignal.Signal();
113 void CEraser::Start( TFunction aFunction )
115 // Start the suspender thread executing function aFunction
120 iRequestedFunction = aFunction;
132 void CEraser::WaitForReady()
134 iWaitingSignal.Wait();
137 void CEraser::EraseBlock( TUint32 aOffset, TUint aLength )
139 // Execute a block erase
144 Start( EEraseBlock );
148 TInt CEraser::EraserThread( TAny* aParam )
150 // The thread which executes suspend functions
153 RDebug::Print( _L("Eraser thread starts") );
155 CEraser& self = *reinterpret_cast<CEraser*>(aParam);
158 // Open our own TBusLogicalDevice channel
161 if( KErrNone != self.iDrive.Connect( KDriveNumber, changedFlag ) )
166 RDebug::Print( _L("Eraser thread connected to drive") );
171 // Signal that we are ready for a request
173 RDebug::Print( _L("Eraser thread waiting...") );
174 self.iWaitingSignal.Signal();
177 // Wait for a request
179 self.iGoSignal.Wait();
180 RDebug::Print( _L("Eraser thread go (%d)"), self.iRequestedFunction );
182 switch( self.iRequestedFunction )
194 self.iDrive.Disconnect();
198 void CEraser::DoEraseBlock()
203 RDebug::Print( _L("Eraser starting erase...") );
205 TInt64 offs( iOffset );
206 TInt r = iDrive.Format( offs, iLength );
210 RDebug::Print( _L("Eraser: FAIL: erase request returns %d"), r );
217 class CSuspendTest : public CBase
228 TInt EraseOneBlock( TInt aBlockNumber );
229 TInt ZeroFillBlock( TInt aBlockNumber );
230 TBool ValidateBlock( TInt aBlockNumber, TUint32 aFillWord );
231 TInt ZeroAllBlocks();
232 TBool ValidateAllBlocks( TUint32 aFillWord );
234 void DoImmediateSuspendTest();
237 TBusLocalDrive iDrive;
246 TBuf8<512> iReadBuffer;
250 CSuspendTest::~CSuspendTest()
262 void CSuspendTest::CreateL()
265 // Create the eraser thread
267 iEraser = new(ELeave) CEraser;
271 // Load the device drivers
274 #ifndef SKIP_PDD_LOAD
275 test.Printf( _L("Loading %S\n"), &KLfsDriverName );
276 r = User::LoadPhysicalDevice( KLfsDriverName );
277 test( KErrNone == r || KErrAlreadyExists == r );
282 test( KErrNone == fs.Connect() );
285 test( KErrNone == fs.SetDefaultPath( _L("Z:\\") ) );
288 fs.FileSystemName( name, KLffsLogicalDriveNumber );
289 if( name.Length() > 0 )
291 test.Printf( _L("Unmounting drive") );
292 test( KErrNone == fs.DismountFileSystem( _L("Lffs"), KLffsLogicalDriveNumber) );
293 User::After( 2000000 );
294 test.Printf( _L("Drive unmounted") );
300 // Open a TBusLogicalDevice to the driver
302 test.Printf( _L("Opening media channel\n") );
303 TBool changedFlag = EFalse;
304 r = iDrive.Connect( KDriveNumber, changedFlag );
305 User::LeaveIfError( r );
306 iDriveOpened = ETrue;
309 // Get size of Flash drive, block size, block count
311 TLocalDriveCapsV2Buf info;
313 iFlashSize = I64LOW(info().iSize);
314 iBlockSize = info().iEraseBlockSize;
315 iBlockCount = iFlashSize / iBlockSize;
317 test.Printf( _L("Flash size is 0x%x bytes\n"), iFlashSize );
318 test.Printf( _L("Block size is 0x%x bytes\n"), iBlockSize );
319 test.Printf( _L("Block count is %d\n"), iBlockCount );
321 test.Printf( _L("CreateL complete\n") );
325 void CSuspendTest::DoTest()
327 // Main test dispatcher
330 DoImmediateSuspendTest();
334 TInt CSuspendTest::EraseOneBlock( TInt aBlockNumber )
336 // Erases block aBlockNumber on Flash
339 TInt blockBaseOffset = aBlockNumber * iBlockSize;
341 test.Printf( _L("Erasing block %d (offs=0x%x)\n"), aBlockNumber, blockBaseOffset );
343 TInt r = iDrive.Format( blockBaseOffset, iBlockSize );
345 test.Printf( _L("... block erased, rv=%d\n"), r );
350 TBool CSuspendTest::ValidateBlock( TInt aBlockNumber, TUint32 aFillWord )
352 // Checks that every word in block aBlockNumber has the value aFillWord
355 TUint offset = aBlockNumber * iBlockSize;
356 test.Printf( _L("Validating block %d (offs=0x%x)\n"), aBlockNumber, offset );
358 TBool failed = EFalse;
359 const TInt readBufLen = iReadBuffer.MaxLength();
361 for( TInt len = iBlockSize; len > 0 && !failed ;)
363 TInt r = iDrive.Read( offset, readBufLen, iReadBuffer );
366 test.Printf( _L("... FAIL: read failed (%d) at offset 0x%x\n"), r, offset );
367 test( KErrNone == r );
369 test( iReadBuffer.Length() == readBufLen );
371 TUint32* p = (TUint32*)iReadBuffer.Ptr();
372 for( TInt i = 0; i < readBufLen; i += 4 )
374 if( aFillWord != *p )
377 test.Printf( _L("... FAILED: word @ offs=0x%x, read=0x%x, expected=0x%x\n"),
378 offset+i, p[0], aFillWord );
383 offset += readBufLen;
391 TInt CSuspendTest::ZeroFillBlock( TInt aBlockNumber )
393 // Zero-fills and entire block
394 // The requires that writing works
397 test.Printf( _L("Zero-filling block %d\n"), aBlockNumber );
400 // Create a buffer full of zeros
402 const TInt KZeroBufSize = 512;
404 TBuf8<KZeroBufSize> buf;
405 buf.FillZ( buf.MaxLength() );
408 // Write the data out to the Flash
410 TInt writeCount = iBlockSize / KZeroBufSize;
412 TInt blockBaseOffset = aBlockNumber * iBlockSize;
413 for( ; (writeCount > 0) && (KErrNone == r); writeCount-- )
415 r = iDrive.Write( blockBaseOffset, buf );
418 test.Printf( _L("... FAIL: write failed (%d) at offset 0x%x\n"), blockBaseOffset );
420 blockBaseOffset += KZeroBufSize;
427 TInt CSuspendTest::ZeroAllBlocks()
429 // Writes zeros to all blocks
432 test.Printf( _L("Zeroing all blocks\n") );
435 for( TInt i = 0; (i < iBlockCount) && (KErrNone == r); i++ )
437 r = ZeroFillBlock( i );
443 TBool CSuspendTest::ValidateAllBlocks( TUint32 aFillWord )
445 // Checks that all blocks contain aFillWord
448 test.Printf( _L("Validating all blocks\n") );
450 TBool failed = EFalse;
451 for( TInt i = 0; (i < iBlockCount) && (!failed); i++ )
453 failed = !ValidateBlock( i, aFillWord );
460 void CSuspendTest::DoImmediateSuspendTest()
462 // For each block issues an erase and then immediately
463 // requests a read on another block. Waits for erase to
464 // finish and validates it
467 test.Next( _L("Immediate suspend test") );
468 test( KErrNone == ZeroAllBlocks() );
469 test( ValidateAllBlocks( 0 ) );
472 // We repeat the test for each block, erasing block n and reading from
473 // block (n+1) modulo iBlockCount
475 for( TInt eraseBlock = 0; eraseBlock < iBlockCount; eraseBlock++ )
477 TUint32 readBlock = (eraseBlock + 1) % iBlockCount;
478 TUint32 erasePos = eraseBlock * iBlockSize;
479 TInt readPos = readBlock * iBlockSize;
486 iEraser->EraseBlock( erasePos, iBlockSize );
489 // Do a read immediately
491 test.Printf( _L("main thread requesting read") );
492 test( KErrNone == iDrive.Read( readPos, buf.MaxLength(), buf ) );
495 // Wait for erase to finish
497 test.Printf( _L("main thread waiting for erase to finish...") );
498 iEraser->WaitForDone();
501 // Now check that the block was erased
503 test( ValidateBlock( eraseBlock, 0xFFFFFFFF ) );
515 test.Start(_L("Testing media erase+suspend operations"));
517 CSuspendTest suspendTest;
518 TRAPD( ret, suspendTest.CreateL() );
519 if( KErrNone == ret )
521 suspendTest.DoTest();