First public contribution.
1 // Copyright (c) 2002-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 // e32test\dma\t_dma.cpp
16 // Test the DMA channel functionality.
18 // RBusLogicalChannel, DLogicalChannelBase, DLogicalDevice
20 // - Load the DMA LDD, create a critical section, an active scheduler and
21 // a CPeriodic object.
22 // - Test one shot single buffer transfers: test simple transfer, request
23 // reconfiguration and cancelling. Verify results are as expected.
24 // - Test one shot double buffer transfers: test simple transfer, request
25 // reconfiguration and cancelling. Verify results are as expected.
26 // - Test streaming single buffer transfers: test simple transfer and
27 // cancelling. Test that framework behaves correctly if one or more DMA
28 // interrupts are missed. Verify results are as expected.
29 // - Test streaming double buffer transfers: test simple transfer and
30 // cancelling. Test that framework behaves correctly if one or more DMA
31 // interrupts are missed. Verify results are as expected.
32 // - Test streaming scatter/gather transfers: test simple transfer and
33 // cancelling. Test that framework behaves correctly if one or more DMA
34 // interrupts are missed. Verify results are as expected.
35 // Platforms/Drives/Compatibility:
36 // Hardware (Automatic).
37 // Assumptions/Requirement/Pre-requisites:
38 // Failures and causes:
39 // Base Port information:
43 #define __E32TEST_EXTENSION__
49 #include <e32def_private.h>
53 RTest test(_L("T_DMASIM"));
55 RTest test(_L("T_DMA"));
58 //////////////////////////////////////////////////////////////////////////////
59 // Mini-framework for running tests either in a single thread or in
60 // several concurrent ones.
64 RCriticalSection TheCriticalSection; // protect following variables
65 TInt ThreadCount; // decremented when tester thread dies
66 CPeriodic* Bipper; // display dots during tests to detect lock-ups
68 // Test macro used inside tester threads
69 _LIT(KTestFailure, "XTEST");
70 static void TestPanic(TInt aLine, TUint32 a1, TUint32 a2, TUint32 a3)
72 RDebug::Printf("Line %d test failed a1=%08x a2=%08x a3=%08x", aLine, a1, a2, a3);
73 RThread().Panic(KTestFailure, aLine);
75 #define XTEST(e) if (!(e)) TestPanic(__LINE__, 0, 0, 0)
76 #define XTEST1(e,a1) if (!(e)) TestPanic(__LINE__, (a1), 0, 0)
77 #define XTEST2(e,a1,a2) if (!(e)) TestPanic(__LINE__, (a1), (a2), 0)
78 #define XTEST3(e,a1,a2,a3) if (!(e)) TestPanic(__LINE__, (a1), (a2), (a3))
83 @note Have not inherited from CBase so that implicit copy ctors are used
88 typedef void (*TTestFunction)(RTestDma aChannel, TInt aMaxFragment, TInt aFragmentSize);
90 CTest(TTestFunction aFn, TInt aMaxIter)
91 :iTestFn(aFn), iChannelId(0), iMaxIter(aMaxIter)
99 virtual TBool OpenChannel(TInt aDesCount, TInt aMaxFragmentSize=0);
101 virtual void AnnounceTest(TDes& aDes)
102 {aDes.AppendFormat(_L("Channel Id %d, iMaxIter %d"), iChannelId, iMaxIter);}
103 virtual void ReportState(TDes& aDes)
104 {aDes.AppendFormat(_L("Channel Id %d, iCurIter %d"), iChannelId, iCurIter);}
107 void SetChannelId(TUint32 aChannelId)
108 {iChannelId = aChannelId;}
110 TInt MaxIter() const {return iMaxIter;}
111 TInt CurIter() const {return iCurIter;}
114 @return A copy of this test
116 virtual CTest* Clone() const =0;
119 TInt virtual DoRunTest() =0;
121 const TTestFunction iTestFn;
129 Specifies a DMA test where the maximum fragmentation is
130 explicitly limited. This tests that requests are split
131 in to the number of fragments expected.
133 This test also requires that physically contiguous buffers
134 are used. For this reason the product of iMaxFragment and
135 iMaxFragmentSize should be kept small
137 class CFragmentationTest : public CTest
140 CFragmentationTest(TTestFunction aFn, TInt aMaxIter, TInt aMaxFragment, TInt aMaxFragmentSize)
141 : CTest(aFn, aMaxIter), iMaxFragment(aMaxFragment), iMaxFragmentSize(aMaxFragmentSize), iCurFragment(0)
144 TInt virtual DoRunTest();
146 virtual void AnnounceTest(TDes& aDes)
148 aDes.AppendFormat(_L("CFragmentationTest: Frag count = [1..%d], Max Frag Size = 0x%08x bytes: "), iMaxFragment, iMaxFragmentSize);
149 CTest::AnnounceTest(aDes);
152 virtual void ReportState(TDes& aDes)
154 aDes.AppendFormat(_L("CFragmentationTest: Current Fragment %d: "), iCurFragment);
155 CTest::ReportState(aDes);
159 {return new CFragmentationTest(*this);}
162 const TInt iMaxFragment;
163 TInt iMaxFragmentSize;
168 Specifies a DMA test where the maximum fragment size is
169 not limited - and we do not care how many fragments are
172 - This checks that transfers work correctly with the DMAC's
173 default fragment size
175 class CDefaultFragTest : public CTest
178 CDefaultFragTest(TTestFunction aFn, TInt aMaxIter, TUint aTotalTransferSize)
179 : CTest(aFn, aMaxIter), iTotalTransferSize(aTotalTransferSize)
182 TInt virtual DoRunTest();
184 virtual void AnnounceTest(TDes& aDes)
186 aDes.AppendFormat(_L("CDefaultFragTest: Transfer = 0x%08x bytes: "), iTotalTransferSize);
187 CTest::AnnounceTest(aDes);
191 {return new CDefaultFragTest(*this);}
193 const TInt iTotalTransferSize;
198 // Active object used to create a tester thread, log on to it and
199 // interpret its exit status.
201 class CTesterThread : public CActive
204 CTesterThread(TInt aIdx, CTest* aTest);
210 static TInt ThreadFunction(TAny* aSelf);
213 virtual void DoCancel();
222 Run the test for iMaxIter iterations
224 TInt CTest::RunTest()
227 for (iCurIter=0; iCurIter<iMaxIter; ++iCurIter)
239 @pre iChannel is not open
241 - KErrNotSupported Channel does not exist on DMAC
245 TInt CTest::OpenChannel(TInt aDesCount, TInt aMaxFragmentSize)
247 ASSERT(!iChannel.Handle());
248 const TInt r = iChannel.Open(iChannelId, aDesCount, aMaxFragmentSize);
249 if (r == KErrNotSupported)
251 XTEST1(KErrNone == r || KErrInUse == r, r);
255 // Channel is in use.
256 RDebug::Printf("\nDMA Channel %d is in use",iChannelId);
259 // Terminate thread by returning this error code KErrInUse.
265 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
267 XTEST1(EFalse, iCurIter);
269 #pragma warning( default : 4127 ) // warning C4127: conditional expression is constant
278 // Spawn thread. Will auto-delete when thread exits.
279 CTesterThread::CTesterThread(TInt aIdx, CTest* aTest)
280 : CActive(EPriorityStandard), iTest(aTest)
282 CActiveScheduler::Add(this);
284 name = _L("TESTER-");
285 name.AppendNum(aIdx);
286 test(iThread.Create(name, ThreadFunction, 0x1000, NULL, this) == KErrNone);
287 iThread.SetPriority(EPriorityLess);
288 iThread.Logon(iStatus);
294 TInt CTesterThread::ThreadFunction(TAny* aSelf)
296 CTesterThread* self = (CTesterThread*)aSelf;
297 return self->StartThread();
300 TInt CTesterThread::StartThread()
302 return iTest->RunTest();
307 TInt CFragmentationTest::DoRunTest()
309 // In case iMaxFragmentSize was larger than suppported (we need to know what fragment
310 // size will actually be used)
311 iMaxFragmentSize = Min(iMaxFragmentSize, Info.iMaxTransferSize);
313 // Open channel with enough descriptors for 3 open DMA
314 // requests (see TestStreaming).
315 TInt r = OpenChannel(3* iMaxFragment, iMaxFragmentSize);
319 //we are controlling fragment size, so we know how
321 for (iCurFragment=1; iCurFragment<=iMaxFragment; iCurFragment*=2)
323 const TInt size = iCurFragment * ( iMaxFragmentSize & ~Info.iMemAlignMask);
324 iTestFn(iChannel, iCurFragment, size);
330 TInt CDefaultFragTest::DoRunTest()
332 // +1 so we don't underestimate maxFragount for inexact division
333 const TUint maxFragCount = (iTotalTransferSize / Info.iMaxTransferSize) +1;
335 // Open channel with enough descriptors for 3 open DMA
336 // requests (see TestStreaming).
337 const TUint descriptorCount = 3 * maxFragCount;
339 TInt r = OpenChannel(descriptorCount);
343 iTestFn(iChannel, 0, iTotalTransferSize);
350 // Called when thread completed.
351 void CTesterThread::RunL()
353 TExitType et = iThread.ExitType();
354 TInt er = iThread.ExitReason();
355 TExitCategoryName ec = iThread.ExitCategory();
356 TName name = iThread.Name();
357 CLOSE_AND_WAIT(iThread);
366 User::SetJustInTime(JitEnabled);
368 iTest->ReportState(buffer);
369 test.Printf(_L("Tester Thread Panic: %S: Test: %S\n"),
371 if (ec.Match(KTestFailure) == 0)
372 test.Panic(_L("Test failure line %d"), er);
374 test.Panic(_L("Unexpected panic: %S-%d"), &ec, er);
378 test.Panic(_L("Invalid thread exit type"));
381 TheCriticalSection.Wait();
382 if (--ThreadCount == 0)
385 test.Console()->Printf(_L("\n"));
386 CActiveScheduler::Stop();
388 TheCriticalSection.Signal();
390 // We commit suicide as the alternative (being deleted by
391 // RunTest()) implies keeping a list of all instances in
397 void CTesterThread::DoCancel()
399 test.Panic(_L("CTesterThread::DoCancel called"));
403 static TInt Bip(TAny*)
405 test.Console()->Printf(_L("."));
410 // Execute provided test object in one or more tester threads.
411 void RunTest(TUint32 aChannelIds[], TInt aMaxThread, CTest* aTest)
418 test.Printf(_L("transfer mode not supported - skipped\n"));
422 test.Printf(_L("Using %d thread(s)\n"), aMaxThread);
424 // We don't want JIT debugging here because the tester threads may panic
425 JitEnabled = User::JustInTime();
426 User::SetJustInTime(EFalse);
428 // must be set before spawning threads to avoid premature active scheduler stop
429 ThreadCount = aMaxThread;
432 for (TInt i=0; i<aMaxThread; ++i)
434 //each CTesterThread needs its own CTest object
435 CTest* dmaTest = aTest->Clone();
436 test_NotNull(dmaTest);
438 dmaTest->SetChannelId(aChannelIds[i]);
441 dmaTest->AnnounceTest(buffer);
442 test.Printf(_L("Thread %d: %S\n"), i, &buffer);
444 test(new CTesterThread(i, dmaTest) != NULL);
445 dmaTest = NULL; //ownership transferred to CTesterThread
447 //the orginal isn't needed
451 const TTimeIntervalMicroSeconds32 KPeriod = 1000000; // 1s
452 Bipper->Start(KPeriod, KPeriod, Bip);
454 CActiveScheduler::Start();
456 User::SetJustInTime(JitEnabled);
460 inline void RunSbTest(TInt aMaxThread, CTest* aTest)
462 RunTest(Info.iSbChannels, Min(aMaxThread,Info.iMaxSbChannels), aTest);
465 inline void RunDbTest(TInt aMaxThread, CTest* aTest)
467 RunTest(Info.iDbChannels, Min(aMaxThread,Info.iMaxDbChannels), aTest);
470 inline void RunSgTest(TInt aMaxThread, CTest* aTest)
472 RunTest(Info.iSgChannels, Min(aMaxThread,Info.iMaxSgChannels), aTest);
474 //////////////////////////////////////////////////////////////////////////////
476 static void GetChannelInfo()
479 test(channel.GetInfo(Info) == KErrNone);
480 test(Info.iMaxSbChannels>0 || Info.iMaxDbChannels>0 || Info.iMaxSgChannels>0);
484 static void TestOneShot(RTestDma aChannel, TInt aFragmentCount, TInt aSize)
486 const TInt KRequest = 0;
487 const TInt KSrcBuf = 0;
488 const TInt KDestBuf1 = 1;
489 const TInt KDestBuf2 = 2;
491 TInt r = aChannel.AllocBuffer(KSrcBuf, aSize);
492 XTEST2(r == KErrNone, r, aSize);
493 aChannel.FillBuffer(KSrcBuf, 'A');
494 r = aChannel.AllocBuffer(KDestBuf1, aSize);
495 XTEST2(r == KErrNone, r, aSize);
496 aChannel.FillBuffer(KDestBuf1, '\0');
497 r = aChannel.AllocBuffer(KDestBuf2, aSize);
498 XTEST2(r == KErrNone, r, aSize);
499 aChannel.FillBuffer(KDestBuf2, '\0');
501 // Test simple transfer
503 r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
504 XTEST2(r == KErrNone, r, aSize);
505 test(aChannel.FragmentCheck(KRequest, aFragmentCount));
506 r = aChannel.Execute(_L8("Q0"));
507 XTEST1(r == KErrNone, r);
508 User::WaitForRequest(rs);
509 XTEST1(rs == KErrNone, rs.Int());
510 XTEST(aChannel.CheckBuffer(KDestBuf1, 'A'));
512 // Test request reconfiguration.
513 aChannel.FillBuffer(KDestBuf1, '\0');
514 r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf2, aSize, &rs);
515 XTEST2(r == KErrNone, r, aSize);
516 test(aChannel.FragmentCheck(KRequest, aFragmentCount));
517 r = aChannel.Execute(_L8("Q0"));
518 XTEST1(r == KErrNone, r);
519 User::WaitForRequest(rs);
520 XTEST1(rs == KErrNone, rs.Int());
521 XTEST(aChannel.CheckBuffer(KDestBuf1, '\0')); // previous dest unchanged?
522 XTEST(aChannel.CheckBuffer(KDestBuf2, 'A'));
525 aChannel.FillBuffer(KDestBuf1, '\0');
526 r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize);
527 XTEST2(r == KErrNone, r, aSize);
528 test(aChannel.FragmentCheck(KRequest, aFragmentCount));
529 r = aChannel.Execute(_L8("Q0C"));
530 XTEST1(r == KErrNone, r);
531 // Part of the destination buffer should be unchanged if the
532 // cancel occured before the transfer completed.
534 // At least part of the last destination buffer should be
535 // unchanged if cancel occured before the transfer completed.
536 // Assert only on WINS as real DMACs are too fast.
537 XTEST(! aChannel.CheckBuffer(KDestBuf2, 'C'));
540 // Perform another transfer to ensure cancel operation let the
541 // framework in a consistent state.
542 aChannel.FillBuffer(KDestBuf1, '\0');
543 r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
544 XTEST2(r == KErrNone, r, aSize);
545 test(aChannel.FragmentCheck(KRequest, aFragmentCount));
546 r = aChannel.Execute(_L8("Q0"));
547 XTEST1(r == KErrNone, r);
548 User::WaitForRequest(rs);
549 XTEST1(rs == KErrNone, rs.Int());
550 XTEST(aChannel.CheckBuffer(KDestBuf1, 'A'));
553 // Test failure if the underlying DMA kernel extension allows it.
555 // As long as only "CancelAllFragments" is supported, it's okay to
556 // always fail on the first fragment.
559 if (aChannel.FailNext(1) == KErrNone)
561 aChannel.FillBuffer(KDestBuf1, '\0');
562 r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
563 XTEST2(r == KErrNone, r, aSize);
564 test(aChannel.FragmentCheck(KRequest, aFragmentCount));
565 r = aChannel.Execute(_L8("Q0"));
566 XTEST1(r == KErrNone, r);
567 User::WaitForRequest(rs);
568 XTEST1(rs != KErrNone, rs.Int());
569 XTEST(! aChannel.CheckBuffer(KDestBuf1, 'A'));
570 r = aChannel.Execute(_L8("C"));
571 XTEST1(r == KErrNone, r);
573 // Perform another transfer to ensure we are still in a
575 aChannel.FillBuffer(KDestBuf1, '\0');
576 r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
577 XTEST2(r == KErrNone, r, aSize);
578 test(aChannel.FragmentCheck(KRequest, aFragmentCount));
579 r = aChannel.Execute(_L8("Q0"));
580 XTEST1(r == KErrNone, r);
581 User::WaitForRequest(rs);
582 XTEST1(rs == KErrNone, rs.Int());
583 XTEST(aChannel.CheckBuffer(KDestBuf1, 'A'));
586 aChannel.FreeAllBuffers();
590 static void TestStreaming(RTestDma aChannel, TInt aFragmentCount, TInt aSize)
592 const TInt KRequest0 = 0;
593 const TInt KRequest1 = 1;
594 const TInt KRequest2 = 2;
595 const TInt KSrcBuf0 = 0;
596 const TInt KSrcBuf1 = 1;
597 const TInt KSrcBuf2 = 2;
598 const TInt KDestBuf0 = 3;
599 const TInt KDestBuf1 = 4;
600 const TInt KDestBuf2 = 5;
603 // Allocate and initialise source buffers
606 TInt r = aChannel.AllocBuffer(KSrcBuf0, aSize);
607 XTEST2(r == KErrNone, r, aSize);
608 aChannel.FillBuffer(KSrcBuf0, 'A');
610 r = aChannel.AllocBuffer(KSrcBuf1, aSize);
611 XTEST2(r == KErrNone, r, aSize);
612 aChannel.FillBuffer(KSrcBuf1, 'B');
614 r = aChannel.AllocBuffer(KSrcBuf2, aSize);
615 XTEST2(r == KErrNone, r, aSize);
616 aChannel.FillBuffer(KSrcBuf2, 'C');
619 // Allocate destination buffers
622 r = aChannel.AllocBuffer(KDestBuf0, aSize);
623 XTEST2(r == KErrNone, r, aSize);
624 r = aChannel.AllocBuffer(KDestBuf1, aSize);
625 XTEST2(r == KErrNone, r, aSize);
626 r = aChannel.AllocBuffer(KDestBuf2, aSize);
627 XTEST2(r == KErrNone, r, aSize);
630 // Test simple transfer.
631 // (no need to test for request reconfiguration afterwards because
632 // this was exercised in the one-shot test case)
636 r = aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0);
637 XTEST2(r == KErrNone, r, aSize);
638 test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
640 r = aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1);
641 XTEST2(r == KErrNone, r, aSize);
642 test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
644 r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
645 XTEST2(r == KErrNone, r, aSize);
646 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
648 r = aChannel.Execute(_L8("Q0Q1Q2"));
649 XTEST1(r == KErrNone, r);
650 User::WaitForRequest(rs0);
651 XTEST1(rs0 == KErrNone, rs0.Int());
652 XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
653 User::WaitForRequest(rs1);
654 XTEST1(rs1 == KErrNone, rs1.Int());
655 XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
656 User::WaitForRequest(rs2);
657 XTEST1(rs2 == KErrNone, rs2.Int());
658 XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
664 aChannel.FillBuffer(KDestBuf0, '\0');
665 aChannel.FillBuffer(KDestBuf1, '\0');
666 aChannel.FillBuffer(KDestBuf2, '\0');
668 r = aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize);
669 XTEST2(r == KErrNone, r, aSize);
670 test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
671 r = aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize);
672 XTEST2(r == KErrNone, r, aSize);
673 test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
674 r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize);
675 XTEST2(r == KErrNone, r, aSize);
676 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
678 r = aChannel.Execute(_L8("Q0Q1Q2C"));
679 XTEST1(r == KErrNone, r);
681 // At least part of the last destination buffer should be
682 // unchanged if cancel occured before the transfer completed.
683 // Assert only on WINS as real DMACs are too fast.
684 XTEST(! aChannel.CheckBuffer(KDestBuf2, 'C'));
688 // Perform another transfer to ensure cancel operation let the
689 // framework in a consistent state.
692 aChannel.FillBuffer(KDestBuf0, '\0');
693 aChannel.FillBuffer(KDestBuf1, '\0');
694 aChannel.FillBuffer(KDestBuf2, '\0');
695 // Reconfigure last request to enable transfer completion notification
696 r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
697 XTEST2(r == KErrNone, r, aSize);
698 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
699 r = aChannel.Execute(_L8("Q0Q1Q2"));
700 XTEST1(r == KErrNone, r);
701 User::WaitForRequest(rs2);
702 XTEST1(rs2 == KErrNone, rs2.Int());
703 XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
704 XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
705 XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
708 // Test for proper implementation of UnlinkHwDes() in the PSL.
711 aChannel.FillBuffer(KDestBuf0, '\0');
712 aChannel.FillBuffer(KDestBuf1, '\0');
713 aChannel.FillBuffer(KDestBuf2, '\0');
714 // Reconfigure last request to enable transfer completion notification
715 r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
716 XTEST2(r == KErrNone, r, aSize);
717 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
718 // Queue first request (Q0)
719 r = aChannel.Execute(_L8("Q0"));
720 // Wait a second, so next request will be queued on its own
721 // (instead of being appended to the previous one)
722 User::After(1000000);
723 // Queue third request (Q2)
724 r = aChannel.Execute(_L8("Q2"));
725 XTEST1(r == KErrNone, r);
726 User::WaitForRequest(rs2);
727 XTEST1(rs2 == KErrNone, rs2.Int());
728 XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
729 // KDestBuf1 should have been left untouched!
730 // If we find all B's in KDestBuf1, that means the last descriptor of the
731 // first request (Q0) wasn't properly unlinked and still points to the Q1
732 // descriptor chain from the previous run.
733 XTEST(aChannel.CheckBuffer(KDestBuf1, '\0'));
734 XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
737 // Test failure if the underlying DMA kernel extension allows it.
739 // As long as only "CancelAllFragments" is supported, it's okay to
740 // always fail on the first fragment.
743 if (aChannel.FailNext(1) == KErrNone)
745 aChannel.FillBuffer(KDestBuf0, '\0');
746 aChannel.FillBuffer(KDestBuf1, '\0');
747 aChannel.FillBuffer(KDestBuf2, '\0');
748 XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
749 test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
750 XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize) == KErrNone);
751 test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
752 XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize) == KErrNone);
753 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
754 XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
755 User::WaitForRequest(rs0);
756 XTEST(rs0 != KErrNone);
757 XTEST(! aChannel.CheckBuffer(KDestBuf0, 'A'));
758 XTEST(! aChannel.CheckBuffer(KDestBuf1, 'B'));
759 XTEST(! aChannel.CheckBuffer(KDestBuf2, 'C'));
760 XTEST(aChannel.Execute(_L8("C")) == KErrNone);
762 // Transfer again to ensure cancel cleaned-up correctly
763 aChannel.FillBuffer(KDestBuf0, '\0');
764 aChannel.FillBuffer(KDestBuf1, '\0');
765 aChannel.FillBuffer(KDestBuf2, '\0');
766 XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
767 test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
768 XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1) == KErrNone);
769 test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
770 XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2) == KErrNone);
771 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
772 XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
773 User::WaitForRequest(rs0);
774 XTEST(rs0 == KErrNone);
775 User::WaitForRequest(rs1);
776 XTEST(rs1 == KErrNone);
777 User::WaitForRequest(rs2);
778 XTEST(rs2 == KErrNone);
779 XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
780 XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
781 XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
785 // Test that framework behaves correctly if one or more DMA interrupts are
789 if (aChannel.MissNextInterrupts(1) == KErrNone)
791 aChannel.FillBuffer(KDestBuf0, '\0');
792 aChannel.FillBuffer(KDestBuf1, '\0');
793 aChannel.FillBuffer(KDestBuf2, '\0');
794 XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
795 test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
796 XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1) == KErrNone);
797 test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
798 XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2) == KErrNone);
799 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
800 XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
801 User::WaitForRequest(rs0);
802 XTEST(rs0 == KErrNone);
803 User::WaitForRequest(rs1);
804 XTEST(rs1 == KErrNone);
805 User::WaitForRequest(rs2);
806 XTEST(rs2 == KErrNone);
807 XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
808 XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
809 XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
812 if (aChannel.MissNextInterrupts(2) == KErrNone)
814 aChannel.FillBuffer(KDestBuf0, '\0');
815 aChannel.FillBuffer(KDestBuf1, '\0');
816 aChannel.FillBuffer(KDestBuf2, '\0');
817 XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
818 test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
819 XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1) == KErrNone);
820 test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
821 XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2) == KErrNone);
822 test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
823 XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
824 User::WaitForRequest(rs0);
825 XTEST(rs0 == KErrNone);
826 User::WaitForRequest(rs1);
827 XTEST(rs1 == KErrNone);
828 User::WaitForRequest(rs2);
829 XTEST(rs2 == KErrNone);
830 XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
831 XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
832 XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
835 aChannel.FreeAllBuffers();
839 static TBool ParseCmdLine(TBool& aCrashDbg, TInt& aMaxfrag, TInt& aMaxIter, TInt& aMaxchannel, TInt& aMaxFragSize)
841 // The command line. Syntax is:
843 // t_dma [enableCrashDebugger [aMaxFrag [aMaxIter [aMaxchannel [aMaxFragSize]]]]]
847 User::CommandLine(cmdline);
854 if (lex.Val(aCrashDbg) != KErrNone)
859 if (lex.Val(aMaxfrag) != KErrNone)
864 if (lex.Val(aMaxIter) != KErrNone)
869 if (lex.Val(aMaxchannel) != KErrNone)
875 return lex.Val(aMaxFragSize) == KErrNone;
883 test.Start(_L("Parsing command-line"));
884 // Default values when run with empty command-line
885 TInt maxfrag = 16; // 5 fragments needed to exercise fully double-buffering state machine
887 TInt maxchannel = KMaxTInt;
888 TBool crashDbg = EFalse;
889 TInt maxFragSize = 0x4000; //16k
891 (void) ParseCmdLine(crashDbg, maxfrag, maxIter, maxchannel, maxFragSize);
895 User::SetCritical(User::ESystemCritical);
896 User::SetProcessCritical(User::ESystemCritical);
901 #if defined(__DMASIM__) && defined(__WINS__)
902 test.Next(_L("Loading DMA simulator"));
903 r = User::LoadLogicalDevice(_L("DMASIM.DLL"));
904 test(r == KErrNone || r == KErrAlreadyExists);
907 test.Next(_L("Loading test LDD"));
909 r = User::LoadLogicalDevice(_L("D_DMASIM"));
910 test(r == KErrNone || r == KErrAlreadyExists);
912 //load either the original test ldd, d_dma.ldd,
913 //or d_dma_compat.ldd - an ldd providing the same interface
914 //but linked against the new MHA dma framework
915 _LIT(KDma, "D_DMA.LDD");
916 r = User::LoadLogicalDevice(KDma);
917 const TBool dmaPresent = (r == KErrNone || r == KErrAlreadyExists);
919 _LIT(KDmaCompat, "D_DMA_COMPAT.LDD");
920 r = User::LoadLogicalDevice(KDmaCompat);
921 const TBool dmaCompatPresent = (r == KErrNone || r == KErrAlreadyExists);
923 if (!(dmaPresent || dmaCompatPresent))
925 test.Printf(_L("DMA test driver not found - test skipped\n"));
928 else if (dmaPresent && !dmaCompatPresent)
930 test.Printf(_L("Loaded %S\n"), &KDma);
932 else if (!dmaPresent && dmaCompatPresent)
934 test.Printf(_L("Loaded %S\n"), &KDmaCompat);
938 test.Printf(_L("The ROM contains %S and %S - only one should be present\n"), &KDma, &KDmaCompat);
943 // Turn off evil lazy dll unloading
945 test(l.Connect()==KErrNone);
946 test(l.CancelLazyDllUnload()==KErrNone);
952 test.Next(_L("Creating critical section"));
953 test(TheCriticalSection.CreateLocal() == KErrNone);
955 test.Next(_L("Creating active scheduler"));
956 CActiveScheduler* pS = new CActiveScheduler;
958 CActiveScheduler::Install(pS);
960 test.Next(_L("Creating bipper"));
961 Bipper = CPeriodic::New(CActive::EPriorityStandard);
962 test(Bipper != NULL);
964 test.Next(_L("Getting channel info"));
967 // Size for the single transfer test
968 TInt totalTransferSize = 64 * KKilo;
970 test.Next(_L("Testing one shot single buffer transfer"));
971 RunSbTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
972 RunSbTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
974 test.Next(_L("Testing one shot double buffer transfer"));
975 RunDbTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
976 RunDbTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
978 test.Next(_L("Testing one shot scatter/gather transfer"));
979 RunSgTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
980 RunSgTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
982 test.Next(_L("Testing streaming single buffer transfer"));
983 RunSbTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
984 RunSbTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
986 test.Next(_L("Testing streaming double buffer transfer"));
987 RunDbTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
988 RunDbTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
990 test.Next(_L("Testing streaming scatter/gather transfer"));
991 RunSgTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
992 RunSgTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
996 TheCriticalSection.Close();
998 UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, (TAny*)5000, 0);