--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/dmav2/t_dma2.cpp Mon Jan 18 21:31:10 2010 +0200
@@ -0,0 +1,1546 @@
+// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\dma\t_dma.cpp
+
+#include "d_dma2.h"
+#include "u32std.h"
+#include "t_dma2.h"
+#include "cap_reqs.h"
+
+#define __E32TEST_EXTENSION__
+#include <e32test.h>
+#include <e32debug.h>
+#include <e32svr.h>
+#include <e32def_private.h>
+
+// DMA test framework command parameter options
+
+// SelfTest Option
+_LIT(KArgSelfTest, "/SELFTEST");
+_LIT(KArgSelfTest2, "/S");
+
+//Verbose Option
+_LIT(KArgVerboseOutput, "/VERBOSE");
+_LIT(KArgVerboseOutput2, "/V");
+
+
+TBool gHelpRequested; // print usage
+TBool gVerboseOutput; // enable verbose output
+TBool gSelfTest; // run SelfTest
+
+/**
+This function prints out the PSL test Information
+*/
+void Print(const TDmaV2TestInfo& aInfo)
+ {
+ PRINT(aInfo.iMaxTransferSize);
+ PRINT(aInfo.iMemAlignMask);
+ PRINT(aInfo.iMemMemPslInfo);
+ PRINT(aInfo.iMaxSbChannels);
+ for(TInt i=0; i<aInfo.iMaxSbChannels; i++)
+ {
+ PRINT(aInfo.iSbChannels[i]);
+ }
+ PRINT(aInfo.iMaxDbChannels);
+ for(TInt j=0; j<aInfo.iMaxDbChannels; j++)
+ {
+ PRINT(aInfo.iDbChannels[j]);
+ }
+ PRINT(aInfo.iMaxSgChannels);
+ for(TInt k=0; k<aInfo.iMaxSgChannels; k++)
+ {
+ PRINT(aInfo.iSgChannels[k]);
+ }
+ }
+
+void CDmaTest::PrintTestInfo() const
+ {
+ TBuf<32> buf;
+ buf.AppendFormat(_L("DMA channel %d"), iChannelCookie);
+ RDebug::RawPrint(buf);
+ }
+
+//////////////////////////////////////////////////////////////////////
+// CDmaTest
+//////////////////////////////////////////////////////////////////////
+
+void CDmaTest::OpenDmaSession()
+ {
+ TInt r = iDmaSession.Open();
+ TEST_ASSERT(r == KErrNone);
+ r = iDmaSession.OpenSharedChunk(iChunk);
+ TEST_ASSERT(r == KErrNone);
+ }
+
+void CDmaTest::CloseDmaSession()
+ {
+ iChunk.Close();
+ iDmaSession.Close();
+ }
+
+//////////////////////////////////////////////////////////////////////
+// CSingleTransferTest
+//////////////////////////////////////////////////////////////////////
+void CSingleTransferTest::RunTest()
+ {
+ OpenDmaSession();
+ PreTransferSetup();
+
+ OpenChannel();
+ CreateDmaRequest();
+ Fragment();
+ Queue();
+ FreeRequest();
+ CloseChannel();
+ PostTransferCheck();
+
+ CloseDmaSession();
+ }
+
+void CSingleTransferTest::OpenChannel()
+ {
+ iActual.iChannelOpenResult =
+ iDmaSession.ChannelOpen(iChannelCookie, iChannelSessionCookie);
+ }
+
+void CSingleTransferTest::CreateDmaRequest()
+ {
+ if(iUseNewRequest)
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Calling New Request API\n");
+ }
+ iActual.iRequestResult.iCreate =
+ iDmaSession.RequestCreateNew(iChannelSessionCookie, iRequestSessionCookie, iMaxFragmentSize);
+ }
+ else
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Calling Old Request API\n");
+ }
+ iActual.iRequestResult.iCreate =
+ iDmaSession.RequestCreate(iChannelSessionCookie, iRequestSessionCookie, iMaxFragmentSize);
+ }
+ }
+
+void CSingleTransferTest::Fragment()
+ {
+ if(iActual.iRequestResult.iCreate != KErrNone)
+ return;
+
+ if(iUseNewFragment)
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Calling New Fragment API\n");
+ }
+ iActual.iRequestResult.iFragmentationResult =
+ iDmaSession.FragmentRequest(iRequestSessionCookie, iTransferArgs);
+ }
+ else
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Calling Old Fragment API\n");
+ }
+ iActual.iRequestResult.iFragmentationResult =
+ iDmaSession.FragmentRequestOld(iRequestSessionCookie, iTransferArgs);
+
+ }
+
+ const TInt fragmentCount = iDmaSession.RequestFragmentCount(iRequestSessionCookie);
+
+ // Record the fragment count if a non-zero value was expected,
+ // or if it was an error value
+ if(iExpected.iRequestResult.iFragmentCount != 0 || fragmentCount < 0)
+ iActual.iRequestResult.iFragmentCount = fragmentCount;
+ }
+
+void CSingleTransferTest::Queue()
+ {
+ if(iActual.iRequestResult.iFragmentationResult == KErrNone)
+ {
+ iActual.iRequestResult.iQueueResult = iDmaSession.QueueRequest(iRequestSessionCookie, &iActual.iCallbackRecord);
+ }
+ }
+
+void CSingleTransferTest::PostTransferCheck()
+ {
+ if(iPostTransferCheck)
+ iActual.iPostTransferCheck = DoPostTransferCheck();
+ }
+
+TInt CSingleTransferTest::DoPostTransferCheck()
+ {
+ return iPostTransferCheck->Check(*this);
+ }
+
+void CSingleTransferTest::FreeRequest()
+ {
+ if(iActual.iRequestResult.iCreate == KErrNone)
+ {
+ TInt r = iDmaSession.RequestDestroy(iRequestSessionCookie);
+ TEST_ASSERT(r == KErrNone);
+ }
+ }
+
+void CSingleTransferTest::CloseChannel()
+ {
+ if(iActual.iChannelOpenResult == KErrNone)
+ {
+ TInt r = iDmaSession.ChannelClose(iChannelSessionCookie);
+ TEST_ASSERT(r == KErrNone);
+ }
+ }
+
+void CSingleTransferTest::PrintTestType() const
+ {
+ RDebug::RawPrint(_L("Single transfer"));
+ }
+
+void CSingleTransferTest::PreTransferSetup()
+ {
+ if(iPreTransfer)
+ iPreTransfer->Setup(*this); //initialize test
+ }
+
+TBool CSingleTransferTest::Result()
+ {
+ const TBool result = iExpected == iActual;
+ if(!result)
+ {
+ RDebug::Printf("TResultSets do not match");
+ }
+ if(!result || gVerboseOutput)
+ {
+ RDebug::Printf("\nExpected error codes:");
+ iExpected.Print();
+ RDebug::Printf("Expected callback record:");
+ iExpected.iCallbackRecord.Print();
+
+ RDebug::Printf("\nActual error codes:");
+ iActual.Print();
+ RDebug::Printf("Actual callback record:");
+ iActual.iCallbackRecord.Print();
+ }
+ return result;
+ }
+
+
+
+//////////////////////////////////////////////////////////////////////
+// CDmaBenchmark
+//////////////////////////////////////////////////////////////////////
+
+CDmaBenchmark::CDmaBenchmark(const TDesC& aName, TInt aIterations, const TResultSet& aExpectedResults, const TDmaTransferArgs& aTransferArgs, TUint aMaxFragmentSize)
+ :CSingleTransferTest(aName, aIterations, aTransferArgs, aExpectedResults, aMaxFragmentSize, NULL, NULL)
+ {
+ UseNewDmaApi(EFalse);
+ }
+
+CDmaBenchmark::~CDmaBenchmark()
+ {
+ iResultArray.Close();
+ }
+
+TUint64 CDmaBenchmark::MeanResult()
+ {
+ if(gVerboseOutput)
+ RDebug::Printf("CDmaBenchmark::MeanResult\n");
+
+ const TInt count = iResultArray.Count();
+
+ TEST_ASSERT(count > 0);
+ TEST_ASSERT(count == iIterations);
+
+ TUint64 sum = 0;
+
+ for(TInt i = 0; i < count; i++)
+ {
+ const TUint64 value = iResultArray[i];
+ if(gVerboseOutput)
+ RDebug::Printf("iResultArray[%d]: %lu", i, value);
+
+ sum += value;
+ }
+
+ return sum / count;
+ }
+
+TBool CDmaBenchmark::Result()
+ {
+ const TBool result = CSingleTransferTest::Result();
+ if(result)
+ {
+ RDebug::Printf(" Mean time: %lu us", MeanResult());
+ }
+
+ //TODO this will be handled by the ctor later
+ iResultArray.Close();
+
+ return result;
+ }
+
+
+//////////////////////////////////////////////////////////////////////
+// CDmaBmFragmentation
+//////////////////////////////////////////////////////////////////////
+
+CDmaBmFragmentation::CDmaBmFragmentation(const TDesC& aName, TInt aIterations, const TDmaTransferArgs& aTransferArgs, TUint aMaxFragmentSize)
+ :CDmaBenchmark(aName, aIterations, ExpectedResults, aTransferArgs, aMaxFragmentSize)
+ {}
+
+const TResultSet CDmaBmFragmentation::ExpectedResults(KErrNone,
+ TRequestResults(KErrNone, 0, KErrNone, KErrUnknown),
+ KErrUnknown,
+ TCallbackRecord::Empty()
+ );
+
+void CDmaBmFragmentation::Fragment()
+ {
+ TUint64 time;
+ iActual.iRequestResult.iFragmentationResult =
+ iDmaSession.FragmentRequestOld(iRequestSessionCookie, iTransferArgs, &time);
+ iResultArray.Append(time);
+ }
+
+void CDmaBmFragmentation::PrintTestType() const
+ {
+ RDebug::RawPrint(_L("Fragmentation Benchmark"));
+ }
+
+void CDmaBmFragmentation::RunTest()
+ {
+ OpenDmaSession();
+
+ OpenChannel();
+ CreateDmaRequest();
+ Fragment();
+ FreeRequest();
+ CloseChannel();
+
+ CloseDmaSession();
+ }
+
+//////////////////////////////////////////////////////////////////////
+// CDmaBmTransfer
+//////////////////////////////////////////////////////////////////////
+
+CDmaBmTransfer::CDmaBmTransfer(const TDesC& aName, TInt aIterations, const TDmaTransferArgs& aTransferArgs, TUint aMaxFragmentSize)
+ :CDmaBenchmark(aName, aIterations,
+ TResultSet(KErrNone, TRequestResults(), KErrUnknown, TCallbackRecord(TCallbackRecord::EThread,1)),
+ aTransferArgs, aMaxFragmentSize)
+ {}
+
+
+void CDmaBmTransfer::PrintTestType() const
+ {
+ RDebug::RawPrint(_L("Transfer Benchmark"));
+ }
+
+void CDmaBmTransfer::RunTest()
+ {
+ OpenDmaSession();
+
+ OpenChannel();
+ CreateDmaRequest();
+ Fragment();
+ Queue();
+ FreeRequest();
+ CloseChannel();
+
+ CloseDmaSession();
+ }
+
+void CDmaBmTransfer::Queue()
+ {
+ if(iActual.iRequestResult.iFragmentationResult == KErrNone)
+ {
+ TUint64 time;
+ iActual.iRequestResult.iQueueResult = iDmaSession.QueueRequest(iRequestSessionCookie, &iActual.iCallbackRecord, &time);
+ iResultArray.Append(time);
+ }
+ }
+
+
+//////////////////////////////////////////////////////////////////////
+// CMultiTransferTest
+//////////////////////////////////////////////////////////////////////
+
+//TODO
+// Add pre and post transfer for CMultiTransferTest
+CMultiTransferTest::CMultiTransferTest(const TDesC& aName, TInt aIterations, const TDmaTransferArgs* aTransferArgs,
+ const TResultSet* aResultSets, TInt aCount)
+ : CDmaTest(aName, aIterations, NULL, NULL), iTransferArgs(aTransferArgs), iTransferArgsCount(aCount), iNewDmaApi(ETrue),
+ iChannelSessionCookie(0), iExpectedArray(aResultSets), iPauseWhileQueuing(EFalse)
+ {}
+
+CMultiTransferTest::CMultiTransferTest(const CMultiTransferTest& aOther)
+ : CDmaTest(aOther), iTransferArgs(aOther.iTransferArgs), iTransferArgsCount(aOther.iTransferArgsCount),
+ iNewDmaApi(aOther.iNewDmaApi),
+ iExpectedArray(aOther.iExpectedArray), iPauseWhileQueuing(aOther.iPauseWhileQueuing)
+ //const cast is required because their isn't a ctor taking const
+ //array values
+ //TODO iRequestCookies(const_cast<TUint*>(&aOther.iRequestCookies[0]), aOther.iRequestCookies.Count())
+ {
+ }
+
+CMultiTransferTest::~CMultiTransferTest()
+ {
+ iRequestCookies.Close();
+ iActualResults.Close();
+ }
+
+TBool CMultiTransferTest::Result()
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Results for %d transfers:", iTransferArgsCount);
+ }
+
+ TBool result = EFalse;
+ for(TInt i=0; i<iTransferArgsCount; i++)
+ {
+ result = Result(i);
+ if(!result)
+ break;
+ }
+ return result;
+ }
+
+TBool CMultiTransferTest::Result(TInt aTransfer)
+ {
+ const TResultSet& expected = iExpectedArray[aTransfer];
+ const TResultSet& actual = iActualResults[aTransfer];
+ const TBool result = expected == actual;
+ if(!result || gVerboseOutput)
+ {
+ RDebug::Printf("Compairing results for transfer %d", aTransfer);
+ }
+
+ if(!result)
+ {
+ RDebug::Printf("TResultSets do not match");
+ }
+ if(!result || gVerboseOutput)
+ {
+ RDebug::Printf("\nExpected error codes:");
+ expected.Print();
+ RDebug::Printf("Expected callback record:");
+ expected.iCallbackRecord.Print();
+
+ RDebug::Printf("\nActual error codes:");
+ actual.Print();
+ RDebug::Printf("Actual callback record:");
+ actual.iCallbackRecord.Print();
+ }
+ return result;
+ }
+void CMultiTransferTest::RunTest()
+ {
+ OpenDmaSession();
+
+ PreTransferSetup();
+ OpenChannel();
+
+ CreateDmaRequests();
+ Fragment();
+
+ QueueRequests();
+
+ TInt r = DoPostTransferCheck();
+ TEST_ASSERT(r == KErrNone);
+
+ CloseDmaSession();
+ }
+
+void CMultiTransferTest::PrintTestType() const
+ {
+ RDebug::RawPrint(_L("Multi Transfer"));
+ }
+
+const TDmaTransferArgs& CMultiTransferTest::TransferArgs(TInt aIndex) const
+ {
+ TEST_ASSERT(Rng(0, aIndex, iTransferArgsCount-1));
+
+ return iTransferArgs[aIndex];
+ }
+
+void CMultiTransferTest::SetPostTransferResult(TInt aIndex, TInt aErrorCode)
+ {
+ TEST_ASSERT(Rng(0, aIndex, iTransferArgsCount-1));
+
+ iActualResults[aIndex].iPostTransferCheck = aErrorCode;
+ }
+
+void CMultiTransferTest::OpenChannel()
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("CMultiTransferTest::OpenChannel()");
+ }
+ TInt r = iDmaSession.ChannelOpen(iChannelCookie, iChannelSessionCookie);
+
+ TEST_ASSERT(iActualResults.Count() == iTransferArgsCount);
+ for(TInt i=0; i<iTransferArgsCount; i++)
+ {
+ // Since all transfers will use the same channel,
+ // they all get the same result
+ // Arguably, iChannelOpenResult doesn't
+ // belong TResultSet
+ iActualResults[i].iChannelOpenResult = r;
+ }
+ }
+
+TInt CMultiTransferTest::CloseChannel()
+ {
+ return iDmaSession.ChannelClose(iChannelSessionCookie);
+ }
+
+void CMultiTransferTest::CreateDmaRequests()
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("CMultiTransferTest::CreateDmaRequests() %d", iTransferArgsCount);
+ }
+ TEST_ASSERT(iActualResults.Count() == iTransferArgsCount);
+ //create a DMA request for each transfer arg struct
+ for(TInt i=0; i<iTransferArgsCount; i++)
+ {
+ if(iActualResults[i].iChannelOpenResult != KErrNone)
+ continue;
+
+ TUint cookie = 0;
+ TInt r = KErrGeneral;
+
+ if(iNewDmaApi)
+ {
+ r = iDmaSession.RequestCreateNew(iChannelSessionCookie, cookie);
+ }
+ else
+ {
+ r = iDmaSession.RequestCreate(iChannelSessionCookie, cookie);
+ }
+ iActualResults[i].iRequestResult.iCreate = r;
+
+ if(r == KErrNone)
+ {
+ r = iRequestCookies.Append(cookie);
+ TEST_ASSERT(r == KErrNone);
+ }
+ }
+ }
+
+void CMultiTransferTest::Fragment()
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("CMultiTransferTest::Fragment() %d", iTransferArgsCount);
+ }
+ TEST_ASSERT(iActualResults.Count() == iTransferArgsCount);
+ // Fragment each dma request
+ for(TInt i=0; i<iTransferArgsCount; i++)
+ {
+ TRequestResults& result = iActualResults[i].iRequestResult;
+ if(result.iCreate != KErrNone)
+ continue;
+
+ TInt r = KErrGeneral;
+ if(iNewDmaApi)
+ r = iDmaSession.FragmentRequest(iRequestCookies[i], iTransferArgs[i]);
+ else
+ r = iDmaSession.FragmentRequestOld(iRequestCookies[i], iTransferArgs[i]);
+
+ result.iFragmentationResult = r;
+ }
+ }
+
+void CMultiTransferTest::QueueRequests()
+ {
+ if(iPauseWhileQueuing)
+ {
+ TInt r = iDmaSession.ChannelPause(iChannelSessionCookie);
+ TEST_ASSERT(r == KErrNone);
+ }
+
+ // Queue all the DMA requests asynchronously
+ TInt i;
+ RArray<TRequestStatus> requestStates;
+
+ TEST_ASSERT(iActualResults.Count() == iTransferArgsCount);
+ for(i=0; i<iTransferArgsCount; i++)
+ {
+ TResultSet& resultSet = iActualResults[i];
+ if(resultSet.iRequestResult.iFragmentationResult != KErrNone)
+ continue;
+
+ TInt r = requestStates.Append(TRequestStatus());
+ TEST_ASSERT(r == KErrNone);
+
+ r = iDmaSession.QueueRequest(iRequestCookies[i], requestStates[i], &resultSet.iCallbackRecord, NULL);
+ resultSet.iRequestResult.iQueueResult = r;
+ }
+
+ if(iPauseWhileQueuing)
+ {
+ TInt r = iDmaSession.ChannelResume(iChannelSessionCookie);
+ TEST_ASSERT(r == KErrNone);
+ }
+
+ // wait for all transfers to complete
+ const TInt count = requestStates.Count();
+
+ for(i=0; i<count; i++)
+ {
+ User::WaitForRequest(requestStates[i]);
+ }
+
+ requestStates.Close();
+ }
+
+//TODO support test setup for CMultiTransferTest
+void CMultiTransferTest::PreTransferSetup()
+ {
+ for(TInt i=0; i<iTransferArgsCount; i++)
+ {
+ //pre-fill actual results with error values
+ TInt r = iActualResults.Append(TResultSet(EFalse));
+ TEST_ASSERT(r == KErrNone);
+ }
+ if(iPreTransfer)
+ iPreTransfer->Setup(*this); //initialize test
+ }
+
+TInt CMultiTransferTest::DoPostTransferCheck()
+ {
+ if(iPostTransferCheck)
+ return iPostTransferCheck->Check(*this);
+ else
+ return KErrNone;
+ }
+//////////////////////////////////////////////////////////////////////
+// CIsrRequeTest
+//////////////////////////////////////////////////////////////////////
+
+
+CIsrRequeTest::CIsrRequeTest(const TDesC& aName, TInt aIterations, const TDmaTransferArgs& aArgs,
+ TIsrRequeArgs* aRequeueArgs, TInt aCount,
+ const TResultSet& aExpected,const MPreTransfer* aPreTfer,const MPostTransferCheck* aPostTferChk, TUint aMaxFragmentSize)
+ :CSingleTransferTest(aName, aIterations, aArgs, aExpected, aMaxFragmentSize, aPostTferChk, aPreTfer), iRequeArgSet(aRequeueArgs, aCount)
+ {}
+
+void CIsrRequeTest::Queue()
+ {
+ if(iActual.iRequestResult.iFragmentationResult == KErrNone)
+ {
+ iActual.iRequestResult.iQueueResult = iDmaSession.QueueRequestWithRequeue(iRequestSessionCookie, iRequeArgSet.iRequeArgs, iRequeArgSet.iCount, &iActual.iCallbackRecord);
+ }
+ }
+
+void CIsrRequeTest::PrintTestType() const
+ {
+ RDebug::RawPrint(_L("ISR Requeue"));
+ }
+
+/*
+//TODO will need to support buffer checking of the trasnfers
+TBool CIsrRequeTest::Result()
+ {
+ return CSingleTransferTest::Result();
+ }
+*/
+
+void CIsrRequeTest::PreTransferSetup()
+ {
+ if(iPreTransfer)
+ iPreTransfer->Setup(*this); //initialize test
+ }
+
+TInt CIsrRequeTest::DoPostTransferCheck()
+ {
+ return iPostTransferCheck->Check(*this);
+ }
+
+//////////////////////////////////////////////////////////////////////
+// TResultSet
+//////////////////////////////////////////////////////////////////////
+
+void TResultSet::Print() const
+ {
+ PRINT(iChannelOpenResult);
+ PRINT(iRequestResult.iCreate);
+ PRINT(iRequestResult.iFragmentCount);
+ PRINT(iRequestResult.iFragmentationResult);
+ PRINT(iRequestResult.iQueueResult);
+ PRINT(iPostTransferCheck);
+ }
+
+TBool TResultSet::operator == (const TResultSet& aOther) const
+ {
+ return (memcompare((TUint8*)this, sizeof(*this), (TUint8*)&aOther, sizeof(aOther)) == 0);
+ }
+
+//////////////////////////////////////////////////////////////////////
+// MPostTransferCheck classes
+//////////////////////////////////////////////////////////////////////
+
+TInt TCompareSrcDst::Check(const CSingleTransferTest& aTest) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Comparing CSingleTransferTest buffers");
+ }
+ return Check(aTest.TransferArgs(), aTest.Chunk().Base());
+ }
+
+//TODO
+//this check will not deal correctly transfers were subsequent
+//requeues overlap
+TInt TCompareSrcDst::Check(const CIsrRequeTest& aTest) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Comparing CIsrRequeTest buffers");
+ }
+ TUint8* chunkBase = aTest.Chunk().Base();
+ const TDmaTransferArgs& transferArgs = aTest.TransferArgs();
+ // check first transfer
+ TInt r = Check(transferArgs, chunkBase);
+
+ if(r != KErrNone)
+ return r;
+
+ // check re-queued transfers
+ const TIsrRequeArgsSet& requeueArgs = aTest.GetRequeueArgs();
+ return Check(requeueArgs, chunkBase, transferArgs);
+ }
+
+TInt TCompareSrcDst::Check(const TDmaTransferArgs& aTransferArgs, TUint8* aChunkBase) const
+ {
+ //TODO could make use of Fixup() method
+ const TUint32 srcOffset = aTransferArgs.iSrcConfig.iAddr;
+ const TUint32 dstOffset = aTransferArgs.iDstConfig.iAddr;
+ const TInt size = aTransferArgs.iTransferCount;
+
+ const TUint8* src = srcOffset + aChunkBase;
+ const TUint8* dst = dstOffset + aChunkBase;
+
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Comparing TDmaTransferArgs buffers src=0x%08x dst=0x%08x size=0x%08x",
+ src, dst, size);
+ }
+
+ return memcompare(src, size, dst, size);
+ }
+
+TInt TCompareSrcDst::Check(const TIsrRequeArgsSet& aRequeueArgSet, TUint8* aChunkBase, const TDmaTransferArgs& aTferArgs) const
+ {
+ TIsrRequeArgsSet argSet(aRequeueArgSet); //copy since Fixup will mutate object
+
+ argSet.Substitute(aTferArgs); // replace any default (0) values with the values in aTferArgs
+
+ argSet.Fixup((TLinAddr)aChunkBase); //convert address offsets to virtual user mode addresses
+
+ TInt r = KErrCorrupt;
+ while(!argSet.IsEmpty())
+ {
+ r = Check(argSet.GetArgs());
+ if(r != KErrNone)
+ break;
+ }
+ return r;
+ }
+
+TInt TCompareSrcDst::Check(const TIsrRequeArgs& aRequeueArgs) const
+ {
+ const TUint8* src = (TUint8*)aRequeueArgs.iSrcAddr;
+ const TUint8* dst = (TUint8*)aRequeueArgs.iDstAddr;
+ const TInt size = aRequeueArgs.iTransferCount;
+
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Comparing TIsrRequeArgs: src=0x%08x dst=0x%08x size=0x%08x",
+ src, dst, size);
+ }
+
+ return memcompare(src, size, dst, size);
+ }
+
+TInt TCompareSrcDst::Check(CMultiTransferTest& aTest) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Comparing CMultiTransferTest buffers");
+ }
+
+ const TInt transferCount = aTest.TransferCount();
+ TUint8* const chunkBase = aTest.Chunk().Base();
+
+ // check buffers for each transfer
+ for(TInt i=0; i<transferCount; i++)
+ {
+ TInt r = Check(aTest.TransferArgs(i), chunkBase);
+ aTest.SetPostTransferResult(i, r);
+ }
+ // CMultiTransferTest is handled differently to the others.
+ // Whereas CSingleTransferTest logs just the return value
+ // of the check, here, we write back a result for each transfer
+ // so the return value from this function is not important
+ return KErrNone;
+ }
+
+TInt TCompare2D::Check(const CSingleTransferTest& aTest) const
+ {
+ const TDmaTransferArgs& args = aTest.TransferArgs();
+ TUint8* const chunkBase = aTest.Chunk().Base();
+
+ TInt ret = KErrNone;
+
+ TTransferIter src_iter(args.iSrcConfig, chunkBase);
+ TTransferIter dst_iter(args.iDstConfig, chunkBase);
+ TTransferIter end;
+ for (; (src_iter != end) && (dst_iter !=end); ++src_iter, ++dst_iter)
+ {
+ if(*src_iter != *dst_iter)
+ {
+ ret = KErrCorrupt;
+ break;
+ }
+ }
+ return ret;
+ }
+
+TInt TCompare2D::Check(const CIsrRequeTest&) const
+ {
+ return KErrNotSupported;
+ }
+
+TInt TCompare2D::Check(CMultiTransferTest&) const
+ {
+ return KErrNotSupported;
+ }
+//////////////////////////////////////////////////////////////////////
+// MPreTransfer classes
+//////////////////////////////////////////////////////////////////////
+
+void TPreTransferIncrBytes::Setup(const CSingleTransferTest& aTest) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("TPreTransferIncrBytes(CSingleTransferTest)");
+ }
+ TAddressParms params = GetAddrParms(aTest.TransferArgs());
+
+ TUint8* const chunkBase = aTest.Chunk().Base();
+ params.Fixup((TLinAddr)chunkBase);
+
+
+ Setup(params);
+ }
+
+void TPreTransferIncrBytes::Setup(const TAddressParms& aParams) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("TPreTransferIncrBytes: setup memory buffers: src=0x%08x dst=0x%08x size=0x%08x",
+ aParams.iSrcAddr, aParams.iDstAddr, aParams.iTransferCount);
+ }
+ TUint8* const src = (TUint8*) aParams.iSrcAddr;
+ const TInt size = aParams.iTransferCount;
+
+ for(TInt i=0; i<size; i++)
+ {src[i] = (TUint8)i;} //each src byte holds its own offset (mod 256)
+
+ TUint8* const dst = (TUint8*) aParams.iDstAddr;
+ memclr(dst, size); //clear destination
+ }
+
+void TPreTransferIncrBytes::Setup(const CIsrRequeTest& aTest) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("TPreTransferIncrBytes(CIsrRequeTest)");
+ }
+ if(!CheckBuffers(aTest))
+ {
+ RDebug::Printf("Successive transfer destinations may not overlap previous src or dst buffers");
+ RDebug::Printf("unless the whole transfer is an exact repeat of a previous one");
+ TEST_FAULT;
+ }
+
+ Setup(static_cast<CSingleTransferTest>(aTest)); // prepare the CSingleTransferTest parts
+
+ TIsrRequeArgsSet requeSet(aTest.GetRequeueArgs());
+
+ requeSet.Substitute(aTest.TransferArgs());
+
+ const TLinAddr chunkBase = (TLinAddr) aTest.Chunk().Base();
+ requeSet.Fixup(chunkBase);
+
+ while(!requeSet.IsEmpty())
+ {
+ TIsrRequeArgs args = requeSet.GetArgs();
+ Setup(args); // perform the setup operation for each TIsrRequeArgs
+ }
+ }
+
+void TPreTransferIncrBytes::Setup(const CMultiTransferTest& aTest) const
+ {
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("TPreTransferIncrBytes(CMultiTransferTest)");
+ }
+ //TODO check for overlap
+
+ TUint8* const chunkBase = aTest.Chunk().Base();
+ const TInt transferCount = aTest.TransferCount();
+
+ // initialise buffers for each transfer
+ for(TInt i=0; i<transferCount; i++)
+ {
+ TAddressParms params = GetAddrParms(aTest.TransferArgs(i));
+
+ params.Fixup((TLinAddr)chunkBase);
+
+ Setup(params);
+ }
+ }
+
+TBool TPreTransferIncrBytes::CheckBuffers(const CIsrRequeTest& aTest) const
+ {
+ RArray<const TAddressParms> array;
+ array.AppendL(TAddressParms(aTest.TransferArgs()));
+
+ TIsrRequeArgsSet requeSet(aTest.GetRequeueArgs());
+ requeSet.Substitute(aTest.TransferArgs());
+
+ const TLinAddr chunkBase = (TLinAddr) aTest.Chunk().Base();
+ requeSet.Fixup(chunkBase);
+ while(!requeSet.IsEmpty())
+ {
+ const TIsrRequeArgs requeArgs = requeSet.GetArgs();
+ array.AppendL(requeArgs);
+ }
+
+ const TBool result = CheckBuffers(array);
+
+ array.Close();
+ return result;
+ }
+
+/**
+Check that the destination of each TAddressParms does not overlap with
+any previous source or destination or that if it does the whole transfer
+matches.
+This is so that successive transfers do not overwrite the destinations or
+sources of preceeding ones.
+Exactly matching transfers are allowed to test the case that a repeat
+transfer is required - though it can't then be determined just from
+looking at the buffers that the repeat was successful
+*/
+TBool TPreTransferIncrBytes::CheckBuffers(const RArray<const TAddressParms> aTransferParams) const
+ {
+ const TInt count = aTransferParams.Count();
+
+ for(TInt i=1; i<count; i++)
+ {
+ const TAddressParms& current = aTransferParams[i];
+ for(TInt j=0; j<i; j++)
+ {
+ const TAddressParms& previous = aTransferParams[j];
+ const TBool ok = !previous.Overlaps(current.DestRange()) || current == previous;
+ if(!ok)
+ return EFalse;
+ }
+ }
+ return ETrue;
+ }
+//////////////////////////////////////////////////////////////////////
+// TTransferIter class
+//////////////////////////////////////////////////////////////////////
+
+void TTransferIter::operator++ ()
+ {
+ iPtr++; //the standard post increment
+ if(iElem < (iCfg->iElementsPerFrame-1))
+ {
+ iPtr += iCfg->iElementSkip;
+ iElem++;
+ iBytes++;
+ }
+ else
+ {
+ TEST_ASSERT(iElem == iCfg->iElementsPerFrame-1);
+ if(iFrame < iCfg->iFramesPerTransfer-1)
+ {
+ iPtr += iCfg->iFrameSkip;
+ iFrame++;
+ iBytes++;
+ iElem = 0;
+ }
+ else
+ {
+ //we have reached the end
+ TEST_ASSERT(iFrame == iCfg->iFramesPerTransfer-1);
+ iPtr = NULL;
+ }
+ }
+
+ Invariant();
+ }
+
+void TTransferIter::Invariant() const
+ {
+ const TInt elemSize = iCfg->iElementSize;
+ RTest test(_L("TTransferIter invariant"));
+ const TInt bytesTransfered = (
+ elemSize * (iFrame * iCfg->iElementsPerFrame + iElem)
+ + ((TUint)iPtr % (elemSize))
+ );
+ test_Equal(iBytes, bytesTransfered);
+ test.Close();
+ }
+
+///////////////////////////////////////////////////////////
+// TTestCase
+///////////////////////////////////////////////////////////
+TTestCase::TTestCase(CDmaTest* aTest,
+ TBool aConcurrent,
+ const TDmaCapability aCap1,
+ const TDmaCapability aCap2,
+ const TDmaCapability aCap3,
+ const TDmaCapability aCap4,
+ const TDmaCapability aCap5
+ )
+:
+ iTest(aTest), iConcurrentTest(aConcurrent)
+ {
+ iChannelCaps[0] = aCap1;
+ iChannelCaps[1] = aCap2;
+ iChannelCaps[2] = aCap3;
+ iChannelCaps[3] = aCap4;
+ iChannelCaps[4] = aCap5;
+ }
+
+TResult TTestCase::TestCaseValid(const SDmacCaps& aChannelCaps) const
+ {
+ const TDmaCapability* cap = &iChannelCaps[0];
+
+ TResult ret = ERun;
+ //We assume that the array is empty at the first ENone found
+ //any caps after this wil be ignored
+ while(cap->iCapsReq != ENone)
+ {
+ TResult t = cap->CompareToDmaCaps(aChannelCaps);
+ if(t > ret) //this relies on the enum ordering
+ ret = t;
+ cap++;
+ }
+ return ret;
+ }
+
+TResult TTestCase::TestCaseValid(const TDmacTestCaps& aChannelCaps) const
+ {
+ const TDmaCapability* cap = &iChannelCaps[0];
+
+ TResult ret = ERun;
+ //We assume that the array is empty at the first ENone found
+ //any caps after this wil be ignored
+ while(cap->iCapsReq != ENone)
+ {
+ TResult t = cap->CompareToDmaCaps(aChannelCaps);
+ if(t > ret) //this relies on the enum ordering
+ ret = t;
+ cap++;
+ }
+ return ret;
+ }
+/**
+Will report whether a value held in aChannelCaps satisfies a
+requirement specfied by this object
+*/
+TBool TDmaCapability::RequirementSatisfied(const SDmacCaps& aChannelCaps) const
+ {
+ switch(iCapsReq)
+ {
+ case ENone:
+ return ETrue;
+ case EChannelPriorities:
+ TEST_FAULT;
+ case EChannelPauseAndResume:
+ return aChannelCaps.iChannelPauseAndResume == (TBool)iValue;
+ case EAddrAlignedToElementSize:
+ TEST_FAULT;
+ case E1DAddressing:
+ return aChannelCaps.i1DIndexAddressing == (TBool)iValue;
+ case E2DAddressing:
+ return aChannelCaps.i2DIndexAddressing == (TBool)iValue;
+ case ESynchronizationTypes:
+ case EBurstTransactions:
+ case EDescriptorInterrupt:
+ case EFrameInterrupt:
+ case ELinkedListPausedInterrupt:
+ case EEndiannessConversion:
+ case EGraphicsOps:
+ case ERepeatingTransfers:
+ case EChannelLinking:
+ TEST_FAULT;
+ case EHwDescriptors:
+ return aChannelCaps.iHwDescriptors == (TBool)iValue;
+ case ESrcDstAsymmetry:
+ case EAsymHwDescriptors:
+ TEST_FAULT;
+ case EBalancedAsymSegments:
+ return aChannelCaps.iBalancedAsymSegments == (TBool)iValue;
+ case EAsymCompletionInterrupt:
+ return aChannelCaps.iAsymCompletionInterrupt == (TBool)iValue;
+ case EAsymDescriptorInterrupt:
+ return aChannelCaps.iAsymDescriptorInterrupt == (TBool)iValue;
+ case EAsymFrameInterrupt:
+ return aChannelCaps.iAsymFrameInterrupt == (TBool)iValue;
+ default:
+ TEST_FAULT;
+ }
+
+ return EFalse;
+ }
+
+/**
+Will report whether a value held in aChannelCaps satisfies a
+requirement specfied by this object
+*/
+TBool TDmaCapability::RequirementSatisfied(const TDmacTestCaps& aChannelCaps) const
+ {
+ switch(iCapsReq)
+ {
+ case EPilVersion:
+ return TestValue(aChannelCaps.iPILVersion);
+ default:
+ return RequirementSatisfied(static_cast<SDmacCaps>(aChannelCaps));
+ }
+ }
+
+TResult TDmaCapability::CompareToDmaCaps(const SDmacCaps& aChannelCaps) const
+ {
+ const TBool reqSatisfied = RequirementSatisfied(aChannelCaps);
+ if(reqSatisfied)
+ {
+ return ERun;
+ }
+ else
+ {
+ return iFail ? EFail : ESkip;
+ }
+ }
+
+TResult TDmaCapability::CompareToDmaCaps(const TDmacTestCaps& aChannelCaps) const
+ {
+ const TBool reqSatisfied = RequirementSatisfied(aChannelCaps);
+ if(reqSatisfied)
+ {
+ return ERun;
+ }
+ else
+ {
+ return iFail ? EFail : ESkip;
+ }
+ }
+/**
+Test that aValue satisfies the comparrison (iCapsReqType) with the
+reference value held in iValue
+*/
+TBool TDmaCapability::TestValue(TUint aValue) const
+ {
+ switch(iCapsReqType)
+ {
+ case EEqual:
+ return aValue == iValue;
+ case EGTE:
+ return aValue >= iValue;
+ case ELTE:
+ return aValue <= iValue;
+ case EBitsSet:
+ case EBitsClear:
+ default:
+ TEST_FAULT;
+ }
+ return EFalse;
+ }
+
+static RTest test(_L("DMAv2 test"));
+
+//////////////////////////////////////////////////////////////////////
+// TTestRunner
+//////////////////////////////////////////////////////////////////////
+TTestRunner::TTestRunner()
+ {
+ // Open RDmaSession handle
+ TInt r = iDmaSession.Open();
+ TEST_ASSERT(r == KErrNone);
+
+ // Get PSI Test info
+ r = iDmaSession.GetTestInfo(iPslTestInfo);
+ TEST_ASSERT(r == KErrNone);
+
+ //Retrieve PSL cookies
+ GetPslCookie();
+
+ //Generate the DMA channel records
+ GenerateChannelRecord();
+ }
+
+TTestRunner::~TTestRunner()
+ {
+ RTest::CloseHandleAndWaitForDestruction(iDmaSession);
+ iTestCases.Close(); //TestRunner does not own test cases
+ iChannelRecords.Close();
+ iPslCookies.Close();
+ }
+
+void TTestRunner::AddTestCases(RPointerArray<TTestCase>& aTTestCases)
+ {
+ const TInt count = aTTestCases.Count();
+ for(TInt i=0; i < count; i++)
+ {
+ iTestCases.AppendL(aTTestCases[i]);
+ }
+ }
+
+void TTestRunner::RunTests()
+ {
+ //Print PslTestInfo
+ if(gVerboseOutput)
+ {
+ Print(iPslTestInfo);
+ }
+
+ //iterate through the test case array
+ const TInt testCaseCount = iTestCases.Count();
+ for(TInt i=0; i < testCaseCount; i++)
+ {
+ const TTestCase& testCase = *iTestCases[i];
+
+ //Here, we must create a test thread for each channel
+ RPointerArray<CTest> concurrentTests;
+
+ if(testCase.iConcurrentTest)
+ RDebug::Printf("== Begin concurrent test run ==");
+
+ const TInt chanRecCount = iChannelRecords.Count();
+ for(TInt j=0; j < chanRecCount; j++)
+ {
+ const TChannelRecord& record = iChannelRecords[j];
+ const TDmacTestCaps& caps = record.iChannelCaps;
+
+ const TResult t = testCase.TestCaseValid(caps);
+
+ switch(t)
+ {
+ case ERun:
+ {
+ CDmaTest* dmaTest = static_cast<CDmaTest*>(testCase.iTest->Clone());
+ TEST_ASSERT(dmaTest != NULL);
+
+ dmaTest->SetChannelCookie(record.iCookie);
+ dmaTest->Announce();
+ if(testCase.iConcurrentTest)
+ {
+ //Add test to array to be run concurrently
+ TInt r = concurrentTests.Append(dmaTest);
+ TEST_ASSERT(r == KErrNone);
+ }
+ else
+ {
+ //Run test in this thread
+ (*dmaTest)();
+ //TTestThread(
+ TBool result = dmaTest->Result();
+ TEST_ASSERT(result);
+
+ delete dmaTest;
+ }
+
+ break;
+ }
+ case ESkip:
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Skipping test-case %S, PSL channel %d", &testCase.iTest->Name(), record.iCookie);
+ }
+ break;
+ case EFail:
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Failling test-case %S, PSL channel %d", &testCase.iTest->Name(), record.iCookie);
+ }
+ TEST_FAULT;
+ default:
+ TEST_FAULT;
+ }
+ //Depending on the value of iConcurrentTest the test runner will either block until the thread has completed or
+ //alternatively run the current test case on the next channel:
+
+ //if the test case has been run on all channels it will then wait for all threads to complete.
+ }
+
+ const TInt count = concurrentTests.Count();
+ if(count>0)
+ {
+ MultipleTestRun(concurrentTests);
+ for(TInt i=0; i<count; i++)
+ {
+ TBool result = static_cast<CDmaTest*>(concurrentTests[i])->Result();
+ TEST_ASSERT(result);
+ }
+ RDebug::Printf("== End concurrent test run ==");
+ }
+
+ concurrentTests.ResetAndDestroy();
+ }
+ }
+
+void TTestRunner::GetPslCookie()
+ {
+ //Get Sb Channel cookies
+ for(TInt sb_channelcount=0; sb_channelcount<iPslTestInfo.iMaxSbChannels; sb_channelcount++)
+ {
+ iPslCookies.AppendL(iPslTestInfo.iSbChannels[sb_channelcount]);
+ }
+
+ //Get Db Channel cookies
+ for(TInt db_channelcount=0; db_channelcount<iPslTestInfo.iMaxDbChannels; db_channelcount++)
+ {
+ iPslCookies.AppendL(iPslTestInfo.iDbChannels[db_channelcount]);
+ }
+
+ //Get Sg Channel cookies
+ for(TInt sg_channelcount=0; sg_channelcount<iPslTestInfo.iMaxSgChannels; sg_channelcount++)
+ {
+ iPslCookies.AppendL(iPslTestInfo.iSgChannels[sg_channelcount]);
+ }
+ }
+
+void TTestRunner::GenerateChannelRecord()
+ {
+ //for each PSL cookie
+ for(TInt count=0; count<iPslCookies.Count(); count++)
+ {
+ //Get channel cookie
+ const TUint pslCookie = iPslCookies[count];
+ TUint sessionCookie;
+ TInt r = iDmaSession.ChannelOpen(pslCookie, sessionCookie);
+ TEST_ASSERT(r == KErrNone);
+ if(gVerboseOutput)
+ {
+ RDebug::Printf("Channel PSL Cookie[%d] :0x%08x",count,pslCookie);
+ }
+
+ TChannelRecord dmaChannelRecord;
+ dmaChannelRecord.iCookie = pslCookie;
+
+ //Get Channel Caps
+ r = iDmaSession.ChannelCaps(sessionCookie, dmaChannelRecord.iChannelCaps);
+ TEST_ASSERT(r == KErrNone);
+
+ r = iDmaSession.ChannelClose(sessionCookie);
+ TEST_ASSERT(r == KErrNone);
+
+ //Append array
+ iChannelRecords.AppendL(dmaChannelRecord);
+ }
+ }
+//////////////////////////////////////////////////////////////////////
+// Global test functions and E32Main
+//////////////////////////////////////////////////////////////////////
+
+/**
+Displayed if used supplied no parameters, garbage, or a ? in the parameters
+*/
+void PrintUsage()
+ {
+ test.Printf(_L("*** DMA TEST FRAMEWORK ***\n"));
+ test.Printf(_L("Usage : t_dma2.exe [/option]\n"));
+ test.Printf(_L(" /V or /VERBOSE = Control test output\n"));
+ test.Printf(_L(" /S or /SELFTEST = Run DMA self test\n"));
+ test.Printf(_L("\n"));
+ }
+
+void ProcessCommandLineL()
+{
+ test.Printf(_L("Process command line arguments\n"));
+
+ TInt cmdLineLength(User::CommandLineLength());
+ HBufC* cmdLine = HBufC::NewMaxLC(cmdLineLength);
+ TPtr cmdLinePtr = cmdLine->Des();
+ User::CommandLine(cmdLinePtr);
+ TBool tokenParsed(EFalse);
+
+ TLex args(*cmdLine);
+ args.SkipSpace(); // args are separated by spaces
+
+ // first arg is the exe name, skip it
+ TPtrC cmdToken = args.NextToken();
+ HBufC* tc = HBufC::NewLC(KParameterTextLenMax);
+ *tc = cmdToken;
+ while (tc->Length())
+ {
+ tokenParsed = EFalse;
+
+ // '/?' help wanted flag '?' or /? parameter
+ if ((0== tc->FindF(_L("?"))) || (0==tc->FindF(_L("/?"))))
+ {
+ gHelpRequested = ETrue;
+ tokenParsed = ETrue;
+ }
+
+ // '/SELFTEST'
+ if ((0== tc->FindF(KArgSelfTest)) || (0==tc->FindF(KArgSelfTest2)))
+ {
+ // Run self test
+ test.Printf(_L("Command Line Options:Selftest option specified.\n"));
+ gSelfTest = ETrue;
+ tokenParsed = ETrue;
+ }
+
+ // '/VERBOSE' option
+ if ((0== tc->FindF(KArgVerboseOutput)) || (0==tc->FindF(KArgVerboseOutput2)))
+ {
+ test.Printf(_L("Command Line Options:Verbose option specified.\n"));
+ gVerboseOutput = ETrue;
+ tokenParsed = ETrue;
+ }
+
+ if (!tokenParsed)
+ {
+ // warn about unparsed parameter
+ test.Printf(_L("Warning: '%lS'??? not parsed\n"), tc);
+ gHelpRequested = ETrue;
+ }
+
+ // next parameter
+ *tc = args.NextToken();
+ }
+ CleanupStack::PopAndDestroy(tc);
+ CleanupStack::PopAndDestroy(cmdLine);
+}
+
+void RunDMATests()
+ {
+ test.Start(_L("Creating test runner\n"));
+ TTestRunner testRunner;
+
+ test.Next(_L("Add global test cases to test runner\n"));
+ testRunner.AddTestCases(TestArray);
+
+ test.Next(_L("call TTestRunner::RunTests()\n"));
+ testRunner.RunTests();
+
+ test.End();
+ }
+
+TInt E32Main()
+ {
+ __UHEAP_MARK;
+ //__KHEAP_MARK;
+ test.Title();
+
+ gHelpRequested = EFalse;
+ TInt r;
+
+ // Create the new trap-cleanup mechanism
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+
+ if (cleanup == NULL)
+ {
+ return KErrNoMemory;
+ }
+
+ // Process the command line parameters for batch/etc
+ TRAPD(err, ProcessCommandLineL());
+ if (err != KErrNone)
+ {
+ User::Panic(_L("DMA test run memory failure"), KErrNoMemory);
+ }
+
+ if (gHelpRequested)
+ {
+ PrintUsage();
+ User::Leave(-2); // nothing to do!
+ }
+ test.Start(_L("Loading test LDD"));
+ //load either the new test ldd, d_dma2.ldd,
+ //or d_dma2_compat.ldd - an ldd linked against
+ //the old DMA framework
+ _LIT(KDma, "D_DMA2.LDD");
+ r = User::LoadLogicalDevice(KDma);
+ const TBool dma2Loaded = ((r == KErrNone) || (r == KErrAlreadyExists));
+
+ _LIT(KDma2Compat, "D_DMA2_COMPAT.LDD");
+ r = User::LoadLogicalDevice(KDma2Compat);
+ const TBool dma2CompatLoaded = ((r == KErrNone) || (r == KErrAlreadyExists));
+
+ if (!(dma2Loaded || dma2CompatLoaded))
+ {
+ //TODO how can we distinguish this case from a platform where
+ //dma is supposed to be supported but the dma test ldd is
+ //missing?
+ test.Printf(_L("DMA not supported - test skipped\n"));
+ return 0;
+ }
+ else if (dma2Loaded && !dma2CompatLoaded)
+ {
+ test.Printf(_L("Loaded %S\n"), &KDma);
+ }
+ else if (!dma2Loaded && dma2CompatLoaded)
+ {
+ test.Printf(_L("Loaded %S\n"), &KDma2Compat);
+ }
+ else
+ {
+ test.Printf(_L("The ROM contains %S and %S - only one should be present\n"), &KDma, &KDma2Compat);
+ TEST_FAULT;
+ }
+ // Turn off evil lazy dll unloading
+ RLoader l;
+ test(l.Connect()==KErrNone);
+ test(l.CancelLazyDllUnload()==KErrNone);
+ RTest::CloseHandleAndWaitForDestruction(l);
+
+ __KHEAP_MARK;
+
+ if (gSelfTest) //Run self tests if specified on command line
+ {
+ SelfTests();
+ }
+
+ ApiTests();
+
+ RunDMATests();
+
+ __KHEAP_MARKEND;
+
+ r = User::FreeLogicalDevice(KTestDmaLddName);
+ test_KErrNone(r);
+ test.End();
+ test.Close();
+
+ delete cleanup;
+
+ //__KHEAP_MARKEND;
+ __UHEAP_MARKEND;
+ return 0;
+ }