kerneltest/e32test/dma/t_dma.cpp
changeset 0 a41df078684a
child 36 538db54a451d
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\dma\t_dma.cpp
       
    15 // Overview:
       
    16 // Test the DMA channel functionality.
       
    17 // API Information:
       
    18 // RBusLogicalChannel, DLogicalChannelBase, DLogicalDevice
       
    19 // Details:	
       
    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:
       
    40 // 
       
    41 //
       
    42 
       
    43 #define __E32TEST_EXTENSION__
       
    44 #include <e32test.h>
       
    45 #include "d_dma.h"
       
    46 #include <e32debug.h>
       
    47 #include <e32svr.h>
       
    48 #include <e32def.h>
       
    49 #include <e32def_private.h>
       
    50 #include "u32std.h"
       
    51 
       
    52 #ifdef __DMASIM__
       
    53 RTest test(_L("T_DMASIM"));
       
    54 #else
       
    55 RTest test(_L("T_DMA"));
       
    56 #endif
       
    57 
       
    58 //////////////////////////////////////////////////////////////////////////////
       
    59 // Mini-framework for running tests either in a single thread or in
       
    60 // several concurrent ones.
       
    61 
       
    62 RTestDma::TInfo Info;
       
    63 TBool JitEnabled;
       
    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
       
    67 
       
    68 // Test macro used inside tester threads
       
    69 _LIT(KTestFailure, "XTEST");
       
    70 static void TestPanic(TInt aLine, TUint32 a1, TUint32 a2, TUint32 a3)
       
    71 	{
       
    72 	RDebug::Printf("Line %d test failed a1=%08x a2=%08x a3=%08x", aLine, a1, a2, a3);
       
    73 	RThread().Panic(KTestFailure, aLine);
       
    74 	}
       
    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))
       
    79 
       
    80 
       
    81 /**
       
    82 Specifies a DMA test
       
    83 @note Have not inherited from CBase so that implicit copy ctors are used
       
    84 */
       
    85 class CTest
       
    86 	{
       
    87 public:
       
    88 	typedef void (*TTestFunction)(RTestDma aChannel, TInt aMaxFragment, TInt aFragmentSize);
       
    89 
       
    90 	CTest(TTestFunction aFn, TInt aMaxIter)
       
    91 		:iTestFn(aFn), iChannelId(0), iMaxIter(aMaxIter)
       
    92 		{}
       
    93 
       
    94 	virtual ~CTest()
       
    95 		{}
       
    96 
       
    97 	TInt RunTest();
       
    98 
       
    99 	virtual TBool OpenChannel(TInt aDesCount, TInt aMaxFragmentSize=0);
       
   100 
       
   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);}
       
   105 
       
   106 
       
   107 	void SetChannelId(TUint32 aChannelId)
       
   108 		{iChannelId = aChannelId;}
       
   109 
       
   110 	TInt MaxIter() const {return iMaxIter;}
       
   111 	TInt CurIter() const {return iCurIter;}
       
   112 
       
   113 	/**
       
   114 	@return A copy of this test
       
   115 	*/	
       
   116 	virtual	CTest* Clone() const =0;
       
   117 
       
   118 protected:
       
   119 	TInt virtual DoRunTest() =0;
       
   120 
       
   121 	const TTestFunction iTestFn;
       
   122 	TUint32 iChannelId;
       
   123 	const TInt iMaxIter;
       
   124 	TInt iCurIter;
       
   125 	RTestDma iChannel;
       
   126 	};	
       
   127 
       
   128 /**
       
   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.
       
   132 
       
   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
       
   136 */
       
   137 class CFragmentationTest : public CTest
       
   138 	{
       
   139 public:
       
   140 	CFragmentationTest(TTestFunction aFn, TInt aMaxIter, TInt aMaxFragment, TInt aMaxFragmentSize)
       
   141 		: CTest(aFn, aMaxIter), iMaxFragment(aMaxFragment), iMaxFragmentSize(aMaxFragmentSize), iCurFragment(0)
       
   142 	{}
       
   143 
       
   144 	TInt virtual DoRunTest();
       
   145 
       
   146 	virtual void AnnounceTest(TDes& aDes)
       
   147 		{
       
   148 		aDes.AppendFormat(_L("CFragmentationTest: Frag count = [1..%d], Max Frag Size = 0x%08x bytes: "), iMaxFragment, iMaxFragmentSize);
       
   149 		CTest::AnnounceTest(aDes);
       
   150 		}
       
   151 
       
   152 	virtual void ReportState(TDes& aDes)
       
   153 		{
       
   154 		aDes.AppendFormat(_L("CFragmentationTest: Current Fragment %d: "), iCurFragment);
       
   155 		CTest::ReportState(aDes);
       
   156 		}
       
   157 
       
   158 	CTest* Clone() const
       
   159 		{return new CFragmentationTest(*this);}
       
   160 
       
   161 private:
       
   162 	const TInt iMaxFragment;
       
   163 	TInt iMaxFragmentSize;
       
   164 	TInt iCurFragment;
       
   165 	};
       
   166 
       
   167 /**
       
   168 Specifies a DMA test where the maximum fragment size is
       
   169 not limited - and we do not care how many fragments are
       
   170 used
       
   171 
       
   172 - This checks that transfers work correctly with the DMAC's
       
   173 default fragment size
       
   174 */
       
   175 class CDefaultFragTest : public CTest
       
   176 	{
       
   177 public:
       
   178 	CDefaultFragTest(TTestFunction aFn, TInt aMaxIter, TUint aTotalTransferSize)
       
   179 		: CTest(aFn, aMaxIter), iTotalTransferSize(aTotalTransferSize)
       
   180 		{}
       
   181 
       
   182 	TInt virtual DoRunTest();
       
   183 
       
   184 	virtual void AnnounceTest(TDes& aDes)
       
   185 		{
       
   186 		aDes.AppendFormat(_L("CDefaultFragTest: Transfer = 0x%08x bytes: "), iTotalTransferSize);
       
   187 		CTest::AnnounceTest(aDes);
       
   188 		}
       
   189 
       
   190 	CTest* Clone() const
       
   191 		{return new CDefaultFragTest(*this);}
       
   192 
       
   193 	const TInt iTotalTransferSize;
       
   194 	};
       
   195 
       
   196 
       
   197 //
       
   198 // Active object used to create a tester thread, log on to it and
       
   199 // interpret its exit status.
       
   200 //
       
   201 class CTesterThread : public CActive
       
   202 	{
       
   203 public:
       
   204 	CTesterThread(TInt aIdx, CTest* aTest);
       
   205 	~CTesterThread()
       
   206 		{
       
   207 		delete iTest;
       
   208 		}
       
   209 private:
       
   210 	static TInt ThreadFunction(TAny* aSelf);
       
   211 	TInt StartThread();
       
   212 	// from CActive
       
   213 	virtual void DoCancel();
       
   214 	virtual void RunL();
       
   215 private:
       
   216 	RThread iThread;
       
   217 	CTest* iTest;
       
   218 	};
       
   219 
       
   220 
       
   221 /**
       
   222 Run the test for iMaxIter iterations
       
   223 */
       
   224 TInt CTest::RunTest()
       
   225 	{
       
   226 	TInt r = KErrNone;
       
   227 	for (iCurIter=0; iCurIter<iMaxIter; ++iCurIter)
       
   228 		{
       
   229 		r =  DoRunTest();
       
   230 		if(KErrNone != r)
       
   231 			break;
       
   232 		}
       
   233 	return r;
       
   234 	}
       
   235 
       
   236 /**
       
   237 Open iChannel
       
   238 
       
   239 @pre iChannel is not open
       
   240 @return
       
   241    - KErrNotSupported Channel does not exist on DMAC
       
   242    - KErrNone Success
       
   243    - KErrInUse
       
   244 */
       
   245 TInt CTest::OpenChannel(TInt aDesCount, TInt aMaxFragmentSize)
       
   246 		{
       
   247 		ASSERT(!iChannel.Handle());
       
   248 		const TInt r = iChannel.Open(iChannelId, aDesCount, aMaxFragmentSize);
       
   249 		if (r == KErrNotSupported)
       
   250 			return r;
       
   251 		XTEST1(KErrNone == r || KErrInUse == r, r);
       
   252 		
       
   253 		if(KErrInUse == r)
       
   254 			{
       
   255 			// Channel is in use.
       
   256 			RDebug::Printf("\nDMA Channel %d is in use",iChannelId);
       
   257 			if(0 == iCurIter)
       
   258 				{
       
   259 				// Terminate thread by returning this error code KErrInUse.
       
   260 				return r;
       
   261 				}
       
   262 			else
       
   263 				{
       
   264 #ifdef __WINS__
       
   265 #pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
       
   266 #endif // __WINS__
       
   267 				XTEST1(EFalse, iCurIter);
       
   268 #ifdef __WINS__
       
   269 #pragma warning( default : 4127 ) // warning C4127: conditional expression is constant
       
   270 #endif // __WINS__
       
   271 				}
       
   272 			}
       
   273 		return r;
       
   274 		}
       
   275 
       
   276 
       
   277 
       
   278 // Spawn thread. Will auto-delete when thread exits.
       
   279 CTesterThread::CTesterThread(TInt aIdx, CTest* aTest)
       
   280 	: CActive(EPriorityStandard), iTest(aTest)
       
   281 	{
       
   282 	CActiveScheduler::Add(this);
       
   283 	TBuf<16> name;
       
   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);
       
   289 	SetActive();
       
   290 	iThread.Resume();
       
   291 	}
       
   292 
       
   293 
       
   294 TInt CTesterThread::ThreadFunction(TAny* aSelf)
       
   295 	{
       
   296 	CTesterThread* self = (CTesterThread*)aSelf;
       
   297 	return self->StartThread();
       
   298 	}
       
   299 
       
   300 TInt CTesterThread::StartThread()
       
   301 	{
       
   302 	return iTest->RunTest();
       
   303 	}
       
   304 
       
   305 
       
   306 
       
   307 TInt CFragmentationTest::DoRunTest()
       
   308 	{
       
   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);
       
   312 
       
   313 	// Open channel with enough descriptors for 3 open DMA
       
   314 	// requests (see TestStreaming).
       
   315 	TInt r = OpenChannel(3* iMaxFragment, iMaxFragmentSize);
       
   316 	if(r != KErrNone)
       
   317 		return r;
       
   318 
       
   319 	//we are controlling fragment size, so we know how
       
   320 	//many to expect
       
   321 	for (iCurFragment=1; iCurFragment<=iMaxFragment; iCurFragment*=2)
       
   322 		{
       
   323 		const TInt size = iCurFragment * ( iMaxFragmentSize & ~Info.iMemAlignMask);
       
   324 		iTestFn(iChannel, iCurFragment, size);
       
   325 		}
       
   326 	iChannel.Close();
       
   327 	return KErrNone;
       
   328 	}
       
   329 
       
   330 TInt CDefaultFragTest::DoRunTest()
       
   331 	{
       
   332 	// +1 so we don't underestimate maxFragount for inexact division
       
   333 	const TUint maxFragCount = (iTotalTransferSize / Info.iMaxTransferSize) +1;
       
   334 
       
   335 	// Open channel with enough descriptors for 3 open DMA
       
   336 	// requests (see TestStreaming).
       
   337 	const TUint descriptorCount = 3 * maxFragCount;
       
   338 
       
   339 	TInt r = OpenChannel(descriptorCount);
       
   340 	if(r != KErrNone)
       
   341 		return r;
       
   342 
       
   343 	iTestFn(iChannel, 0, iTotalTransferSize);
       
   344 	
       
   345 	iChannel.Close();
       
   346 	return KErrNone;
       
   347 	}
       
   348 
       
   349 
       
   350 // Called when thread completed.
       
   351 void CTesterThread::RunL()
       
   352 	{
       
   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);
       
   358 
       
   359 	switch (et)
       
   360 		{
       
   361 	case EExitKill:
       
   362 		// nothing to do
       
   363 		break;
       
   364 	case EExitPanic:
       
   365 			{
       
   366 			User::SetJustInTime(JitEnabled);
       
   367 			TBuf<128> buffer;
       
   368 			iTest->ReportState(buffer);
       
   369 			test.Printf(_L("Tester Thread Panic: %S: Test: %S\n"),
       
   370 						&name, &buffer);
       
   371 			if (ec.Match(KTestFailure) == 0)
       
   372 				test.Panic(_L("Test failure line %d"), er);
       
   373 			else
       
   374 				test.Panic(_L("Unexpected panic: %S-%d"), &ec, er);
       
   375 			break;
       
   376 			}
       
   377 	default:
       
   378 		test.Panic(_L("Invalid thread exit type"));
       
   379 		}
       
   380 
       
   381 	TheCriticalSection.Wait();
       
   382 	if (--ThreadCount == 0)
       
   383 		{
       
   384 		Bipper->Cancel();
       
   385 		test.Console()->Printf(_L("\n"));
       
   386 		CActiveScheduler::Stop();
       
   387 		}
       
   388 	TheCriticalSection.Signal();
       
   389 
       
   390 	// We commit suicide as the alternative (being deleted by
       
   391 	// RunTest()) implies keeping a list of all instances in
       
   392 	// RunTest().
       
   393 	delete this;
       
   394 	}
       
   395 
       
   396 
       
   397 void CTesterThread::DoCancel()
       
   398 	{
       
   399 	test.Panic(_L("CTesterThread::DoCancel called"));
       
   400 	}
       
   401 
       
   402 
       
   403 static TInt Bip(TAny*)
       
   404 	{
       
   405 	test.Console()->Printf(_L("."));
       
   406 	return 0;
       
   407 	}
       
   408 
       
   409 
       
   410 // Execute provided test object in one or more tester threads.
       
   411 void RunTest(TUint32 aChannelIds[], TInt aMaxThread, CTest* aTest)			 
       
   412 	{
       
   413 	test_NotNull(aTest);
       
   414 
       
   415 	if (aMaxThread == 0)
       
   416 		{
       
   417 		delete aTest;
       
   418 		test.Printf(_L("transfer mode not supported - skipped\n"));
       
   419 		return;
       
   420 		}
       
   421 
       
   422 	test.Printf(_L("Using %d thread(s)\n"), aMaxThread);
       
   423 
       
   424 	// We don't want JIT debugging here because the tester threads may panic
       
   425 	JitEnabled = User::JustInTime();
       
   426 	User::SetJustInTime(EFalse);
       
   427 
       
   428 	// must be set before spawning threads to avoid premature active scheduler stop
       
   429 	ThreadCount = aMaxThread;
       
   430 
       
   431 	TBuf<128> buffer;
       
   432 	for (TInt i=0; i<aMaxThread; ++i)
       
   433 		{
       
   434 		//each CTesterThread needs its own CTest object
       
   435 		CTest* dmaTest = aTest->Clone();
       
   436 		test_NotNull(dmaTest);
       
   437 
       
   438 		dmaTest->SetChannelId(aChannelIds[i]);
       
   439 
       
   440 		buffer.Zero();
       
   441 		dmaTest->AnnounceTest(buffer);
       
   442 		test.Printf(_L("Thread %d: %S\n"), i, &buffer);
       
   443 		
       
   444 		test(new CTesterThread(i, dmaTest) != NULL);
       
   445 		dmaTest = NULL; //ownership transferred to CTesterThread
       
   446 		}
       
   447 	//the orginal isn't needed
       
   448 	delete aTest;
       
   449 	aTest = NULL;
       
   450 
       
   451 	const TTimeIntervalMicroSeconds32 KPeriod = 1000000;	// 1s
       
   452 	Bipper->Start(KPeriod, KPeriod, Bip);
       
   453 
       
   454 	CActiveScheduler::Start();
       
   455 
       
   456 	User::SetJustInTime(JitEnabled);
       
   457 	}
       
   458 
       
   459 
       
   460 inline void RunSbTest(TInt aMaxThread, CTest* aTest)
       
   461 	{
       
   462 	RunTest(Info.iSbChannels, Min(aMaxThread,Info.iMaxSbChannels), aTest);
       
   463 	}
       
   464 
       
   465 inline void RunDbTest(TInt aMaxThread, CTest* aTest)
       
   466 	{
       
   467 	RunTest(Info.iDbChannels, Min(aMaxThread,Info.iMaxDbChannels), aTest);
       
   468 	}
       
   469 
       
   470 inline void RunSgTest(TInt aMaxThread, CTest* aTest)
       
   471 	{
       
   472 	RunTest(Info.iSgChannels, Min(aMaxThread,Info.iMaxSgChannels), aTest);
       
   473 	}
       
   474 //////////////////////////////////////////////////////////////////////////////
       
   475 
       
   476 static void GetChannelInfo()
       
   477 	{
       
   478 	RTestDma channel;
       
   479 	test(channel.GetInfo(Info) == KErrNone);
       
   480 	test(Info.iMaxSbChannels>0 || Info.iMaxDbChannels>0 || Info.iMaxSgChannels>0);
       
   481 	}
       
   482 
       
   483 
       
   484 static void TestOneShot(RTestDma aChannel, TInt aFragmentCount, TInt aSize)
       
   485 	{
       
   486 	const TInt KRequest = 0;
       
   487 	const TInt KSrcBuf = 0;
       
   488 	const TInt KDestBuf1 = 1;
       
   489 	const TInt KDestBuf2 = 2;
       
   490 
       
   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');
       
   500 
       
   501 	// Test simple transfer
       
   502 	TRequestStatus rs;
       
   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'));
       
   511 
       
   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'));
       
   523 
       
   524 	// Test cancelling
       
   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.
       
   533 #ifdef __DMASIM__
       
   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'));
       
   538 #endif
       
   539 
       
   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'));
       
   551 
       
   552 	//
       
   553 	// Test failure if the underlying DMA kernel extension allows it.
       
   554 	//
       
   555 	// As long as only "CancelAllFragments" is supported, it's okay to
       
   556 	// always fail on the first fragment.
       
   557 	//
       
   558 
       
   559 	if (aChannel.FailNext(1) == KErrNone)
       
   560 		{
       
   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);
       
   572 
       
   573 		// Perform another transfer to ensure we are still in a
       
   574 		// consistent state.
       
   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'));
       
   584 		}
       
   585 
       
   586 	aChannel.FreeAllBuffers();
       
   587 	}
       
   588 
       
   589 
       
   590 static void TestStreaming(RTestDma aChannel, TInt aFragmentCount, TInt aSize)
       
   591 	{
       
   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;
       
   601 
       
   602 	//
       
   603 	// Allocate and initialise source buffers
       
   604 	//
       
   605 
       
   606 	TInt r = aChannel.AllocBuffer(KSrcBuf0, aSize);
       
   607 	XTEST2(r == KErrNone, r, aSize);
       
   608 	aChannel.FillBuffer(KSrcBuf0, 'A');
       
   609 
       
   610 	r = aChannel.AllocBuffer(KSrcBuf1, aSize);
       
   611 	XTEST2(r == KErrNone, r, aSize);
       
   612 	aChannel.FillBuffer(KSrcBuf1, 'B');
       
   613 
       
   614 	r = aChannel.AllocBuffer(KSrcBuf2, aSize);
       
   615 	XTEST2(r == KErrNone, r, aSize);
       
   616 	aChannel.FillBuffer(KSrcBuf2, 'C');
       
   617 
       
   618 	//
       
   619 	// Allocate destination buffers
       
   620 	//
       
   621 
       
   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);
       
   628 
       
   629 	//
       
   630 	// Test simple transfer.
       
   631 	// (no need to test for request reconfiguration afterwards because
       
   632 	// this was exercised in the one-shot test case)
       
   633 	//
       
   634 
       
   635 	TRequestStatus rs0;
       
   636 	r = aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0);
       
   637 	XTEST2(r == KErrNone, r, aSize);
       
   638 	test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
       
   639 	TRequestStatus rs1;
       
   640  	r = aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1);
       
   641 	XTEST2(r == KErrNone, r, aSize);
       
   642 	test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
       
   643 	TRequestStatus rs2;
       
   644 	r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
       
   645 	XTEST2(r == KErrNone, r, aSize);
       
   646 	test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
       
   647 
       
   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'));
       
   659 
       
   660 	//
       
   661 	// Test cancel
       
   662 	//
       
   663 
       
   664 	aChannel.FillBuffer(KDestBuf0, '\0');
       
   665 	aChannel.FillBuffer(KDestBuf1, '\0');
       
   666 	aChannel.FillBuffer(KDestBuf2, '\0');
       
   667 
       
   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));
       
   677 
       
   678 	r = aChannel.Execute(_L8("Q0Q1Q2C"));
       
   679 	XTEST1(r == KErrNone, r);
       
   680 #ifdef __DMASIM__
       
   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'));
       
   685 #endif
       
   686 
       
   687 	//
       
   688 	// Perform another transfer to ensure cancel operation let the
       
   689 	// framework in a consistent state.
       
   690 	//
       
   691 
       
   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'));
       
   706 
       
   707 	//
       
   708 	// Test for proper implementation of UnlinkHwDes() in the PSL.
       
   709 	//
       
   710 
       
   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'));
       
   735 
       
   736 	//
       
   737 	// Test failure if the underlying DMA kernel extension allows it.
       
   738 	//
       
   739 	// As long as only "CancelAllFragments" is supported, it's okay to
       
   740 	// always fail on the first fragment.
       
   741 	//
       
   742 
       
   743 	if (aChannel.FailNext(1) == KErrNone)
       
   744 		{
       
   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);
       
   761 
       
   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'));
       
   782 		}
       
   783 
       
   784 	//
       
   785 	// Test that framework behaves correctly if one or more DMA interrupts are
       
   786 	// missed.
       
   787 	//
       
   788 
       
   789 	if (aChannel.MissNextInterrupts(1) == KErrNone)
       
   790 		{
       
   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'));
       
   810 		}
       
   811 
       
   812 	if (aChannel.MissNextInterrupts(2) == KErrNone)
       
   813 		{
       
   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'));
       
   833 		}
       
   834 
       
   835 	aChannel.FreeAllBuffers();
       
   836 	}
       
   837 
       
   838 
       
   839 static TBool ParseCmdLine(TBool& aCrashDbg, TInt& aMaxfrag, TInt& aMaxIter, TInt& aMaxchannel, TInt& aMaxFragSize)
       
   840 //
       
   841 // The command line. Syntax is:
       
   842 //
       
   843 //     t_dma [enableCrashDebugger [aMaxFrag [aMaxIter [aMaxchannel [aMaxFragSize]]]]]
       
   844 //
       
   845 	{
       
   846 	TBuf<256> cmdline;
       
   847 	User::CommandLine(cmdline);
       
   848 	TLex lex(cmdline);
       
   849 
       
   850 	lex.SkipSpace();
       
   851 
       
   852 	if (lex.Eos())
       
   853 		return ETrue;
       
   854 	if (lex.Val(aCrashDbg) != KErrNone)
       
   855 		return EFalse;
       
   856 	lex.SkipSpace();
       
   857 	if (lex.Eos())
       
   858 		return ETrue;
       
   859 	if (lex.Val(aMaxfrag) != KErrNone)
       
   860 		return EFalse;
       
   861 	lex.SkipSpace();
       
   862 	if (lex.Eos())
       
   863 		return ETrue;
       
   864 	if (lex.Val(aMaxIter) != KErrNone)
       
   865 		return EFalse;
       
   866 	lex.SkipSpace();
       
   867 	if (lex.Eos())
       
   868 		return ETrue;
       
   869 	if (lex.Val(aMaxchannel) != KErrNone)
       
   870 		return EFalse;
       
   871 	lex.SkipSpace();
       
   872 	if (lex.Eos())
       
   873 		return ETrue;
       
   874 
       
   875 	return lex.Val(aMaxFragSize) == KErrNone;
       
   876 	}
       
   877 
       
   878 
       
   879 TInt E32Main()
       
   880 	{
       
   881 	test.Title();
       
   882 
       
   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
       
   886 	TInt maxIter = 3;
       
   887 	TInt maxchannel = KMaxTInt;
       
   888 	TBool crashDbg = EFalse;
       
   889 	TInt maxFragSize = 0x4000; //16k
       
   890 
       
   891 	(void) ParseCmdLine(crashDbg, maxfrag, maxIter, maxchannel, maxFragSize);
       
   892 
       
   893 	if (crashDbg)
       
   894 		{
       
   895 		User::SetCritical(User::ESystemCritical);
       
   896 		User::SetProcessCritical(User::ESystemCritical);
       
   897 		}
       
   898 
       
   899 	TInt r;
       
   900 #if defined(__DMASIM__) && defined(__WINS__)
       
   901 	test.Next(_L("Loading DMA simulator"));
       
   902 	r = User::LoadLogicalDevice(_L("DMASIM.DLL"));
       
   903 	test(r == KErrNone || r == KErrAlreadyExists);
       
   904 #endif
       
   905 
       
   906 	test.Next(_L("Loading test LDD"));
       
   907 #ifdef __DMASIM__
       
   908 	r = User::LoadLogicalDevice(_L("D_DMASIM"));
       
   909 #else
       
   910 	r = User::LoadLogicalDevice(_L("D_DMA"));
       
   911 	if (r == KErrNotFound)
       
   912 		{
       
   913 		test.Printf(_L("DMA not supported - test skipped\n"));
       
   914 		return 0;
       
   915 		}
       
   916 #endif
       
   917 	test(r == KErrNone || r == KErrAlreadyExists);
       
   918 
       
   919 	// Turn off evil lazy dll unloading
       
   920 	RLoader l;
       
   921 	test(l.Connect()==KErrNone);
       
   922 	test(l.CancelLazyDllUnload()==KErrNone);
       
   923 	l.Close();
       
   924 
       
   925 	__UHEAP_MARK;
       
   926 	__KHEAP_MARK;
       
   927 
       
   928 	test.Next(_L("Creating critical section"));
       
   929 	test(TheCriticalSection.CreateLocal() == KErrNone);
       
   930 
       
   931 	test.Next(_L("Creating active scheduler"));
       
   932 	CActiveScheduler* pS = new CActiveScheduler;
       
   933 	test(pS != NULL);
       
   934 	CActiveScheduler::Install(pS);
       
   935 
       
   936 	test.Next(_L("Creating bipper"));
       
   937 	Bipper = CPeriodic::New(CActive::EPriorityStandard);
       
   938 	test(Bipper != NULL);
       
   939 
       
   940 	test.Next(_L("Getting channel info"));
       
   941 	GetChannelInfo();
       
   942 
       
   943 	// Size for the single transfer test
       
   944 	TInt totalTransferSize = 64 * KKilo;
       
   945 
       
   946 	test.Next(_L("Testing one shot single buffer transfer"));
       
   947 	RunSbTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
       
   948 	RunSbTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
       
   949 
       
   950 	test.Next(_L("Testing one shot double buffer transfer"));
       
   951 	RunDbTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
       
   952 	RunDbTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
       
   953 
       
   954 	test.Next(_L("Testing one shot scatter/gather transfer"));
       
   955 	RunSgTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
       
   956 	RunSgTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
       
   957 
       
   958 	test.Next(_L("Testing streaming single buffer transfer"));
       
   959 	RunSbTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
       
   960 	RunSbTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
       
   961 
       
   962 	test.Next(_L("Testing streaming double buffer transfer"));
       
   963 	RunDbTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
       
   964 	RunDbTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
       
   965 
       
   966 	test.Next(_L("Testing streaming scatter/gather transfer"));
       
   967 	RunSgTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
       
   968 	RunSgTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
       
   969 
       
   970 	delete pS;
       
   971 	delete Bipper;
       
   972 	TheCriticalSection.Close();
       
   973 
       
   974 	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, (TAny*)5000, 0);
       
   975 	__KHEAP_MARKEND;
       
   976 	__UHEAP_MARKEND;
       
   977 
       
   978 	test.End();
       
   979 	return 0;
       
   980 	}