sl@0: /* sl@0: * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: Implmentation of DMAv2 test code, common sl@0: * to both user and kernel side sl@0: * sl@0: */ sl@0: #ifdef __KERNEL_MODE__ sl@0: #include sl@0: #endif sl@0: sl@0: #include "d_dma2.h" sl@0: sl@0: TInt Log2(TInt aNum) sl@0: { sl@0: TInt res = -1; sl@0: while(aNum) sl@0: { sl@0: res++; sl@0: aNum >>= 1; sl@0: } sl@0: return res; sl@0: } sl@0: sl@0: TCallbackRecord::TCallbackRecord( sl@0: TCbContext aContext, sl@0: TInt aReq, sl@0: TInt aReqSrc, sl@0: TInt aReqDst, sl@0: TInt aDes, sl@0: TInt aDesSrc, sl@0: TInt aDesDst, sl@0: TInt aFrame, sl@0: TInt aFrameSrc, sl@0: TInt aFrameDst, sl@0: TInt aPause, sl@0: TInt aPauseSrc, sl@0: TInt aPauseDst, sl@0: TDmaResult aResult sl@0: ) sl@0: //Default iIsrRedoRequestResult is 1 as this is an invalid error code sl@0: :iResult(aResult), iContext(aContext), iIsrRedoRequestResult(1) sl@0: { sl@0: SetCount(EDmaCallbackRequestCompletion, aReq); sl@0: SetCount(EDmaCallbackRequestCompletion_Src, aReqSrc); sl@0: SetCount(EDmaCallbackRequestCompletion_Dst, aReqDst); sl@0: SetCount(EDmaCallbackDescriptorCompletion, aDes); sl@0: SetCount(EDmaCallbackDescriptorCompletion_Src, aDesSrc); sl@0: SetCount(EDmaCallbackDescriptorCompletion_Dst, aDesDst); sl@0: SetCount(EDmaCallbackFrameCompletion, aFrame); sl@0: SetCount(EDmaCallbackFrameCompletion_Src, aFrameSrc); sl@0: SetCount(EDmaCallbackFrameCompletion_Dst, aFrameDst); sl@0: SetCount(EDmaCallbackLinkedListPaused, aPause); sl@0: SetCount(EDmaCallbackLinkedListPaused_Src, aPauseSrc); sl@0: SetCount(EDmaCallbackLinkedListPaused_Dst, aPauseDst); sl@0: } sl@0: sl@0: TCallbackRecord TCallbackRecord::Empty() sl@0: { sl@0: return TCallbackRecord(EInvalid,0,0,0,0,0,0,0,0,0,0,0,0,EDmaResultError); sl@0: } sl@0: sl@0: void TCallbackRecord::Reset() sl@0: { sl@0: new (this) TCallbackRecord(); sl@0: } sl@0: sl@0: TBool TCallbackRecord::operator == (const TCallbackRecord aOther) const sl@0: { sl@0: return (memcompare((TUint8*)this, sizeof(*this), (TUint8*)&aOther, sizeof(aOther)) == 0); sl@0: } sl@0: sl@0: TInt TCallbackRecord::GetCount(TDmaCallbackType aCbType) const sl@0: { sl@0: const TInt index = BitToIndex(aCbType); sl@0: return iCallbackLog[index]; sl@0: } sl@0: sl@0: void TCallbackRecord::SetCount(TDmaCallbackType aCbType, TInt aCount) sl@0: { sl@0: const TInt index = BitToIndex(aCbType); sl@0: iCallbackLog[index] = aCount; sl@0: } sl@0: sl@0: TInt TCallbackRecord::BitToIndex(TDmaCallbackType aCbType) const sl@0: { sl@0: const TInt index = Log2(aCbType); sl@0: TEST_ASSERT(index >=0 && index < KNumberOfCallbacks); sl@0: sl@0: return index; sl@0: } sl@0: sl@0: void TCallbackRecord::ProcessCallback(TUint aCallbackMask, TDmaResult aResult) sl@0: { sl@0: // This function may be called several sl@0: // times and will accumulate the number of each callback sl@0: // received. However, it will only ever remember the last sl@0: // result and context value, sl@0: iResult = aResult; sl@0: iContext = CurrentContext(); sl@0: TEST_ASSERT(iContext != EInvalid); sl@0: sl@0: for(TInt i=0; i < KNumberOfCallbacks; i++) sl@0: { sl@0: if(aCallbackMask & 1) sl@0: { sl@0: iCallbackLog[i]++; sl@0: } sl@0: aCallbackMask >>= 1; sl@0: } sl@0: // Assert that we have handled all bits sl@0: // if not then maybe KNumberOfCallbacks is too small sl@0: // or there is a spurious bit in aCallbackMask sl@0: TEST_ASSERT(aCallbackMask == 0); sl@0: } sl@0: sl@0: TCallbackRecord::TCbContext TCallbackRecord::CurrentContext() const sl@0: { sl@0: #ifdef __KERNEL_MODE__ sl@0: switch(NKern::CurrentContext()) sl@0: { sl@0: case NKern::EThread: sl@0: return EThread; sl@0: case NKern::EInterrupt: sl@0: return EIsr; sl@0: case NKern::EIDFC: //fall-through sl@0: case NKern::EEscaped: sl@0: default: sl@0: return EInvalid; sl@0: } sl@0: #else sl@0: //for the benefit of user-mode testing sl@0: return EThread; sl@0: #endif sl@0: } sl@0: sl@0: void TCallbackRecord::Print() const sl@0: { sl@0: PRINT(GetCount(EDmaCallbackRequestCompletion)); sl@0: PRINT(GetCount(EDmaCallbackRequestCompletion_Src)); sl@0: PRINT(GetCount(EDmaCallbackRequestCompletion_Dst)); sl@0: PRINT(GetCount(EDmaCallbackDescriptorCompletion)); sl@0: PRINT(GetCount(EDmaCallbackDescriptorCompletion_Src)); sl@0: PRINT(GetCount(EDmaCallbackDescriptorCompletion_Dst)); sl@0: PRINT(GetCount(EDmaCallbackFrameCompletion)); sl@0: PRINT(GetCount(EDmaCallbackFrameCompletion_Src)); sl@0: PRINT(GetCount(EDmaCallbackFrameCompletion_Dst)); sl@0: PRINT(GetCount(EDmaCallbackLinkedListPaused)); sl@0: PRINT(GetCount(EDmaCallbackLinkedListPaused_Src)); sl@0: PRINT(GetCount(EDmaCallbackLinkedListPaused_Dst)); sl@0: PRINT(iResult); sl@0: PRINT(iContext); sl@0: PRINT(iIsrRedoRequestResult); sl@0: } sl@0: sl@0: TDmacTestCaps::TDmacTestCaps() sl@0: :iPILVersion(1) sl@0: { sl@0: } sl@0: sl@0: TDmacTestCaps::TDmacTestCaps(const SDmacCaps& aDmacCaps, TInt aVersion) sl@0: :SDmacCaps(aDmacCaps), iPILVersion(aVersion) sl@0: {} sl@0: sl@0: TAddrRange::TAddrRange(TUint aStart, TUint aLength) sl@0: :iStart(aStart), iLength(aLength) sl@0: { sl@0: TEST_ASSERT(iLength > 0); sl@0: } sl@0: sl@0: TBool TAddrRange::Contains(TAddrRange aRange) const sl@0: { sl@0: return Contains(aRange.Start()) && Contains(aRange.End()); sl@0: } sl@0: sl@0: TBool TAddrRange::Overlaps(const TAddrRange& aRange) const sl@0: { sl@0: return (aRange.Contains(iStart) || aRange.Contains(End()) || sl@0: Contains(aRange.Start()) || Contains(aRange.End())); sl@0: } sl@0: /** sl@0: If addresses have been left as KPhysAddrInvalid or the count as 0 sl@0: (ie. the default values used for IsrRedoRequest) sl@0: then substitute the values from aTransferArgs. sl@0: */ sl@0: void TAddressParms::Substitute(const TDmaTransferArgs& aTransferArgs) sl@0: { sl@0: if(iSrcAddr == KPhysAddrInvalidUser) sl@0: iSrcAddr = aTransferArgs.iSrcConfig.iAddr; sl@0: sl@0: if(iDstAddr == KPhysAddrInvalidUser) sl@0: iDstAddr = aTransferArgs.iDstConfig.iAddr; sl@0: sl@0: if(iTransferCount == 0) sl@0: iTransferCount = aTransferArgs.iTransferCount; sl@0: } sl@0: sl@0: /** sl@0: Addresses are converted into absolute, sl@0: addresses (virtual in user mode, physical in kernel) sl@0: unless they are KPhysAddrInvalid sl@0: */ sl@0: void TAddressParms::Fixup(TLinAddr aChunkBase) sl@0: { sl@0: if(iSrcAddr != KPhysAddrInvalidUser) sl@0: { sl@0: iSrcAddr += aChunkBase; sl@0: sl@0: #ifdef __KERNEL_MODE__ sl@0: iSrcAddr = Epoc::LinearToPhysical(iSrcAddr); sl@0: TEST_ASSERT(iSrcAddr != KPhysAddrInvalid); sl@0: #endif sl@0: } sl@0: #ifndef __KERNEL_MODE__ sl@0: else sl@0: { sl@0: // Substitute must be called before sl@0: // Fixup on user side sl@0: TEST_FAULT; sl@0: } sl@0: #endif sl@0: sl@0: if(iDstAddr != KPhysAddrInvalidUser) sl@0: { sl@0: iDstAddr += aChunkBase; sl@0: sl@0: #ifdef __KERNEL_MODE__ sl@0: iDstAddr = Epoc::LinearToPhysical(iDstAddr); sl@0: TEST_ASSERT(iDstAddr != KPhysAddrInvalid); sl@0: #endif sl@0: } sl@0: #ifndef __KERNEL_MODE__ sl@0: else sl@0: { sl@0: // Substitute must be called before sl@0: // Fixup on user side sl@0: TEST_FAULT; sl@0: } sl@0: #endif sl@0: } sl@0: sl@0: TBool TAddressParms::CheckRange(TLinAddr aStart, TUint aSize) sl@0: { sl@0: TAddrRange chunk(aStart, aSize); sl@0: return chunk.Contains(SourceRange()) && chunk.Contains(DestRange()); sl@0: } sl@0: sl@0: /** sl@0: @return ETrue if the source or destination range of this object sl@0: overlaps with aRange sl@0: */ sl@0: TBool TAddressParms::Overlaps(const TAddrRange aRange) const sl@0: { sl@0: return SourceRange().Overlaps(aRange) || DestRange().Overlaps(aRange); sl@0: } sl@0: sl@0: /** sl@0: @return ETrue if either the source or dest range of this sl@0: overlap with either of those of aParm sl@0: */ sl@0: TBool TAddressParms::Overlaps(const TAddressParms aParm) const sl@0: { sl@0: return Overlaps(aParm.SourceRange()) || Overlaps(aParm.DestRange()); sl@0: } sl@0: sl@0: TBool TAddressParms::operator==(const TAddressParms& aOther) const sl@0: { sl@0: return iSrcAddr == aOther.iSrcAddr && sl@0: iDstAddr == aOther.iDstAddr && sl@0: iTransferCount == aOther.iTransferCount; sl@0: } sl@0: sl@0: TAddressParms GetAddrParms(const TDmaTransferArgs& aArgs) sl@0: { sl@0: return TAddressParms(aArgs); sl@0: } sl@0: sl@0: TAddrRange TAddressParms::SourceRange() const sl@0: { sl@0: return TAddrRange(iSrcAddr, iTransferCount); sl@0: } sl@0: sl@0: TAddrRange TAddressParms::DestRange() const sl@0: { sl@0: return TAddrRange(iDstAddr, iTransferCount); sl@0: } sl@0: sl@0: void SetAddrParms(TDmaTransferArgs& aTransferArgs, const TAddressParms& aAddrParams) sl@0: { sl@0: aTransferArgs.iSrcConfig.iAddr = aAddrParams.iSrcAddr; sl@0: aTransferArgs.iDstConfig.iAddr = aAddrParams.iDstAddr; sl@0: aTransferArgs.iTransferCount = aAddrParams.iTransferCount; sl@0: } sl@0: sl@0: TIsrRequeArgs TIsrRequeArgsSet::GetArgs() sl@0: { sl@0: TEST_ASSERT(!IsEmpty()); sl@0: const TIsrRequeArgs args(iRequeArgs[iIndex]); sl@0: iIndex++; sl@0: iCount--; sl@0: return args; sl@0: } sl@0: sl@0: sl@0: void TIsrRequeArgsSet::Substitute(const TDmaTransferArgs& aTransferArgs) sl@0: { sl@0: for(TInt i=0; i