kerneltest/e32test/dmav2/d_dma2_cmn.cpp
branchRCL_3
changeset 43 c1f20ce4abcf
equal deleted inserted replaced
42:a179b74831c9 43:c1f20ce4abcf
       
     1 /*
       
     2 * Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Implmentation of DMAv2 test code, common
       
    15 * to both user and kernel side
       
    16 *
       
    17 */
       
    18 #ifdef __KERNEL_MODE__
       
    19 #include <platform.h>
       
    20 
       
    21 #ifdef __DMASIM__
       
    22 #ifdef __WINS__
       
    23 typedef TLinAddr TPhysAddr;
       
    24 #endif
       
    25 static inline TPhysAddr LinToPhys(TLinAddr aLin) {return aLin;}
       
    26 #else
       
    27 static inline TPhysAddr LinToPhys(TLinAddr aLin) {return Epoc::LinearToPhysical(aLin);}
       
    28 #endif
       
    29 #endif
       
    30 
       
    31 #include "d_dma2.h"
       
    32 
       
    33 
       
    34 TInt Log2(TInt aNum)
       
    35 	{
       
    36 	TInt res = -1;
       
    37 	while(aNum)
       
    38 		{
       
    39 		res++;
       
    40 		aNum >>= 1;
       
    41 		}
       
    42 	return res;
       
    43 	}
       
    44 
       
    45 TCallbackRecord::TCallbackRecord(
       
    46 		TCbContext aContext,
       
    47 		TInt aReq,
       
    48 		TInt aReqSrc,
       
    49 		TInt aReqDst,
       
    50 		TInt aDes,
       
    51 		TInt aDesSrc,
       
    52 		TInt aDesDst,
       
    53 		TInt aFrame,
       
    54 		TInt aFrameSrc,
       
    55 		TInt aFrameDst,
       
    56 		TInt aPause,
       
    57 		TInt aPauseSrc,
       
    58 		TInt aPauseDst,
       
    59 		TDmaResult aResult
       
    60 	)
       
    61 	//Default iIsrRedoRequestResult is 1 as this is an invalid error code
       
    62 	:iResult(aResult), iContext(aContext), iIsrRedoRequestResult(1)
       
    63 	{
       
    64 	SetCount(EDmaCallbackRequestCompletion, aReq);
       
    65 	SetCount(EDmaCallbackRequestCompletion_Src, aReqSrc);
       
    66 	SetCount(EDmaCallbackRequestCompletion_Dst, aReqDst);
       
    67 	SetCount(EDmaCallbackDescriptorCompletion, aDes);
       
    68 	SetCount(EDmaCallbackDescriptorCompletion_Src, aDesSrc);
       
    69 	SetCount(EDmaCallbackDescriptorCompletion_Dst, aDesDst);
       
    70 	SetCount(EDmaCallbackFrameCompletion, aFrame);
       
    71 	SetCount(EDmaCallbackFrameCompletion_Src, aFrameSrc);
       
    72 	SetCount(EDmaCallbackFrameCompletion_Dst, aFrameDst);
       
    73 	SetCount(EDmaCallbackLinkedListPaused, aPause);
       
    74 	SetCount(EDmaCallbackLinkedListPaused_Src, aPauseSrc);
       
    75 	SetCount(EDmaCallbackLinkedListPaused_Dst, aPauseDst);
       
    76 	}
       
    77 
       
    78 TCallbackRecord TCallbackRecord::Empty()
       
    79 	{
       
    80 	return TCallbackRecord(EInvalid,0,0,0,0,0,0,0,0,0,0,0,0,EDmaResultError);
       
    81 	}
       
    82 
       
    83 void TCallbackRecord::Reset()
       
    84 	{
       
    85 	new (this) TCallbackRecord();
       
    86 	}
       
    87 
       
    88 TBool TCallbackRecord::operator == (const TCallbackRecord aOther) const
       
    89 	{
       
    90 	return (memcompare((TUint8*)this, sizeof(*this), (TUint8*)&aOther, sizeof(aOther)) == 0);
       
    91 	}
       
    92 
       
    93 TInt TCallbackRecord::GetCount(TDmaCallbackType aCbType) const
       
    94 	{
       
    95 	const TInt index = BitToIndex(aCbType);
       
    96 	return iCallbackLog[index];
       
    97 	}
       
    98 
       
    99 void TCallbackRecord::SetCount(TDmaCallbackType aCbType, TInt aCount)
       
   100 	{
       
   101 	const TInt index = BitToIndex(aCbType);
       
   102 	iCallbackLog[index] = aCount;
       
   103 	}
       
   104 
       
   105 TInt TCallbackRecord::BitToIndex(TDmaCallbackType aCbType) const
       
   106 	{
       
   107 	const TInt index = Log2(aCbType);
       
   108 	TEST_ASSERT(index >=0 && index < KNumberOfCallbacks);
       
   109 
       
   110 	return index;
       
   111 	}
       
   112 
       
   113 void TCallbackRecord::ProcessCallback(TUint aCallbackMask, TDmaResult aResult)
       
   114 	{
       
   115 	// This function may be called several
       
   116 	// times and will accumulate the number of each callback
       
   117 	// received. However, it will only ever remember the last
       
   118 	// result and context value,
       
   119 	iResult = aResult;
       
   120 	iContext = CurrentContext();
       
   121 	TEST_ASSERT(iContext != EInvalid);
       
   122 
       
   123 	for(TInt i=0; i < KNumberOfCallbacks; i++)
       
   124 		{
       
   125 		if(aCallbackMask & 1)
       
   126 			{
       
   127 			iCallbackLog[i]++;
       
   128 			}
       
   129 		aCallbackMask >>= 1;
       
   130 		}
       
   131 	// Assert that we have handled all bits
       
   132 	// if not then maybe KNumberOfCallbacks is too small
       
   133 	// or there is a spurious bit in aCallbackMask
       
   134 	TEST_ASSERT(aCallbackMask == 0);
       
   135 	}
       
   136 
       
   137 TCallbackRecord::TCbContext TCallbackRecord::CurrentContext() const
       
   138 	{
       
   139 #ifdef __KERNEL_MODE__
       
   140 	switch(NKern::CurrentContext())
       
   141 		{
       
   142 	case NKern::EThread:
       
   143 		return EThread;
       
   144 	case NKern::EInterrupt:
       
   145 		return EIsr;
       
   146 	//Fall-through: If context is IDFC or the EEscaped marker occur
       
   147 	//it is an error
       
   148 	case NKern::EIDFC:
       
   149 	case NKern::EEscaped:
       
   150 	default:
       
   151 		return EInvalid;
       
   152 		}
       
   153 #else
       
   154 	//for the benefit of user-mode testing
       
   155 	return EThread;
       
   156 #endif
       
   157 	}
       
   158 
       
   159 void TCallbackRecord::Print() const
       
   160 	{
       
   161 	PRINT(GetCount(EDmaCallbackRequestCompletion));
       
   162 	PRINT(GetCount(EDmaCallbackRequestCompletion_Src));
       
   163 	PRINT(GetCount(EDmaCallbackRequestCompletion_Dst));
       
   164 	PRINT(GetCount(EDmaCallbackDescriptorCompletion));
       
   165 	PRINT(GetCount(EDmaCallbackDescriptorCompletion_Src));
       
   166 	PRINT(GetCount(EDmaCallbackDescriptorCompletion_Dst));
       
   167 	PRINT(GetCount(EDmaCallbackFrameCompletion));
       
   168 	PRINT(GetCount(EDmaCallbackFrameCompletion_Src));
       
   169 	PRINT(GetCount(EDmaCallbackFrameCompletion_Dst));
       
   170 	PRINT(GetCount(EDmaCallbackLinkedListPaused));
       
   171 	PRINT(GetCount(EDmaCallbackLinkedListPaused_Src));
       
   172 	PRINT(GetCount(EDmaCallbackLinkedListPaused_Dst));
       
   173 	PRINT(iResult);
       
   174 	PRINT(iContext);
       
   175 	PRINT(iIsrRedoRequestResult);
       
   176 	}
       
   177 
       
   178 TDmacTestCaps::TDmacTestCaps()
       
   179 	:iPILVersion(1)
       
   180 	{
       
   181 	}
       
   182 
       
   183 TDmacTestCaps::TDmacTestCaps(const SDmacCaps& aDmacCaps, TInt aVersion)
       
   184 	:SDmacCaps(aDmacCaps), iPILVersion(aVersion)
       
   185 	{}
       
   186 
       
   187 TAddrRange::TAddrRange(TUint aStart, TUint aLength)
       
   188 	:iStart(aStart), iLength(aLength)
       
   189 	{
       
   190 	}
       
   191 
       
   192 TBool TAddrRange::Contains(TAddrRange aRange) const
       
   193 	{
       
   194 	return Contains(aRange.Start()) && Contains(aRange.End());
       
   195 	}
       
   196 
       
   197 TBool TAddrRange::Overlaps(const TAddrRange& aRange) const
       
   198 	{
       
   199 	return (aRange.Contains(iStart) || aRange.Contains(End()) ||
       
   200 			Contains(aRange.Start()) || Contains(aRange.End()));
       
   201 	}
       
   202 
       
   203 TBool TAddrRange::IsFilled(TUint8 aValue) const
       
   204 	{
       
   205 	TUint8* buffer = reinterpret_cast<TUint8*>(iStart);
       
   206 	for(TUint i = 0; i < iLength; i++)
       
   207 		{
       
   208 		if(buffer[i] != aValue)
       
   209 			return EFalse;
       
   210 		}
       
   211 	return ETrue;
       
   212 	}
       
   213 
       
   214 /**
       
   215 If addresses have been left as KPhysAddrInvalid or the count as 0 (ie. the
       
   216 default values used for IsrRedoRequest) then substitute the values from
       
   217 aTransferArgs.
       
   218 */
       
   219 void TAddressParms::Substitute(const TDmaTransferArgs& aTransferArgs)
       
   220 	{
       
   221 	Substitute(GetAddrParms(aTransferArgs));
       
   222 	}
       
   223 
       
   224 /**
       
   225 If addresses have been left as KPhysAddrInvalid or the count as 0 (ie. the
       
   226 default values used for IsrRedoRequest) then substitute the values from
       
   227 aTransferArgs.
       
   228 */
       
   229 void TAddressParms::Substitute(const TAddressParms& aAddrParams)
       
   230 	{
       
   231 	if(iSrcAddr == KPhysAddrInvalidUser)
       
   232 		iSrcAddr = aAddrParams.iSrcAddr;
       
   233 
       
   234 	if(iDstAddr == KPhysAddrInvalidUser)
       
   235 		iDstAddr = aAddrParams.iDstAddr;
       
   236 
       
   237 	if(iTransferCount == 0)
       
   238 		iTransferCount = aAddrParams.iTransferCount;
       
   239 	}
       
   240 
       
   241 /**
       
   242 Addresses are converted into absolute,
       
   243 addresses (virtual in user mode, physical in kernel)
       
   244 unless they are KPhysAddrInvalid
       
   245 */
       
   246 void TAddressParms::Fixup(TLinAddr aChunkBase)
       
   247 	{
       
   248 	if(iSrcAddr != KPhysAddrInvalidUser)
       
   249 		{
       
   250 		iSrcAddr += aChunkBase;
       
   251 
       
   252 #ifdef __KERNEL_MODE__
       
   253 		iSrcAddr = LinToPhys(iSrcAddr);
       
   254 		TEST_ASSERT(iSrcAddr != KPhysAddrInvalid);
       
   255 #endif
       
   256 		}
       
   257 #ifndef __KERNEL_MODE__
       
   258 	else
       
   259 		{
       
   260 		// Substitute must be called before
       
   261 		// Fixup on user side
       
   262 		TEST_FAULT;
       
   263 		}
       
   264 #endif
       
   265 
       
   266 	if(iDstAddr != KPhysAddrInvalidUser)
       
   267 		{
       
   268 		iDstAddr += aChunkBase;
       
   269 
       
   270 #ifdef __KERNEL_MODE__
       
   271 		iDstAddr = LinToPhys(iDstAddr);
       
   272 		TEST_ASSERT(iDstAddr != KPhysAddrInvalid);
       
   273 #endif
       
   274 		}
       
   275 #ifndef __KERNEL_MODE__
       
   276 	else
       
   277 		{
       
   278 		// Substitute must be called before
       
   279 		// Fixup on user side
       
   280 		TEST_FAULT;
       
   281 		}
       
   282 #endif
       
   283 	}
       
   284 
       
   285 TBool TAddressParms::CheckRange(TLinAddr aStart, TUint aSize)
       
   286 	{
       
   287 	TAddrRange chunk(aStart, aSize);
       
   288 	return chunk.Contains(SourceRange()) && chunk.Contains(DestRange());
       
   289 	}
       
   290 
       
   291 /**
       
   292 @return ETrue if the source or destination range of this object
       
   293 overlaps with aRange
       
   294 */
       
   295 TBool TAddressParms::Overlaps(const TAddrRange aRange) const
       
   296 	{
       
   297 	return SourceRange().Overlaps(aRange) || DestRange().Overlaps(aRange);
       
   298 	}
       
   299 
       
   300 /**
       
   301 @return ETrue if either the source or dest range of this
       
   302 overlap with either of those of aParm
       
   303 */
       
   304 TBool TAddressParms::Overlaps(const TAddressParms aParm) const
       
   305 	{
       
   306 	return Overlaps(aParm.SourceRange()) || Overlaps(aParm.DestRange());
       
   307 	}
       
   308 
       
   309 TBool TAddressParms::operator==(const TAddressParms& aOther) const
       
   310 	{
       
   311 	return iSrcAddr == aOther.iSrcAddr &&
       
   312 		iDstAddr == aOther.iDstAddr &&
       
   313 		iTransferCount == aOther.iTransferCount;
       
   314 	}
       
   315 
       
   316 TAddressParms GetAddrParms(const TDmaTransferArgs& aArgs)
       
   317 	{
       
   318 	return TAddressParms(aArgs);
       
   319 	}
       
   320 
       
   321 TAddrRange TAddressParms::SourceRange() const
       
   322 	{
       
   323 	return TAddrRange(iSrcAddr, iTransferCount);
       
   324 	}
       
   325 
       
   326 TAddrRange TAddressParms::DestRange() const
       
   327 	{
       
   328 	return TAddrRange(iDstAddr, iTransferCount);
       
   329 	}
       
   330 
       
   331 void TAddressParms::MakePhysical()
       
   332 	{
       
   333 #ifdef __KERNEL_MODE__
       
   334 	iSrcAddr = LinToPhys(iSrcAddr);
       
   335 	TEST_ASSERT(iSrcAddr != KPhysAddrInvalid);
       
   336 	iDstAddr = LinToPhys(iDstAddr);
       
   337 	TEST_ASSERT(iDstAddr != KPhysAddrInvalid);
       
   338 #else
       
   339 	TEST_FAULT;
       
   340 #endif
       
   341 	}
       
   342 
       
   343 void SetAddrParms(TDmaTransferArgs& aTransferArgs, const TAddressParms& aAddrParams)
       
   344 	{
       
   345 	aTransferArgs.iSrcConfig.iAddr = aAddrParams.iSrcAddr;
       
   346 	aTransferArgs.iDstConfig.iAddr = aAddrParams.iDstAddr;
       
   347 	aTransferArgs.iTransferCount = aAddrParams.iTransferCount;
       
   348 	}
       
   349 
       
   350 TIsrRequeArgs TIsrRequeArgsSet::GetArgs()
       
   351 	{
       
   352 	TEST_ASSERT(!IsEmpty());
       
   353 	const TIsrRequeArgs args(iRequeArgs[iIndex]);
       
   354 	iIndex++;
       
   355 	iCount--;
       
   356 	return args;
       
   357 	}
       
   358 
       
   359 void TIsrRequeArgsSet::Substitute(const TDmaTransferArgs& aTransferArgs)
       
   360 	{
       
   361 	TAddressParms initial(aTransferArgs);
       
   362 
       
   363 	//if on user side it is assumed that aTransferArgs addresses will be offset
       
   364 	//based (from a virtual address). In kernel mode it is expected that address
       
   365 	//will be absolute virtual addresses, and must therefore be made physical
       
   366 #ifdef __KERNEL_MODE__
       
   367 	initial.MakePhysical();
       
   368 #endif
       
   369 
       
   370 	const TAddressParms* previous = &initial;
       
   371 
       
   372 	for(TInt i=0; i<iCount; i++)
       
   373 		{
       
   374 		TAddressParms& current = iRequeArgs[i];
       
   375 		current.Substitute(*previous);
       
   376 		previous = &current;
       
   377 		}
       
   378 	}
       
   379 
       
   380 void TIsrRequeArgsSet::Fixup(TLinAddr aChunkBase)
       
   381 	{
       
   382 	for(TInt i=0; i<iCount; i++)
       
   383 		{
       
   384 		iRequeArgs[i].Fixup(aChunkBase);
       
   385 		}
       
   386 	}
       
   387 
       
   388 /** Check that both source and destination of ISR reque args will lie within the
       
   389 range specified by aStart and aSize.
       
   390 
       
   391 @param aStart The linear base address of the region
       
   392 @param aSize The size of the region
       
   393 */
       
   394 TBool TIsrRequeArgs::CheckRange(TLinAddr aStart, TUint aSize) const
       
   395 	{
       
   396 	TUint chunkStart = 0;
       
   397 #ifdef __KERNEL_MODE__
       
   398 	chunkStart = LinToPhys(aStart);
       
   399 	TEST_ASSERT(chunkStart != KPhysAddrInvalid);
       
   400 #else
       
   401 	chunkStart = aStart;
       
   402 #endif
       
   403 
       
   404 	// If an address is still KPhysAddrInvalid it means the arguments haven't
       
   405 	// yet been substituted
       
   406 	TAddrRange chunk(chunkStart, aSize);
       
   407 	TBool sourceOk = (iSrcAddr != KPhysAddrInvalid) && chunk.Contains(SourceRange());
       
   408 
       
   409 	TBool destOk = (iDstAddr != KPhysAddrInvalid) && chunk.Contains(DestRange());
       
   410 
       
   411 	TBool ok = sourceOk && destOk;
       
   412 	if(!ok)
       
   413 		{
       
   414 		PRINTF(("Error, re-queue args: "));
       
   415 		TBuf<128> buf;
       
   416 		AppendString(buf);
       
   417 		PRINTF(("%S", &buf));
       
   418 		PRINTF(("overflow buffer base=0x%08x, size=0x%08x", chunkStart, aSize));
       
   419 		}
       
   420 	return ok;
       
   421 	}
       
   422 
       
   423 TBool TIsrRequeArgsSet::CheckRange(TLinAddr aAddr, TUint aSize) const
       
   424 	{
       
   425 	for(TInt i=0; i<iCount; i++)
       
   426 		{
       
   427 		if(!iRequeArgs[i].CheckRange(aAddr, aSize))
       
   428 			return EFalse;
       
   429 		}
       
   430 	return ETrue;
       
   431 	}
       
   432 
       
   433 TBool TIsrRequeArgsSet::CheckRange(TLinAddr aAddr, TUint aSize, const TDmaTransferArgs& aInitialParms) const
       
   434 	{
       
   435 	// apply substitution, without modifying the original
       
   436 	TIsrRequeArgsSet copy(*this);
       
   437 	copy.Substitute(aInitialParms);
       
   438 
       
   439 	return copy.CheckRange(aAddr, aSize);
       
   440 	}
       
   441