kerneltest/e32test/dmav2/d_dma2.cpp
changeset 130 c30940f6d922
parent 36 538db54a451d
child 199 189ece41fa29
child 247 d8d70de2bd36
--- a/kerneltest/e32test/dmav2/d_dma2.cpp	Thu Apr 29 11:08:53 2010 +0100
+++ b/kerneltest/e32test/dmav2/d_dma2.cpp	Tue May 04 09:44:26 2010 +0100
@@ -1,4 +1,4 @@
-// Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2002-2010 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"
@@ -55,7 +55,7 @@
 			}
 		return FastCountToMicroSecs(diff);
 #else
-		//TODO On SMP it is possible for the value returned from
+		//On SMP it is possible for the value returned from
 		//NKern::FastCounter to depend on the current CPU (ie.
 		//NaviEngine)
 		//
@@ -100,6 +100,7 @@
 	TInt DoGetInfo(TAny* aInfo);
 
 	TInt OpenDmaChannel(TUint aPslCookie, TUint& aDriverCookie);
+	TInt OpenDmaChannel(TUint& aDriverCookie, TDmaChannel::SCreateInfo& aInfo);
 	TInt CloseDmaChannelByCookie(TUint aDriverCookie);
 	TInt PauseDmaChannelByCookie(TUint aDriverCookie);
 	TInt ResumeDmaChannelByCookie(TUint aDriverCookie);
@@ -127,9 +128,6 @@
 	*/
 	TInt CreateDmaRequest(TUint aChannelCookie, TUint& aRequestCookie, TBool aNewCallback = EFalse, TInt aMaxFragmentSizeBytes=0);
 
-	//TODO what happens if a client closes a channel that
-	//it still has dma requests associated with?
-	
 	/**
 	Destroys a previously created dma request object
 	*/
@@ -141,7 +139,7 @@
 	TInt CookieToChannelIndex(TUint aDriverCookie) const;
 	TInt CookieToRequestIndex(TUint aRequestCookie) const;
 
-	void FixupTransferArgs(TDmaTransferArgs& aTransferArgs) const;
+	void MakeAddressesAbsoulute(TDmaTransferArgs& aTransferArgs) const;
 	TInt FragmentRequest(TUint aRequestCookie, const TDmaTransferArgs& aTransferArgs, TBool aLegacy=ETrue);
 
 	TInt QueueRequest(TUint aRequestCookie, TRequestStatus* aStatus, TCallbackRecord* aRecord, TUint64* aDurationMicroSecs);
@@ -177,6 +175,19 @@
 	TUint64 GetDuration()
 		{return iStopwatch.ReadMicroSecs();}
 
+	/**
+	Store a copy of the TDmaTransferArgs which was used for fragmentation
+	for argument checking
+	*/
+	void SetAddressParms(const TDmaTransferArgs& aAddressParms)
+		{iFragmentedTransfer = aAddressParms;}
+
+	/**
+	Retrieve stored TDmaTransferArgs
+	*/
+	const TDmaTransferArgs& GetAddressParms() const
+		{return iFragmentedTransfer;}
+
 protected:
 	TInt Create();
 	/** Construct with old style callback */
@@ -202,6 +213,13 @@
 
 	TStopwatch iStopwatch;
 	TIsrRequeArgsSet iIsrRequeArgSet;
+
+	/**
+	This will be updated each time fragment is called.
+	It is required so that, at queue time, if ISR re-queue
+	arguments are added, they can be checked for sanity
+	*/
+	TDmaTransferArgs iFragmentedTransfer;
 	};
 
 DClientDmaRequest* DClientDmaRequest::Construct(DThread* aClient, TDfcQue* const aDfcQ, TDmaChannel& aChannel, TBool aNewStyle, TInt aMaxTransferSize)
@@ -341,38 +359,7 @@
 #endif
 	}
 
-/**
-Check that both source and destination of ISR reque args will
-lie within the range specified by aStart and aSize.
-
-@param aStart The linear base address of the region
-@param aSize The size of the region
-*/
-TBool TIsrRequeArgs::CheckRange(TLinAddr aStart, TUint aSize) const
-	{
-	TUint physStart = Epoc::LinearToPhysical(aStart);
-	TEST_ASSERT(physStart != KPhysAddrInvalid);
-
-	TAddrRange chunk(physStart, aSize);
-	TBool sourceOk = (iSrcAddr == KPhysAddrInvalid) ? ETrue : chunk.Contains(SourceRange());
-
-	TBool destOk = (iDstAddr == KPhysAddrInvalid) ? ETrue : chunk.Contains(DestRange());
-
-	return sourceOk && destOk;
-	}
-
-TBool TIsrRequeArgsSet::CheckRange(TLinAddr aAddr, TUint aSize) const
-	{
-	for(TInt i=0; i<iCount; i++)
-		{
-		if(!iRequeArgs[i].CheckRange(aAddr, aSize))
-			return EFalse;
-		}
-	return ETrue;
-	}
-
-/**
-Translate an old style dma callback to a new-style one
+/** Translate an old style dma callback to a new-style one
 */
 void DClientDmaRequest::CallbackOldStyle(TResult aResult, TAny* aArg)
 	{
@@ -431,7 +418,9 @@
 		self.iDfc.Add();
 		break;
 		}
-	case NKern::EIDFC: //fall-through
+	//Fall-through: If context is IDFC or the EEscaped marker occur
+	//it is an error
+	case NKern::EIDFC:
 	case NKern::EEscaped:
 	default:
 		TEST_FAULT;
@@ -593,10 +582,34 @@
 			{
 			TUint pslCookie = (TUint)a1;
 			TUint driverCookie = 0;
-			TInt r = OpenDmaChannel(pslCookie, driverCookie);	
+			TInt r = OpenDmaChannel(pslCookie, driverCookie);
 			umemput32(a2, &driverCookie, sizeof(TAny*));
 			return r;
 			}
+	case RDmaSession::EOpenChannelExposed:
+			{
+			TDmaChannel::SCreateInfo openInfo;
+			TUint driverCookie = 0;
+
+			TPckgBuf<SCreateInfoTest> openArgsBuf;
+			Kern::KUDesGet(openArgsBuf, *reinterpret_cast<TDes8*>(a2));
+
+			SCreateInfoTest& openTestInfo = openArgsBuf();
+			openInfo.iCookie = openTestInfo.iCookie;
+			openInfo.iDesCount = openTestInfo.iDesCount;
+			openInfo.iDfcQ = iDfcQ;
+			openInfo.iDfcPriority = openTestInfo.iDfcPriority;
+
+			#ifdef DMA_APIV2
+				openInfo.iPriority = openTestInfo.iPriority;
+				openInfo.iDynChannel = openTestInfo.iDynChannel;
+			#endif
+
+			TInt r = OpenDmaChannel(driverCookie, openInfo);
+			umemput32(a1, &driverCookie, sizeof(TAny*));
+			Kern::KUDesPut(*reinterpret_cast<TDes8*>(a2), openArgsBuf);
+			return r;
+			}
 	case RDmaSession::ECloseChannel:
 			{
 			TUint driverCookie = reinterpret_cast<TUint>(a1);
@@ -660,11 +673,15 @@
 			TDmaTransferArgs& transferArgs = const_cast<TDmaTransferArgs&>(argsBuff().iTransferArgs);
 
 			//convert address offsets in to kernel virtual addresses
-			FixupTransferArgs(transferArgs);
-
-			TEST_ASSERT((TAddressParms(transferArgs).CheckRange(iChunkBase, iChunk->Size())));
+			MakeAddressesAbsoulute(transferArgs);
 
 			TInt r = KErrGeneral;
+			if (!TAddressParms(transferArgs).CheckRange(iChunkBase, iChunk->Size()))
+			{
+				// Return error code for invalid src and destination arguments used in tranferArgs
+				r=KErrArgument;
+				return r;
+			}
 
 			TStopwatch clock;
 			clock.Start();
@@ -708,7 +725,6 @@
 			}	
 	case RDmaSession::EQueueRequestWithReque:
 			{
-			//TODO can common code with EQueueRequest be extracted?
 			TPckgBuf<RDmaSession::TQueueArgsWithReque> argsBuff;
 			Kern::KUDesGet(argsBuff, *reinterpret_cast<TDes8*>(a1));
 
@@ -723,13 +739,11 @@
 			DClientDmaRequest* const request = RequestFromCookie(requestCookie);
 			if(request != NULL)
 				{
-				argsBuff().iRequeSet.Fixup(iChunkBase);
-				//TODO reque args must be substituted in order to
-				//check the range. The original transfer args are not
-				//available when queue is called, they could
-				//however be stored within DClientDmaRequest
-				//TEST_ASSERT((argsBuff().iRequeSet.CheckRange(iChunkBase, iChunk->Size())));
-				request->AddRequeArgs(argsBuff().iRequeSet);
+				TIsrRequeArgsSet& requeArgs = argsBuff().iRequeSet;
+				requeArgs.Fixup(iChunkBase);
+
+				TEST_ASSERT(requeArgs.CheckRange(iChunkBase, iChunk->Size(), request->GetAddressParms() ));
+				request->AddRequeArgs(requeArgs);
 
 				r = QueueRequest(requestCookie, requestStatus, callbackRec, duration);
 				}
@@ -740,21 +754,6 @@
 				}
 			return r;
 			}
-	case RDmaSession::EIsrRedoRequest:
-			{
-			TPckgBuf<RDmaSession::TIsrRedoReqArgs> argsBuff;
-			Kern::KUDesGet(argsBuff, *reinterpret_cast<TDes8*>(a1));
-
-			const TUint driverCookie = argsBuff().iDriverCookie;
-			const TUint32 srcAddr = argsBuff().iSrcAddr;
-			const TUint32 dstAddr = argsBuff().iDstAddr;
-			const TInt transferCount = argsBuff().iTransferCount;
-			const TUint32 pslRequestInfo = argsBuff().iPslRequestInfo;
-			const TBool isrCb = argsBuff().iIsrCb;
-
-			TInt r = IsrRedoRequestByCookie(driverCookie,srcAddr,dstAddr,transferCount,pslRequestInfo,isrCb);
-			return r;
-			}
 	case RDmaSession::EIsOpened:
 			{
 			TUint driverCookie = (TUint)a1;
@@ -797,29 +796,21 @@
 		}
 	}
 
-TInt DDmaTestSession::OpenDmaChannel(TUint aPslCookie, TUint& aDriverCookie )
+TInt DDmaTestSession::OpenDmaChannel(TUint& aDriverCookie, TDmaChannel::SCreateInfo& aInfo)
 	{
-	TDmaChannel::SCreateInfo info;
-	info.iCookie = aPslCookie;
-	info.iDfcQ = iDfcQ;
-	info.iDfcPriority = 3;
-	info.iDesCount = 128;
-
-	TDmaChannel* channel = NULL;
-
 	//cs so thread can't be killed between
 	//opening channel and adding to array
 	NKern::ThreadEnterCS();
-	TInt r = TDmaChannel::Open(info, channel);
+	TDmaChannel* channel = NULL;
+	TInt r = TDmaChannel::Open(aInfo, channel);
 	if(KErrNone == r)
 		{
 		__NK_ASSERT_ALWAYS(channel);
-		
-		__KTRACE_OPT(KDMA, Kern::Printf("OpenDmaChannel: channel@ 0x%08x", channel)); 
+
+		__KTRACE_OPT(KDMA, Kern::Printf("OpenDmaChannel: channel@ 0x%08x", channel));
 
-
-		TInt err = iChannels.Append(channel);
-		if(KErrNone == err)
+		r = iChannels.Append(channel);
+		if(KErrNone == r)
 			{
 			aDriverCookie = reinterpret_cast<TUint>(channel);
 			}
@@ -834,6 +825,20 @@
 	return r;
 	}
 
+/**
+Open a DMA channel with arbitrary default parameters
+*/
+TInt DDmaTestSession::OpenDmaChannel(TUint aPslCookie, TUint& aDriverCookie )
+	{
+	TDmaChannel::SCreateInfo info;
+	info.iCookie = aPslCookie;
+	info.iDfcQ = iDfcQ;
+	info.iDfcPriority = 3;
+	info.iDesCount = 128;
+
+	return OpenDmaChannel(aDriverCookie, info);
+	}
+
 TInt DDmaTestSession::CookieToChannelIndex(TUint aDriverCookie) const
 	{
 	const TInt r = iChannels.Find(reinterpret_cast<TDmaChannel*>(aDriverCookie));
@@ -906,8 +911,7 @@
 	__KTRACE_OPT(KDMA, Kern::Printf("CancelAllByIndex: %d", aIndex)); 
 	__NK_ASSERT_DEBUG(aIndex < iChannels.Count()); 
 	
-	TDmaChannel* channel = iChannels[aIndex];
-	iChannels.Remove(aIndex);
+	TDmaChannel* channel = iChannels[aIndex];	
 	channel->CancelAll();
 	}
 
@@ -1188,7 +1192,11 @@
 	return r;
 	}
 
-void DDmaTestSession::FixupTransferArgs(TDmaTransferArgs& aTransferArgs) const
+/**
+Replace addresses specified as an offset from the chunk base with absolute
+virtual addresses.
+*/
+void DDmaTestSession::MakeAddressesAbsoulute(TDmaTransferArgs& aTransferArgs) const
 	{
 	aTransferArgs.iSrcConfig.iAddr += iChunkBase;
 	aTransferArgs.iDstConfig.iAddr += iChunkBase;
@@ -1225,23 +1233,29 @@
 	if(requestIndex < 0)
 		return requestIndex;
 
+	DClientDmaRequest& request = *iClientDmaReqs[requestIndex];
+	request.SetAddressParms(aTransferArgs);
+
 	TInt r = KErrNotSupported;
+
+	if (aTransferArgs.iTransferCount < 1)
+		{
+		// Return error code for invalid transfer size used in tranferArgs
+		r=KErrArgument;
+		return r;
+		}
+
 	if(aLegacy)
 		{
-		// TODO we can extract the required info from the struct to
-		// set flags
 		TUint flags = KDmaMemSrc | KDmaIncSrc | KDmaMemDest | KDmaIncDest;
-
 		const TUint src = aTransferArgs.iSrcConfig.iAddr;
 		const TUint dst = aTransferArgs.iDstConfig.iAddr;
-		r = iClientDmaReqs[requestIndex]->Fragment(src, dst, aTransferArgs.iTransferCount, flags, NULL);
+		r = request.Fragment(src, dst, aTransferArgs.iTransferCount, flags, NULL);
 		}
 	else
 		{
 #ifdef DMA_APIV2
-		r = iClientDmaReqs[requestIndex]->Fragment(aTransferArgs);
-#else
-		r = KErrNotSupported;
+		r = request.Fragment(aTransferArgs);
 #endif
 		}
 	return r;
@@ -1296,9 +1310,6 @@
 	for(TInt i=0; i<aOldInfo.iMaxSgChannels; i++)
 		newInfo.iSgChannels[i] = aOldInfo.iSgChannels[i];
 
-	//TODO will want to add initialisation for Asym channels
-	//when these are available
-
 	return newInfo;
 	}
 //////////////////////////////////////////////////////////////////////////////
@@ -1321,8 +1332,7 @@
 DDmaTestFactory::DDmaTestFactory()
     {
     iVersion = TestDmaLddVersion();
-    iParseMask = KDeviceAllowUnit;							// no info, no PDD
-    // iUnitsMask = 0;										// Only one thing
+    iParseMask = KDeviceAllowUnit;							// no info, no PDD    
     }