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: // e32test\pccd\t_mmcdrv.cpp sl@0: // Test the MultiMediaCard (MMC) media driver sl@0: // Spare Test case Numbers 0513-0519 sl@0: // sl@0: // sl@0: sl@0: #include "../mmu/d_sharedchunk.h" sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: const TInt KDiskSectorSize=512; sl@0: const TInt KDiskSectorShift=9; sl@0: const TUint KDiskSectorMask=0xFFFFFE00; sl@0: const TInt KSectBufSizeInSectors=8; sl@0: const TInt KSectBufSizeInBytes=(KSectBufSizeInSectors< than largest transfer sl@0: sl@0: const TInt KSingSectorNo=1; sl@0: const TInt64 KTwoGigbytes = 0x80000000; sl@0: sl@0: TBool mediaChangeSupported=EFalse; // ??? sl@0: TBool ManualMode=EFalse; sl@0: sl@0: // Wrappers for the test asserts sl@0: GLREF_C void TestIfError( TInt aValue, TInt aLine, const TText* aFile ); sl@0: GLREF_C void TestIfErrorMsg( TInt aValue, TInt aLine, const TText* aFile, const TDesC& aMessageOnError ); sl@0: GLREF_C void TestEqual( TInt aValue, TInt aExpected, TInt aLine, const TText* aFile ); sl@0: GLREF_C void TestEqualMsg( TInt aValue, TInt aExpected, TInt aLine, const TText* aFile, const TDesC& aMessageOnError ); sl@0: GLREF_C void TestEitherEqual( TInt aValue, TInt aExpected1, TInt aExpected2, TInt aLine, const TText* aFile ); sl@0: GLREF_C void TestRange( TInt aValue, TInt aMin, TInt Max, TInt aLine, const TText* aFile ); sl@0: sl@0: #define TEST_FOR_ERROR2( r, l, f ) TestIfError( r, l, _S(f) ) sl@0: #define TEST_FOR_ERROR_ERRMSG2( r, l, f, m ) TestIfErrorMsg( r, l, _S(f), m ) sl@0: #define TEST_FOR_VALUE2( r, e, l, f ) TestEqual( r, e, l, _S(f) ) sl@0: #define TEST_FOR_VALUE_ERRMSG2( r, e, l, f, m ) TestEqualMsg( r, e, l, _S(f), m ) sl@0: #define TEST_FOR_EITHER_VALUE2( r, e1, e2, l, f ) TestEitherEqual( r, e1, e2, l, _S(f) ) sl@0: #define TEST_FOR_RANGE2( r, min, max, l, f ) TestRange( r, min, max, l, _S(f) ) sl@0: sl@0: #define TEST_FOR_ERROR( r ) TEST_FOR_ERROR2( r, __LINE__, __FILE__ ) sl@0: #define TEST_FOR_ERROR_ERRMSG( r, m ) TEST_FOR_ERRORMSG2( r, __LINE__, __FILE__, m ) sl@0: #define TEST_FOR_VALUE( r, expected ) TEST_FOR_VALUE2( r, expected, __LINE__, __FILE__ ) sl@0: #define TEST_FOR_VALUE_ERRMSG( r, expected, m ) TEST_FOR_VALUE_ERRMSG2( r, expected, __LINE__, __FILE__, m ) sl@0: #define TEST_FOR_EITHER_VALUE( r, expected1, expected2 ) TEST_FOR_EITHER_VALUE2( r, expected1, expected2, __LINE__, __FILE__ ) sl@0: #define TEST_FOR_RANGE( r, min, max ) TEST_FOR_RANGE2( r, min, max, __LINE__, __FILE__ ) sl@0: sl@0: GLDEF_C void TestIfError( TInt aValue, TInt aLine, const TText* aFile ) sl@0: { sl@0: if( aValue < 0 ) sl@0: { sl@0: _LIT( KErrorTestFailMsg, "ERROR %d\n\r" ); sl@0: test.Printf( KErrorTestFailMsg, aValue ); sl@0: test.operator()( EFalse, aLine, (const TText*)(aFile) ); sl@0: } sl@0: } sl@0: sl@0: GLDEF_C void TestIfErrorMsg( TInt aValue, TInt aLine, const TText* aFile, const TDesC& aMessageOnError ) sl@0: { sl@0: if( aValue < 0 ) sl@0: { sl@0: _LIT( KErrorTestFailMsg, "ERROR %d %S\n\r" ); sl@0: test.Printf( KErrorTestFailMsg, aValue, &aMessageOnError ); sl@0: test.operator()( EFalse, aLine, (const TText*)(aFile) ); sl@0: } sl@0: } sl@0: sl@0: sl@0: GLDEF_C void TestEqual( TInt aValue, TInt aExpected, TInt aLine, const TText* aFile ) sl@0: { sl@0: if( aExpected != aValue ) sl@0: { sl@0: _LIT( KEqualTestFailMsg, "ERROR %d expected %d\n\r" ); sl@0: test.Printf( KEqualTestFailMsg, aValue, aExpected ); sl@0: test.operator()( EFalse, aLine, (const TText*)(aFile) ); sl@0: } sl@0: } sl@0: sl@0: GLDEF_C void TestEqualMsg( TInt aValue, TInt aExpected, TInt aLine, const TText* aFile, const TDesC& aMessageOnError ) sl@0: { sl@0: if( aExpected != aValue ) sl@0: { sl@0: _LIT( KEqualTestFailMsg, "ERROR %d expected %d %S\n\r" ); sl@0: test.Printf( KEqualTestFailMsg, aValue, aExpected, &aMessageOnError ); sl@0: test.operator()( EFalse, aLine, (const TText*)(aFile) ); sl@0: } sl@0: } sl@0: sl@0: GLDEF_C void TestEitherEqual( TInt aValue, TInt aExpected1, TInt aExpected2, TInt aLine, const TText* aFile ) sl@0: { sl@0: if( (aExpected1 != aValue) && (aExpected2 != aValue) ) sl@0: { sl@0: _LIT( KEqualTestFailMsg, "ERROR %d expected %d or %d\n\r" ); sl@0: test.Printf( KEqualTestFailMsg, aValue, aExpected1, aExpected2 ); sl@0: test.operator()( EFalse, aLine, (const TText*)(aFile) ); sl@0: } sl@0: } sl@0: sl@0: GLDEF_C void TestRange( TInt aValue, TInt aMin, TInt aMax, TInt aLine, const TText* aFile ) sl@0: { sl@0: if( (aValue < aMin) || (aValue > aMax) ) sl@0: { sl@0: _LIT( KRangeTestFailMsg, "ERROR 0x%x expected 0x%x..0x%x\n\r" ); sl@0: test.Printf( KRangeTestFailMsg, aValue, aMin, aMax ); sl@0: test.operator()( EFalse, aLine, (const TText*)(aFile) ); sl@0: } sl@0: } sl@0: sl@0: //// sl@0: sl@0: TMMCDrive::TMMCDrive() sl@0: : iTestMode(ETestPartition), sl@0: iDriveSize(0), sl@0: iMediaSize(0) sl@0: { sl@0: } sl@0: sl@0: TInt TMMCDrive::Read(TInt64 aPos,TInt aLength,TDes8& aTrg) sl@0: { sl@0: if(iTestMode == ETestWholeMedia) sl@0: { sl@0: return TBusLocalDrive::Read(aPos, aLength, &aTrg, KLocalMessageHandle, 0, RLocalDrive::ELocDrvWholeMedia); sl@0: } sl@0: else if(iTestMode != ETestPartition && aLength <= (TInt)ChunkSize) sl@0: { sl@0: TPtr8 wholeBufPtr(TheChunk.Base(),aLength); sl@0: sl@0: TInt r = TBusLocalDrive::Read(aPos, aLength, wholeBufPtr); sl@0: sl@0: aTrg.Copy(wholeBufPtr); sl@0: return r; sl@0: } sl@0: sl@0: return TBusLocalDrive::Read(aPos, aLength, aTrg); sl@0: } sl@0: sl@0: TInt TMMCDrive::Write(TInt64 aPos,const TDesC8& aSrc) sl@0: { sl@0: if(iTestMode == ETestWholeMedia) sl@0: { sl@0: return TBusLocalDrive::Write(aPos, aSrc.Length(), &aSrc, KLocalMessageHandle, 0, RLocalDrive::ELocDrvWholeMedia); sl@0: } sl@0: else if(iTestMode != ETestPartition && aSrc.Length() <= (TInt)ChunkSize) sl@0: { sl@0: TPtr8 wholeBufPtr(TheChunk.Base(),aSrc.Length()); sl@0: wholeBufPtr.Copy(aSrc); sl@0: sl@0: TInt r = TBusLocalDrive::Write(aPos, wholeBufPtr); sl@0: sl@0: return r; sl@0: } sl@0: sl@0: return TBusLocalDrive::Write(aPos, aSrc); sl@0: } sl@0: sl@0: TInt TMMCDrive::SetTestMode(TTestMode aTestMode) sl@0: { sl@0: switch (aTestMode) sl@0: { sl@0: case ETestWholeMedia : test.Printf(_L("\nTesting Whole Media\n")); break; sl@0: case ETestPartition : test.Printf(_L("\nTesting Partition\n")); break; sl@0: case ETestSharedMemory : test.Printf(_L("\nTesting Shared Memory\n")); break; sl@0: case ETestSharedMemoryCache : test.Printf(_L("\nTesting Shared Memory (Caching)\n")); break; sl@0: case ETestSharedMemoryFrag : test.Printf(_L("\nTesting Shared Memory (Fragmented)\n")); break; sl@0: default : test.Printf(_L("\nTesting Shared Memory (Fragmented/Caching)\n")); break; sl@0: } sl@0: sl@0: if(aTestMode == ETestWholeMedia && iMediaSize == 0) sl@0: { sl@0: test.Printf(_L("...not supported")); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: iTestMode = aTestMode; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TMMCDrive::TTestMode TMMCDrive::TestMode() sl@0: { sl@0: return iTestMode; sl@0: } sl@0: sl@0: void TMMCDrive::SetSize(TInt64 aDriveSize, TInt64 aMediaSize) sl@0: { sl@0: iDriveSize = aDriveSize; sl@0: iMediaSize = aMediaSize; sl@0: } sl@0: sl@0: TInt64 TMMCDrive::Size() sl@0: { sl@0: switch (iTestMode) sl@0: { sl@0: case ETestWholeMedia : return iMediaSize; sl@0: default : return iDriveSize; sl@0: } sl@0: } sl@0: sl@0: ////// sl@0: sl@0: GLDEF_C void DumpBuffer( const TDesC8& aBuffer ) sl@0: /** sl@0: * Dump the content of aBuffer in hex sl@0: */ sl@0: { sl@0: static const TText hextab[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', sl@0: 'A', 'B', 'C', 'D', 'E', 'F' }; sl@0: const TInt KBytesPerLine = 32; sl@0: const TInt KCharsPerLine = KBytesPerLine * 2; sl@0: sl@0: TInt remaining = aBuffer.Length(); sl@0: TUint8* pSrc = const_cast(aBuffer.Ptr()); sl@0: sl@0: TBuf line; sl@0: line.SetLength( KCharsPerLine ); // don't need to print trailing space sl@0: TInt bytesPerLine = KBytesPerLine; sl@0: TInt lineOffs = 0; sl@0: while( remaining ) sl@0: { sl@0: if( remaining < KBytesPerLine ) sl@0: { sl@0: bytesPerLine = remaining; sl@0: line.SetLength( (bytesPerLine*2) ); sl@0: } sl@0: TUint16* pDest = const_cast(line.Ptr()); sl@0: remaining -= bytesPerLine; sl@0: for( TInt i = bytesPerLine; i > 0; --i ) sl@0: { sl@0: TUint8 c = *pSrc++; sl@0: *pDest++ = hextab[c >> 4]; sl@0: *pDest++ = hextab[c & 0xF]; sl@0: } sl@0: _LIT( KFmt, "%06x: %S\n\r" ); sl@0: test.Printf( KFmt, lineOffs, &line ); sl@0: lineOffs += bytesPerLine; sl@0: } sl@0: } sl@0: sl@0: sl@0: GLDEF_C TBool CompareBuffers( const TDesC8& aBuf1, const TDesC8& aBuf2 ) sl@0: { sl@0: TInt count = 32; sl@0: if (aBuf1.Length() < count) sl@0: count = aBuf1.Length(); sl@0: sl@0: sl@0: for (TInt i = 0; i < (aBuf1.Length()-count); i+= count) sl@0: { sl@0: if( aBuf1.Mid(i,count).Compare(aBuf2.Mid(i,count)) != 0) sl@0: { sl@0: // now need to find where mismatch ends sl@0: TInt j =i; sl@0: for (; j <= (aBuf1.Length()-count); j+= count) sl@0: { sl@0: if( aBuf1.Mid(j,count).Compare(aBuf2.Mid(j,count)) == 0) break; sl@0: } sl@0: test.Printf(_L("buf1 len: %d, buf2 len: %d\n"),aBuf1.Length(),aBuf2.Length()); sl@0: test.Printf( _L("Buffer mismatch @%d to %d (%d Bytes)\n\r"),i,j, (j-i) ); sl@0: test.Printf( _L("buffer 1 ------------------\n\r") ); sl@0: DumpBuffer( aBuf1.Mid(i,(j-i)) ); sl@0: test.Printf( _L("buffer 2 ------------------\n\r") ); sl@0: DumpBuffer( aBuf2.Mid(i,(j-i)) ); sl@0: test.Printf(_L("buf1 len: %d, buf2 len: %d\n"),aBuf1.Length(),aBuf2.Length()); sl@0: test.Printf( _L("Buffer mismatch @%d to %d (%d Bytes)\n\r"),i,j, (j-i) ); sl@0: return EFalse; sl@0: } sl@0: } sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: void singleSectorRdWrTest(TInt aSectorOffset,TInt aLen) sl@0: // sl@0: // Perform a write / read test on a single sector (KSingSectorNo). Verify that the sl@0: // write / read back is successful and that the rest of the sector is unchanged. sl@0: // sl@0: { sl@0: sl@0: TBuf8 saveBuf; sl@0: test.Start(_L("Single sector write/read test")); sl@0: test(aSectorOffset+aLen<=KDiskSectorSize); sl@0: sl@0: // Now save state of sector before we write to it sl@0: TInt secStart=(KSingSectorNo< saveBuf1; sl@0: TBuf8 saveBuf2; sl@0: sl@0: test.Printf(_L(" MBW[%d] : MBR[%d]\n\r"), aWrMB, aRdMB); sl@0: sl@0: test(aFirstSectorOffset infoPckg(info); sl@0: nTest(anotherMmcDrive.Caps(infoPckg)==KErrNone); sl@0: nTest(info.iType==EMediaHardDisk); sl@0: sl@0: nTest.End(); sl@0: return(KErrNone); sl@0: } sl@0: sl@0: LOCAL_C void ProgressBar(TInt64 aPos,TInt64 anEndPos,TInt anXPos) sl@0: // sl@0: // Display progress of local drive operation on screen (1-16 dots) sl@0: // sl@0: { sl@0: static TInt64 prev; sl@0: TInt64 curr; sl@0: if ((curr=(aPos-1)/(anEndPos>>4))>prev) sl@0: { // Update progress bar sl@0: test.Console()->SetPos(anXPos); sl@0: for (TInt64 i=curr;i>=0;i--) sl@0: test.Printf(_L(".")); sl@0: } sl@0: prev=curr; sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0510 sl@0: @SYMTestCaseDesc Test Write/Read during media Change sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a.) Test Read during a Media Change sl@0: b.) Test Write during a Media Change sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: */ sl@0: LOCAL_C void TestHugeReadWrite(TBool aIsRead, TInt aLen) sl@0: // sl@0: // Writes aLen bytes to the MMC drive. Gives user enough time to flip the media sl@0: // change switch. Request should abort with KErrNotReady on write command, but nothing sl@0: // on read command. sl@0: // Each read or write is started from sector KMultSectNo (2). sl@0: // The media change operation only works when the switch is moved from the closed position sl@0: // to the open position. sl@0: // sl@0: { sl@0: test.Start(_L("TestHugeReadWrite: media change during I/O test.")); sl@0: test.Printf(_L("aIsRead = %x, aLen = %x.\n"), aIsRead, aLen); sl@0: sl@0: HBufC8 *buf = HBufC8::New(aLen); sl@0: test(buf != NULL); sl@0: sl@0: TInt startSectPos = KMultSectorNo << KDiskSectorShift; sl@0: if (aIsRead) sl@0: { sl@0: test.Printf(_L("Launching %08x byte read at %08x.\n"), aLen, startSectPos); sl@0: test.Printf(_L("Move media change from closed to open position before finished.\n")); sl@0: TPtr8 ptr(buf->Des()); sl@0: TInt r = TheMmcDrive.Read(startSectPos, aLen, ptr); sl@0: test.Printf(_L("r = %d.\n"), r); sl@0: test(r == KErrNone); sl@0: } sl@0: else sl@0: { sl@0: buf->Des().Fill(0xff, aLen); sl@0: test.Printf(_L("Launching %08x byte write at %08x.\n"), aLen, startSectPos); sl@0: test.Printf(_L("Move media change from closed to open position before finished.\n")); sl@0: TInt r = TheMmcDrive.Write(startSectPos, *buf); sl@0: test.Printf(_L("r = %d.\n"), r); sl@0: test(r == KErrNotReady); sl@0: } sl@0: sl@0: test.Printf(_L("Pausing for 5 seconds to move media change switch back to closed.\n")); sl@0: User::After(5 * 1000 * 1000); sl@0: delete buf; sl@0: test.End(); sl@0: } sl@0: sl@0: sl@0: LOCAL_C void FillBufferWithPattern(TDes8 &aBuf) sl@0: // sl@0: // Fills aBuf with cycling hex digits up to aBuf.Length(). sl@0: // sl@0: { sl@0: TInt len = aBuf.Length() & ~3; sl@0: for (TInt i = 0; i < len; i+=4) sl@0: { sl@0: *((TUint32*) &aBuf[i]) = i; sl@0: } sl@0: } sl@0: sl@0: sl@0: LOCAL_C void WriteAndReadBack(TInt64 aStartPos, const TDesC8 &aWrBuf) sl@0: // sl@0: // This function tests the multiple block reads when aWrBuf is sufficiently large. sl@0: // sl@0: { sl@0: test.Start(_L("WriteAndReadBack")); sl@0: sl@0: TInt r; // general error values sl@0: sl@0: // Allocate a same size buffer to read back into and compare with. sl@0: HBufC8 *rdBuf = aWrBuf.Alloc(); sl@0: test(rdBuf != NULL); sl@0: TPtr8 rdPtr(rdBuf->Des()); sl@0: sl@0: test.Next(_L("wrb: writing")); sl@0: r = TheMmcDrive.Write(aStartPos, aWrBuf); sl@0: test.Printf(_L("\nwrb:r=%d"), r); sl@0: test(r == KErrNone); sl@0: sl@0: test.Printf(_L("\n")); sl@0: test.Next(_L("wrb: reading")); sl@0: r = TheMmcDrive.Read(aStartPos, rdPtr.Length(), rdPtr); sl@0: test.Printf(_L("rb:r=%d"), r); sl@0: test(r == KErrNone); sl@0: sl@0: // Compare the pattern that has just been read back with the original. sl@0: test.Printf(_L("\n")); sl@0: test.Next(_L("wrb: comparing")); sl@0: test.Printf( sl@0: _L("rdPtr.Length() = %04x, aWrBuf.Length() = %04x"), sl@0: rdPtr.Length(), aWrBuf.Length()); sl@0: test(rdPtr == aWrBuf); sl@0: sl@0: #if 0 // extra debug when buffers not compare. sl@0: for (TInt j = 0; j < rdPtr.Length(); j++) sl@0: { sl@0: test.Printf(_L("%d: w%02x r%02x"), j, aWrBuf[j], rdBuf[j]); sl@0: sl@0: if (rdPtr[j] != aWrBuf[j]) sl@0: { sl@0: test.Printf(_L("buffer mismatch at %04x: %02x v %02x"), j, rdPtr[j], aWrBuf[j]); sl@0: test(EFalse); sl@0: } sl@0: } sl@0: #endif sl@0: sl@0: test.Printf(_L("\n")); sl@0: delete rdBuf; sl@0: test.End(); sl@0: } sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0169 sl@0: @SYMTestCaseDesc Test Multiple Block Reads sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a.) Test Multiple Block Reads at the internal buffer size sl@0: b.) Test Multiple Block Reads greater than the internal buffer size sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: sl@0: @TODO: increase Buffer size to match current reference platform (128KB) sl@0: */ sl@0: LOCAL_C void TestMultipleBlockReads() sl@0: { sl@0: // Test multiple block reads. sl@0: static TBuf8<256 * 1024> rw_wrBuf; sl@0: sl@0: rw_wrBuf.SetLength(rw_wrBuf.MaxLength()); sl@0: FillBufferWithPattern(rw_wrBuf); sl@0: sl@0: test.Next(_L("Testing multiple block reads at internal buffer size")); sl@0: rw_wrBuf.SetLength(8 * KDiskSectorSize); sl@0: WriteAndReadBack(KMultSectorNo << KDiskSectorShift, rw_wrBuf); sl@0: sl@0: test.Next(_L("Testing multiple block reads at gt internal buffer size")); sl@0: rw_wrBuf.SetLength(10 * KDiskSectorSize); sl@0: WriteAndReadBack(KMultSectorNo << KDiskSectorShift, rw_wrBuf); sl@0: sl@0: test.Next(_L("Testing unaligned large block read ")); sl@0: rw_wrBuf.SetLength(rw_wrBuf.MaxLength()); sl@0: WriteAndReadBack((KMultSectorNo << KDiskSectorShift) + 128, rw_wrBuf); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0558 sl@0: @SYMTestCaseDesc Test Long Read/Write Boundaries sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: sl@0: Perform and Write/Read/Verify for the given length (L) of data across the following boundaries. sl@0: Depending on the length provided, this will also perform a partial write/read at the end sector. sl@0: sl@0: ------------------- sl@0: | Start | End | sl@0: |-------------------| sl@0: | 0 | L | sl@0: | 507 | L-507 | sl@0: | 10 | L | sl@0: | 0 | L-3 | sl@0: | 27 | L-512 | sl@0: | 0 | L-509 | sl@0: | 3 | L-3 | sl@0: ------------------- sl@0: sl@0: For each combination, the write/read/verify operations are performed in the following sequence: sl@0: sl@0: a: Write and Read in single 512-byte blocks. sl@0: b: Write in a single operation (multiple blocks), Read in 512-Byte blocks. sl@0: c: Write in 512-Byte blocks, Read in a single operation (multiple-blocks). sl@0: d: Write and Read in a single operation (multiple-blocks). sl@0: sl@0: In the cases where a partial read/write operation occurs (ie - the start and/or end position don't lie within sl@0: a sector boundary), the original contents of the start and/or end sectors are read and stored at the start of sl@0: the test, and compared with the contents of the sectors at the end of the test to ensure that unwritten data within sl@0: the sectors remain unaffected. sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: sl@0: @SYMPREQ1389 REQ6951 Double Buffering and SD Switch sl@0: */ sl@0: sl@0: LOCAL_C void TestLongReadWriteBoundaries(TUint aLen, TBool aMBOnly = EFalse) sl@0: { sl@0: TBuf<64> b; sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(1) (%dbytes at %d)"),aLen,0); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(0, aLen, aMBOnly); // Exceeds driver's buffer, starts/ends on sector boundary sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(2) (%dbytes at %d)"),(aLen-KDiskSectorSize+5),507); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(507, (aLen-KDiskSectorSize+5), aMBOnly); // Exceeds driver's buffer, ends on sector boundary sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(3) (%dbytes at %d)"),aLen,10); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(10, aLen, aMBOnly); // Exceeds driver's buffer, starts/ends off sector boundary sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(4) (%dbytes at %d)"),(aLen-3),0); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(0, aLen-3, aMBOnly); // Exceeds driver's buffer, starts on sector boundary sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(5) (%dbytes at %d)"),(aLen-KDiskSectorSize),27); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(27, (aLen-KDiskSectorSize), aMBOnly); // Exceeds driver's buffer (due to start offset), starts/ends off sector boundary sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(6) (%dbytes at %d)"),(aLen-KDiskSectorSize-3),0); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(0, aLen-KDiskSectorSize-3, aMBOnly); // Equals driver's buffer, starts on sector boundary sl@0: sl@0: b.Format(_L("MMC drive: Very long RdWr(7) (%dbytes at %d)"),(aLen-3),3); sl@0: test.Next(b); sl@0: MultipleSectorRdWrTest(3, aLen-3, aMBOnly); // Equals driver's buffer, ends on sector boundary sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0509 sl@0: @SYMTestCaseDesc Test Sector Read/Writing sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a.) Test Writing blocks on sector boundaries sl@0: b.) Test Reading blocks on sector boundaries sl@0: c.) Test single sector Write/Read at: sl@0: i.) Sector Start sl@0: ii.) Mid Sector sl@0: iii.) Sector End sl@0: d.) Test Multiple Sector Write/Read: sl@0: i.) Start on Sector Boundary sl@0: ii.) Start/End on Sector Boundary sl@0: iii.) End on Sector Boundary sl@0: e.) Test Write/Read over sector boundary sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: */ sl@0: LOCAL_C void TestSectorReadWrite() sl@0: { sl@0: TBuf<64> b; sl@0: b.Format(_L("MMC drive: Sector RdWr(%d)"), KDiskSectorSize); sl@0: sl@0: test.Next(b); sl@0: sl@0: TInt len; sl@0: sl@0: // Fill wrBuf with a pattern of ascending numbers. sl@0: wrBuf.SetLength(KDiskSectorSize); sl@0: TUint32 *p = REINTERPRET_CAST(TUint32 *, &wrBuf[0]); sl@0: TInt secPos; sl@0: for (secPos = 0; secPos < KDiskSectorSize; secPos++) sl@0: { sl@0: wrBuf[secPos] = TUint8(secPos % 0x0100); sl@0: } sl@0: sl@0: // Write 512 byte blocks to the card, writing the sector number to the first sl@0: // word in each buffer. sl@0: sl@0: test.Printf(_L("Writing ")); sl@0: TInt64 i; sl@0: // for (i=0;i savBuf1,savBuf2; sl@0: TInt fmtTestPos=(10< 0) sl@0: { sl@0: wrBuf.SetLength(rem); sl@0: defEraseVal = rdBuf[sec * KDiskSectorSize]; sl@0: test(defEraseVal == 0x00 || defEraseVal == 0xFF); // The card should erase with 0x00 or 0xFF sl@0: wrBuf.Fill(defEraseVal, rem); sl@0: test( CompareBuffers( wrBuf, rdBuf.Mid( sec * KDiskSectorSize, rem ) ) ); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: sl@0: class TRandGen sl@0: { sl@0: public: sl@0: TRandGen(); sl@0: void Seed(); sl@0: void Seed( const TInt64& aSeed ); sl@0: TUint Next(); sl@0: sl@0: private: sl@0: TInt64 iValue; sl@0: }; sl@0: sl@0: sl@0: TRandGen::TRandGen() sl@0: : iValue(KDefaultRandSeed) sl@0: { sl@0: } sl@0: sl@0: sl@0: void TRandGen::Seed( const TInt64& aSeed ) sl@0: { sl@0: iValue = aSeed; sl@0: } sl@0: sl@0: void TRandGen::Seed() sl@0: { sl@0: iValue = KDefaultRandSeed; sl@0: } sl@0: sl@0: TUint TRandGen::Next() sl@0: { sl@0: iValue *= 214013; sl@0: iValue += 2531011; sl@0: return static_cast( I64LOW(iValue) ); sl@0: } sl@0: sl@0: sl@0: GLDEF_C void FillRandomBuffer( TDes8& aBuf, TRandGen& aRand ) sl@0: /** sl@0: * Fill buffer aBuf with data generated by aRand sl@0: */ sl@0: { sl@0: TUint l = aBuf.MaxLength(); sl@0: aBuf.SetLength( l ); sl@0: TUint* p = (TUint*)aBuf.Ptr(); sl@0: sl@0: // Do any unaligned bytes at the start sl@0: TInt preAlign = (TUint)p & 3; sl@0: if( preAlign ) sl@0: { sl@0: preAlign = 4 - preAlign; sl@0: TUint8* p8 = (TUint8*)p; sl@0: TUint rand = aRand.Next(); sl@0: while( preAlign && l ) sl@0: { sl@0: *p8 = (TUint8)(rand & 0xFF); sl@0: rand >>= 8; sl@0: ++p8; sl@0: --preAlign; sl@0: --l; sl@0: } sl@0: p = (TUint*)p8; sl@0: } sl@0: sl@0: for( ; l > 3; l-=4 ) sl@0: { sl@0: *p++ = aRand.Next(); sl@0: } sl@0: // Fill in any trailing bytes sl@0: if( l > 0 ) sl@0: { sl@0: TUint8* q = (TUint8*)p; sl@0: TUint r = aRand.Next(); sl@0: if( l > 1 ) sl@0: { sl@0: *((TUint16*)q) = (TUint16)(r & 0xFFFF); sl@0: q += 2; sl@0: l -= 2; sl@0: r >>= 16; sl@0: } sl@0: if( l > 0 ) sl@0: { sl@0: *q = (TUint8)(r & 0xFF); sl@0: } sl@0: } sl@0: } sl@0: sl@0: GLDEF_C void FillRandomBuffer( HBufC8* aBuf, TRandGen& aRand ) sl@0: /** sl@0: * Fill buffer aBuf with data generated by aRand sl@0: * For convenience this version takes a HBufC8* sl@0: */ sl@0: { sl@0: TPtr8 ptr = aBuf->Des(); sl@0: FillRandomBuffer( ptr, aRand ); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0164 sl@0: @SYMTestCaseDesc Test MMC Drive Capabilities sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a. Obtain MMC Drive Capabilities sl@0: b. If the card size is greater than 2GBytes, test that the driver reports FAT32 file system supported. sl@0: c. Test that the type of media is reported as EMediaHardDisk sl@0: d. Test that the drive attributes report KDriveAttLocal and KDriveAttRemovable sl@0: e. Test that the drive attributes do not report KDriveAttRemote sl@0: f. If the drive is not write protected or a ROM card, test that the media attributes report that the drive is formattable sl@0: g. If the drive is write protected or a ROM card, test that the media attributes do not report that the drive is formattable sl@0: h. Test that the media attributes do not report variable sized media. sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: sl@0: @SYMPREQ1389 CR0795 Support for >2G SD Cards sl@0: */ sl@0: TBool TestDriveInfo() sl@0: { sl@0: test.Next( _L("Test drive info") ); sl@0: sl@0: TEST_FOR_ERROR( TheMmcDrive.Caps( DriveCaps ) ); sl@0: sl@0: test.Printf( _L("Caps V1:\n\tiSize=0x%lx\n\tiType=%d\n\tiConnectionBusType=%d\n\tiDriveAtt=0x%x\n\tiMediaAtt=0x%x\n\tiBaseAddress=0x%x\n\tiFileSystemId=0x%x\n\tiPartitionType=0x%x\n"), sl@0: DriveCaps().iSize, sl@0: DriveCaps().iType, sl@0: DriveCaps().iConnectionBusType, sl@0: DriveCaps().iDriveAtt, sl@0: DriveCaps().iMediaAtt, sl@0: DriveCaps().iBaseAddress, sl@0: DriveCaps().iFileSystemId, sl@0: DriveCaps().iPartitionType ); sl@0: sl@0: test.Printf( _L("Caps V2:\n\tiHiddenSectors=0x%x\n\tiEraseBlockSize=0x%x\nCaps V3:\n\tiExtraInfo=%x\n\tiMaxBytesPerFormat=0x%x\n"), sl@0: DriveCaps().iHiddenSectors, sl@0: DriveCaps().iEraseBlockSize, sl@0: DriveCaps().iExtraInfo, sl@0: DriveCaps().iMaxBytesPerFormat ); sl@0: sl@0: test.Printf( _L("Format info:\n\tiCapacity=0x%lx\n\tiSectorsPerCluster=0x%x\n\tiSectorsPerTrack=0x%x\n\tiNumberOfSides=0x%x\n\tiFatBits=%d\n"), sl@0: DriveCaps().iFormatInfo.iCapacity, sl@0: DriveCaps().iFormatInfo.iSectorsPerCluster, sl@0: DriveCaps().iFormatInfo.iSectorsPerTrack, sl@0: DriveCaps().iFormatInfo.iNumberOfSides, sl@0: DriveCaps().iFormatInfo.iFATBits ); sl@0: sl@0: if(DriveCaps().iSerialNumLength > 0) sl@0: { sl@0: test.Printf( _L("Serial Number : ") ); sl@0: TBuf8<2*KMaxSerialNumLength> snBuf; sl@0: TUint i; sl@0: for (i=0; i2GB is marked as requesting FAT32 sl@0: if( DriveCaps().iSize > KTwoGigbytes && DriveCaps().iExtraInfo) sl@0: { sl@0: TEST_FOR_VALUE( DriveCaps().iFormatInfo.iFATBits, TLDFormatInfo::EFB32 ); sl@0: } sl@0: sl@0: TEST_FOR_VALUE( DriveCaps().iType, EMediaHardDisk ); sl@0: sl@0: const TUint KExpectedDriveAtt = KDriveAttLocal | KDriveAttRemovable; sl@0: const TUint KNotExpectedDriveAtt = KDriveAttRemote; sl@0: TEST_FOR_VALUE( DriveCaps().iDriveAtt & KExpectedDriveAtt, KExpectedDriveAtt ); sl@0: TEST_FOR_VALUE( DriveCaps().iDriveAtt & KNotExpectedDriveAtt, 0 ); sl@0: sl@0: TUint expectedMediaAtt = KMediaAttFormattable; sl@0: TUint notExpectedMediaAtt = KMediaAttVariableSize; sl@0: sl@0: TBool isReadOnly = DriveCaps().iMediaAtt & KMediaAttWriteProtected; sl@0: if(isReadOnly) sl@0: { sl@0: expectedMediaAtt &= ~KMediaAttFormattable; sl@0: sl@0: test.Printf( _L("\n ---------------------------\n") ); sl@0: test.Printf( _L(" Media is Write Protected\n") ); sl@0: if((DriveCaps().iMediaAtt & KMediaAttFormattable) != KMediaAttFormattable) sl@0: { sl@0: test.Printf( _L(" Media is a ROM card\n") ); sl@0: } sl@0: test.Printf( _L(" Some tests will be skipped\n") ); sl@0: test.Printf( _L(" ---------------------------\n") ); sl@0: } sl@0: sl@0: TEST_FOR_VALUE( DriveCaps().iMediaAtt & expectedMediaAtt, expectedMediaAtt ); sl@0: TEST_FOR_VALUE( DriveCaps().iMediaAtt & notExpectedMediaAtt, 0 ); sl@0: sl@0: return(isReadOnly); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0165 sl@0: @SYMTestCaseDesc Test MMC Card Reads sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a. Read 64K in one operation from the start of the media and store the contents. sl@0: b. Read 512 byte blocks from the start of the media at various offsets and compare with initial read. sl@0: b. Read 64K in 512 byte blocks from the start of the media and compare with the initial read. sl@0: c. read 64K from the end of the drive sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: sl@0: @SYMPREQ1389 CR0795 Support for >2G SD Cards sl@0: */ sl@0: void TestRead() sl@0: { sl@0: // This just tests that we can read *something* from the drive sl@0: // We check elsewhere that we can read what we've written sl@0: test.Next( _L("Test reading" ) ); sl@0: sl@0: HBufC8* bigBuf = HBufC8::New( 65536 ); sl@0: HBufC8* smallBuf = HBufC8::New( 512 ); sl@0: sl@0: test( bigBuf != NULL ); sl@0: test( smallBuf != NULL ); sl@0: TPtr8 bigPtr( bigBuf->Des() ); sl@0: TPtr8 smallPtr( smallBuf->Des() ); sl@0: sl@0: test.Printf( _L("Read block from start of media\n") ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( TInt64(0), 65536, bigPtr) ); sl@0: sl@0: test.Printf( _L("Read smaller blocks which should match the data in big block\n\r" ) ); sl@0: TInt i; sl@0: for( i = 0; i <= 512; ++i ) sl@0: { sl@0: test.Printf( _L("\toffset: %d\r"), i ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( TInt64(i), 512, smallPtr ) ); sl@0: test( CompareBuffers( smallBuf->Des(), bigBuf->Mid( i, 512 ) ) ); sl@0: } sl@0: sl@0: for( i = 512; i <= 65536-512; i += 512 ) sl@0: { sl@0: test.Printf( _L("\toffset: %d\r"), i ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( TInt64(i), 512, smallPtr ) ); sl@0: test( CompareBuffers( smallBuf->Des(), bigBuf->Mid( i, 512 ) ) ); sl@0: } sl@0: sl@0: test.Printf( _L("\nTest read from end of drive\n") ); sl@0: sl@0: if(CardType == TKnownCardTypes::EBuffalloMiniSD_512M || sl@0: CardType == TKnownCardTypes::EIntegralHSSD_2G) sl@0: { sl@0: // These cards have issues with reading at the end of the drive... sl@0: test.Printf( _L(" -- Skipping Test - Known card detected --\n") ); sl@0: } sl@0: else sl@0: { sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( TheMmcDrive.Size() - 65536, 65536, bigPtr) ); sl@0: } sl@0: sl@0: delete smallBuf; sl@0: delete bigBuf; sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0511 sl@0: @SYMTestCaseDesc Test Moving Read/Write sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a.) Test Read/Verify Whole Sectors sl@0: b.) Test Read/Verify Sliding sector sized window sl@0: c.) Test Read/Verify Sliding byte sized window sl@0: d.) Test Read/Verify Increasing sized window sl@0: e.) Test Write/Read/Verify Whole Sectors sl@0: f.) Test Write/Read/Verify Sliding sector sized window sl@0: g.) Test Write/Read/Verify Increasing sized window sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: */ sl@0: void DoReadWriteTest( TInt64 aPos, TInt aWindowSize, TBool aQuick ) sl@0: { sl@0: // Do various read/write tests within a aWindowSize window starting at aPos sl@0: HBufC8* wholeBuf = HBufC8::New( aWindowSize ); sl@0: test( wholeBuf != NULL ); sl@0: sl@0: HBufC8* readBuf = HBufC8::New( aWindowSize ); sl@0: test( readBuf != NULL ); sl@0: sl@0: TBuf8<512> sectorBuf; sl@0: TRandGen rand; sl@0: sl@0: test.Printf( _L("Walking sector read\n\r") ); sl@0: FillRandomBuffer( wholeBuf, rand ); sl@0: TPtr8 wholeBufPtr( wholeBuf->Des() ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aPos, *wholeBuf ) ); sl@0: sl@0: // Read each sector back and check that it's correct sl@0: TInt64 pos( aPos ); sl@0: TInt i; sl@0: for( i = 0; i < aWindowSize - 512; i += 512 ) sl@0: { sl@0: pos = aPos + i; sl@0: test.Printf(_L("\tRead @0x%lx\r"), pos); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( pos, 512, sectorBuf ) ); sl@0: test( CompareBuffers( sectorBuf, wholeBuf->Mid( i, 512 ) ) ); sl@0: } sl@0: sl@0: test.Printf( _L("\nSliding sector read\n\r") ); sl@0: // Slide a sector-sized window over the data sl@0: TInt maxl = Min( aWindowSize - 512, 512 * 3 ); sl@0: for( i = 0; i < maxl; i++ ) sl@0: { sl@0: pos = aPos + i; sl@0: test.Printf(_L("\tRead @0x%lx\r"), pos); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( pos, 512, sectorBuf ) ); sl@0: test( CompareBuffers( sectorBuf, wholeBuf->Mid( i, 512 ) ) ); sl@0: } sl@0: sl@0: if( !aQuick ) sl@0: { sl@0: test.Printf( _L("\nSliding byte read\n\r") ); sl@0: // Slide a byte-sized window over the data sl@0: for( i = 0; i < maxl; i++ ) sl@0: { sl@0: pos = aPos + i; sl@0: test.Printf(_L("\tRead @0x%lx\r"), pos); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( pos, 1, sectorBuf ) ); sl@0: test( CompareBuffers( sectorBuf, wholeBuf->Mid( i, 1 ) ) ); sl@0: } sl@0: sl@0: test.Printf( _L("\nGrowing read\n\r") ); sl@0: // Read from an increasing-sized window sl@0: for( i = 1; i < 512; i++ ) sl@0: { sl@0: test.Printf(_L("\tRead length: %d\r"), i); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aPos, i, sectorBuf ) ); sl@0: test( CompareBuffers( sectorBuf, wholeBuf->Left( i ) ) ); sl@0: } sl@0: sl@0: test.Printf( _L("\nDownward-expanding read\n\r") ); sl@0: // Read from a window that grows downward from the end of the test region sl@0: for( i = 1; i <= 512; i++ ) sl@0: { sl@0: pos = aPos + aWindowSize - i; sl@0: test.Printf(_L("\t[pos:len] %lx:%d\r"), pos, i); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( pos, i, sectorBuf ) ); sl@0: test( CompareBuffers( sectorBuf, wholeBuf->Mid( aWindowSize - i, i ) ) ); sl@0: } sl@0: } sl@0: sl@0: test.Printf( _L("\nWalking sector write\n\r") ); sl@0: // Overwrite each sector and check the whole region is correct sl@0: for( i = 0; i < aWindowSize - 512; i += 512 ) sl@0: { sl@0: FillRandomBuffer( sectorBuf, rand ); sl@0: pos = aPos + i; sl@0: test.Printf(_L("\tWrite @0x%lx\r"), pos); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( pos, sectorBuf ) ); sl@0: wholeBufPtr.MidTPtr( i, 512 ) = sectorBuf; // update our match data sl@0: sl@0: TPtr8 ptr( readBuf->Des() ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aPos, aWindowSize, ptr ) ); sl@0: test( CompareBuffers( *readBuf, *wholeBuf ) ); sl@0: } sl@0: sl@0: if( !aQuick ) sl@0: { sl@0: test.Printf( _L("\nSliding sector overwrite\n\r") ); sl@0: // Overwrite a sector-sized region that slides across the test region sl@0: for( i = 0; i < maxl; i += 1 ) sl@0: { sl@0: FillRandomBuffer( sectorBuf, rand ); sl@0: pos = aPos + i; sl@0: test.Printf(_L("\tWrite @0x%lx\r"), pos); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( pos, sectorBuf ) ); sl@0: wholeBufPtr.MidTPtr( i, 512 ) = sectorBuf; // update our match data sl@0: sl@0: TPtr8 ptr( readBuf->Des() ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aPos, aWindowSize, ptr ) ); sl@0: test( CompareBuffers( *readBuf, *wholeBuf ) ); sl@0: } sl@0: sl@0: test.Printf( _L("\nGrowing sector overwrite\n\r") ); sl@0: // Overwrite an expanding region starting at aPos sl@0: for( i = 1; i < 512; i += 1 ) sl@0: { sl@0: FillRandomBuffer( sectorBuf, rand ); sl@0: test.Printf(_L("\tWrite length: %d\r"), i); sl@0: sectorBuf.SetLength( i ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aPos, sectorBuf ) ); sl@0: wholeBufPtr.LeftTPtr( i ) = sectorBuf; // update our match data sl@0: sl@0: TPtr8 ptr( readBuf->Des() ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aPos, aWindowSize, ptr ) ); sl@0: test( CompareBuffers( *readBuf, *wholeBuf ) ); sl@0: } sl@0: } sl@0: sl@0: test.Printf( _L("\nTest zero-length read\n") ); sl@0: FillRandomBuffer( sectorBuf, rand ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aPos, 0, sectorBuf ) ); sl@0: TEST_FOR_VALUE( sectorBuf.Length(), 0 ); sl@0: sl@0: delete wholeBuf; sl@0: delete readBuf; sl@0: } sl@0: sl@0: sl@0: // This tests for a bug observed in certain ESanDiskMmcMobile_1GB cards which never exit the busy state sl@0: // when writing a buffer which is one sector bigger than the PSL buffer size (resulting in a single write sl@0: // request split into 2 fragments, the last of which is one sector only). The "fix" for this is to make the sl@0: // PSL reject CMD23 (SET_BLOCK_COUNT) for these particular cards, forcing the PIL to issue a CMD12 (STOP_TRANSMISSION) sl@0: void TestFragmentedWrite(TInt aLength) sl@0: { sl@0: test.Next( _L("Test a large write just bigger than PSL buffer size") ); sl@0: sl@0: HBufC8* bigBuf = HBufC8::New( aLength); sl@0: test( bigBuf != NULL ); sl@0: TPtr8 bigPtr( bigBuf->Des() ); sl@0: sl@0: TInt64 startPos = 0; sl@0: sl@0: // for a dual-slot enabled H4, buffer size is 132K - (512 * 2) = 131K sl@0: sl@0: sl@0: test.Printf( _L("Initializing buffer contents...\n")); sl@0: bigPtr.SetLength(aLength); sl@0: TInt n; sl@0: for (n=0; n2G SD Cards sl@0: */ sl@0: void TestCapacity() sl@0: { sl@0: if(!IsReadOnly) sl@0: { sl@0: test.Next( _L("Test access at end of media") ); sl@0: DoReadWriteTest( TheMmcDrive.Size() - 65536, 65536, ETrue ); sl@0: } sl@0: sl@0: test.Printf( _L("Test accesses past end of media produce an error\n") ); sl@0: sl@0: TBuf8<1024> buf; sl@0: sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size(), 1, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size(), 2, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size(), 512, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() + 1, 512, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() + 512, 512, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() - 1, 2, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() - 511, 512, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() - 512, 513, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() - 65536, 65537, buf ) ); sl@0: test( KErrNone != TheMmcDrive.Read( TheMmcDrive.Size() - 512, 1024, buf ) ); sl@0: } sl@0: sl@0: sl@0: void WriteAcrossBoundaries(TInt64 aBoundary) sl@0: { sl@0: test.Printf( _L("Test for aliasing around boundary\n") ); sl@0: TBuf8<512> bufLo; sl@0: TBuf8<512> bufHi; sl@0: TBuf8<8192> bufRead; sl@0: sl@0: bufLo.Fill( 0xE4, 512 ); sl@0: bufHi.Fill( 0x19, 512 ); sl@0: sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( 0, bufLo ) ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aBoundary, bufHi ) ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( 0, 512, bufRead ) ); sl@0: test( bufRead == bufLo ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aBoundary, 512, bufRead ) ); sl@0: test( bufRead == bufHi ); sl@0: sl@0: bufHi.Fill( 0xBB, 1 ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aBoundary, bufHi ) ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( 0, 512, bufRead ) ); sl@0: test( bufRead == bufLo ); sl@0: sl@0: bufHi.Fill( 0xCC, 1 ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( (aBoundary+1), bufHi ) ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( 0, 512, bufRead ) ); sl@0: test( bufRead == bufLo ); sl@0: sl@0: test.Printf( _L("Test write which ends at boundary\n") ); sl@0: bufHi.Fill( 0x33, 512 ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aBoundary, bufHi ) ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aBoundary, 512, bufRead ) ); sl@0: test( bufRead == bufHi ); sl@0: sl@0: bufHi.Fill( 0x44, 512 ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aBoundary - 512, bufHi ) ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aBoundary - 512, 512, bufRead ) ); sl@0: test( bufRead == bufHi ); sl@0: sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( 0, 512, bufRead ) ); sl@0: test( bufRead == bufLo ); sl@0: sl@0: bufHi.Fill( 0x33, 512 ); sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aBoundary, 512, bufRead ) ); sl@0: test( bufRead == bufHi ); sl@0: sl@0: test.Printf( _L("Test read-modify-write across boundary\n") ); sl@0: TBuf8<512> rmw; sl@0: TBuf8<8192> data; sl@0: rmw.Fill( 0x66, 512 ); sl@0: data.Fill( 0x11, 8192 ); sl@0: sl@0: for( TInt i = 1; i < 511; ++i ) sl@0: { sl@0: ProgressBar(i, 511, 11); sl@0: sl@0: // Create initial data block sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aBoundary - 512, data ) ); sl@0: sl@0: // Read-modify-write some data sl@0: TEST_FOR_ERROR( TheMmcDrive.Write( aBoundary - 512 + i, rmw ) ); sl@0: sl@0: // Modify buffer to what we expect sl@0: data.MidTPtr( i, 512 ) = rmw; sl@0: sl@0: // Read it back and check it matches sl@0: TEST_FOR_ERROR( TheMmcDrive.Read( aBoundary - 512, 8192, bufRead ) ); sl@0: test( CompareBuffers( bufRead, data ) ); sl@0: } sl@0: test.Printf(_L("\n")); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0167 sl@0: @SYMTestCaseDesc Test that the boundary >2GB doesn't produce aliases or errors sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a. Test that writing at the 2G boundary does not produce aliases. sl@0: b. Test writes that end at the 2G boundary. sl@0: c. Test read/modify/write across the 2G boundary. sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: sl@0: @SYMPREQ1389 CR0795 Support for >2G SD Cards sl@0: */ sl@0: void TestBoundaries() sl@0: { sl@0: sl@0: if( TheMmcDrive.Size() < 0x80008000 ) sl@0: { sl@0: test.Printf( _L("Drive not large enough for 2GB boundary test... skipped\n") ); sl@0: return; sl@0: } sl@0: sl@0: // Test that the boundary 2GB doesn't produce aliases or errors sl@0: // >2Gb cards change addressing scheme from byte to block base sl@0: test.Next( _L("Test 2GB boundary") ); sl@0: WriteAcrossBoundaries(0x80000000); sl@0: sl@0: // N.B. Commented Out for now due to compiler warnings sl@0: // if( TheMmcDrive.Size() < 0x100008000ll ) sl@0: // { sl@0: // test.Printf( _L("Drive not large enough for 4GB boundary test... skipped\n") ); sl@0: // return; sl@0: // } sl@0: // // Test that the boundary 4GB doesn't produce aliases or errors sl@0: // // >4GB cards change addressing scheme from 32bit to 64bit addresses sl@0: // test.Next( _L("Test 4GB boundary") ); sl@0: // WriteAcrossBoundaries(0x100000000ll); sl@0: } sl@0: sl@0: sl@0: /** sl@0: @SYMTestCaseID PBASE-T_MMCDRV-0512 sl@0: @SYMTestCaseDesc Test Media Change/Capabilities Reporting sl@0: @SYMTestPriority High sl@0: sl@0: @SYMTestActions sl@0: a.) Test Media Change flag after Media Change sl@0: b.) Test Capabilities reporting for Out Of Memory Conditions sl@0: c.) Test Media Change flag after Machine power-off sl@0: d.) Test Capabilities reporting after Machine power-off sl@0: e.) Test Multiple Media Change flags after Media Change sl@0: sl@0: @SYMTestExpectedResults All tests must pass sl@0: */ sl@0: void TestMediaChange() sl@0: { sl@0: test.Next(_L("MMC drive: Media change")); sl@0: #if defined (__WINS__) sl@0: test.Printf( _L("<<>>\r\n")); sl@0: #else sl@0: test.Printf( _L("<<>>\r\n")); sl@0: #endif sl@0: test.Getch(); sl@0: User::After(300000); // Allow 0.3s after power down for controller to detect door closed. sl@0: test(ChangeFlag!=EFalse); sl@0: sl@0: test.Next(_L("MMC drive: Caps following media change")); sl@0: sl@0: TLocalDriveCapsV4 info; sl@0: TPckg infoPckg(info); sl@0: sl@0: test(TheMmcDrive.Caps(infoPckg)==KErrNone); sl@0: test(info.iType==EMediaHardDisk); sl@0: sl@0: test.Next(_L("MMC drive: Caps while OOM")); sl@0: TInt err; sl@0: test.Printf(_L("Mount returns:")); sl@0: for (TInt j=1;j<16;j++) sl@0: { sl@0: __KHEAP_SETFAIL(RHeap::EDeterministic,j); sl@0: err=TheMmcDrive.Caps(infoPckg); sl@0: test.Printf(_L("(%d)"),err); sl@0: __KHEAP_RESET; sl@0: } sl@0: test.Printf(_L("\r\n")); sl@0: sl@0: test.Next(_L("MMC drive: Machine power-off.")); sl@0: ChangeFlag=EFalse; sl@0: RTimer timer; sl@0: TRequestStatus trs; sl@0: test(timer.CreateLocal()==KErrNone); sl@0: TTime tim; sl@0: tim.HomeTime(); sl@0: tim+=TTimeIntervalSeconds(8); sl@0: timer.At(trs,tim); sl@0: UserHal::SwitchOff(); sl@0: User::WaitForRequest(trs); sl@0: test(trs.Int()==KErrNone); sl@0: test(ChangeFlag==EFalse); // ie machine power off hasn't updated it sl@0: sl@0: test.Next(_L("MMC drive: Caps following power off")); sl@0: TInt r=TheMmcDrive.Caps(infoPckg); sl@0: test(r==KErrNone); sl@0: test(info.iType==EMediaHardDisk); sl@0: sl@0: test.Next(_L("Starting 2nd thread")); sl@0: SecThreadChangeFlag=EFalse; sl@0: RThread thread; sl@0: TRequestStatus stat; sl@0: test(thread.Create(_L("Thread"),dontDisconnectThread,KDefaultStackSize,KHeapSize,KHeapSize,NULL)==KErrNone); sl@0: thread.Logon(stat); sl@0: thread.Resume(); sl@0: User::WaitForRequest(stat); sl@0: test(stat==KErrNone); sl@0: thread.Close(); sl@0: sl@0: test.Next(_L("MMC drive: 2nd media change")); sl@0: // UserSvr::ForceRemountMedia(ERemovableMedia0); // Generate media change sl@0: test(ChangeFlag!=EFalse); sl@0: test(SecThreadChangeFlag==EFalse); // Closed 2nd thread so shouldn't have been updated sl@0: } sl@0: sl@0: sl@0: //// End of Test sl@0: void Format() sl@0: // sl@0: // Format current drive sl@0: // sl@0: { sl@0: RFs TheFs; sl@0: test(TheFs.Connect() == KErrNone); sl@0: sl@0: test.Next(_L("Format")); sl@0: TBuf<4> driveBuf=_L("?:\\"); sl@0: driveBuf[0]=(TText)(RFsDNum+'A'); sl@0: sl@0: RFormat format; sl@0: TInt count; sl@0: TInt r=format.Open(TheFs,driveBuf,EQuickFormat,count); sl@0: test(r==KErrNone); sl@0: while(count) sl@0: { sl@0: TInt r=format.Next(count); sl@0: test(r==KErrNone); sl@0: } sl@0: format.Close(); sl@0: } sl@0: sl@0: void AllocateBuffers() sl@0: { sl@0: test.Next(_L("Allocate Buffers")); sl@0: sl@0: //HBufC8* wrBufH = NULL; sl@0: //HBufC8* rdBufH = NULL; sl@0: sl@0: wrBufH = HBufC8::New(KVeryLongRdWrBufLen); sl@0: test(wrBufH != NULL); sl@0: sl@0: rdBufH = HBufC8::New(KVeryLongRdWrBufLen); sl@0: if(rdBufH == NULL) delete wrBufH; sl@0: test(rdBufH != NULL); sl@0: sl@0: wrBuf.Set(wrBufH->Des()); sl@0: rdBuf.Set(rdBufH->Des()); sl@0: } sl@0: sl@0: void AllocateSharedBuffers(TBool Fragmented, TBool Caching) sl@0: { sl@0: // Setup SharedMemory Buffers sl@0: test.Next(_L("Allocate Shared Memory\n")); sl@0: sl@0: RLoader l; sl@0: test(l.Connect()==KErrNone); sl@0: test(l.CancelLazyDllUnload()==KErrNone); sl@0: l.Close(); sl@0: sl@0: test.Printf(_L("Initialise\n")); sl@0: TInt r = UserHal::PageSizeInBytes(PageSize); sl@0: test(r==KErrNone); sl@0: sl@0: test.Printf(_L("Loading test driver\n")); sl@0: r = User::LoadLogicalDevice(KSharedChunkLddName); sl@0: test(r==KErrNone || r==KErrAlreadyExists); sl@0: sl@0: test.Printf(_L("Opening channel\n")); sl@0: r = Ldd.Open(); sl@0: test(r==KErrNone); sl@0: sl@0: test.Printf(_L("Create chunk\n")); sl@0: sl@0: TUint aCreateFlags = EMultiple|EOwnsMemory; sl@0: sl@0: if (Caching) sl@0: { sl@0: test.Printf(_L("Chunk Type:Caching\n")); sl@0: aCreateFlags |= ECached; sl@0: } sl@0: else sl@0: test.Printf(_L("Chunk Type:Fully Blocking\n")); sl@0: sl@0: TCommitType aCommitType = EContiguous; sl@0: sl@0: TUint TotalChunkSize = ChunkSize; // rounded to nearest Page Size sl@0: sl@0: TUint ChunkAttribs = TotalChunkSize|aCreateFlags; sl@0: r = Ldd.CreateChunk(ChunkAttribs); sl@0: test(r==KErrNone); sl@0: sl@0: if(Fragmented) sl@0: { sl@0: test.Printf(_L("Commit Fragmented Memory\n")); sl@0: sl@0: // Allocate Pages in reverse order to maximise memory fragmentation sl@0: TUint i = ChunkSize; sl@0: do sl@0: { sl@0: i-=PageSize; sl@0: test.Printf(_L("Commit %d\n"), i); sl@0: r = Ldd.CommitMemory(aCommitType|i,PageSize); sl@0: test(r==KErrNone); sl@0: }while (i>0); sl@0: } sl@0: else sl@0: { sl@0: test.Printf(_L("Commit Contigouos Memory\n")); sl@0: r = Ldd.CommitMemory(aCommitType,TotalChunkSize); sl@0: test(r==KErrNone); sl@0: } sl@0: sl@0: test.Printf(_L("Open user handle\n")); sl@0: r = Ldd.GetChunkHandle(TheChunk); sl@0: test(r==KErrNone); sl@0: sl@0: } sl@0: sl@0: sl@0: void DeAllocateBuffers() sl@0: { sl@0: delete rdBufH; sl@0: delete wrBufH; sl@0: } sl@0: sl@0: void DeAllocareSharedMemory() sl@0: { sl@0: // destory chunk sl@0: test.Printf(_L("Shared Memory\n")); sl@0: test.Printf(_L("Close user chunk handle\n")); sl@0: TheChunk.Close(); sl@0: sl@0: test.Printf(_L("Close kernel chunk handle\n")); sl@0: TInt r = Ldd.CloseChunk(); // 1==DObject::EObjectDeleted sl@0: test(r==1); sl@0: sl@0: test.Printf(_L("Check chunk is destroyed\n")); sl@0: r = Ldd.IsDestroyed(); sl@0: test(r==1); sl@0: sl@0: test.Printf(_L("Close test driver\n")); sl@0: Ldd.Close(); sl@0: } sl@0: sl@0: sl@0: TBool SetupDrivesForPlatform(TInt& aDrive, TInt &aRFsDriveNum) sl@0: /** sl@0: * Finds a MMC/SD suitable drive for testing sl@0: * sl@0: * @param aDrive The number of the local drive to test sl@0: * @return TBool ETrue if a suitable drive is found, EFalse otherwise. sl@0: */ sl@0: { sl@0: sl@0: TDriveInfoV1Buf diBuf; sl@0: UserHal::DriveInfo(diBuf); sl@0: TDriveInfoV1 &di=diBuf(); sl@0: sl@0: test.Printf(_L(" iRegisteredDriveBitmask 0x%08X"), di.iRegisteredDriveBitmask); sl@0: sl@0: aDrive = -1; sl@0: sl@0: TLocalDriveCapsV5Buf capsBuf; sl@0: TBusLocalDrive TBLD; sl@0: TLocalDriveCapsV5& caps = capsBuf(); sl@0: TPtrC8 localSerialNum; sl@0: TInt registeredDriveNum = 0; sl@0: for(aDrive=0; aDrive < KMaxLocalDrives; aDrive++) sl@0: { sl@0: TInt driveNumberMask = 1 << aDrive; sl@0: if ((di.iRegisteredDriveBitmask & driveNumberMask) == 0) sl@0: continue; sl@0: sl@0: test.Printf(_L(" Drive %d - %S\r\n"), aDrive, &di.iDriveName[registeredDriveNum]); sl@0: sl@0: // check that the card is readable (so we can ignore for empty card slots) sl@0: if ((di.iDriveName[registeredDriveNum].MatchF(_L("MultiMediaCard0")) == KErrNone) || sl@0: (di.iDriveName[registeredDriveNum].MatchF(_L("SDIOCard0")) == KErrNone)) sl@0: { sl@0: sl@0: TBool TBLDChangedFlag; sl@0: TInt r = TBLD.Connect(aDrive, TBLDChangedFlag); sl@0: //test.Printf(_L(" Connect returned %d\n"), r); sl@0: if (r == KErrNone) sl@0: { sl@0: r = TBLD.Caps(capsBuf); sl@0: localSerialNum.Set(caps.iSerialNum, caps.iSerialNumLength); sl@0: const TInt KSectSize = 512; sl@0: TBuf8 sect; sl@0: r = TBLD.Read(0, KSectSize, sect); sl@0: //test.Printf(_L(" Read returned %d\n"), r); sl@0: sl@0: TBLD.Disconnect(); sl@0: if (r == KErrNone) sl@0: break; sl@0: } sl@0: } sl@0: registeredDriveNum++; sl@0: } sl@0: sl@0: if(aDrive == KMaxLocalDrives) sl@0: { sl@0: test.Printf(_L(" MMC Drive Not Found\r\n")); sl@0: return EFalse; sl@0: } sl@0: sl@0: // Work out the file server drive number (which isn't necessarily the same sl@0: // as the TBusLocalDrive drive number) sl@0: RFs theFs; sl@0: test(theFs.Connect() == KErrNone); sl@0: sl@0: TInt i; sl@0: for (i = EDriveA; i < EDriveZ; i++) sl@0: { sl@0: TMediaSerialNumber serialNum; sl@0: TInt r = theFs.GetMediaSerialNumber(serialNum, i); sl@0: TInt len = serialNum.Length(); sl@0: TInt n; sl@0: for (n=0; n buf; sl@0: for (TInt m=n; m hexBuf; sl@0: hexBuf.Format(_L("%02X "),serialNum[m]); sl@0: buf.Append(hexBuf); sl@0: } sl@0: buf.Append(_L("\n")); sl@0: test.Printf(buf); sl@0: } sl@0: if (serialNum.Compare(localSerialNum) == 0) sl@0: { sl@0: TVolumeInfo vi; sl@0: r = theFs.Volume(vi, i); sl@0: TBool sizeMatch = (vi.iSize < caps.iSize); sl@0: if (sizeMatch) sl@0: { sl@0: aRFsDriveNum = i; sl@0: break; sl@0: } sl@0: } sl@0: sl@0: } sl@0: if (i == EDriveZ) sl@0: { sl@0: test.Printf(_L(" RFs MMC Drive Not Found\r\n")); sl@0: return EFalse; sl@0: } sl@0: sl@0: theFs.Close(); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: LOCAL_D TBool ParseCommandLineArgs() sl@0: { sl@0: sl@0: TBuf<0x100> cmd; sl@0: User::CommandLine(cmd); sl@0: TLex lex(cmd); sl@0: sl@0: for (TPtrC token=lex.NextToken(); token.Length() != 0;token.Set(lex.NextToken())) sl@0: { sl@0: if (token.CompareF(_L("-m"))== 0) sl@0: { sl@0: ManualMode = ETrue; sl@0: continue; sl@0: } sl@0: } sl@0: sl@0: if (ManualMode) sl@0: { sl@0: // Get the list of drives sl@0: TDriveInfoV1Buf diBuf; sl@0: UserHal::DriveInfo(diBuf); sl@0: TDriveInfoV1 &di=diBuf(); sl@0: TInt driveCount = di.iTotalSupportedDrives; sl@0: sl@0: //Print the list of usable drives sl@0: test.Printf(_L("\nDRIVES USED AT PRESENT :\r\n")); sl@0: sl@0: for (TInt i=0; i < driveCount; i++) sl@0: { sl@0: TBool flag=EFalse; sl@0: RLocalDrive d; sl@0: TInt r=d.Connect(i,flag); sl@0: //Not all the drives are used at present sl@0: if (r == KErrNotSupported) sl@0: continue; sl@0: sl@0: test.Printf(_L("%d : DRIVE NAME :%- 16S\r\n"), i, &di.iDriveName[i]); sl@0: } sl@0: sl@0: test.Printf(_L("\r\nWarning - all data on removable drive will be lost.\r\n")); sl@0: test.Printf(_L("<<>>\r\n")); sl@0: sl@0: TChar driveToTest; sl@0: driveToTest=(TUint)test.Getch(); sl@0: DriveNumber=((TUint)driveToTest) - '0'; sl@0: test(DriveNumber >= 1 && DriveNumber < di.iTotalSupportedDrives); sl@0: sl@0: return ETrue; sl@0: } sl@0: else sl@0: { sl@0: //Auto Mode sl@0: //Lets find an MMC Drive to Test with.... sl@0: return SetupDrivesForPlatform(DriveNumber, RFsDNum); sl@0: } sl@0: } sl@0: sl@0: sl@0: GLDEF_C TInt E32Main() sl@0: { sl@0: test.Title(); sl@0: test.Start(_L("Test the MultiMediaCard (MMC) media driver")); sl@0: sl@0: if (!ParseCommandLineArgs()) sl@0: { sl@0: test.Printf(_L("MMC Drive Not Found - Skipping test\r\n")); sl@0: test.End(); sl@0: return(0); sl@0: } sl@0: sl@0: AllocateBuffers(); sl@0: sl@0: test.Printf(_L("Connect to local drive (%d)\n"),DriveNumber); sl@0: sl@0: ChangeFlag=EFalse; sl@0: test(TheMmcDrive.Connect(DriveNumber,ChangeFlag)==KErrNone); sl@0: sl@0: TTime startTime; sl@0: startTime.HomeTime(); sl@0: sl@0: IsReadOnly = TestDriveInfo(); sl@0: sl@0: // The following line causes t_mmcdrv to jump to the tests that check if the sl@0: // mmc driver will carry on reading when the door is opened, but abort with sl@0: // KErrGeneral when it is not. Enabling the goto here is useful because it sl@0: // allows the tester to skip the long read and write tests, which can take several sl@0: // minutes on a 16Mb card, and longer if tracing is enabled. It also stops the test sl@0: // from returning when !mediaChangeSupported and not getting to the door opening tests. sl@0: sl@0: #if TEST_DOOR_CLOSE sl@0: goto doorTest; sl@0: #endif sl@0: sl@0: for(TInt pass = 0; pass < TMMCDrive::EMaxTestModes; pass++) sl@0: { sl@0: TInt r = KErrNone; sl@0: switch (pass) sl@0: { sl@0: case 0 : r = TheMmcDrive.SetTestMode(TMMCDrive::ETestPartition); break; sl@0: case 1 : sl@0: // don't trash partition table in automated mode because... sl@0: // cards in test rigs have often got deliberately small partition sizes to testing (!) sl@0: if (!ManualMode) sl@0: continue; sl@0: r = TheMmcDrive.SetTestMode(TMMCDrive::ETestWholeMedia); sl@0: break; sl@0: case 2 : { sl@0: r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemory); sl@0: AllocateSharedBuffers(EFalse,EFalse); sl@0: break; sl@0: } sl@0: case 3 : { sl@0: r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryCache); sl@0: AllocateSharedBuffers(EFalse, ETrue); sl@0: break; sl@0: } sl@0: case 4 : { sl@0: r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFrag); sl@0: AllocateSharedBuffers(ETrue, EFalse); sl@0: break; sl@0: } sl@0: default: { sl@0: r = TheMmcDrive.SetTestMode(TMMCDrive::ETestSharedMemoryFragCache); sl@0: AllocateSharedBuffers(ETrue, ETrue); sl@0: break; sl@0: } sl@0: } sl@0: sl@0: sl@0: if(r == KErrNone) sl@0: { sl@0: TestRead(); sl@0: TestCapacity(); sl@0: sl@0: if(IsReadOnly == EFalse) sl@0: { sl@0: TestMultipleBlockReads(); sl@0: TestSectorReadWrite(); sl@0: TestWrite(); sl@0: TestBoundaries(); sl@0: TestFormat(); sl@0: } sl@0: } sl@0: sl@0: if (pass > 1) sl@0: { sl@0: // Shared memory Test Mode in use sl@0: DeAllocareSharedMemory(); sl@0: } sl@0: } sl@0: sl@0: if (mediaChangeSupported) sl@0: { sl@0: // Remainder of tests involve media change sl@0: TestMediaChange(); sl@0: sl@0: #if TEST_DOOR_CLOSE sl@0: doorTest: sl@0: #endif sl@0: test.Next(_L("Launching 1.0Mb Read to interrupt with media change.\n")); sl@0: TestHugeReadWrite(ETrue, 512 * 1024); sl@0: sl@0: test.Next(_L("Launching 1.0Mb Write to interrupt with media change.\n")); sl@0: TestHugeReadWrite(EFalse, 512 * 1024); sl@0: } sl@0: sl@0: TTime endTime; sl@0: endTime.HomeTime(); sl@0: TTimeIntervalMicroSeconds elapsed=endTime.MicroSecondsFrom(startTime); sl@0: test.Printf(_L("\n\r (Elapsed time: %dmS)\r\n"),(elapsed.Int64()/1000)); sl@0: sl@0: test.Printf(_L("Disconnect from local drive (%d)"),DriveNumber); sl@0: TheMmcDrive.Disconnect(); sl@0: sl@0: DeAllocateBuffers(); sl@0: sl@0: // Format card with a File System i.e. FAT sl@0: // Such that it is re-usable by next test sl@0: Format(); sl@0: sl@0: test.End(); sl@0: sl@0: return(0); sl@0: } sl@0: