kerneltest/e32test/dmav2/d_dma2_cmn.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 8 538db54a451d
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

/*
* 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);
		}
	}