os/kernelhwsrv/kerneltest/e32test/system/d_mstim.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1997-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 the License "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 // e32test\system\d_mstim.cpp
    15 // LDD for testing millisecond timer
    16 // 
    17 //
    18 
    19 #include "plat_priv.h"
    20 #if defined(__MEIG__)
    21 #include <cl7211.h>
    22 #elif defined(__MAWD__)
    23 #include <windermere.h>
    24 #elif defined(__MISA__)
    25 #include <sa1100.h>
    26 #elif defined(__MCOT__)
    27 #include <cotulla.h>
    28 #elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
    29 #include <omap.h>
    30 #include <omap_timer.h>
    31 #elif defined(__MI920__) || defined(__NI1136__)
    32 #ifdef __MI920__
    33 #define USE_CM920_FRC
    34 #endif
    35 #ifdef USE_CM920_FRC
    36 #include <iolines.h>
    37 #else
    38 #include <integratorap.h>
    39 #endif
    40 #elif defined(__RVEMUBOARD__)
    41 #include <rvemuboard.h>
    42 #elif defined(__NE1_TB__)
    43 #include <upd35001_timer.h>
    44 #endif
    45 #include "d_mstim.h"
    46 #include "../misc/prbs.h"
    47 
    48 #if defined(__WINS__)
    49 typedef Int64 TCounter;
    50 typedef Int64 TDelta;
    51 const TDelta KMaxDelta = 0x7fffffffffffffff;
    52 const TDelta KMinDelta = 0x8000000000000000;
    53 #else
    54 typedef TUint TCounter;
    55 typedef TInt TDelta;
    56 const TDelta KMaxDelta = KMaxTInt;
    57 const TDelta KMinDelta = KMinTInt;
    58 #endif
    59 
    60 #ifdef __MISA__
    61 inline TCounter TIMER()
    62 	{ return *(volatile TUint*)KHwRwOstOscr; }
    63 #endif
    64 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
    65 inline TCounter TIMER()
    66 	{ return TOmapTimer::Timer3Value(); }
    67 #endif
    68 #ifdef __MCOT__
    69 inline TCounter TIMER()
    70 	{ return *(volatile TUint*)KHwRwOstOscr; }
    71 #endif
    72 #ifdef __MAWD__
    73 inline TCounter TIMER()
    74 	{ return *(volatile TUint*)(KWindBaseAddress+KWindTimer1Value16)&0xffff; }
    75 #endif
    76 #ifdef __MEIG__
    77 inline TCounter TIMER()
    78 { return *(volatile TUint*)(KEigerBaseAddress+KEigerTimer1Data16)&0xffff;}
    79 #endif
    80 #if defined(__MI920__) || defined(__NI1136__)
    81 inline TCounter TIMER()
    82 #ifdef USE_CM920_FRC
    83 	{ return *(volatile TUint*)(KHwRwCoreClkCounter);}		// 32-bit Core module counter inc's at 24MHz
    84 #else
    85 	{ return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
    86 #endif
    87 #endif
    88 #if defined(__RVEMUBOARD__)
    89 inline TCounter TIMER()
    90 	{ return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
    91 #endif
    92 #ifdef __NE1_TB__
    93 inline TCounter TIMER()
    94 	{ return NETimer::Timer(2).iTimerCount; }
    95 #endif
    96 #if defined(__EPOC32__) && defined(__CPU_X86)
    97 TCounter TIMER();
    98 void SetUpTimerChannel2();
    99 #endif
   100 
   101 #ifdef __WINS__
   102 inline TCounter TIMER()
   103 	{
   104 	LARGE_INTEGER c;
   105 	QueryPerformanceCounter(&c);
   106 	return c.QuadPart;
   107 	}
   108 #endif
   109 
   110 #if defined(__MISA__) || (defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__)))
   111 inline TDelta TimeDelta(TCounter initial, TCounter final)
   112 	{ return final-initial; }				// SA1100 timer counts up
   113 #endif
   114 #if defined(__MCOT__)
   115 inline TDelta TimeDelta(TCounter initial, TCounter final)
   116 	{ return final-initial; }				// Cotulla timer counts up
   117 #endif
   118 #if defined(__MAWD__) || defined(__MEIG__) || (!defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__))) 
   119 inline TDelta TimeDelta(TCounter initial, TCounter final)
   120 	{ return (initial-final)&0xffff; }		// Eiger/Windermere/Integrator timer counts down
   121 #endif
   122 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
   123 inline TDelta TimeDelta(TCounter initial, TCounter final)
   124 	{ return (initial-final);}		// OMAP timer counts down
   125 #endif
   126 #if defined(__EPOC32__) && defined(__CPU_X86)
   127 TDelta TimeDelta(TUint initial, TUint final)
   128 	{
   129 	TUint tickdiff=(initial-final)&0xffff;
   130 	TUint msdiff=((final>>16)-(initial>>16))&0xffff;
   131 	msdiff=1193*msdiff-tickdiff;
   132 	msdiff=(msdiff+32768)&~0xffff;
   133 	return msdiff+tickdiff;
   134 	}
   135 #endif
   136 #ifdef __NE1_TB__
   137 inline TDelta TimeDelta(TCounter initial, TCounter final)
   138 	{ return final - initial; }
   139 #endif
   140 #ifdef __WINS__
   141 inline TDelta TimeDelta(TCounter initial, TCounter final)
   142 	{ return final-initial; }		// counts up
   143 #endif
   144 #if defined(__RVEMUBOARD__)
   145 inline TDelta TimeDelta(TCounter initial, TCounter final)
   146 	{ return (initial-final)&0xffff; }		// Timer counts down
   147 #endif
   148 
   149 const TInt KMajorVersionNumber=0;
   150 const TInt KMinorVersionNumber=1;
   151 const TInt KBuildVersionNumber=1;
   152 
   153 const TInt KMaxMsTim=9;
   154 const TInt KMaxMsTimR=9;
   155 
   156 TInt TicksToMicroseconds(TDelta aTicks)
   157 	{
   158 #if defined(__MISA__) || defined(__MCOT__)
   159 	Int64 ticks(aTicks);
   160 	ticks*=(1000000);
   161 	ticks+=KHwOscFreqHz/2;		// 3.6864MHz tick
   162 	ticks/=KHwOscFreqHz;
   163 	return (TInt)ticks;
   164 #endif
   165 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
   166 	// Timer runs at 12Mhz/32 = 375kHz. Each tick is 2.66...us which is 16/6us
   167 	aTicks<<=4;		// * 16
   168 	aTicks+=3;	    // rounding to the closest number of us
   169 	return (TInt)(aTicks/6);	// us = (ticks*16+3)/6
   170 #endif
   171 #if defined(__MI920__) || defined(__NI1136__)
   172 #if defined(USE_CM920_FRC)
   173 	Int64 ticks(aTicks);
   174 	ticks*=(1000000);
   175 	ticks+=24000000/2;
   176 	ticks/=24000000;
   177 	return (TInt)ticks;
   178 #else
   179 	aTicks<<=14;	// 1 tick = 32/3 us
   180 	aTicks+=768;	// round
   181 	return (TInt)(aTicks/1536);
   182 #endif
   183 #endif
   184 #if defined(__RVEMUBOARD__)
   185 	return (TInt)(aTicks*256);  // 1 tick = 256 us
   186 #endif
   187 #if defined(__MAWD__) || defined(__MEIG__)
   188 	return aTicks*500;					// 2kHz tick
   189 #endif
   190 #if defined(__NE1_TB__)
   191 	NETimer& T2 = NETimer::Timer(2);
   192 	TUint prescale = __e32_find_ms1_32(T2.iPrescaler & 0x3f);
   193 	TInt f = 66666667 >> prescale;
   194 	TInt64 x = I64LIT(1000000);
   195 	x *= TInt64(aTicks);
   196 	x += TInt64(f>>1);
   197 	x /= TInt64(f);
   198 	return (TInt)x;
   199 #endif
   200 #if defined(__EPOC32__) && defined(__CPU_X86)
   201 	TInt x = aTicks;
   202 	TInt y = x;
   203 	y -= ((3*x)>>4);	// * 0.D
   204 	y += (aTicks>>12);	// * 0.D00D
   205 	TInt z = (6*x)>>8;	// * 0.06
   206 	y += z;				// * 0.D60D
   207 	y += (x>>9);		// * 0.D68D
   208 	y += (z>>16);		// * 0.D68D6
   209 	y += (z>>20);		// * 0.D68D66
   210 	return y;
   211 #endif
   212 #ifdef __WINS__
   213 	LARGE_INTEGER f;
   214 	QueryPerformanceFrequency(&f);
   215 	aTicks*=1000000;
   216 	aTicks+=f.QuadPart-1;
   217 	aTicks/=f.QuadPart;
   218 	return (TInt)aTicks;
   219 #endif
   220 	}
   221 
   222 
   223 void InitTimer()
   224 	{
   225 #ifdef __MAWD__
   226 	// Set up timer 1 as free running 2kHz clock
   227 	TWind::SetBuzzerControl(0);		// disable buzzer
   228 	TWind::SetTimer1Control(KWindTimer1ControlTimerEnable);
   229 	TWind::SetTimer1Load(0);
   230 #endif
   231 #ifdef __MEIG__
   232 	// Set up timer 1 as free running 2kHz clock
   233 	TEiger::ModifyControl21(KEigerControlTimer1PreOrFree|KEigerControlTimer1K512OrK2|
   234 							KEigerControlBuzzerToggle|KEigerControlBuzzerTimer1OrToggle,0);
   235 	TEiger::SetTimer1Data(0);
   236 #endif
   237 #if defined(__MISA__)
   238 	// MISA free running counter is always active - no initialisation required
   239 #endif
   240 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
   241 	// Set up Timer3 as a free-running timer at 12Mhz/32 = 375kHz
   242 	TOmapTimer::SetTimer3Ctrl(	TOmapTimer::KHtOSTimer_Cntl_Ar
   243 									| TOmapTimer::KHtOSTimer_Cntl_Free
   244 									| TOmapTimer::KHtOSTimer_Cntl_ClkEnable );
   245 	TOmapTimer::SetTimer3Prescale( TOmapTimer::EPrescaleBy32 );
   246 	// Autoreload 0xFFFFFFFF to effectively wrap from zero back to 0xFFFFFFFF
   247 	TOmapTimer::SetTimer3LoadTim( 0xFFFFFFFF );
   248 	TOmapTimer::StartTimer3();
   249 #endif
   250 #if defined(__MI920__) || defined(__NI1136__)
   251 #if !defined(USE_CM920_FRC)
   252     TIntegratorAP::SetTimerMode(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerModeFreeRunning);
   253     TIntegratorAP::SetTimerPreScale(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerPreScaleDiv256);	// 93.75kHz wrap 699ms
   254     TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EEnable);
   255 #endif
   256 #endif
   257 #if defined(__RVEMUBOARD__)
   258 	// Switch timer 1 to a 1MHz clock in the system controller Ctrl register
   259 	TRvEmuBoard::SetSCCtrl(KTimer1EnSel);
   260 
   261 	// Set up timer 1 as free running 3.90625kHz clock
   262 	TRvEmuBoard::SetTimerMode(KHwCounterTimer1, TRvEmuBoard::ETimerModeFreeRunning);
   263 	TRvEmuBoard::SetTimerPreScale(KHwCounterTimer1, TRvEmuBoard::ETimerPreScaleDiv256);// 3.90625kHz wrap 16.777s
   264 	TRvEmuBoard::EnableTimer(KHwCounterTimer1, TRvEmuBoard::EEnable);
   265 #endif
   266 #if defined(__NE1_TB__)
   267 	// nothing to do since variant has already set up timer
   268 #endif
   269 #if defined(__EPOC32__) && defined(__CPU_X86)
   270 	// Set up timer channel 2 as free running counter at 14318180/12 Hz
   271 	SetUpTimerChannel2();
   272 #endif
   273 	}
   274 
   275 // global Dfc Que
   276 TDynamicDfcQue* gDfcQ;
   277 
   278 class NTimerQTest
   279 	{
   280 public:
   281 	static inline NTimerQ& Timer()
   282 		{ return *(NTimerQ*)NTimerQ::TimerAddress(); }
   283 	static inline TUint32 MsCount()
   284 		{ return Timer().iMsCount; }
   285 	static inline void Setup(TAny* aPtr)
   286 		{ NTimerQ& m=Timer(); m.iDebugFn=Test; m.iDebugPtr=aPtr; }
   287 	static inline void Stop()
   288 		{ NTimerQ& m=Timer(); m.iDebugFn=NULL; m.iDebugPtr=NULL; }
   289 	static inline TBool XferC()
   290 		{ return Timer().iTransferringCancelled; }
   291 	static inline TBool CritC()
   292 		{ return Timer().iCriticalCancelled; }
   293 	static void Test(TAny* aPtr, TInt aPos);
   294 	};
   295 
   296 class DMsTim;
   297 
   298 class TMsTim : public NTimer
   299 	{
   300 public:
   301 	enum TMode
   302 		{
   303 		EIntAfter,
   304 		EDfcAfter,
   305 		EIntAgain,
   306 		EDfcAgain,
   307 		EIntCancel,
   308 		EDfcCancel,
   309 		EUserDfcAfter
   310 		};
   311 
   312 	enum TModeX
   313 		{
   314 		EIntAgainOnce=7,
   315 		EUserDfcAgainOnce
   316 		};
   317 public:
   318 	TMsTim();
   319 	~TMsTim();
   320 	TInt Create();
   321 	TInt Start(TInt aMode, TInt aInterval, TInt aParam);
   322 	static void MsCallBack(TAny* aPtr);
   323 	static void IDfcFn(TAny* aPtr);
   324 	static void DfcFn(TAny* aPtr);
   325 	void CompleteClient(TInt aValue);
   326 public:
   327 	TMode iMode;
   328 	TInt iInterval;
   329 	TInt iParam;
   330 	TCounter iStartTime;
   331 	TDelta iMin;
   332 	TDelta iMax;
   333 	Int64 iTotal;
   334 	TInt iCount;
   335 	DMsTim* iLdd;
   336 	TInt iId;
   337 	TClientRequest* iRequest;
   338 	TDfc iIDfc;
   339 	TDfc iCompletionDfc;
   340 	};
   341 
   342 class TMsTimRand : public NTimer
   343 	{
   344 public:
   345 	TMsTimRand();
   346 #ifdef __SMP__
   347 	~TMsTimRand();
   348 #endif
   349 	TInt Start(TInt aInterval, DMsTim* aLdd, TInt aPos);
   350 	static void MsCallBack(TAny* aPtr);
   351 	void FillWithGarbage(TUint aFillValue);
   352 public:
   353 	TInt iInterval;
   354 	TCounter iStartTime;
   355 	DMsTim* iLdd;
   356 	};
   357 
   358 class DMsTimFactory : public DLogicalDevice
   359 //
   360 // Millisecond timer LDD factory
   361 //
   362 	{
   363 public:
   364 	DMsTimFactory();
   365 	~DMsTimFactory();
   366 	virtual TInt Install();						//overriding pure virtual
   367 	virtual void GetCaps(TDes8& aDes) const;	//overriding pure virtual
   368 	virtual TInt Create(DLogicalChannelBase*& aChannel);	//overriding pure virtual
   369 	};
   370 
   371 class DMsTim : public DLogicalChannel
   372 //
   373 // Millisecond timer LDD channel
   374 //
   375 	{
   376 public:
   377 	DMsTim();
   378 	~DMsTim();
   379 protected:
   380 	virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
   381 	TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
   382 	TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
   383 	virtual void HandleMsg(TMessageBase* aMsg);
   384 public:
   385 	void TimerExpired(TInt anId);
   386 	inline DThread* Client() { return iThread; }
   387 public:
   388 	DThread* iThread;
   389 	TMsTim iMsTim[KMaxMsTim];
   390 	TMsTimRand iMsTimR[KMaxMsTimR];
   391 	TInt iRandMin;
   392 	TInt iRandMax;
   393 	TInt iXferC;
   394 	TInt iCritC;
   395 	TInt iStartFail;
   396 	TInt iCallBacks;
   397 	TInt iCompletions;
   398 	TUint iSeed[2];
   399 	};
   400 
   401 TMsTim::TMsTim()
   402 	:	NTimer(MsCallBack,this),
   403 		iMode(EIntAfter),
   404 		iInterval(0),
   405 		iParam(0),
   406 		iStartTime(0),
   407 		iMin(KMaxDelta),
   408 		iMax(KMinDelta),
   409 		iTotal(0),
   410 		iCount(0),
   411 		iRequest(NULL),
   412 		iIDfc(IDfcFn,this),
   413 		iCompletionDfc(DfcFn,this,gDfcQ,1)
   414 	{
   415 	}
   416 
   417 TMsTim::~TMsTim()
   418 	{
   419 	Kern::DestroyClientRequest(iRequest);
   420 #ifdef __SMP__
   421 	NTimer* nt = STATIC_CAST(NTimer*,this);
   422 	new (nt) NTimer(&MsCallBack, this);	// so NTimer destructor doesn't kill us
   423 #endif
   424 	}
   425 
   426 TInt TMsTim::Create()
   427 	{
   428 	return Kern::CreateClientRequest(iRequest);
   429 	}
   430 
   431 void TMsTim::IDfcFn(TAny* aPtr)
   432 	{
   433 	TMsTim& m=*(TMsTim*)aPtr;
   434 	TInt c = NKern::CurrentContext();
   435 	__NK_ASSERT_ALWAYS(c == NKern::EIDFC);
   436 	__NK_ASSERT_ALWAYS(NKern::KernelLocked(1));
   437 	m.iCompletionDfc.DoEnque();
   438 	}
   439 
   440 void TMsTim::DfcFn(TAny* aPtr)
   441 	{
   442 	TMsTim& m=*(TMsTim*)aPtr;
   443 	if (m.iMode==EUserDfcAfter)
   444 		{
   445 		TCounter timer_val=TIMER();
   446 		TDelta time=TimeDelta(m.iStartTime, timer_val);
   447 		++m.iCount;
   448 		if (time<m.iMin)
   449 			m.iMin=time;
   450 		if (time>m.iMax)
   451 			m.iMax=time;
   452 		m.iTotal+=time;
   453 		}
   454 	m.iLdd->TimerExpired(m.iId);
   455 	}
   456 
   457 void TestThreadContext()
   458 	{
   459 	TInt c1 = NKern::CurrentContext();
   460 	NKern::Lock();
   461 	TInt c2 = NKern::CurrentContext();
   462 	NKern::Unlock();
   463 	__NK_ASSERT_ALWAYS((c1 == NKern::EThread) && (c2 == NKern::EThread));
   464 	}
   465 
   466 void TMsTim::MsCallBack(TAny* aPtr)
   467 	{
   468 	TInt c = NKern::CurrentContext();
   469 	TCounter timer_val=TIMER();
   470 	TMsTim& m=*(TMsTim*)aPtr;
   471 	TDelta time=TimeDelta(m.iStartTime, timer_val);
   472 	if (++m.iCount>0 || (m.iMode!=EIntAgain && m.iMode!=EDfcAgain))
   473 		{
   474 		if (time<m.iMin)
   475 			m.iMin=time;
   476 		if (time>m.iMax)
   477 			m.iMax=time;
   478 		m.iTotal+=time;
   479 		}
   480 	switch (m.iMode)
   481 		{
   482 		case EIntAfter:
   483 			__NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
   484 			m.iIDfc.Add();
   485 			break;
   486 		case EDfcAfter:
   487 			TestThreadContext();
   488 			m.iCompletionDfc.Enque();
   489 			break;
   490 		case EIntAgain:
   491 			__NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
   492 			m.iStartTime=TIMER();
   493 			m.Again(m.iInterval);
   494 			break;
   495 		case EDfcAgain:
   496 			TestThreadContext();
   497 			m.iStartTime=TIMER();
   498 			m.Again(m.iInterval);
   499 			break;
   500 		case EIntCancel:
   501 			__NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
   502 			m.iLdd->iMsTim[m.iParam].Cancel();
   503 			m.iIDfc.Add();
   504 			break;
   505 		case EDfcCancel:
   506 			TestThreadContext();
   507 			m.iLdd->iMsTim[m.iParam].Cancel();
   508 			m.iCompletionDfc.Enque();
   509 			break;
   510 		case EUserDfcAfter:
   511 			__NK_ASSERT_ALWAYS(EFalse);
   512 			break;
   513 		}
   514 	}
   515 
   516 TInt TMsTim::Start(TInt aMode, TInt aInterval, TInt aParam)
   517 	{
   518 	TInt r=KErrGeneral;
   519 	TInt c=0;
   520 	TCounter holder=TIMER();		// holds the start value of timer
   521 	switch (aMode)
   522 		{
   523 		case EIntAgain:
   524 			c=-1;
   525 		case EIntAfter:
   526 		case EIntCancel:
   527 			r=OneShot(aInterval);
   528 			break;
   529 		case EDfcAgain:
   530 			c=-1;
   531 		case EDfcAfter:
   532 		case EDfcCancel:
   533 			r=OneShot(aInterval,ETrue);
   534 			break;
   535 		case EIntAgainOnce:
   536 		case EUserDfcAgainOnce:
   537 #ifdef __SMP__
   538 			i8888.iHState2=FALSE;
   539 #else
   540 			iCompleteInDfc=FALSE;
   541 #endif
   542 			r=Again(aInterval);
   543 			if (aMode==EUserDfcAgainOnce)
   544 				aMode=EUserDfcAfter;
   545 			else
   546 				aMode=EIntAfter;
   547 			break;
   548 		case EUserDfcAfter:
   549 			r=OneShot(aInterval, iCompletionDfc);
   550 			break;
   551 		}
   552 	if (r!=KErrNone)
   553 		return r;
   554 	iStartTime=holder;
   555 	iMode=TMode(aMode);
   556 	iInterval=aInterval;
   557 	iParam=aParam;
   558 	iMin=KMaxDelta;
   559 	iMax=KMinDelta;
   560 	iTotal=0;
   561 	iCount=c;
   562 	return KErrNone;
   563 	}
   564 
   565 void TMsTim::CompleteClient(TInt aValue)
   566 	{
   567 	Kern::QueueRequestComplete(iLdd->Client(),iRequest,aValue);
   568 	}
   569 
   570 TMsTimRand::TMsTimRand()
   571 	:	NTimer(&MsCallBack,this)
   572 	{
   573 	memset(this,0,sizeof(TMsTimRand));
   574 #ifdef __SMP__
   575 	NTimer* nt = STATIC_CAST(NTimer*,this);
   576 	new (nt) NTimer(&MsCallBack,this);
   577 #else
   578 	iFunction=MsCallBack;	// avoid triggering assertion in NTimer::OneShot()
   579 #endif
   580 	}
   581 
   582 #ifdef __SMP__
   583 TMsTimRand::~TMsTimRand()
   584 	{
   585 	NTimer* nt = STATIC_CAST(NTimer*,this);
   586 	new (nt) NTimer(&MsCallBack, this);	// so NTimer destructor doesn't kill us
   587 	}
   588 #endif
   589 
   590 void TMsTimRand::FillWithGarbage(TUint aFill)
   591 	{
   592 #ifdef __SMP__
   593 	TUint32 f = aFill;
   594 	f |= (f<<8);
   595 	f |= (f<<16);
   596 	iNext = (SDblQueLink*)f;
   597 	iPrev = (SDblQueLink*)f;
   598 	iDfcQ = (TDfcQue*)f;
   599 	iPtr = (TAny*)f;
   600 	iFn = (NEventFn)f;
   601 	iTiedLink.iNext = (SDblQueLink*)f;
   602 	iTiedLink.iPrev = (SDblQueLink*)f;
   603 #else
   604 	memset(this, (TUint8)aFill, 16);
   605 #endif
   606 	}
   607 
   608 TInt TMsTimRand::Start(TInt aInterval, DMsTim* aLdd, TInt aPos)
   609 	{
   610 	iLdd=aLdd;
   611 #ifdef __SMP__
   612 	TUint fill=(aPos<<5)|(i8888.iHState1<<2)|3;
   613 #else
   614 	TUint fill=(aPos<<5)|(iState<<2)|3;
   615 	iPad1 = (TUint8)fill;
   616 #endif
   617 	TInt r=OneShot(aInterval,ETrue);
   618 	if (r==KErrNone)
   619 		{
   620 		iPtr=this;
   621 		iInterval=aInterval;
   622 		iStartTime=TIMER();
   623 #ifdef __SMP__
   624 		iFn=MsCallBack;
   625 		i8888.iHState0 = (TUint8)fill;
   626 		if (i8888.iHState1!=EHolding)
   627 			*(TUint*)0xfcd1fcd1=i8888.iHState1;
   628 #else
   629 		iFunction=MsCallBack;
   630 		iUserFlags = (TUint8)fill;
   631 		if (iState!=EHolding)
   632 			*(TUint*)0xfcd1fcd1=iState;
   633 #endif
   634 		}
   635 	return r;
   636 	}
   637 
   638 void TMsTimRand::MsCallBack(TAny* aPtr)
   639 	{
   640 	TMsTimRand& m=*(TMsTimRand*)aPtr;
   641 	TCounter time=TIMER();
   642 	TDelta elapsed=TimeDelta(m.iStartTime,time);
   643 	TInt error=TicksToMicroseconds(elapsed)-m.iInterval*1000;
   644 	if (error<m.iLdd->iRandMin)
   645 		m.iLdd->iRandMin=error;
   646 	if (error>m.iLdd->iRandMax)
   647 		m.iLdd->iRandMax=error;
   648 	++m.iLdd->iCompletions;
   649 	m.FillWithGarbage(0xd9);
   650 	}
   651 
   652 void NTimerQTest::Test(TAny* aPtr, TInt aPos)
   653 	{
   654 	DMsTim& ldd=*(DMsTim*)aPtr;
   655 	++ldd.iCallBacks;
   656 	if (aPos==7)
   657 		return;
   658 	TUint action=Random(ldd.iSeed)&31;
   659 	TMsTimRand& m=ldd.iMsTimR[action&7];
   660 	if (action<8)
   661 		{
   662 #ifdef __SMP__
   663 		TUint fill=(aPos<<5)|(m.i8888.iHState1<<2)|3;
   664 #else
   665 		TUint fill=(aPos<<5)|(m.iState<<2)|3;
   666 #endif
   667 		m.Cancel();
   668 		m.FillWithGarbage(fill);
   669 		}
   670 	else if (action<16)
   671 		{
   672 		TUint iv=(Random(ldd.iSeed)&31)+32;
   673 		TInt r=m.Start(iv,&ldd,aPos);
   674 		if (r!=KErrNone)
   675 			++ldd.iStartFail;
   676 		}
   677 	if (XferC())
   678 		++ldd.iXferC;
   679 	if (CritC())
   680 		++ldd.iCritC;
   681 	}
   682 
   683 DECLARE_STANDARD_LDD()
   684 	{
   685     return new DMsTimFactory;
   686     }
   687 
   688 DMsTimFactory::DMsTimFactory()
   689 //
   690 // Constructor
   691 //
   692     {
   693     iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
   694     //iParseMask=0;//No units, no info, no PDD
   695     //iUnitsMask=0;//Only one thing
   696     }
   697 
   698 TInt DMsTimFactory::Create(DLogicalChannelBase*& aChannel)
   699 //
   700 // Create a new DMsTim on this logical device
   701 //
   702     {
   703 	aChannel=new DMsTim;
   704 	return aChannel?KErrNone:KErrNoMemory;
   705     }
   706 
   707 const TInt KDMsTimThreadPriority = 27;
   708 _LIT(KDMsTimThread,"DMsTimThread");
   709 
   710 TInt DMsTimFactory::Install()
   711 //
   712 // Install the LDD - overriding pure virtual
   713 //
   714     {
   715 	// Allocate a kernel thread to run the DFC 
   716 	TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMsTimThreadPriority, KDMsTimThread);
   717 
   718 #ifdef CPU_AFFINITY_ANY
   719 			NKern::ThreadSetCpuAffinity((NThread*)(gDfcQ->iThread), KCpuAffinityAny);			
   720 #endif
   721 
   722 	if (r != KErrNone)
   723 		return r; 	
   724 
   725     return SetName(&KMsTimerLddName);
   726     }
   727 
   728 void DMsTimFactory::GetCaps(TDes8& aDes) const
   729 //
   730 // Get capabilities - overriding pure virtual
   731 //
   732     {
   733     TCapsMsTimV01 b;
   734     b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
   735     Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
   736     }
   737 
   738 /**
   739   Destructor
   740 */
   741 DMsTimFactory::~DMsTimFactory()
   742 	{
   743 	if (gDfcQ)
   744 		gDfcQ->Destroy();
   745 	}
   746 
   747 DMsTim::DMsTim()
   748 //
   749 // Constructor
   750 //
   751     {
   752 	iThread=&Kern::CurrentThread();
   753 	iThread->Open();
   754 	TInt i;
   755 	for (i=0; i<KMaxMsTim; i++)
   756 		{
   757 		iMsTim[i].iLdd=this;
   758 		iMsTim[i].iId=i;
   759 		}
   760 	for (i=0; i<KMaxMsTimR; i++)
   761 		{
   762 		iMsTimR[i].iLdd=this;
   763 		}
   764 	iSeed[0]=NTimerQTest::MsCount();
   765 	iSeed[1]=0;
   766     }
   767 
   768 TInt DMsTim::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
   769 //
   770 // Create channel
   771 //
   772     {
   773     if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
   774     	return KErrNotSupported;
   775 	InitTimer();
   776 	SetDfcQ(gDfcQ);
   777 	for (TInt i = 0 ; i < KMaxMsTim ; ++i)
   778 		{
   779 		TInt r = iMsTim[i].Create();
   780 		if (r != KErrNone)
   781 			return r;
   782 		}
   783 	iMsgQ.Receive();
   784 #ifdef __SMP__
   785 	NKern::ThreadSetCpuAffinity(NKern::CurrentThread(), NKern::NumberOfCpus() - 1); // Try and avoid the cpu the test app is running on
   786 #endif
   787 	return KErrNone;
   788 	}
   789 
   790 DMsTim::~DMsTim()
   791 //
   792 // Destructor
   793 //
   794     {
   795 #if defined(__MI920__) || defined(__NI1136__)
   796 #if !defined(USE_CM920_FRC)
   797 	TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EDisable);
   798 #endif
   799 #endif
   800 #if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) 
   801 	TOmapTimer::SetTimer3Ctrl( 0 );	// disable the timer
   802 #endif
   803 	Kern::SafeClose((DObject*&)iThread, NULL);
   804     }
   805 
   806 void DMsTim::HandleMsg(TMessageBase* aMsg)
   807 	{
   808 	TInt r=KErrNone;
   809 	TThreadMessage& m=*(TThreadMessage*)aMsg;
   810 	TInt id=m.iValue;
   811 	if (id==(TInt)ECloseMsg)
   812 		{
   813 		NTimerQTest::Stop();
   814 		TInt i;
   815 		for (i=0; i<KMaxMsTim; i++)
   816 			{
   817 			iMsTim[i].Cancel();
   818 			iMsTim[i].iCompletionDfc.Cancel();
   819 			iMsTim[i].CompleteClient(KErrCancel);
   820 			}
   821 		for (i=0; i<KMaxMsTimR; i++)
   822 			{
   823 			iMsTimR[i].Cancel();
   824 			iMsTimR[i].FillWithGarbage(0x01);
   825 			}
   826 		m.Complete(KErrNone,EFalse);
   827 		iMsgQ.CompleteAll(KErrServerTerminated);
   828 		return;
   829 		}
   830 	else if (id<0)
   831 		{
   832 		TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
   833 		r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
   834 		}
   835 	else
   836 		{
   837 		r=DoControl(id,m.Ptr0(),m.Ptr1());
   838 		}
   839 	m.Complete(r,ETrue);
   840 	}
   841 
   842 TInt DMsTim::DoControl(TInt aFunction, TAny* a1, TAny* a2)
   843 	{
   844 	TInt r=KErrNone;
   845 	TInt id=(TInt)a1;
   846 	TMsTim& m=iMsTim[id];
   847 	TInt interval=(TInt)a2;
   848 	switch (aFunction)
   849 		{
   850 		case RMsTim::EControlStartPeriodicInt:
   851 			r=m.Start(TMsTim::EIntAgain,interval,0);
   852 			break;
   853 		case RMsTim::EControlStartPeriodicDfc:
   854 			r=m.Start(TMsTim::EDfcAgain,interval,0);
   855 			break;
   856 		case RMsTim::EControlStopPeriodic:
   857 			m.Cancel();
   858 			m.iCompletionDfc.Cancel();
   859 			break;
   860 		case RMsTim::EControlGetInfo:
   861 			{
   862 			SMsTimerInfo info;
   863 			info.iCount=m.iCount;
   864 			Int64 avg=m.iTotal/m.iCount;
   865 			info.iAvg=TicksToMicroseconds((TInt)avg);
   866 #ifdef __SMP__
   867 			info.iMin=info.iAvg;
   868 			info.iMax=info.iAvg;
   869 #else
   870 			info.iMin=TicksToMicroseconds(m.iMin);
   871 			info.iMax=TicksToMicroseconds(m.iMax);
   872 #endif
   873 
   874 			r=Kern::ThreadRawWrite(iThread,a2,&info,sizeof(info));
   875 			break;
   876 			}
   877 		case RMsTim::EControlBeginRandomTest:
   878 			{
   879 			iRandMin=KMaxTInt;
   880 			iRandMax=KMinTInt;
   881 			iXferC=0;
   882 			iCritC=0;
   883 			iStartFail=0;
   884 			iCallBacks=0;
   885 			iCompletions=0;
   886 			NTimerQTest::Setup(this);
   887 			break;
   888 			}
   889 		case RMsTim::EControlEndRandomTest:
   890 			{
   891 			NTimerQTest::Stop();
   892 			TInt i;
   893 			for (i=0; i<KMaxMsTimR; i++)
   894 				{
   895 				iMsTimR[i].Cancel();
   896 				iMsTimR[i].FillWithGarbage(0x35);
   897 				}
   898 			break;
   899 			}
   900 		case RMsTim::EControlGetRandomTestInfo:
   901 			{
   902 			SRandomTestInfo info;
   903 			info.iMin=iRandMin;
   904 			info.iMax=iRandMax;
   905 			info.iXferC=iXferC;
   906 			info.iCritC=iCritC;
   907 			info.iStartFail=iStartFail;
   908 			info.iCallBacks=iCallBacks;
   909 			info.iCompletions=iCompletions;
   910 			r=Kern::ThreadRawWrite(iThread,a1,&info,sizeof(info));
   911 			break;
   912 			}
   913 		case RMsTim::EControlGetIdleTime:
   914 			{
   915 			TInt irq=NKern::DisableAllInterrupts();
   916 			r=NTimerQ::IdleTime();
   917 			NKern::RestoreInterrupts(irq);
   918 			break;
   919 			}
   920 		default:
   921 			r=KErrNotSupported;
   922 			break;
   923 		}
   924 	return r;
   925 	}
   926 
   927 TInt DMsTim::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
   928 	{
   929 	TInt id=(TInt)a1;
   930 	TMsTim& m=iMsTim[aFunction == RMsTim::ERequestIntCancel ? 7 : id];
   931 	TInt interval=(TInt)a2;
   932 	TInt r=KErrNone;
   933 	switch (aFunction)
   934 		{
   935 		case RMsTim::ERequestOneShotInt:
   936 			r=m.Start(TMsTim::EIntAfter,interval,0);
   937 			break;
   938 		case RMsTim::ERequestOneShotDfc:
   939 			r=m.Start(TMsTim::EDfcAfter,interval,0);
   940 			break;
   941 		case RMsTim::ERequestIntCancel:
   942 			r=m.Start(TMsTim::EIntCancel,interval,id);
   943 			break;
   944 		case RMsTim::ERequestOneShotIntAgain:
   945 			r=m.Start(TMsTim::EIntAgainOnce,interval,0);
   946 			break;
   947 		case RMsTim::ERequestOneShotUserDfc:
   948 			r=m.Start(TMsTim::EUserDfcAfter,interval,0);
   949 			break;
   950 		case RMsTim::ERequestOneShotUserDfcAgain:
   951 			r=m.Start(TMsTim::EUserDfcAgainOnce,interval,0);
   952 			break;
   953 		default:
   954 			r=KErrNotSupported;
   955 			break;
   956 		}
   957 	m.iRequest->SetStatus(aStatus);
   958 	if (r!=KErrNone)
   959 		Kern::QueueRequestComplete(iThread,m.iRequest,r);
   960 	return r;
   961 	}
   962 
   963 void DMsTim::TimerExpired(TInt anId)
   964 	{
   965 	TMsTim& m=iMsTim[anId];
   966 	switch (m.iMode)
   967 		{
   968 		case TMsTim::EIntAfter:
   969 		case TMsTim::EDfcAfter:
   970 		case TMsTim::EUserDfcAfter:
   971 			m.CompleteClient(KErrNone);
   972 			break;
   973 		case TMsTim::EIntAgain:
   974 		case TMsTim::EDfcAgain:
   975 			break;
   976 		case TMsTim::EIntCancel:
   977 		case TMsTim::EDfcCancel:
   978 			{
   979 			TMsTim& cancelled=iMsTim[m.iParam];
   980 			cancelled.CompleteClient(KErrAbort);
   981 			m.CompleteClient(KErrNone);
   982 			break;
   983 			}
   984 		}
   985 	}
   986