os/kernelhwsrv/kerneltest/e32test/dma/t_dma.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of the License "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// e32test\dma\t_dma.cpp
sl@0
    15
// Overview:
sl@0
    16
// Test the DMA channel functionality.
sl@0
    17
// API Information:
sl@0
    18
// RBusLogicalChannel, DLogicalChannelBase, DLogicalDevice
sl@0
    19
// Details:	
sl@0
    20
// - Load the DMA LDD, create a critical section, an active scheduler and
sl@0
    21
// a CPeriodic object.
sl@0
    22
// - Test one shot single buffer transfers: test simple transfer, request 
sl@0
    23
// reconfiguration and cancelling. Verify results are as expected.
sl@0
    24
// - Test one shot double buffer transfers: test simple transfer, request 
sl@0
    25
// reconfiguration and cancelling. Verify results are as expected.
sl@0
    26
// - Test streaming single buffer transfers: test simple transfer and
sl@0
    27
// cancelling. Test that framework behaves correctly if one or more DMA
sl@0
    28
// interrupts are missed. Verify results are as expected.
sl@0
    29
// - Test streaming double buffer transfers: test simple transfer and
sl@0
    30
// cancelling. Test that framework behaves correctly if one or more DMA
sl@0
    31
// interrupts are missed. Verify results are as expected.
sl@0
    32
// - Test streaming scatter/gather transfers: test simple transfer and
sl@0
    33
// cancelling. Test that framework behaves correctly if one or more DMA
sl@0
    34
// interrupts are missed. Verify results are as expected.
sl@0
    35
// Platforms/Drives/Compatibility:
sl@0
    36
// Hardware (Automatic).
sl@0
    37
// Assumptions/Requirement/Pre-requisites:
sl@0
    38
// Failures and causes:
sl@0
    39
// Base Port information:
sl@0
    40
// 
sl@0
    41
//
sl@0
    42
sl@0
    43
#define __E32TEST_EXTENSION__
sl@0
    44
#include <e32test.h>
sl@0
    45
#include "d_dma.h"
sl@0
    46
#include <e32debug.h>
sl@0
    47
#include <e32svr.h>
sl@0
    48
#include <e32def.h>
sl@0
    49
#include <e32def_private.h>
sl@0
    50
#include "u32std.h"
sl@0
    51
sl@0
    52
#ifdef __DMASIM__
sl@0
    53
RTest test(_L("T_DMASIM"));
sl@0
    54
#else
sl@0
    55
RTest test(_L("T_DMA"));
sl@0
    56
#endif
sl@0
    57
sl@0
    58
//////////////////////////////////////////////////////////////////////////////
sl@0
    59
// Mini-framework for running tests either in a single thread or in
sl@0
    60
// several concurrent ones.
sl@0
    61
sl@0
    62
RTestDma::TInfo Info;
sl@0
    63
TBool JitEnabled;
sl@0
    64
RCriticalSection TheCriticalSection;						// protect following variables
sl@0
    65
TInt ThreadCount;											// decremented when tester thread dies
sl@0
    66
CPeriodic* Bipper;											// display dots during tests to detect lock-ups
sl@0
    67
sl@0
    68
// Test macro used inside tester threads
sl@0
    69
_LIT(KTestFailure, "XTEST");
sl@0
    70
static void TestPanic(TInt aLine, TUint32 a1, TUint32 a2, TUint32 a3)
sl@0
    71
	{
sl@0
    72
	RDebug::Printf("Line %d test failed a1=%08x a2=%08x a3=%08x", aLine, a1, a2, a3);
sl@0
    73
	RThread().Panic(KTestFailure, aLine);
sl@0
    74
	}
sl@0
    75
#define XTEST(e)				if (!(e)) TestPanic(__LINE__, 0, 0, 0)
sl@0
    76
#define XTEST1(e,a1)			if (!(e)) TestPanic(__LINE__, (a1), 0, 0)
sl@0
    77
#define XTEST2(e,a1,a2)			if (!(e)) TestPanic(__LINE__, (a1), (a2), 0)
sl@0
    78
#define XTEST3(e,a1,a2,a3)		if (!(e)) TestPanic(__LINE__, (a1), (a2), (a3))
sl@0
    79
sl@0
    80
sl@0
    81
/**
sl@0
    82
Specifies a DMA test
sl@0
    83
@note Have not inherited from CBase so that implicit copy ctors are used
sl@0
    84
*/
sl@0
    85
class CTest
sl@0
    86
	{
sl@0
    87
public:
sl@0
    88
	typedef void (*TTestFunction)(RTestDma aChannel, TInt aMaxFragment, TInt aFragmentSize);
sl@0
    89
sl@0
    90
	CTest(TTestFunction aFn, TInt aMaxIter)
sl@0
    91
		:iTestFn(aFn), iChannelId(0), iMaxIter(aMaxIter)
sl@0
    92
		{}
sl@0
    93
sl@0
    94
	virtual ~CTest()
sl@0
    95
		{}
sl@0
    96
sl@0
    97
	TInt RunTest();
sl@0
    98
sl@0
    99
	virtual TBool OpenChannel(TInt aDesCount, TInt aMaxFragmentSize=0);
sl@0
   100
sl@0
   101
	virtual void AnnounceTest(TDes& aDes)
sl@0
   102
		{aDes.AppendFormat(_L("Channel Id %d, iMaxIter %d"), iChannelId, iMaxIter);}
sl@0
   103
	virtual void ReportState(TDes& aDes)
sl@0
   104
		{aDes.AppendFormat(_L("Channel Id %d, iCurIter %d"), iChannelId, iCurIter);}
sl@0
   105
sl@0
   106
sl@0
   107
	void SetChannelId(TUint32 aChannelId)
sl@0
   108
		{iChannelId = aChannelId;}
sl@0
   109
sl@0
   110
	TInt MaxIter() const {return iMaxIter;}
sl@0
   111
	TInt CurIter() const {return iCurIter;}
sl@0
   112
sl@0
   113
	/**
sl@0
   114
	@return A copy of this test
sl@0
   115
	*/	
sl@0
   116
	virtual	CTest* Clone() const =0;
sl@0
   117
sl@0
   118
protected:
sl@0
   119
	TInt virtual DoRunTest() =0;
sl@0
   120
sl@0
   121
	const TTestFunction iTestFn;
sl@0
   122
	TUint32 iChannelId;
sl@0
   123
	const TInt iMaxIter;
sl@0
   124
	TInt iCurIter;
sl@0
   125
	RTestDma iChannel;
sl@0
   126
	};	
sl@0
   127
sl@0
   128
/**
sl@0
   129
Specifies a DMA test where the maximum fragmentation is
sl@0
   130
explicitly limited. This tests that requests are split
sl@0
   131
in to the number of fragments expected.
sl@0
   132
sl@0
   133
This test also requires that physically contiguous buffers
sl@0
   134
are used. For this reason the product of iMaxFragment and
sl@0
   135
iMaxFragmentSize should be kept small
sl@0
   136
*/
sl@0
   137
class CFragmentationTest : public CTest
sl@0
   138
	{
sl@0
   139
public:
sl@0
   140
	CFragmentationTest(TTestFunction aFn, TInt aMaxIter, TInt aMaxFragment, TInt aMaxFragmentSize)
sl@0
   141
		: CTest(aFn, aMaxIter), iMaxFragment(aMaxFragment), iMaxFragmentSize(aMaxFragmentSize), iCurFragment(0)
sl@0
   142
	{}
sl@0
   143
sl@0
   144
	TInt virtual DoRunTest();
sl@0
   145
sl@0
   146
	virtual void AnnounceTest(TDes& aDes)
sl@0
   147
		{
sl@0
   148
		aDes.AppendFormat(_L("CFragmentationTest: Frag count = [1..%d], Max Frag Size = 0x%08x bytes: "), iMaxFragment, iMaxFragmentSize);
sl@0
   149
		CTest::AnnounceTest(aDes);
sl@0
   150
		}
sl@0
   151
sl@0
   152
	virtual void ReportState(TDes& aDes)
sl@0
   153
		{
sl@0
   154
		aDes.AppendFormat(_L("CFragmentationTest: Current Fragment %d: "), iCurFragment);
sl@0
   155
		CTest::ReportState(aDes);
sl@0
   156
		}
sl@0
   157
sl@0
   158
	CTest* Clone() const
sl@0
   159
		{return new CFragmentationTest(*this);}
sl@0
   160
sl@0
   161
private:
sl@0
   162
	const TInt iMaxFragment;
sl@0
   163
	TInt iMaxFragmentSize;
sl@0
   164
	TInt iCurFragment;
sl@0
   165
	};
sl@0
   166
sl@0
   167
/**
sl@0
   168
Specifies a DMA test where the maximum fragment size is
sl@0
   169
not limited - and we do not care how many fragments are
sl@0
   170
used
sl@0
   171
sl@0
   172
- This checks that transfers work correctly with the DMAC's
sl@0
   173
default fragment size
sl@0
   174
*/
sl@0
   175
class CDefaultFragTest : public CTest
sl@0
   176
	{
sl@0
   177
public:
sl@0
   178
	CDefaultFragTest(TTestFunction aFn, TInt aMaxIter, TUint aTotalTransferSize)
sl@0
   179
		: CTest(aFn, aMaxIter), iTotalTransferSize(aTotalTransferSize)
sl@0
   180
		{}
sl@0
   181
sl@0
   182
	TInt virtual DoRunTest();
sl@0
   183
sl@0
   184
	virtual void AnnounceTest(TDes& aDes)
sl@0
   185
		{
sl@0
   186
		aDes.AppendFormat(_L("CDefaultFragTest: Transfer = 0x%08x bytes: "), iTotalTransferSize);
sl@0
   187
		CTest::AnnounceTest(aDes);
sl@0
   188
		}
sl@0
   189
sl@0
   190
	CTest* Clone() const
sl@0
   191
		{return new CDefaultFragTest(*this);}
sl@0
   192
sl@0
   193
	const TInt iTotalTransferSize;
sl@0
   194
	};
sl@0
   195
sl@0
   196
sl@0
   197
//
sl@0
   198
// Active object used to create a tester thread, log on to it and
sl@0
   199
// interpret its exit status.
sl@0
   200
//
sl@0
   201
class CTesterThread : public CActive
sl@0
   202
	{
sl@0
   203
public:
sl@0
   204
	CTesterThread(TInt aIdx, CTest* aTest);
sl@0
   205
	~CTesterThread()
sl@0
   206
		{
sl@0
   207
		delete iTest;
sl@0
   208
		}
sl@0
   209
private:
sl@0
   210
	static TInt ThreadFunction(TAny* aSelf);
sl@0
   211
	TInt StartThread();
sl@0
   212
	// from CActive
sl@0
   213
	virtual void DoCancel();
sl@0
   214
	virtual void RunL();
sl@0
   215
private:
sl@0
   216
	RThread iThread;
sl@0
   217
	CTest* iTest;
sl@0
   218
	};
sl@0
   219
sl@0
   220
sl@0
   221
/**
sl@0
   222
Run the test for iMaxIter iterations
sl@0
   223
*/
sl@0
   224
TInt CTest::RunTest()
sl@0
   225
	{
sl@0
   226
	TInt r = KErrNone;
sl@0
   227
	for (iCurIter=0; iCurIter<iMaxIter; ++iCurIter)
sl@0
   228
		{
sl@0
   229
		r =  DoRunTest();
sl@0
   230
		if(KErrNone != r)
sl@0
   231
			break;
sl@0
   232
		}
sl@0
   233
	return r;
sl@0
   234
	}
sl@0
   235
sl@0
   236
/**
sl@0
   237
Open iChannel
sl@0
   238
sl@0
   239
@pre iChannel is not open
sl@0
   240
@return
sl@0
   241
   - KErrNotSupported Channel does not exist on DMAC
sl@0
   242
   - KErrNone Success
sl@0
   243
   - KErrInUse
sl@0
   244
*/
sl@0
   245
TInt CTest::OpenChannel(TInt aDesCount, TInt aMaxFragmentSize)
sl@0
   246
		{
sl@0
   247
		ASSERT(!iChannel.Handle());
sl@0
   248
		const TInt r = iChannel.Open(iChannelId, aDesCount, aMaxFragmentSize);
sl@0
   249
		if (r == KErrNotSupported)
sl@0
   250
			return r;
sl@0
   251
		XTEST1(KErrNone == r || KErrInUse == r, r);
sl@0
   252
		
sl@0
   253
		if(KErrInUse == r)
sl@0
   254
			{
sl@0
   255
			// Channel is in use.
sl@0
   256
			RDebug::Printf("\nDMA Channel %d is in use",iChannelId);
sl@0
   257
			if(0 == iCurIter)
sl@0
   258
				{
sl@0
   259
				// Terminate thread by returning this error code KErrInUse.
sl@0
   260
				return r;
sl@0
   261
				}
sl@0
   262
			else
sl@0
   263
				{
sl@0
   264
#ifdef __WINS__
sl@0
   265
#pragma warning( disable : 4127 ) // warning C4127: conditional expression is constant
sl@0
   266
#endif // __WINS__
sl@0
   267
				XTEST1(EFalse, iCurIter);
sl@0
   268
#ifdef __WINS__
sl@0
   269
#pragma warning( default : 4127 ) // warning C4127: conditional expression is constant
sl@0
   270
#endif // __WINS__
sl@0
   271
				}
sl@0
   272
			}
sl@0
   273
		return r;
sl@0
   274
		}
sl@0
   275
sl@0
   276
sl@0
   277
sl@0
   278
// Spawn thread. Will auto-delete when thread exits.
sl@0
   279
CTesterThread::CTesterThread(TInt aIdx, CTest* aTest)
sl@0
   280
	: CActive(EPriorityStandard), iTest(aTest)
sl@0
   281
	{
sl@0
   282
	CActiveScheduler::Add(this);
sl@0
   283
	TBuf<16> name;
sl@0
   284
	name = _L("TESTER-");
sl@0
   285
	name.AppendNum(aIdx);
sl@0
   286
	test(iThread.Create(name, ThreadFunction, 0x1000, NULL, this) == KErrNone);
sl@0
   287
	iThread.SetPriority(EPriorityLess);
sl@0
   288
	iThread.Logon(iStatus);
sl@0
   289
	SetActive();
sl@0
   290
	iThread.Resume();
sl@0
   291
	}
sl@0
   292
sl@0
   293
sl@0
   294
TInt CTesterThread::ThreadFunction(TAny* aSelf)
sl@0
   295
	{
sl@0
   296
	CTesterThread* self = (CTesterThread*)aSelf;
sl@0
   297
	return self->StartThread();
sl@0
   298
	}
sl@0
   299
sl@0
   300
TInt CTesterThread::StartThread()
sl@0
   301
	{
sl@0
   302
	return iTest->RunTest();
sl@0
   303
	}
sl@0
   304
sl@0
   305
sl@0
   306
sl@0
   307
TInt CFragmentationTest::DoRunTest()
sl@0
   308
	{
sl@0
   309
	// In case iMaxFragmentSize was larger than suppported (we need to know what fragment
sl@0
   310
	// size will actually be used)
sl@0
   311
	iMaxFragmentSize = Min(iMaxFragmentSize, Info.iMaxTransferSize);
sl@0
   312
sl@0
   313
	// Open channel with enough descriptors for 3 open DMA
sl@0
   314
	// requests (see TestStreaming).
sl@0
   315
	TInt r = OpenChannel(3* iMaxFragment, iMaxFragmentSize);
sl@0
   316
	if(r != KErrNone)
sl@0
   317
		return r;
sl@0
   318
sl@0
   319
	//we are controlling fragment size, so we know how
sl@0
   320
	//many to expect
sl@0
   321
	for (iCurFragment=1; iCurFragment<=iMaxFragment; iCurFragment*=2)
sl@0
   322
		{
sl@0
   323
		const TInt size = iCurFragment * ( iMaxFragmentSize & ~Info.iMemAlignMask);
sl@0
   324
		iTestFn(iChannel, iCurFragment, size);
sl@0
   325
		}
sl@0
   326
	iChannel.Close();
sl@0
   327
	return KErrNone;
sl@0
   328
	}
sl@0
   329
sl@0
   330
TInt CDefaultFragTest::DoRunTest()
sl@0
   331
	{
sl@0
   332
	// +1 so we don't underestimate maxFragount for inexact division
sl@0
   333
	const TUint maxFragCount = (iTotalTransferSize / Info.iMaxTransferSize) +1;
sl@0
   334
sl@0
   335
	// Open channel with enough descriptors for 3 open DMA
sl@0
   336
	// requests (see TestStreaming).
sl@0
   337
	const TUint descriptorCount = 3 * maxFragCount;
sl@0
   338
sl@0
   339
	TInt r = OpenChannel(descriptorCount);
sl@0
   340
	if(r != KErrNone)
sl@0
   341
		return r;
sl@0
   342
sl@0
   343
	iTestFn(iChannel, 0, iTotalTransferSize);
sl@0
   344
	
sl@0
   345
	iChannel.Close();
sl@0
   346
	return KErrNone;
sl@0
   347
	}
sl@0
   348
sl@0
   349
sl@0
   350
// Called when thread completed.
sl@0
   351
void CTesterThread::RunL()
sl@0
   352
	{
sl@0
   353
	TExitType et = iThread.ExitType();
sl@0
   354
	TInt er = iThread.ExitReason();
sl@0
   355
	TExitCategoryName ec = iThread.ExitCategory();
sl@0
   356
	TName name = iThread.Name();
sl@0
   357
	CLOSE_AND_WAIT(iThread);
sl@0
   358
sl@0
   359
	switch (et)
sl@0
   360
		{
sl@0
   361
	case EExitKill:
sl@0
   362
		// nothing to do
sl@0
   363
		break;
sl@0
   364
	case EExitPanic:
sl@0
   365
			{
sl@0
   366
			User::SetJustInTime(JitEnabled);
sl@0
   367
			TBuf<128> buffer;
sl@0
   368
			iTest->ReportState(buffer);
sl@0
   369
			test.Printf(_L("Tester Thread Panic: %S: Test: %S\n"),
sl@0
   370
						&name, &buffer);
sl@0
   371
			if (ec.Match(KTestFailure) == 0)
sl@0
   372
				test.Panic(_L("Test failure line %d"), er);
sl@0
   373
			else
sl@0
   374
				test.Panic(_L("Unexpected panic: %S-%d"), &ec, er);
sl@0
   375
			break;
sl@0
   376
			}
sl@0
   377
	default:
sl@0
   378
		test.Panic(_L("Invalid thread exit type"));
sl@0
   379
		}
sl@0
   380
sl@0
   381
	TheCriticalSection.Wait();
sl@0
   382
	if (--ThreadCount == 0)
sl@0
   383
		{
sl@0
   384
		Bipper->Cancel();
sl@0
   385
		test.Console()->Printf(_L("\n"));
sl@0
   386
		CActiveScheduler::Stop();
sl@0
   387
		}
sl@0
   388
	TheCriticalSection.Signal();
sl@0
   389
sl@0
   390
	// We commit suicide as the alternative (being deleted by
sl@0
   391
	// RunTest()) implies keeping a list of all instances in
sl@0
   392
	// RunTest().
sl@0
   393
	delete this;
sl@0
   394
	}
sl@0
   395
sl@0
   396
sl@0
   397
void CTesterThread::DoCancel()
sl@0
   398
	{
sl@0
   399
	test.Panic(_L("CTesterThread::DoCancel called"));
sl@0
   400
	}
sl@0
   401
sl@0
   402
sl@0
   403
static TInt Bip(TAny*)
sl@0
   404
	{
sl@0
   405
	test.Console()->Printf(_L("."));
sl@0
   406
	return 0;
sl@0
   407
	}
sl@0
   408
sl@0
   409
sl@0
   410
// Execute provided test object in one or more tester threads.
sl@0
   411
void RunTest(TUint32 aChannelIds[], TInt aMaxThread, CTest* aTest)			 
sl@0
   412
	{
sl@0
   413
	test_NotNull(aTest);
sl@0
   414
sl@0
   415
	if (aMaxThread == 0)
sl@0
   416
		{
sl@0
   417
		delete aTest;
sl@0
   418
		test.Printf(_L("transfer mode not supported - skipped\n"));
sl@0
   419
		return;
sl@0
   420
		}
sl@0
   421
sl@0
   422
	test.Printf(_L("Using %d thread(s)\n"), aMaxThread);
sl@0
   423
sl@0
   424
	// We don't want JIT debugging here because the tester threads may panic
sl@0
   425
	JitEnabled = User::JustInTime();
sl@0
   426
	User::SetJustInTime(EFalse);
sl@0
   427
sl@0
   428
	// must be set before spawning threads to avoid premature active scheduler stop
sl@0
   429
	ThreadCount = aMaxThread;
sl@0
   430
sl@0
   431
	TBuf<128> buffer;
sl@0
   432
	for (TInt i=0; i<aMaxThread; ++i)
sl@0
   433
		{
sl@0
   434
		//each CTesterThread needs its own CTest object
sl@0
   435
		CTest* dmaTest = aTest->Clone();
sl@0
   436
		test_NotNull(dmaTest);
sl@0
   437
sl@0
   438
		dmaTest->SetChannelId(aChannelIds[i]);
sl@0
   439
sl@0
   440
		buffer.Zero();
sl@0
   441
		dmaTest->AnnounceTest(buffer);
sl@0
   442
		test.Printf(_L("Thread %d: %S\n"), i, &buffer);
sl@0
   443
		
sl@0
   444
		test(new CTesterThread(i, dmaTest) != NULL);
sl@0
   445
		dmaTest = NULL; //ownership transferred to CTesterThread
sl@0
   446
		}
sl@0
   447
	//the orginal isn't needed
sl@0
   448
	delete aTest;
sl@0
   449
	aTest = NULL;
sl@0
   450
sl@0
   451
	const TTimeIntervalMicroSeconds32 KPeriod = 1000000;	// 1s
sl@0
   452
	Bipper->Start(KPeriod, KPeriod, Bip);
sl@0
   453
sl@0
   454
	CActiveScheduler::Start();
sl@0
   455
sl@0
   456
	User::SetJustInTime(JitEnabled);
sl@0
   457
	}
sl@0
   458
sl@0
   459
sl@0
   460
inline void RunSbTest(TInt aMaxThread, CTest* aTest)
sl@0
   461
	{
sl@0
   462
	RunTest(Info.iSbChannels, Min(aMaxThread,Info.iMaxSbChannels), aTest);
sl@0
   463
	}
sl@0
   464
sl@0
   465
inline void RunDbTest(TInt aMaxThread, CTest* aTest)
sl@0
   466
	{
sl@0
   467
	RunTest(Info.iDbChannels, Min(aMaxThread,Info.iMaxDbChannels), aTest);
sl@0
   468
	}
sl@0
   469
sl@0
   470
inline void RunSgTest(TInt aMaxThread, CTest* aTest)
sl@0
   471
	{
sl@0
   472
	RunTest(Info.iSgChannels, Min(aMaxThread,Info.iMaxSgChannels), aTest);
sl@0
   473
	}
sl@0
   474
//////////////////////////////////////////////////////////////////////////////
sl@0
   475
sl@0
   476
static void GetChannelInfo()
sl@0
   477
	{
sl@0
   478
	RTestDma channel;
sl@0
   479
	test(channel.GetInfo(Info) == KErrNone);
sl@0
   480
	test(Info.iMaxSbChannels>0 || Info.iMaxDbChannels>0 || Info.iMaxSgChannels>0);
sl@0
   481
	}
sl@0
   482
sl@0
   483
sl@0
   484
static void TestOneShot(RTestDma aChannel, TInt aFragmentCount, TInt aSize)
sl@0
   485
	{
sl@0
   486
	const TInt KRequest = 0;
sl@0
   487
	const TInt KSrcBuf = 0;
sl@0
   488
	const TInt KDestBuf1 = 1;
sl@0
   489
	const TInt KDestBuf2 = 2;
sl@0
   490
sl@0
   491
	TInt r = aChannel.AllocBuffer(KSrcBuf, aSize);
sl@0
   492
	XTEST2(r == KErrNone, r, aSize);
sl@0
   493
	aChannel.FillBuffer(KSrcBuf, 'A');
sl@0
   494
	r = aChannel.AllocBuffer(KDestBuf1, aSize);
sl@0
   495
	XTEST2(r == KErrNone, r, aSize);
sl@0
   496
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   497
	r = aChannel.AllocBuffer(KDestBuf2, aSize);
sl@0
   498
	XTEST2(r == KErrNone, r, aSize);
sl@0
   499
	aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   500
sl@0
   501
	// Test simple transfer
sl@0
   502
	TRequestStatus rs;
sl@0
   503
	r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
sl@0
   504
	XTEST2(r == KErrNone, r, aSize);
sl@0
   505
	test(aChannel.FragmentCheck(KRequest, aFragmentCount));
sl@0
   506
	r = aChannel.Execute(_L8("Q0"));
sl@0
   507
	XTEST1(r == KErrNone, r);
sl@0
   508
	User::WaitForRequest(rs);
sl@0
   509
	XTEST1(rs == KErrNone, rs.Int());
sl@0
   510
	XTEST(aChannel.CheckBuffer(KDestBuf1, 'A'));
sl@0
   511
sl@0
   512
	// Test request reconfiguration.
sl@0
   513
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   514
	r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf2, aSize, &rs);
sl@0
   515
	XTEST2(r == KErrNone, r, aSize);
sl@0
   516
	test(aChannel.FragmentCheck(KRequest, aFragmentCount));
sl@0
   517
	r = aChannel.Execute(_L8("Q0"));
sl@0
   518
	XTEST1(r == KErrNone, r);
sl@0
   519
	User::WaitForRequest(rs);
sl@0
   520
	XTEST1(rs == KErrNone, rs.Int());
sl@0
   521
	XTEST(aChannel.CheckBuffer(KDestBuf1, '\0'));			// previous dest unchanged?
sl@0
   522
	XTEST(aChannel.CheckBuffer(KDestBuf2, 'A'));
sl@0
   523
sl@0
   524
	// Test cancelling
sl@0
   525
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   526
	r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize);
sl@0
   527
	XTEST2(r == KErrNone, r, aSize);
sl@0
   528
	test(aChannel.FragmentCheck(KRequest, aFragmentCount));
sl@0
   529
	r = aChannel.Execute(_L8("Q0C"));
sl@0
   530
	XTEST1(r == KErrNone, r);
sl@0
   531
	// Part of the destination buffer should be unchanged if the
sl@0
   532
	// cancel occured before the transfer completed.
sl@0
   533
#ifdef __DMASIM__
sl@0
   534
	// At least part of the last destination buffer should be
sl@0
   535
	// unchanged if cancel occured before the transfer completed.
sl@0
   536
	// Assert only on WINS as real DMACs are too fast.
sl@0
   537
	XTEST(! aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   538
#endif
sl@0
   539
sl@0
   540
	// Perform another transfer to ensure cancel operation let the
sl@0
   541
	// framework in a consistent state.
sl@0
   542
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   543
	r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
sl@0
   544
	XTEST2(r == KErrNone, r, aSize);
sl@0
   545
	test(aChannel.FragmentCheck(KRequest, aFragmentCount));
sl@0
   546
	r = aChannel.Execute(_L8("Q0"));
sl@0
   547
	XTEST1(r == KErrNone, r);
sl@0
   548
	User::WaitForRequest(rs);
sl@0
   549
	XTEST1(rs == KErrNone, rs.Int());
sl@0
   550
	XTEST(aChannel.CheckBuffer(KDestBuf1, 'A'));
sl@0
   551
sl@0
   552
	//
sl@0
   553
	// Test failure if the underlying DMA kernel extension allows it.
sl@0
   554
	//
sl@0
   555
	// As long as only "CancelAllFragments" is supported, it's okay to
sl@0
   556
	// always fail on the first fragment.
sl@0
   557
	//
sl@0
   558
sl@0
   559
	if (aChannel.FailNext(1) == KErrNone)
sl@0
   560
		{
sl@0
   561
		aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   562
		r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
sl@0
   563
		XTEST2(r == KErrNone, r, aSize);
sl@0
   564
		test(aChannel.FragmentCheck(KRequest, aFragmentCount));
sl@0
   565
		r = aChannel.Execute(_L8("Q0"));
sl@0
   566
		XTEST1(r == KErrNone, r);
sl@0
   567
		User::WaitForRequest(rs);
sl@0
   568
		XTEST1(rs != KErrNone, rs.Int());
sl@0
   569
		XTEST(! aChannel.CheckBuffer(KDestBuf1, 'A'));
sl@0
   570
		r = aChannel.Execute(_L8("C"));
sl@0
   571
		XTEST1(r == KErrNone, r);
sl@0
   572
sl@0
   573
		// Perform another transfer to ensure we are still in a
sl@0
   574
		// consistent state.
sl@0
   575
		aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   576
		r = aChannel.Fragment(KRequest, KSrcBuf, KDestBuf1, aSize, &rs);
sl@0
   577
		XTEST2(r == KErrNone, r, aSize);
sl@0
   578
		test(aChannel.FragmentCheck(KRequest, aFragmentCount));
sl@0
   579
		r = aChannel.Execute(_L8("Q0"));
sl@0
   580
		XTEST1(r == KErrNone, r);
sl@0
   581
		User::WaitForRequest(rs);
sl@0
   582
		XTEST1(rs == KErrNone, rs.Int());
sl@0
   583
		XTEST(aChannel.CheckBuffer(KDestBuf1, 'A'));
sl@0
   584
		}
sl@0
   585
sl@0
   586
	aChannel.FreeAllBuffers();
sl@0
   587
	}
sl@0
   588
sl@0
   589
sl@0
   590
static void TestStreaming(RTestDma aChannel, TInt aFragmentCount, TInt aSize)
sl@0
   591
	{
sl@0
   592
	const TInt KRequest0 = 0;
sl@0
   593
	const TInt KRequest1 = 1;
sl@0
   594
	const TInt KRequest2 = 2;
sl@0
   595
	const TInt KSrcBuf0 = 0;
sl@0
   596
	const TInt KSrcBuf1 = 1;
sl@0
   597
	const TInt KSrcBuf2 = 2;
sl@0
   598
	const TInt KDestBuf0 = 3;
sl@0
   599
	const TInt KDestBuf1 = 4;
sl@0
   600
	const TInt KDestBuf2 = 5;
sl@0
   601
sl@0
   602
	//
sl@0
   603
	// Allocate and initialise source buffers
sl@0
   604
	//
sl@0
   605
sl@0
   606
	TInt r = aChannel.AllocBuffer(KSrcBuf0, aSize);
sl@0
   607
	XTEST2(r == KErrNone, r, aSize);
sl@0
   608
	aChannel.FillBuffer(KSrcBuf0, 'A');
sl@0
   609
sl@0
   610
	r = aChannel.AllocBuffer(KSrcBuf1, aSize);
sl@0
   611
	XTEST2(r == KErrNone, r, aSize);
sl@0
   612
	aChannel.FillBuffer(KSrcBuf1, 'B');
sl@0
   613
sl@0
   614
	r = aChannel.AllocBuffer(KSrcBuf2, aSize);
sl@0
   615
	XTEST2(r == KErrNone, r, aSize);
sl@0
   616
	aChannel.FillBuffer(KSrcBuf2, 'C');
sl@0
   617
sl@0
   618
	//
sl@0
   619
	// Allocate destination buffers
sl@0
   620
	//
sl@0
   621
sl@0
   622
	r = aChannel.AllocBuffer(KDestBuf0, aSize);
sl@0
   623
	XTEST2(r == KErrNone, r, aSize);
sl@0
   624
	r = aChannel.AllocBuffer(KDestBuf1, aSize);
sl@0
   625
	XTEST2(r == KErrNone, r, aSize);
sl@0
   626
	r = aChannel.AllocBuffer(KDestBuf2, aSize);
sl@0
   627
	XTEST2(r == KErrNone, r, aSize);
sl@0
   628
sl@0
   629
	//
sl@0
   630
	// Test simple transfer.
sl@0
   631
	// (no need to test for request reconfiguration afterwards because
sl@0
   632
	// this was exercised in the one-shot test case)
sl@0
   633
	//
sl@0
   634
sl@0
   635
	TRequestStatus rs0;
sl@0
   636
	r = aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0);
sl@0
   637
	XTEST2(r == KErrNone, r, aSize);
sl@0
   638
	test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
sl@0
   639
	TRequestStatus rs1;
sl@0
   640
 	r = aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1);
sl@0
   641
	XTEST2(r == KErrNone, r, aSize);
sl@0
   642
	test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
sl@0
   643
	TRequestStatus rs2;
sl@0
   644
	r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
sl@0
   645
	XTEST2(r == KErrNone, r, aSize);
sl@0
   646
	test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   647
sl@0
   648
	r = aChannel.Execute(_L8("Q0Q1Q2"));
sl@0
   649
	XTEST1(r == KErrNone, r);
sl@0
   650
	User::WaitForRequest(rs0);
sl@0
   651
	XTEST1(rs0 == KErrNone, rs0.Int());
sl@0
   652
	XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   653
	User::WaitForRequest(rs1);
sl@0
   654
	XTEST1(rs1 == KErrNone, rs1.Int());
sl@0
   655
	XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
sl@0
   656
	User::WaitForRequest(rs2);
sl@0
   657
	XTEST1(rs2 == KErrNone, rs2.Int());
sl@0
   658
	XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   659
sl@0
   660
	//
sl@0
   661
	// Test cancel
sl@0
   662
	//
sl@0
   663
sl@0
   664
	aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   665
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   666
	aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   667
sl@0
   668
	r = aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize);
sl@0
   669
	XTEST2(r == KErrNone, r, aSize);
sl@0
   670
	test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
sl@0
   671
 	r = aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize);
sl@0
   672
	XTEST2(r == KErrNone, r, aSize);
sl@0
   673
	test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
sl@0
   674
	r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize);
sl@0
   675
	XTEST2(r == KErrNone, r, aSize);
sl@0
   676
	test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   677
sl@0
   678
	r = aChannel.Execute(_L8("Q0Q1Q2C"));
sl@0
   679
	XTEST1(r == KErrNone, r);
sl@0
   680
#ifdef __DMASIM__
sl@0
   681
	// At least part of the last destination buffer should be
sl@0
   682
	// unchanged if cancel occured before the transfer completed.
sl@0
   683
	// Assert only on WINS as real DMACs are too fast.
sl@0
   684
	XTEST(! aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   685
#endif
sl@0
   686
sl@0
   687
	//
sl@0
   688
	// Perform another transfer to ensure cancel operation let the
sl@0
   689
	// framework in a consistent state.
sl@0
   690
	//
sl@0
   691
sl@0
   692
	aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   693
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   694
	aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   695
	// Reconfigure last request to enable transfer completion notification
sl@0
   696
	r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
sl@0
   697
	XTEST2(r == KErrNone, r, aSize);
sl@0
   698
	test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   699
	r = aChannel.Execute(_L8("Q0Q1Q2"));
sl@0
   700
	XTEST1(r == KErrNone, r);
sl@0
   701
	User::WaitForRequest(rs2);
sl@0
   702
	XTEST1(rs2 == KErrNone, rs2.Int());
sl@0
   703
	XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   704
	XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
sl@0
   705
	XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   706
sl@0
   707
	//
sl@0
   708
	// Test for proper implementation of UnlinkHwDes() in the PSL.
sl@0
   709
	//
sl@0
   710
sl@0
   711
	aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   712
	aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   713
	aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   714
	// Reconfigure last request to enable transfer completion notification
sl@0
   715
	r = aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2);
sl@0
   716
	XTEST2(r == KErrNone, r, aSize);
sl@0
   717
	test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   718
	// Queue first request (Q0)
sl@0
   719
	r = aChannel.Execute(_L8("Q0"));
sl@0
   720
	// Wait a second, so next request will be queued on its own
sl@0
   721
	// (instead of being appended to the previous one)
sl@0
   722
	User::After(1000000);
sl@0
   723
	// Queue third request (Q2)
sl@0
   724
	r = aChannel.Execute(_L8("Q2"));
sl@0
   725
	XTEST1(r == KErrNone, r);
sl@0
   726
	User::WaitForRequest(rs2);
sl@0
   727
	XTEST1(rs2 == KErrNone, rs2.Int());
sl@0
   728
	XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   729
	// KDestBuf1 should have been left untouched!
sl@0
   730
	// If we find all B's in KDestBuf1, that means the last descriptor of the
sl@0
   731
	// first request (Q0) wasn't properly unlinked and still points to the Q1
sl@0
   732
	// descriptor chain from the previous run.
sl@0
   733
	XTEST(aChannel.CheckBuffer(KDestBuf1, '\0'));
sl@0
   734
	XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   735
sl@0
   736
	//
sl@0
   737
	// Test failure if the underlying DMA kernel extension allows it.
sl@0
   738
	//
sl@0
   739
	// As long as only "CancelAllFragments" is supported, it's okay to
sl@0
   740
	// always fail on the first fragment.
sl@0
   741
	//
sl@0
   742
sl@0
   743
	if (aChannel.FailNext(1) == KErrNone)
sl@0
   744
		{
sl@0
   745
		aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   746
		aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   747
		aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   748
		XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
sl@0
   749
		test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
sl@0
   750
		XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize) == KErrNone);
sl@0
   751
		test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
sl@0
   752
		XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize) == KErrNone);
sl@0
   753
		test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   754
		XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
sl@0
   755
		User::WaitForRequest(rs0);
sl@0
   756
		XTEST(rs0 != KErrNone);
sl@0
   757
		XTEST(! aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   758
		XTEST(! aChannel.CheckBuffer(KDestBuf1, 'B'));
sl@0
   759
		XTEST(! aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   760
		XTEST(aChannel.Execute(_L8("C")) == KErrNone);
sl@0
   761
sl@0
   762
		// Transfer again to ensure cancel cleaned-up correctly
sl@0
   763
		aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   764
		aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   765
		aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   766
		XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
sl@0
   767
		test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
sl@0
   768
		XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1) == KErrNone);
sl@0
   769
		test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
sl@0
   770
		XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2) == KErrNone);
sl@0
   771
		test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   772
		XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
sl@0
   773
		User::WaitForRequest(rs0);
sl@0
   774
		XTEST(rs0 == KErrNone);
sl@0
   775
		User::WaitForRequest(rs1);
sl@0
   776
		XTEST(rs1 == KErrNone);
sl@0
   777
		User::WaitForRequest(rs2);
sl@0
   778
		XTEST(rs2 == KErrNone);
sl@0
   779
		XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   780
		XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
sl@0
   781
		XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   782
		}
sl@0
   783
sl@0
   784
	//
sl@0
   785
	// Test that framework behaves correctly if one or more DMA interrupts are
sl@0
   786
	// missed.
sl@0
   787
	//
sl@0
   788
sl@0
   789
	if (aChannel.MissNextInterrupts(1) == KErrNone)
sl@0
   790
		{
sl@0
   791
		aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   792
		aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   793
		aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   794
		XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
sl@0
   795
		test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
sl@0
   796
		XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1) == KErrNone);
sl@0
   797
		test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
sl@0
   798
		XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2) == KErrNone);
sl@0
   799
		test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   800
		XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
sl@0
   801
		User::WaitForRequest(rs0);
sl@0
   802
		XTEST(rs0 == KErrNone);
sl@0
   803
		User::WaitForRequest(rs1);
sl@0
   804
		XTEST(rs1 == KErrNone);
sl@0
   805
		User::WaitForRequest(rs2);
sl@0
   806
		XTEST(rs2 == KErrNone);
sl@0
   807
		XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   808
		XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
sl@0
   809
		XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   810
		}
sl@0
   811
sl@0
   812
	if (aChannel.MissNextInterrupts(2) == KErrNone)
sl@0
   813
		{
sl@0
   814
		aChannel.FillBuffer(KDestBuf0, '\0');
sl@0
   815
		aChannel.FillBuffer(KDestBuf1, '\0');
sl@0
   816
		aChannel.FillBuffer(KDestBuf2, '\0');
sl@0
   817
		XTEST(aChannel.Fragment(KRequest0, KSrcBuf0, KDestBuf0, aSize, &rs0) == KErrNone);
sl@0
   818
		test(aChannel.FragmentCheck(KRequest0, aFragmentCount));
sl@0
   819
		XTEST(aChannel.Fragment(KRequest1, KSrcBuf1, KDestBuf1, aSize, &rs1) == KErrNone);
sl@0
   820
		test(aChannel.FragmentCheck(KRequest1, aFragmentCount));
sl@0
   821
		XTEST(aChannel.Fragment(KRequest2, KSrcBuf2, KDestBuf2, aSize, &rs2) == KErrNone);
sl@0
   822
		test(aChannel.FragmentCheck(KRequest2, aFragmentCount));
sl@0
   823
		XTEST(aChannel.Execute(_L8("Q0Q1Q2")) == KErrNone);
sl@0
   824
		User::WaitForRequest(rs0);
sl@0
   825
		XTEST(rs0 == KErrNone);
sl@0
   826
		User::WaitForRequest(rs1);
sl@0
   827
		XTEST(rs1 == KErrNone);
sl@0
   828
		User::WaitForRequest(rs2);
sl@0
   829
		XTEST(rs2 == KErrNone);
sl@0
   830
		XTEST(aChannel.CheckBuffer(KDestBuf0, 'A'));
sl@0
   831
		XTEST(aChannel.CheckBuffer(KDestBuf1, 'B'));
sl@0
   832
		XTEST(aChannel.CheckBuffer(KDestBuf2, 'C'));
sl@0
   833
		}
sl@0
   834
sl@0
   835
	aChannel.FreeAllBuffers();
sl@0
   836
	}
sl@0
   837
sl@0
   838
sl@0
   839
static TBool ParseCmdLine(TBool& aCrashDbg, TInt& aMaxfrag, TInt& aMaxIter, TInt& aMaxchannel, TInt& aMaxFragSize)
sl@0
   840
//
sl@0
   841
// The command line. Syntax is:
sl@0
   842
//
sl@0
   843
//     t_dma [enableCrashDebugger [aMaxFrag [aMaxIter [aMaxchannel [aMaxFragSize]]]]]
sl@0
   844
//
sl@0
   845
	{
sl@0
   846
	TBuf<256> cmdline;
sl@0
   847
	User::CommandLine(cmdline);
sl@0
   848
	TLex lex(cmdline);
sl@0
   849
sl@0
   850
	lex.SkipSpace();
sl@0
   851
sl@0
   852
	if (lex.Eos())
sl@0
   853
		return ETrue;
sl@0
   854
	if (lex.Val(aCrashDbg) != KErrNone)
sl@0
   855
		return EFalse;
sl@0
   856
	lex.SkipSpace();
sl@0
   857
	if (lex.Eos())
sl@0
   858
		return ETrue;
sl@0
   859
	if (lex.Val(aMaxfrag) != KErrNone)
sl@0
   860
		return EFalse;
sl@0
   861
	lex.SkipSpace();
sl@0
   862
	if (lex.Eos())
sl@0
   863
		return ETrue;
sl@0
   864
	if (lex.Val(aMaxIter) != KErrNone)
sl@0
   865
		return EFalse;
sl@0
   866
	lex.SkipSpace();
sl@0
   867
	if (lex.Eos())
sl@0
   868
		return ETrue;
sl@0
   869
	if (lex.Val(aMaxchannel) != KErrNone)
sl@0
   870
		return EFalse;
sl@0
   871
	lex.SkipSpace();
sl@0
   872
	if (lex.Eos())
sl@0
   873
		return ETrue;
sl@0
   874
sl@0
   875
	return lex.Val(aMaxFragSize) == KErrNone;
sl@0
   876
	}
sl@0
   877
sl@0
   878
sl@0
   879
TInt E32Main()
sl@0
   880
	{
sl@0
   881
	test.Title();
sl@0
   882
sl@0
   883
	test.Start(_L("Parsing command-line"));
sl@0
   884
	// Default values when run with empty command-line
sl@0
   885
	TInt maxfrag = 16; // 5 fragments needed to exercise fully double-buffering state machine
sl@0
   886
	TInt maxIter = 3;
sl@0
   887
	TInt maxchannel = KMaxTInt;
sl@0
   888
	TBool crashDbg = EFalse;
sl@0
   889
	TInt maxFragSize = 0x4000; //16k
sl@0
   890
sl@0
   891
	(void) ParseCmdLine(crashDbg, maxfrag, maxIter, maxchannel, maxFragSize);
sl@0
   892
sl@0
   893
	if (crashDbg)
sl@0
   894
		{
sl@0
   895
		User::SetCritical(User::ESystemCritical);
sl@0
   896
		User::SetProcessCritical(User::ESystemCritical);
sl@0
   897
		}
sl@0
   898
sl@0
   899
sl@0
   900
	TInt r;
sl@0
   901
#if defined(__DMASIM__) && defined(__WINS__)
sl@0
   902
	test.Next(_L("Loading DMA simulator"));
sl@0
   903
	r = User::LoadLogicalDevice(_L("DMASIM.DLL"));
sl@0
   904
	test(r == KErrNone || r == KErrAlreadyExists);
sl@0
   905
#endif
sl@0
   906
sl@0
   907
	test.Next(_L("Loading test LDD"));
sl@0
   908
#ifdef __DMASIM__
sl@0
   909
	r = User::LoadLogicalDevice(_L("D_DMASIM"));
sl@0
   910
	test(r == KErrNone || r == KErrAlreadyExists);
sl@0
   911
#else
sl@0
   912
	//load either the original test ldd, d_dma.ldd,
sl@0
   913
	//or d_dma_compat.ldd - an ldd providing the same interface
sl@0
   914
	//but linked against the new MHA dma framework
sl@0
   915
	_LIT(KDma, "D_DMA.LDD");
sl@0
   916
	r = User::LoadLogicalDevice(KDma);
sl@0
   917
	const TBool dmaPresent = (r == KErrNone || r == KErrAlreadyExists);
sl@0
   918
sl@0
   919
	_LIT(KDmaCompat, "D_DMA_COMPAT.LDD");
sl@0
   920
	r = User::LoadLogicalDevice(KDmaCompat);
sl@0
   921
	const TBool dmaCompatPresent = (r == KErrNone || r == KErrAlreadyExists);
sl@0
   922
sl@0
   923
	if (!(dmaPresent || dmaCompatPresent))
sl@0
   924
		{
sl@0
   925
		test.Printf(_L("DMA test driver not found - test skipped\n"));
sl@0
   926
		return 0;
sl@0
   927
		}
sl@0
   928
	else if (dmaPresent && !dmaCompatPresent)
sl@0
   929
		{
sl@0
   930
		test.Printf(_L("Loaded %S\n"), &KDma);
sl@0
   931
		}
sl@0
   932
	else if (!dmaPresent && dmaCompatPresent)
sl@0
   933
		{
sl@0
   934
		test.Printf(_L("Loaded %S\n"), &KDmaCompat);
sl@0
   935
		}
sl@0
   936
	else
sl@0
   937
		{
sl@0
   938
		test.Printf(_L("The ROM contains %S and %S - only one should be present\n"), &KDma, &KDmaCompat);
sl@0
   939
		test(EFalse);
sl@0
   940
		}
sl@0
   941
#endif
sl@0
   942
sl@0
   943
	// Turn off evil lazy dll unloading
sl@0
   944
	RLoader l;
sl@0
   945
	test(l.Connect()==KErrNone);
sl@0
   946
	test(l.CancelLazyDllUnload()==KErrNone);
sl@0
   947
	l.Close();
sl@0
   948
sl@0
   949
	__UHEAP_MARK;
sl@0
   950
	__KHEAP_MARK;
sl@0
   951
sl@0
   952
	test.Next(_L("Creating critical section"));
sl@0
   953
	test(TheCriticalSection.CreateLocal() == KErrNone);
sl@0
   954
sl@0
   955
	test.Next(_L("Creating active scheduler"));
sl@0
   956
	CActiveScheduler* pS = new CActiveScheduler;
sl@0
   957
	test(pS != NULL);
sl@0
   958
	CActiveScheduler::Install(pS);
sl@0
   959
sl@0
   960
	test.Next(_L("Creating bipper"));
sl@0
   961
	Bipper = CPeriodic::New(CActive::EPriorityStandard);
sl@0
   962
	test(Bipper != NULL);
sl@0
   963
sl@0
   964
	test.Next(_L("Getting channel info"));
sl@0
   965
	GetChannelInfo();
sl@0
   966
sl@0
   967
	// Size for the single transfer test
sl@0
   968
	TInt totalTransferSize = 64 * KKilo;
sl@0
   969
sl@0
   970
	test.Next(_L("Testing one shot single buffer transfer"));
sl@0
   971
	RunSbTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
sl@0
   972
	RunSbTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
sl@0
   973
sl@0
   974
	test.Next(_L("Testing one shot double buffer transfer"));
sl@0
   975
	RunDbTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
sl@0
   976
	RunDbTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
sl@0
   977
sl@0
   978
	test.Next(_L("Testing one shot scatter/gather transfer"));
sl@0
   979
	RunSgTest(maxchannel, new CFragmentationTest(TestOneShot, maxIter, maxfrag, maxFragSize));
sl@0
   980
	RunSgTest(maxchannel, new CDefaultFragTest(TestOneShot, maxIter, totalTransferSize));
sl@0
   981
sl@0
   982
	test.Next(_L("Testing streaming single buffer transfer"));
sl@0
   983
	RunSbTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
sl@0
   984
	RunSbTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
sl@0
   985
sl@0
   986
	test.Next(_L("Testing streaming double buffer transfer"));
sl@0
   987
	RunDbTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
sl@0
   988
	RunDbTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
sl@0
   989
sl@0
   990
	test.Next(_L("Testing streaming scatter/gather transfer"));
sl@0
   991
	RunSgTest(maxchannel, new CFragmentationTest(TestStreaming, maxIter, maxfrag, maxFragSize));
sl@0
   992
	RunSgTest(maxchannel, new CDefaultFragTest(TestStreaming, maxIter, totalTransferSize));
sl@0
   993
sl@0
   994
	delete pS;
sl@0
   995
	delete Bipper;
sl@0
   996
	TheCriticalSection.Close();
sl@0
   997
sl@0
   998
	UserSvr::HalFunction(EHalGroupKernel, EKernelHalSupervisorBarrier, (TAny*)5000, 0);
sl@0
   999
	__KHEAP_MARKEND;
sl@0
  1000
	__UHEAP_MARKEND;
sl@0
  1001
sl@0
  1002
	test.End();
sl@0
  1003
	return 0;
sl@0
  1004
	}