traceservices/tracefw/integ_test/ost/TEF/perfdevicedriver/src/te_drv.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
equal deleted inserted replaced
-1:000000000000 0:08ec8eefde2f
       
     1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\drivers\trace\btrace.cpp
       
    15 //
       
    16 
       
    17 
       
    18 #include <kern_priv.h>
       
    19 #include <kernel.h>
       
    20 #include <platform.h>
       
    21 #include "te_d32perfdrv.h"
       
    22 //#include "te_instrumentationpoints.h"
       
    23 #include "te_perfcacheflush.h"
       
    24 #include "timer/te_perfkerneltimer.h"
       
    25 #include "sanity/te_perfsanitytimer.h"
       
    26 
       
    27 
       
    28 
       
    29 
       
    30 //
       
    31 // Device driver
       
    32 //
       
    33 
       
    34 class DUptUTraceFactory : public DLogicalDevice
       
    35 	{
       
    36 public:
       
    37 	DUptUTraceFactory();
       
    38 	virtual TInt Install();
       
    39 	virtual void GetCaps(TDes8& aDes) const;
       
    40 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
    41 	};
       
    42 
       
    43 /**
       
    44  * We need this class to derive from DLogicalChannel rather than DLogicalChannelBase
       
    45  * This is for several reasons:
       
    46  * We are making calls that take a long time, which means we don't want the
       
    47  * user side thread to block while doing this, and we don't want to be interrupted
       
    48  * and loose our state. So we solve this by running the device driver as
       
    49  * as it's own separate thread in the kernel (DLogicalChannelBase runs a user thread in kernel mode,
       
    50  * DLogicalChannel runs a kernel thread called from a user thread).
       
    51  * We also solve the long timing issue by making an asynchrounous call by using the DoRequest call.
       
    52  * For this to work we need to create a DfcQ, i.e. a queue of all the incoming calls from the user side.
       
    53  * These then get's run in turn.
       
    54  */
       
    55 class DUptUTraceChannel : public DLogicalChannel
       
    56 	{
       
    57 public:
       
    58 	DUptUTraceChannel();
       
    59 	virtual ~DUptUTraceChannel();
       
    60 	//	Inherited from DObject
       
    61 	/**
       
    62 	 * I think this is similar to RunL when using active objects...
       
    63 	 * Because we are now using a Dfc queue all calls are routed
       
    64 	 * through this method.
       
    65 	 * The aMsg.iValue are these: http://lon-engbuild130:6794/doc_source/EKA2DeviceDriver/WritingANewDeviceDriver/LogicalChannel.guide.html#DD%2dlogical%2dchannel%2emodel1%2ehandling%2dreqs%2eyou1
       
    66 	 */
       
    67 	virtual void HandleMsg(TMessageBase* aMsg);
       
    68 	// Inherited from DLogicalChannel
       
    69 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
       
    70 	//Make an asynchronous call...
       
    71 	virtual TInt DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2);
       
    72 
       
    73 	void TestUptTraces(const TApiRunConfig& aApiRunConfig, TApiRunResults& aApiRunResults);
       
    74 	void TimeUptTraces(const TApiRunConfig& aApiRunConfig, TApiRunResults& aApiRunResults);
       
    75 
       
    76 private:
       
    77 	//This current thread
       
    78 	DThread*		iClient;
       
    79 	//This is a queue of requests (calls) to this device driver
       
    80 	TDfcQue* 		iDfcQ;
       
    81 
       
    82 	TKernelTimer	iTimer;
       
    83  	//This is used to signal when one of the async calls (to DoRequest) is finished.
       
    84  	TRequestStatus	iStatus;
       
    85 	};
       
    86 
       
    87 
       
    88 DECLARE_STANDARD_LDD()
       
    89 {
       
    90 	return new DUptUTraceFactory;
       
    91 }
       
    92 
       
    93 EXPORT_C DLogicalDevice* CreateLogicalDevice();
       
    94 
       
    95 //
       
    96 // DBTraceFactory
       
    97 //
       
    98 DUptUTraceFactory::DUptUTraceFactory()
       
    99 	{
       
   100 	iVersion = RUptUTrace::VersionRequired();
       
   101 	}
       
   102 
       
   103 
       
   104 TInt DUptUTraceFactory::Install()
       
   105 	{
       
   106 #ifdef TE_UPT_TRACE_ENABLED
       
   107 	return SetName(&KUptUTraceDDEnabled);
       
   108 #else
       
   109 	return SetName(&KUptUTraceDDDisabled);
       
   110 #endif
       
   111 	}
       
   112 
       
   113 void DUptUTraceFactory::GetCaps(TDes8& aDes) const
       
   114 	{
       
   115 	Kern::InfoCopy(aDes,0,0);
       
   116 	}
       
   117 
       
   118 TInt DUptUTraceFactory::Create(DLogicalChannelBase*& aChannel)
       
   119 	{
       
   120 	aChannel=new DUptUTraceChannel();
       
   121 	if(!aChannel)
       
   122 		return KErrNoMemory;
       
   123 	return KErrNone;
       
   124 	}
       
   125 
       
   126 
       
   127 //
       
   128 // DBTraceChannel
       
   129 //
       
   130 
       
   131 DUptUTraceChannel::DUptUTraceChannel()
       
   132 	{
       
   133 	iClient = &Kern::CurrentThread();
       
   134 	((DObject*)iClient)->Open();
       
   135 	}
       
   136 
       
   137 DUptUTraceChannel::~DUptUTraceChannel()
       
   138 	{
       
   139 	Kern::SafeClose((DObject*&)iClient,NULL);
       
   140 	}
       
   141 
       
   142 TInt DUptUTraceChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/)
       
   143 	{
       
   144 	//skipping security checks and version control since this is just a test driver
       
   145 	iDfcQ = Kern::DfcQue0();
       
   146 	SetDfcQ(iDfcQ);
       
   147 	iMsgQ.Receive();
       
   148 	return KErrNone;
       
   149 	}
       
   150 
       
   151 void DUptUTraceChannel::HandleMsg(TMessageBase* aMsg)
       
   152 	{
       
   153 	TThreadMessage& message = *(TThreadMessage*) aMsg;
       
   154 	TInt id = message.iValue;
       
   155 	if(id == (TInt) ECloseMsg)
       
   156 		{
       
   157 		//Close DUptUTraceChannel
       
   158 		message.Complete(KErrNone, EFalse);
       
   159 		return;
       
   160 		}
       
   161 	else if(id == KMaxTInt)
       
   162 		{
       
   163 		//DoCancel(message.Int0());
       
   164 		message.Complete(KErrNone, ETrue);
       
   165 		return;
       
   166 		}
       
   167 	if(id < 0 )  //it was a call for DoRequest()
       
   168 		{
       
   169 		TRequestStatus* status = (TRequestStatus*)message.Ptr0();
       
   170 		DoRequest(~id, status, message.Ptr1(), message.Ptr2());
       
   171 		message.Complete(KErrNone, ETrue);
       
   172 		}
       
   173 	else //it was a call for DoControl, we dont implement that now so just fall through
       
   174 		{
       
   175 		TRequestStatus* status=(TRequestStatus*)message.Ptr0();
       
   176 		Kern::RequestComplete(iClient,status,KErrNotSupported);
       
   177 		message.Complete(KErrNotSupported, ETrue);
       
   178 		}
       
   179 	}
       
   180 
       
   181 TInt DUptUTraceChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
       
   182 	{
       
   183 	TInt error = KErrNone;
       
   184 
       
   185 /**
       
   186  * This is the beginning of the new implementation for creating a new thread
       
   187  * to run the timers in.
       
   188  *
       
   189 	 NKern::ThreadEnterCS();
       
   190 	{
       
   191 		SThreadCreateInfo info;
       
   192 		#ifdef DEBUG
       
   193 			TPtrC8 name((TUint8*)get_thread_name(priority));
       
   194 		#endif
       
   195 		info.iType = EThreadSupervisor;
       
   196 		info.iFunction = thread_wrapper;
       
   197 		info.iPtr = thread;
       
   198 		info.iSupervisorStack = NULL;
       
   199 		info.iSupervisorStackSize = 0; // zero means use default value
       
   200 		info.iInitialThreadPriority = hal_convert_priority(priority);
       
   201 		info.iTotalSize = sizeof(info);
       
   202 		#ifdef DEBUG
       
   203 			info.iName.Set(name);
       
   204 		#endif
       
   205 		if (Kern::ThreadCreate(info) != KErrNone)
       
   206 		{
       
   207 		     rc = EINVAL;
       
   208 		       goto Error;
       
   209 		 }
       
   210 
       
   211 		thread->func = func;
       
   212 		thread->arg = arg;
       
   213 			Kern::ThreadResume(*(DThread *)info.iHandle);
       
   214 		}
       
   215 		NKern::ThreadLeaveCS();
       
   216 
       
   217 
       
   218 	//TInt NKern::ThreadCreate(NThread *aThread, SNThreadCreateInfo &anInfo);
       
   219 	 *
       
   220 	 * */
       
   221 	if(!error)
       
   222 		{
       
   223 		switch(aReqNo)
       
   224 			{
       
   225 			case RUptUTrace::ETestUTrace:
       
   226 				{
       
   227 				TApiRunConfig configData;
       
   228 			    error = Kern::ThreadRawRead(iClient, a1, (TUint8 *)&configData, sizeof(TApiRunConfig));
       
   229 				TApiRunResults configResults;
       
   230 			    error = Kern::ThreadRawRead(iClient, a2, (TUint8 *)&configResults, sizeof(TApiRunResults));
       
   231 			    if(!error)
       
   232 			    	TestUptTraces(configData, configResults);
       
   233 			    if(!error)
       
   234 			    	error = Kern::ThreadRawWrite(iClient, a2, (TUint8 *)&configResults, sizeof(TApiRunResults));
       
   235 				}
       
   236 			break;
       
   237 			case RUptUTrace::ETimeUTrace:
       
   238 				{
       
   239 				TApiRunConfig configData;
       
   240 			    error = Kern::ThreadRawRead(iClient, a1, (TUint8 *)&configData, sizeof(TApiRunConfig));
       
   241 				TApiRunResults configResults;
       
   242 			    error = Kern::ThreadRawRead(iClient, a2, (TUint8 *)&configResults, sizeof(TApiRunResults));
       
   243 			    if(!error)
       
   244 			    	{
       
   245 			    	TimeUptTraces(configData, configResults);
       
   246 			    	}
       
   247 			    if(!error)
       
   248 			    	error = Kern::ThreadRawWrite(iClient, a2, (TUint8 *)&configResults, sizeof(TApiRunResults));
       
   249 				}
       
   250 			break;
       
   251 			case RUptUTrace::ESanityTestTimer:
       
   252 			case RUptUTrace::ESanityUtraceTimer:
       
   253 			case RUptUTrace::ESanityTestLongTimer:
       
   254 				{
       
   255 				TSanityResults results;
       
   256 			    error = Kern::ThreadRawRead(iClient, a1, (TUint8 *)&results, sizeof(TSanityResults));
       
   257 			    if(!error)
       
   258 			    	{
       
   259 			    	TTestTimer timer;
       
   260 			    	if(aReqNo == RUptUTrace::ESanityTestTimer)
       
   261 			    		results.iPass = timer.TestKernelTimer(results.iTime);
       
   262 			    	if(aReqNo == RUptUTrace::ESanityTestLongTimer)
       
   263 			    		results.iPass = timer.TestKernelLongTimer(results.iTime);
       
   264 			    	if(aReqNo == RUptUTrace::ESanityUtraceTimer)
       
   265 			    		results.iPass = timer.TestUTraceKernelTimer(results.iTime);
       
   266 			    	}
       
   267 			    if(!error)
       
   268 			    	error = Kern::ThreadRawWrite(iClient, a1, (TUint8 *)&results, sizeof(TSanityResults));
       
   269 				}
       
   270 			break;
       
   271 
       
   272 			default:
       
   273 				error = KErrNotSupported;
       
   274 			break;
       
   275 			}
       
   276 		}
       
   277 	Kern::RequestComplete(iClient, aStatus, error);
       
   278 	return error;
       
   279 	}
       
   280 
       
   281 void DUptUTraceChannel::TestUptTraces(const TApiRunConfig& /*aApiRunConfig*/, TApiRunResults& aApiRunResults)
       
   282 	{
       
   283 	//TInt error = TUptTraceCalls::DoSendTraceL(aApiRunConfig, aApiRunResults); //not implemented
       
   284 	TInt error = KErrNotSupported;
       
   285 	aApiRunResults.iError = error;
       
   286 	}
       
   287 
       
   288 void DUptUTraceChannel::TimeUptTraces(const TApiRunConfig& /*aApiRunConfig*/, TApiRunResults& aApiRunResults)
       
   289 	{
       
   290 /*	TInt error = iTimer.StartBackgroundTimer(); //not implemented
       
   291 	if(!error)
       
   292 		{
       
   293 	    while(!iTimer.IsTimerExpired())
       
   294 	   	 {
       
   295 	   	 if(aApiRunConfig.iDoFlush)
       
   296 	   		 {
       
   297 	   		 Te_Flush_The_Cache();
       
   298 	   		 }
       
   299 	   	 	aApiRunResults.iError = TUptTraceCalls::DoSendTraceL(aApiRunConfig, aApiRunResults);
       
   300 	   	 	aApiRunResults.iError = KErrNotSupported;
       
   301 	   	 	iTimer.IncreaseCount();
       
   302 	   	 }
       
   303 	    aApiRunResults.iApiTraceTime = iTimer.FinalTime();
       
   304 	    aApiRunResults.iTimeCount = iTimer.FinalCount();
       
   305 		}
       
   306 		*/
       
   307  	aApiRunResults.iError = KErrNotSupported;
       
   308 	}