kerneltest/e32test/dmav2/d_dma2_cmn.cpp
changeset 36 538db54a451d
child 130 c30940f6d922
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/dmav2/d_dma2_cmn.cpp	Mon Jan 18 21:31:10 2010 +0200
@@ -0,0 +1,328 @@
+/*
+* Copyright (c) 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: Implmentation of DMAv2 test code, common
+* to both user and kernel side
+*
+*/
+#ifdef __KERNEL_MODE__
+#include <platform.h>
+#endif
+
+#include "d_dma2.h"
+
+TInt Log2(TInt aNum)
+	{
+	TInt res = -1;
+	while(aNum)
+		{
+		res++;
+		aNum >>= 1;
+		}
+	return res;
+	}
+
+TCallbackRecord::TCallbackRecord(
+		TCbContext aContext,
+		TInt aReq,
+		TInt aReqSrc,
+		TInt aReqDst,
+		TInt aDes,
+		TInt aDesSrc,
+		TInt aDesDst,
+		TInt aFrame,
+		TInt aFrameSrc,
+		TInt aFrameDst,
+		TInt aPause,
+		TInt aPauseSrc,
+		TInt aPauseDst,
+		TDmaResult aResult
+	)
+	//Default iIsrRedoRequestResult is 1 as this is an invalid error code
+	:iResult(aResult), iContext(aContext), iIsrRedoRequestResult(1)
+	{
+	SetCount(EDmaCallbackRequestCompletion, aReq);
+	SetCount(EDmaCallbackRequestCompletion_Src, aReqSrc);
+	SetCount(EDmaCallbackRequestCompletion_Dst, aReqDst);
+	SetCount(EDmaCallbackDescriptorCompletion, aDes);
+	SetCount(EDmaCallbackDescriptorCompletion_Src, aDesSrc);
+	SetCount(EDmaCallbackDescriptorCompletion_Dst, aDesDst);
+	SetCount(EDmaCallbackFrameCompletion, aFrame);
+	SetCount(EDmaCallbackFrameCompletion_Src, aFrameSrc);
+	SetCount(EDmaCallbackFrameCompletion_Dst, aFrameDst);
+	SetCount(EDmaCallbackLinkedListPaused, aPause);
+	SetCount(EDmaCallbackLinkedListPaused_Src, aPauseSrc);
+	SetCount(EDmaCallbackLinkedListPaused_Dst, aPauseDst);
+	}
+
+TCallbackRecord TCallbackRecord::Empty()
+	{
+	return TCallbackRecord(EInvalid,0,0,0,0,0,0,0,0,0,0,0,0,EDmaResultError);
+	}
+
+void TCallbackRecord::Reset()
+	{
+	new (this) TCallbackRecord();
+	}
+
+TBool TCallbackRecord::operator == (const TCallbackRecord aOther) const
+	{
+	return (memcompare((TUint8*)this, sizeof(*this), (TUint8*)&aOther, sizeof(aOther)) == 0);
+	}
+
+TInt TCallbackRecord::GetCount(TDmaCallbackType aCbType) const
+	{
+	const TInt index = BitToIndex(aCbType);
+	return iCallbackLog[index];
+	}
+
+void TCallbackRecord::SetCount(TDmaCallbackType aCbType, TInt aCount)
+	{
+	const TInt index = BitToIndex(aCbType);
+	iCallbackLog[index] = aCount;
+	}
+
+TInt TCallbackRecord::BitToIndex(TDmaCallbackType aCbType) const
+	{
+	const TInt index = Log2(aCbType);
+	TEST_ASSERT(index >=0 && index < KNumberOfCallbacks);
+
+	return index;
+	}
+
+void TCallbackRecord::ProcessCallback(TUint aCallbackMask, TDmaResult aResult)
+	{
+	// This function may be called several
+	// times and will accumulate the number of each callback
+	// received. However, it will only ever remember the last
+	// result and context value,
+	iResult = aResult;
+	iContext = CurrentContext();
+	TEST_ASSERT(iContext != EInvalid);
+
+	for(TInt i=0; i < KNumberOfCallbacks; i++)
+		{
+		if(aCallbackMask & 1)
+			{
+			iCallbackLog[i]++;
+			}
+		aCallbackMask >>= 1;
+		}
+	// Assert that we have handled all bits
+	// if not then maybe KNumberOfCallbacks is too small
+	// or there is a spurious bit in aCallbackMask
+	TEST_ASSERT(aCallbackMask == 0);
+	}
+
+TCallbackRecord::TCbContext TCallbackRecord::CurrentContext() const
+	{
+#ifdef __KERNEL_MODE__
+	switch(NKern::CurrentContext())
+		{
+	case NKern::EThread:
+		return EThread;
+	case NKern::EInterrupt:
+		return EIsr;
+	case NKern::EIDFC: //fall-through
+	case NKern::EEscaped:
+	default:
+		return EInvalid;
+		}
+#else
+	//for the benefit of user-mode testing
+	return EThread;
+#endif
+	}
+
+void TCallbackRecord::Print() const
+	{
+	PRINT(GetCount(EDmaCallbackRequestCompletion));
+	PRINT(GetCount(EDmaCallbackRequestCompletion_Src));
+	PRINT(GetCount(EDmaCallbackRequestCompletion_Dst));
+	PRINT(GetCount(EDmaCallbackDescriptorCompletion));
+	PRINT(GetCount(EDmaCallbackDescriptorCompletion_Src));
+	PRINT(GetCount(EDmaCallbackDescriptorCompletion_Dst));
+	PRINT(GetCount(EDmaCallbackFrameCompletion));
+	PRINT(GetCount(EDmaCallbackFrameCompletion_Src));
+	PRINT(GetCount(EDmaCallbackFrameCompletion_Dst));
+	PRINT(GetCount(EDmaCallbackLinkedListPaused));
+	PRINT(GetCount(EDmaCallbackLinkedListPaused_Src));
+	PRINT(GetCount(EDmaCallbackLinkedListPaused_Dst));
+	PRINT(iResult);
+	PRINT(iContext);
+	PRINT(iIsrRedoRequestResult);
+	}
+
+TDmacTestCaps::TDmacTestCaps()
+	:iPILVersion(1)
+	{
+	}
+
+TDmacTestCaps::TDmacTestCaps(const SDmacCaps& aDmacCaps, TInt aVersion)
+	:SDmacCaps(aDmacCaps), iPILVersion(aVersion)
+	{}
+
+TAddrRange::TAddrRange(TUint aStart, TUint aLength)
+	:iStart(aStart), iLength(aLength)
+	{
+	TEST_ASSERT(iLength > 0);
+	}
+
+TBool TAddrRange::Contains(TAddrRange aRange) const
+	{
+	return Contains(aRange.Start()) && Contains(aRange.End());
+	}
+
+TBool TAddrRange::Overlaps(const TAddrRange& aRange) const
+	{
+	return (aRange.Contains(iStart) || aRange.Contains(End()) ||
+			Contains(aRange.Start()) || Contains(aRange.End()));
+	}
+/**
+If addresses have been left as KPhysAddrInvalid or the count as 0
+(ie. the default values used for IsrRedoRequest)
+then substitute the values from aTransferArgs.
+*/
+void TAddressParms::Substitute(const TDmaTransferArgs& aTransferArgs)
+	{
+	if(iSrcAddr == KPhysAddrInvalidUser)
+		iSrcAddr = aTransferArgs.iSrcConfig.iAddr;
+
+	if(iDstAddr == KPhysAddrInvalidUser)
+		iDstAddr = aTransferArgs.iDstConfig.iAddr;
+
+	if(iTransferCount == 0)
+		iTransferCount = aTransferArgs.iTransferCount;
+	}
+
+/**
+Addresses are converted into absolute,
+addresses (virtual in user mode, physical in kernel)
+unless they are KPhysAddrInvalid
+*/
+void TAddressParms::Fixup(TLinAddr aChunkBase)
+	{
+	if(iSrcAddr != KPhysAddrInvalidUser)
+		{
+		iSrcAddr += aChunkBase;
+
+#ifdef __KERNEL_MODE__
+		iSrcAddr = Epoc::LinearToPhysical(iSrcAddr);
+		TEST_ASSERT(iSrcAddr != KPhysAddrInvalid);
+#endif
+		}
+#ifndef __KERNEL_MODE__
+	else
+		{
+		// Substitute must be called before
+		// Fixup on user side
+		TEST_FAULT;
+		}
+#endif
+
+	if(iDstAddr != KPhysAddrInvalidUser)
+		{
+		iDstAddr += aChunkBase;
+
+#ifdef __KERNEL_MODE__
+		iDstAddr = Epoc::LinearToPhysical(iDstAddr);
+		TEST_ASSERT(iDstAddr != KPhysAddrInvalid);
+#endif
+		}
+#ifndef __KERNEL_MODE__
+	else
+		{
+		// Substitute must be called before
+		// Fixup on user side
+		TEST_FAULT;
+		}
+#endif
+	}
+
+TBool TAddressParms::CheckRange(TLinAddr aStart, TUint aSize)
+	{
+	TAddrRange chunk(aStart, aSize);
+	return chunk.Contains(SourceRange()) && chunk.Contains(DestRange());
+	}
+
+/**
+@return ETrue if the source or destination range of this object
+overlaps with aRange
+*/
+TBool TAddressParms::Overlaps(const TAddrRange aRange) const
+	{
+	return SourceRange().Overlaps(aRange) || DestRange().Overlaps(aRange);
+	}
+
+/**
+@return ETrue if either the source or dest range of this
+overlap with either of those of aParm
+*/
+TBool TAddressParms::Overlaps(const TAddressParms aParm) const
+	{
+	return Overlaps(aParm.SourceRange()) || Overlaps(aParm.DestRange());
+	}
+
+TBool TAddressParms::operator==(const TAddressParms& aOther) const
+	{
+	return iSrcAddr == aOther.iSrcAddr &&
+		iDstAddr == aOther.iDstAddr &&
+		iTransferCount == aOther.iTransferCount;
+	}
+
+TAddressParms GetAddrParms(const TDmaTransferArgs& aArgs)
+	{
+	return TAddressParms(aArgs);
+	}
+
+TAddrRange TAddressParms::SourceRange() const
+	{
+	return TAddrRange(iSrcAddr, iTransferCount);
+	}
+
+TAddrRange TAddressParms::DestRange() const
+	{
+	return TAddrRange(iDstAddr, iTransferCount);
+	}
+
+void SetAddrParms(TDmaTransferArgs& aTransferArgs, const TAddressParms& aAddrParams)
+	{
+	aTransferArgs.iSrcConfig.iAddr = aAddrParams.iSrcAddr;
+	aTransferArgs.iDstConfig.iAddr = aAddrParams.iDstAddr;
+	aTransferArgs.iTransferCount = aAddrParams.iTransferCount;
+	}
+
+TIsrRequeArgs TIsrRequeArgsSet::GetArgs()
+	{
+	TEST_ASSERT(!IsEmpty());
+	const TIsrRequeArgs args(iRequeArgs[iIndex]);
+	iIndex++;
+	iCount--;
+	return args;
+	}
+
+
+void TIsrRequeArgsSet::Substitute(const TDmaTransferArgs& aTransferArgs)
+	{
+	for(TInt i=0; i<iCount; i++)
+		{
+		iRequeArgs[i].Substitute(aTransferArgs);
+		}
+	}
+void TIsrRequeArgsSet::Fixup(TLinAddr aChunkBase)
+	{
+	for(TInt i=0; i<iCount; i++)
+		{
+		iRequeArgs[i].Fixup(aChunkBase);
+		}
+	}