diff -r 2d65c2f76d7b -r 947f0dc9f7a8 kerneltest/e32test/dma/t_dma.cpp --- a/kerneltest/e32test/dma/t_dma.cpp Tue Feb 02 01:24:03 2010 +0200 +++ b/kerneltest/e32test/dma/t_dma.cpp Fri Apr 16 16:24:37 2010 +0300 @@ -1,4 +1,4 @@ -// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +// Copyright (c) 2002-2010 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available // under the terms of the License "Eclipse Public License v1.0" @@ -69,7 +69,7 @@ _LIT(KTestFailure, "XTEST"); static void TestPanic(TInt aLine, TUint32 a1, TUint32 a2, TUint32 a3) { - RDebug::Printf("Line %d test failed a1=%08x a2=%08x a3=%08x", aLine, a1, a2, a3); + RDebug::Printf("Line %d test failed a1=%08x (%d) a2=%08x (%d) a3=%08x (%d)", aLine, a1, a1, a2, a2, a3, a3); RThread().Panic(KTestFailure, aLine); } #define XTEST(e) if (!(e)) TestPanic(__LINE__, 0, 0, 0) @@ -193,6 +193,71 @@ const TInt iTotalTransferSize; }; +/** +Test that it is possible to close a channel from a callback +*/ +class CCloseInCb : public CTest + { +public: + CCloseInCb() + : CTest(NULL, 1), iTransferSize(4 * KKilo) + {} + + TInt virtual DoRunTest(); + + virtual void AnnounceTest(TDes& aDes) + { + aDes.AppendFormat(_L("CCloseInCb")); + CTest::AnnounceTest(aDes); + } + + CTest* Clone() const + {return new CCloseInCb(*this);} +private: + const TInt iTransferSize; + + }; + +/** +Perform multiple transfers with different fragment counts and with smaller +and smaller fragment size + +This checks that the PSL's ISR(s) are properly written, and do not miss interrupts +or notify the PIL spuriously. +*/ +class CFragSizeRange : public CTest + { +public: + CFragSizeRange(TInt aMaxIter, TInt aFragCount, TInt aInitialFragmentSize, TInt aInnerIteraions) + : CTest(NULL, aMaxIter), iMaxFragCount(aFragCount), iFragCount(1), iInitialFragmentSize(aInitialFragmentSize), + iInnerIterations(aInnerIteraions) + {} + + TInt virtual DoRunTest(); + + virtual void AnnounceTest(TDes& aDes) + { + aDes.AppendFormat(_L("CFragSizeRange: Fragments %d, intital frag size %d, inner iters %d "), iFragCount, iInitialFragmentSize, iInnerIterations); + CTest::AnnounceTest(aDes); + } + + CTest* Clone() const + {return new CFragSizeRange(*this);} + +private: + /** + Run the transfer + */ + TInt Transfer(TInt aFragSize); + + + TInt iMaxFragCount; + TInt iFragCount; + const TInt iInitialFragmentSize; + const TInt iInnerIterations; + + RTimer iTimer; + }; // // Active object used to create a tester thread, log on to it and @@ -346,6 +411,140 @@ return KErrNone; } +TInt CCloseInCb::DoRunTest() + { + TInt r = KErrNone; + RTest test(_L("CCloseInCb test")); + + r = OpenChannel(1); + test_KErrNone(r); + + const TInt KRequest = 0; + const TInt KSrcBuf = 0; + const TInt KDestBuf = 1; + + const TInt size = Min(iTransferSize, Info.iMaxTransferSize); + + r = iChannel.AllocBuffer(KSrcBuf, size); + test_KErrNone(r); + iChannel.FillBuffer(KSrcBuf, 'A'); + r = iChannel.AllocBuffer(KDestBuf, size); + test_KErrNone(r); + iChannel.FillBuffer(KDestBuf, '\0'); + + TRequestStatus rs = KRequestPending; + r = iChannel.Fragment(KRequest, KSrcBuf, KDestBuf, size, &rs); + test_KErrNone(r); + + // "X" will cause channel to be closed during callback + r = iChannel.Execute(_L8("QX0")); + test_KErrNone(r); + + User::WaitForRequest(rs); + test_KErrNone(rs.Int()); + + test(iChannel.CheckBuffer(KDestBuf, 'A')); + iChannel.FreeAllBuffers(); + + test.Close(); + return KErrNone; + } + +TInt CFragSizeRange::DoRunTest() + { + const TInt initialFragmentSize = Min(iInitialFragmentSize, Info.iMaxTransferSize); + + TInt r = KErrNone; + RTest test(_L("CFragSizeRange test")); + + r = iTimer.CreateLocal(); + test_KErrNone(r); + + + TInt fragSize = initialFragmentSize; + TInt step = 0; + do + { + fragSize -= step; + // make sure size is aligned + fragSize = fragSize & ~Info.iMemAlignMask; + + r = OpenChannel(iMaxFragCount, fragSize); + test_KErrNone(r); + + for(iFragCount=1; iFragCount <= iMaxFragCount; iFragCount++) + { + test.Printf(_L("Fragment size %d bytes, %d fragments\nIter: "), fragSize, iFragCount); + for(TInt i=0; i 0); + + iTimer.Close(); + + test.Close(); + return r; + } + +TInt CFragSizeRange::Transfer(TInt aFragmentSize) + { + const TInt KRequest = 0; + const TInt KSrcBuf = 0; + const TInt KDestBuf = 1; + + const TInt size = aFragmentSize * iFragCount; + + TInt r = iChannel.AllocBuffer(KSrcBuf, size); + test_KErrNone(r); + iChannel.FillBuffer(KSrcBuf, 'A'); + r = iChannel.AllocBuffer(KDestBuf, size); + XTEST2(r == KErrNone, r, size); + iChannel.FillBuffer(KDestBuf, '\0'); + + // Test simple transfer + TRequestStatus rs = KRequestPending; + r = iChannel.Fragment(KRequest, KSrcBuf, KDestBuf, size, &rs); + test_KErrNone(r); + + test(iChannel.FragmentCheck(KRequest, iFragCount)); + r = iChannel.Execute(_L8("Q0")); + test_KErrNone(r); + + const TInt microSecTimeout = 1000000; // 1s + TRequestStatus timerStatus; + iTimer.After(timerStatus, microSecTimeout); + + User::WaitForRequest(rs, timerStatus); + if(rs.Int() == KRequestPending) + { + RDebug::Print(_L("Transfer timed out!")); + // timed out + test(EFalse); + } + iTimer.Cancel(); + test_KErrNone(rs.Int()); + test(iChannel.CheckBuffer(KDestBuf, 'A')); + + // Queue, then cancel request - Checks + // that there there is no spurious callback + // to the PIL + r = iChannel.Execute(_L8("Q0C")); + test_KErrNone(r); + + iChannel.FreeAllBuffers(); + return KErrNone; + } + // Called when thread completed. void CTesterThread::RunL() @@ -414,7 +613,6 @@ if (aMaxThread == 0) { - delete aTest; test.Printf(_L("transfer mode not supported - skipped\n")); return; } @@ -444,9 +642,6 @@ test(new CTesterThread(i, dmaTest) != NULL); dmaTest = NULL; //ownership transferred to CTesterThread } - //the orginal isn't needed - delete aTest; - aTest = NULL; const TTimeIntervalMicroSeconds32 KPeriod = 1000000; // 1s Bipper->Start(KPeriod, KPeriod, Bip); @@ -459,17 +654,29 @@ inline void RunSbTest(TInt aMaxThread, CTest* aTest) { + RunTest(Info.iSbChannels, Min(1,Info.iMaxSbChannels), aTest); RunTest(Info.iSbChannels, Min(aMaxThread,Info.iMaxSbChannels), aTest); + + //the orginal isn't needed + delete aTest; } inline void RunDbTest(TInt aMaxThread, CTest* aTest) { + RunTest(Info.iDbChannels, Min(1,Info.iMaxDbChannels), aTest); RunTest(Info.iDbChannels, Min(aMaxThread,Info.iMaxDbChannels), aTest); + + //the orginal isn't needed + delete aTest; } inline void RunSgTest(TInt aMaxThread, CTest* aTest) { + RunTest(Info.iSgChannels, Min(1,Info.iMaxSgChannels), aTest); RunTest(Info.iSgChannels, Min(aMaxThread,Info.iMaxSgChannels), aTest); + + //the orginal isn't needed + delete aTest; } ////////////////////////////////////////////////////////////////////////////// @@ -964,6 +1171,35 @@ test.Next(_L("Getting channel info")); GetChannelInfo(); + test.Next(_L("Test that channel can be closed from callback")); + test.Next(_L("sb")); + RunSbTest(maxchannel, new CCloseInCb() ); + test.Next(_L("db")); + RunDbTest(maxchannel, new CCloseInCb() ); + test.Next(_L("sg")); + RunSgTest(maxchannel, new CCloseInCb() ); + + test.Next(_L("Testing different fragment sizes")); + + const TInt rangeFragSize = 4096; +#ifdef __DMASIM__ + // Use fewer iterations on the emulator + // since it is slower. Also this test is really + // intended to find errors in PSL implmentations + const TInt iterPerFragSize = 1; +#else + const TInt iterPerFragSize = 30; +#endif + const TInt rangeMaxFragCount = 8; + + test.Next(_L("sb")); + RunSbTest(maxchannel, new CFragSizeRange(1, rangeMaxFragCount, rangeFragSize, iterPerFragSize)); + test.Next(_L("db")); + RunDbTest(maxchannel, new CFragSizeRange(1, rangeMaxFragCount, rangeFragSize, iterPerFragSize)); + test.Next(_L("sg")); + RunSgTest(maxchannel, new CFragSizeRange(1, rangeMaxFragCount, rangeFragSize, iterPerFragSize)); + + // Size for the single transfer test TInt totalTransferSize = 64 * KKilo;