1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/system/d_mstim.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,986 @@
1.4 +// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test\system\d_mstim.cpp
1.18 +// LDD for testing millisecond timer
1.19 +//
1.20 +//
1.21 +
1.22 +#include "plat_priv.h"
1.23 +#if defined(__MEIG__)
1.24 +#include <cl7211.h>
1.25 +#elif defined(__MAWD__)
1.26 +#include <windermere.h>
1.27 +#elif defined(__MISA__)
1.28 +#include <sa1100.h>
1.29 +#elif defined(__MCOT__)
1.30 +#include <cotulla.h>
1.31 +#elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
1.32 +#include <omap.h>
1.33 +#include <omap_timer.h>
1.34 +#elif defined(__MI920__) || defined(__NI1136__)
1.35 +#ifdef __MI920__
1.36 +#define USE_CM920_FRC
1.37 +#endif
1.38 +#ifdef USE_CM920_FRC
1.39 +#include <iolines.h>
1.40 +#else
1.41 +#include <integratorap.h>
1.42 +#endif
1.43 +#elif defined(__RVEMUBOARD__)
1.44 +#include <rvemuboard.h>
1.45 +#elif defined(__NE1_TB__)
1.46 +#include <upd35001_timer.h>
1.47 +#endif
1.48 +#include "d_mstim.h"
1.49 +#include "../misc/prbs.h"
1.50 +
1.51 +#if defined(__WINS__)
1.52 +typedef Int64 TCounter;
1.53 +typedef Int64 TDelta;
1.54 +const TDelta KMaxDelta = 0x7fffffffffffffff;
1.55 +const TDelta KMinDelta = 0x8000000000000000;
1.56 +#else
1.57 +typedef TUint TCounter;
1.58 +typedef TInt TDelta;
1.59 +const TDelta KMaxDelta = KMaxTInt;
1.60 +const TDelta KMinDelta = KMinTInt;
1.61 +#endif
1.62 +
1.63 +#ifdef __MISA__
1.64 +inline TCounter TIMER()
1.65 + { return *(volatile TUint*)KHwRwOstOscr; }
1.66 +#endif
1.67 +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
1.68 +inline TCounter TIMER()
1.69 + { return TOmapTimer::Timer3Value(); }
1.70 +#endif
1.71 +#ifdef __MCOT__
1.72 +inline TCounter TIMER()
1.73 + { return *(volatile TUint*)KHwRwOstOscr; }
1.74 +#endif
1.75 +#ifdef __MAWD__
1.76 +inline TCounter TIMER()
1.77 + { return *(volatile TUint*)(KWindBaseAddress+KWindTimer1Value16)&0xffff; }
1.78 +#endif
1.79 +#ifdef __MEIG__
1.80 +inline TCounter TIMER()
1.81 +{ return *(volatile TUint*)(KEigerBaseAddress+KEigerTimer1Data16)&0xffff;}
1.82 +#endif
1.83 +#if defined(__MI920__) || defined(__NI1136__)
1.84 +inline TCounter TIMER()
1.85 +#ifdef USE_CM920_FRC
1.86 + { return *(volatile TUint*)(KHwRwCoreClkCounter);} // 32-bit Core module counter inc's at 24MHz
1.87 +#else
1.88 + { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
1.89 +#endif
1.90 +#endif
1.91 +#if defined(__RVEMUBOARD__)
1.92 +inline TCounter TIMER()
1.93 + { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
1.94 +#endif
1.95 +#ifdef __NE1_TB__
1.96 +inline TCounter TIMER()
1.97 + { return NETimer::Timer(2).iTimerCount; }
1.98 +#endif
1.99 +#if defined(__EPOC32__) && defined(__CPU_X86)
1.100 +TCounter TIMER();
1.101 +void SetUpTimerChannel2();
1.102 +#endif
1.103 +
1.104 +#ifdef __WINS__
1.105 +inline TCounter TIMER()
1.106 + {
1.107 + LARGE_INTEGER c;
1.108 + QueryPerformanceCounter(&c);
1.109 + return c.QuadPart;
1.110 + }
1.111 +#endif
1.112 +
1.113 +#if defined(__MISA__) || (defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__)))
1.114 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.115 + { return final-initial; } // SA1100 timer counts up
1.116 +#endif
1.117 +#if defined(__MCOT__)
1.118 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.119 + { return final-initial; } // Cotulla timer counts up
1.120 +#endif
1.121 +#if defined(__MAWD__) || defined(__MEIG__) || (!defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__)))
1.122 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.123 + { return (initial-final)&0xffff; } // Eiger/Windermere/Integrator timer counts down
1.124 +#endif
1.125 +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
1.126 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.127 + { return (initial-final);} // OMAP timer counts down
1.128 +#endif
1.129 +#if defined(__EPOC32__) && defined(__CPU_X86)
1.130 +TDelta TimeDelta(TUint initial, TUint final)
1.131 + {
1.132 + TUint tickdiff=(initial-final)&0xffff;
1.133 + TUint msdiff=((final>>16)-(initial>>16))&0xffff;
1.134 + msdiff=1193*msdiff-tickdiff;
1.135 + msdiff=(msdiff+32768)&~0xffff;
1.136 + return msdiff+tickdiff;
1.137 + }
1.138 +#endif
1.139 +#ifdef __NE1_TB__
1.140 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.141 + { return final - initial; }
1.142 +#endif
1.143 +#ifdef __WINS__
1.144 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.145 + { return final-initial; } // counts up
1.146 +#endif
1.147 +#if defined(__RVEMUBOARD__)
1.148 +inline TDelta TimeDelta(TCounter initial, TCounter final)
1.149 + { return (initial-final)&0xffff; } // Timer counts down
1.150 +#endif
1.151 +
1.152 +const TInt KMajorVersionNumber=0;
1.153 +const TInt KMinorVersionNumber=1;
1.154 +const TInt KBuildVersionNumber=1;
1.155 +
1.156 +const TInt KMaxMsTim=9;
1.157 +const TInt KMaxMsTimR=9;
1.158 +
1.159 +TInt TicksToMicroseconds(TDelta aTicks)
1.160 + {
1.161 +#if defined(__MISA__) || defined(__MCOT__)
1.162 + Int64 ticks(aTicks);
1.163 + ticks*=(1000000);
1.164 + ticks+=KHwOscFreqHz/2; // 3.6864MHz tick
1.165 + ticks/=KHwOscFreqHz;
1.166 + return (TInt)ticks;
1.167 +#endif
1.168 +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
1.169 + // Timer runs at 12Mhz/32 = 375kHz. Each tick is 2.66...us which is 16/6us
1.170 + aTicks<<=4; // * 16
1.171 + aTicks+=3; // rounding to the closest number of us
1.172 + return (TInt)(aTicks/6); // us = (ticks*16+3)/6
1.173 +#endif
1.174 +#if defined(__MI920__) || defined(__NI1136__)
1.175 +#if defined(USE_CM920_FRC)
1.176 + Int64 ticks(aTicks);
1.177 + ticks*=(1000000);
1.178 + ticks+=24000000/2;
1.179 + ticks/=24000000;
1.180 + return (TInt)ticks;
1.181 +#else
1.182 + aTicks<<=14; // 1 tick = 32/3 us
1.183 + aTicks+=768; // round
1.184 + return (TInt)(aTicks/1536);
1.185 +#endif
1.186 +#endif
1.187 +#if defined(__RVEMUBOARD__)
1.188 + return (TInt)(aTicks*256); // 1 tick = 256 us
1.189 +#endif
1.190 +#if defined(__MAWD__) || defined(__MEIG__)
1.191 + return aTicks*500; // 2kHz tick
1.192 +#endif
1.193 +#if defined(__NE1_TB__)
1.194 + NETimer& T2 = NETimer::Timer(2);
1.195 + TUint prescale = __e32_find_ms1_32(T2.iPrescaler & 0x3f);
1.196 + TInt f = 66666667 >> prescale;
1.197 + TInt64 x = I64LIT(1000000);
1.198 + x *= TInt64(aTicks);
1.199 + x += TInt64(f>>1);
1.200 + x /= TInt64(f);
1.201 + return (TInt)x;
1.202 +#endif
1.203 +#if defined(__EPOC32__) && defined(__CPU_X86)
1.204 + TInt x = aTicks;
1.205 + TInt y = x;
1.206 + y -= ((3*x)>>4); // * 0.D
1.207 + y += (aTicks>>12); // * 0.D00D
1.208 + TInt z = (6*x)>>8; // * 0.06
1.209 + y += z; // * 0.D60D
1.210 + y += (x>>9); // * 0.D68D
1.211 + y += (z>>16); // * 0.D68D6
1.212 + y += (z>>20); // * 0.D68D66
1.213 + return y;
1.214 +#endif
1.215 +#ifdef __WINS__
1.216 + LARGE_INTEGER f;
1.217 + QueryPerformanceFrequency(&f);
1.218 + aTicks*=1000000;
1.219 + aTicks+=f.QuadPart-1;
1.220 + aTicks/=f.QuadPart;
1.221 + return (TInt)aTicks;
1.222 +#endif
1.223 + }
1.224 +
1.225 +
1.226 +void InitTimer()
1.227 + {
1.228 +#ifdef __MAWD__
1.229 + // Set up timer 1 as free running 2kHz clock
1.230 + TWind::SetBuzzerControl(0); // disable buzzer
1.231 + TWind::SetTimer1Control(KWindTimer1ControlTimerEnable);
1.232 + TWind::SetTimer1Load(0);
1.233 +#endif
1.234 +#ifdef __MEIG__
1.235 + // Set up timer 1 as free running 2kHz clock
1.236 + TEiger::ModifyControl21(KEigerControlTimer1PreOrFree|KEigerControlTimer1K512OrK2|
1.237 + KEigerControlBuzzerToggle|KEigerControlBuzzerTimer1OrToggle,0);
1.238 + TEiger::SetTimer1Data(0);
1.239 +#endif
1.240 +#if defined(__MISA__)
1.241 + // MISA free running counter is always active - no initialisation required
1.242 +#endif
1.243 +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
1.244 + // Set up Timer3 as a free-running timer at 12Mhz/32 = 375kHz
1.245 + TOmapTimer::SetTimer3Ctrl( TOmapTimer::KHtOSTimer_Cntl_Ar
1.246 + | TOmapTimer::KHtOSTimer_Cntl_Free
1.247 + | TOmapTimer::KHtOSTimer_Cntl_ClkEnable );
1.248 + TOmapTimer::SetTimer3Prescale( TOmapTimer::EPrescaleBy32 );
1.249 + // Autoreload 0xFFFFFFFF to effectively wrap from zero back to 0xFFFFFFFF
1.250 + TOmapTimer::SetTimer3LoadTim( 0xFFFFFFFF );
1.251 + TOmapTimer::StartTimer3();
1.252 +#endif
1.253 +#if defined(__MI920__) || defined(__NI1136__)
1.254 +#if !defined(USE_CM920_FRC)
1.255 + TIntegratorAP::SetTimerMode(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerModeFreeRunning);
1.256 + TIntegratorAP::SetTimerPreScale(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerPreScaleDiv256); // 93.75kHz wrap 699ms
1.257 + TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EEnable);
1.258 +#endif
1.259 +#endif
1.260 +#if defined(__RVEMUBOARD__)
1.261 + // Switch timer 1 to a 1MHz clock in the system controller Ctrl register
1.262 + TRvEmuBoard::SetSCCtrl(KTimer1EnSel);
1.263 +
1.264 + // Set up timer 1 as free running 3.90625kHz clock
1.265 + TRvEmuBoard::SetTimerMode(KHwCounterTimer1, TRvEmuBoard::ETimerModeFreeRunning);
1.266 + TRvEmuBoard::SetTimerPreScale(KHwCounterTimer1, TRvEmuBoard::ETimerPreScaleDiv256);// 3.90625kHz wrap 16.777s
1.267 + TRvEmuBoard::EnableTimer(KHwCounterTimer1, TRvEmuBoard::EEnable);
1.268 +#endif
1.269 +#if defined(__NE1_TB__)
1.270 + // nothing to do since variant has already set up timer
1.271 +#endif
1.272 +#if defined(__EPOC32__) && defined(__CPU_X86)
1.273 + // Set up timer channel 2 as free running counter at 14318180/12 Hz
1.274 + SetUpTimerChannel2();
1.275 +#endif
1.276 + }
1.277 +
1.278 +// global Dfc Que
1.279 +TDynamicDfcQue* gDfcQ;
1.280 +
1.281 +class NTimerQTest
1.282 + {
1.283 +public:
1.284 + static inline NTimerQ& Timer()
1.285 + { return *(NTimerQ*)NTimerQ::TimerAddress(); }
1.286 + static inline TUint32 MsCount()
1.287 + { return Timer().iMsCount; }
1.288 + static inline void Setup(TAny* aPtr)
1.289 + { NTimerQ& m=Timer(); m.iDebugFn=Test; m.iDebugPtr=aPtr; }
1.290 + static inline void Stop()
1.291 + { NTimerQ& m=Timer(); m.iDebugFn=NULL; m.iDebugPtr=NULL; }
1.292 + static inline TBool XferC()
1.293 + { return Timer().iTransferringCancelled; }
1.294 + static inline TBool CritC()
1.295 + { return Timer().iCriticalCancelled; }
1.296 + static void Test(TAny* aPtr, TInt aPos);
1.297 + };
1.298 +
1.299 +class DMsTim;
1.300 +
1.301 +class TMsTim : public NTimer
1.302 + {
1.303 +public:
1.304 + enum TMode
1.305 + {
1.306 + EIntAfter,
1.307 + EDfcAfter,
1.308 + EIntAgain,
1.309 + EDfcAgain,
1.310 + EIntCancel,
1.311 + EDfcCancel,
1.312 + EUserDfcAfter
1.313 + };
1.314 +
1.315 + enum TModeX
1.316 + {
1.317 + EIntAgainOnce=7,
1.318 + EUserDfcAgainOnce
1.319 + };
1.320 +public:
1.321 + TMsTim();
1.322 + ~TMsTim();
1.323 + TInt Create();
1.324 + TInt Start(TInt aMode, TInt aInterval, TInt aParam);
1.325 + static void MsCallBack(TAny* aPtr);
1.326 + static void IDfcFn(TAny* aPtr);
1.327 + static void DfcFn(TAny* aPtr);
1.328 + void CompleteClient(TInt aValue);
1.329 +public:
1.330 + TMode iMode;
1.331 + TInt iInterval;
1.332 + TInt iParam;
1.333 + TCounter iStartTime;
1.334 + TDelta iMin;
1.335 + TDelta iMax;
1.336 + Int64 iTotal;
1.337 + TInt iCount;
1.338 + DMsTim* iLdd;
1.339 + TInt iId;
1.340 + TClientRequest* iRequest;
1.341 + TDfc iIDfc;
1.342 + TDfc iCompletionDfc;
1.343 + };
1.344 +
1.345 +class TMsTimRand : public NTimer
1.346 + {
1.347 +public:
1.348 + TMsTimRand();
1.349 +#ifdef __SMP__
1.350 + ~TMsTimRand();
1.351 +#endif
1.352 + TInt Start(TInt aInterval, DMsTim* aLdd, TInt aPos);
1.353 + static void MsCallBack(TAny* aPtr);
1.354 + void FillWithGarbage(TUint aFillValue);
1.355 +public:
1.356 + TInt iInterval;
1.357 + TCounter iStartTime;
1.358 + DMsTim* iLdd;
1.359 + };
1.360 +
1.361 +class DMsTimFactory : public DLogicalDevice
1.362 +//
1.363 +// Millisecond timer LDD factory
1.364 +//
1.365 + {
1.366 +public:
1.367 + DMsTimFactory();
1.368 + ~DMsTimFactory();
1.369 + virtual TInt Install(); //overriding pure virtual
1.370 + virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual
1.371 + virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual
1.372 + };
1.373 +
1.374 +class DMsTim : public DLogicalChannel
1.375 +//
1.376 +// Millisecond timer LDD channel
1.377 +//
1.378 + {
1.379 +public:
1.380 + DMsTim();
1.381 + ~DMsTim();
1.382 +protected:
1.383 + virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
1.384 + TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
1.385 + TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
1.386 + virtual void HandleMsg(TMessageBase* aMsg);
1.387 +public:
1.388 + void TimerExpired(TInt anId);
1.389 + inline DThread* Client() { return iThread; }
1.390 +public:
1.391 + DThread* iThread;
1.392 + TMsTim iMsTim[KMaxMsTim];
1.393 + TMsTimRand iMsTimR[KMaxMsTimR];
1.394 + TInt iRandMin;
1.395 + TInt iRandMax;
1.396 + TInt iXferC;
1.397 + TInt iCritC;
1.398 + TInt iStartFail;
1.399 + TInt iCallBacks;
1.400 + TInt iCompletions;
1.401 + TUint iSeed[2];
1.402 + };
1.403 +
1.404 +TMsTim::TMsTim()
1.405 + : NTimer(MsCallBack,this),
1.406 + iMode(EIntAfter),
1.407 + iInterval(0),
1.408 + iParam(0),
1.409 + iStartTime(0),
1.410 + iMin(KMaxDelta),
1.411 + iMax(KMinDelta),
1.412 + iTotal(0),
1.413 + iCount(0),
1.414 + iRequest(NULL),
1.415 + iIDfc(IDfcFn,this),
1.416 + iCompletionDfc(DfcFn,this,gDfcQ,1)
1.417 + {
1.418 + }
1.419 +
1.420 +TMsTim::~TMsTim()
1.421 + {
1.422 + Kern::DestroyClientRequest(iRequest);
1.423 +#ifdef __SMP__
1.424 + NTimer* nt = STATIC_CAST(NTimer*,this);
1.425 + new (nt) NTimer(&MsCallBack, this); // so NTimer destructor doesn't kill us
1.426 +#endif
1.427 + }
1.428 +
1.429 +TInt TMsTim::Create()
1.430 + {
1.431 + return Kern::CreateClientRequest(iRequest);
1.432 + }
1.433 +
1.434 +void TMsTim::IDfcFn(TAny* aPtr)
1.435 + {
1.436 + TMsTim& m=*(TMsTim*)aPtr;
1.437 + TInt c = NKern::CurrentContext();
1.438 + __NK_ASSERT_ALWAYS(c == NKern::EIDFC);
1.439 + __NK_ASSERT_ALWAYS(NKern::KernelLocked(1));
1.440 + m.iCompletionDfc.DoEnque();
1.441 + }
1.442 +
1.443 +void TMsTim::DfcFn(TAny* aPtr)
1.444 + {
1.445 + TMsTim& m=*(TMsTim*)aPtr;
1.446 + if (m.iMode==EUserDfcAfter)
1.447 + {
1.448 + TCounter timer_val=TIMER();
1.449 + TDelta time=TimeDelta(m.iStartTime, timer_val);
1.450 + ++m.iCount;
1.451 + if (time<m.iMin)
1.452 + m.iMin=time;
1.453 + if (time>m.iMax)
1.454 + m.iMax=time;
1.455 + m.iTotal+=time;
1.456 + }
1.457 + m.iLdd->TimerExpired(m.iId);
1.458 + }
1.459 +
1.460 +void TestThreadContext()
1.461 + {
1.462 + TInt c1 = NKern::CurrentContext();
1.463 + NKern::Lock();
1.464 + TInt c2 = NKern::CurrentContext();
1.465 + NKern::Unlock();
1.466 + __NK_ASSERT_ALWAYS((c1 == NKern::EThread) && (c2 == NKern::EThread));
1.467 + }
1.468 +
1.469 +void TMsTim::MsCallBack(TAny* aPtr)
1.470 + {
1.471 + TInt c = NKern::CurrentContext();
1.472 + TCounter timer_val=TIMER();
1.473 + TMsTim& m=*(TMsTim*)aPtr;
1.474 + TDelta time=TimeDelta(m.iStartTime, timer_val);
1.475 + if (++m.iCount>0 || (m.iMode!=EIntAgain && m.iMode!=EDfcAgain))
1.476 + {
1.477 + if (time<m.iMin)
1.478 + m.iMin=time;
1.479 + if (time>m.iMax)
1.480 + m.iMax=time;
1.481 + m.iTotal+=time;
1.482 + }
1.483 + switch (m.iMode)
1.484 + {
1.485 + case EIntAfter:
1.486 + __NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
1.487 + m.iIDfc.Add();
1.488 + break;
1.489 + case EDfcAfter:
1.490 + TestThreadContext();
1.491 + m.iCompletionDfc.Enque();
1.492 + break;
1.493 + case EIntAgain:
1.494 + __NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
1.495 + m.iStartTime=TIMER();
1.496 + m.Again(m.iInterval);
1.497 + break;
1.498 + case EDfcAgain:
1.499 + TestThreadContext();
1.500 + m.iStartTime=TIMER();
1.501 + m.Again(m.iInterval);
1.502 + break;
1.503 + case EIntCancel:
1.504 + __NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
1.505 + m.iLdd->iMsTim[m.iParam].Cancel();
1.506 + m.iIDfc.Add();
1.507 + break;
1.508 + case EDfcCancel:
1.509 + TestThreadContext();
1.510 + m.iLdd->iMsTim[m.iParam].Cancel();
1.511 + m.iCompletionDfc.Enque();
1.512 + break;
1.513 + case EUserDfcAfter:
1.514 + __NK_ASSERT_ALWAYS(EFalse);
1.515 + break;
1.516 + }
1.517 + }
1.518 +
1.519 +TInt TMsTim::Start(TInt aMode, TInt aInterval, TInt aParam)
1.520 + {
1.521 + TInt r=KErrGeneral;
1.522 + TInt c=0;
1.523 + TCounter holder=TIMER(); // holds the start value of timer
1.524 + switch (aMode)
1.525 + {
1.526 + case EIntAgain:
1.527 + c=-1;
1.528 + case EIntAfter:
1.529 + case EIntCancel:
1.530 + r=OneShot(aInterval);
1.531 + break;
1.532 + case EDfcAgain:
1.533 + c=-1;
1.534 + case EDfcAfter:
1.535 + case EDfcCancel:
1.536 + r=OneShot(aInterval,ETrue);
1.537 + break;
1.538 + case EIntAgainOnce:
1.539 + case EUserDfcAgainOnce:
1.540 +#ifdef __SMP__
1.541 + i8888.iHState2=FALSE;
1.542 +#else
1.543 + iCompleteInDfc=FALSE;
1.544 +#endif
1.545 + r=Again(aInterval);
1.546 + if (aMode==EUserDfcAgainOnce)
1.547 + aMode=EUserDfcAfter;
1.548 + else
1.549 + aMode=EIntAfter;
1.550 + break;
1.551 + case EUserDfcAfter:
1.552 + r=OneShot(aInterval, iCompletionDfc);
1.553 + break;
1.554 + }
1.555 + if (r!=KErrNone)
1.556 + return r;
1.557 + iStartTime=holder;
1.558 + iMode=TMode(aMode);
1.559 + iInterval=aInterval;
1.560 + iParam=aParam;
1.561 + iMin=KMaxDelta;
1.562 + iMax=KMinDelta;
1.563 + iTotal=0;
1.564 + iCount=c;
1.565 + return KErrNone;
1.566 + }
1.567 +
1.568 +void TMsTim::CompleteClient(TInt aValue)
1.569 + {
1.570 + Kern::QueueRequestComplete(iLdd->Client(),iRequest,aValue);
1.571 + }
1.572 +
1.573 +TMsTimRand::TMsTimRand()
1.574 + : NTimer(&MsCallBack,this)
1.575 + {
1.576 + memset(this,0,sizeof(TMsTimRand));
1.577 +#ifdef __SMP__
1.578 + NTimer* nt = STATIC_CAST(NTimer*,this);
1.579 + new (nt) NTimer(&MsCallBack,this);
1.580 +#else
1.581 + iFunction=MsCallBack; // avoid triggering assertion in NTimer::OneShot()
1.582 +#endif
1.583 + }
1.584 +
1.585 +#ifdef __SMP__
1.586 +TMsTimRand::~TMsTimRand()
1.587 + {
1.588 + NTimer* nt = STATIC_CAST(NTimer*,this);
1.589 + new (nt) NTimer(&MsCallBack, this); // so NTimer destructor doesn't kill us
1.590 + }
1.591 +#endif
1.592 +
1.593 +void TMsTimRand::FillWithGarbage(TUint aFill)
1.594 + {
1.595 +#ifdef __SMP__
1.596 + TUint32 f = aFill;
1.597 + f |= (f<<8);
1.598 + f |= (f<<16);
1.599 + iNext = (SDblQueLink*)f;
1.600 + iPrev = (SDblQueLink*)f;
1.601 + iDfcQ = (TDfcQue*)f;
1.602 + iPtr = (TAny*)f;
1.603 + iFn = (NEventFn)f;
1.604 + iTiedLink.iNext = (SDblQueLink*)f;
1.605 + iTiedLink.iPrev = (SDblQueLink*)f;
1.606 +#else
1.607 + memset(this, (TUint8)aFill, 16);
1.608 +#endif
1.609 + }
1.610 +
1.611 +TInt TMsTimRand::Start(TInt aInterval, DMsTim* aLdd, TInt aPos)
1.612 + {
1.613 + iLdd=aLdd;
1.614 +#ifdef __SMP__
1.615 + TUint fill=(aPos<<5)|(i8888.iHState1<<2)|3;
1.616 +#else
1.617 + TUint fill=(aPos<<5)|(iState<<2)|3;
1.618 + iPad1 = (TUint8)fill;
1.619 +#endif
1.620 + TInt r=OneShot(aInterval,ETrue);
1.621 + if (r==KErrNone)
1.622 + {
1.623 + iPtr=this;
1.624 + iInterval=aInterval;
1.625 + iStartTime=TIMER();
1.626 +#ifdef __SMP__
1.627 + iFn=MsCallBack;
1.628 + i8888.iHState0 = (TUint8)fill;
1.629 + if (i8888.iHState1!=EHolding)
1.630 + *(TUint*)0xfcd1fcd1=i8888.iHState1;
1.631 +#else
1.632 + iFunction=MsCallBack;
1.633 + iUserFlags = (TUint8)fill;
1.634 + if (iState!=EHolding)
1.635 + *(TUint*)0xfcd1fcd1=iState;
1.636 +#endif
1.637 + }
1.638 + return r;
1.639 + }
1.640 +
1.641 +void TMsTimRand::MsCallBack(TAny* aPtr)
1.642 + {
1.643 + TMsTimRand& m=*(TMsTimRand*)aPtr;
1.644 + TCounter time=TIMER();
1.645 + TDelta elapsed=TimeDelta(m.iStartTime,time);
1.646 + TInt error=TicksToMicroseconds(elapsed)-m.iInterval*1000;
1.647 + if (error<m.iLdd->iRandMin)
1.648 + m.iLdd->iRandMin=error;
1.649 + if (error>m.iLdd->iRandMax)
1.650 + m.iLdd->iRandMax=error;
1.651 + ++m.iLdd->iCompletions;
1.652 + m.FillWithGarbage(0xd9);
1.653 + }
1.654 +
1.655 +void NTimerQTest::Test(TAny* aPtr, TInt aPos)
1.656 + {
1.657 + DMsTim& ldd=*(DMsTim*)aPtr;
1.658 + ++ldd.iCallBacks;
1.659 + if (aPos==7)
1.660 + return;
1.661 + TUint action=Random(ldd.iSeed)&31;
1.662 + TMsTimRand& m=ldd.iMsTimR[action&7];
1.663 + if (action<8)
1.664 + {
1.665 +#ifdef __SMP__
1.666 + TUint fill=(aPos<<5)|(m.i8888.iHState1<<2)|3;
1.667 +#else
1.668 + TUint fill=(aPos<<5)|(m.iState<<2)|3;
1.669 +#endif
1.670 + m.Cancel();
1.671 + m.FillWithGarbage(fill);
1.672 + }
1.673 + else if (action<16)
1.674 + {
1.675 + TUint iv=(Random(ldd.iSeed)&31)+32;
1.676 + TInt r=m.Start(iv,&ldd,aPos);
1.677 + if (r!=KErrNone)
1.678 + ++ldd.iStartFail;
1.679 + }
1.680 + if (XferC())
1.681 + ++ldd.iXferC;
1.682 + if (CritC())
1.683 + ++ldd.iCritC;
1.684 + }
1.685 +
1.686 +DECLARE_STANDARD_LDD()
1.687 + {
1.688 + return new DMsTimFactory;
1.689 + }
1.690 +
1.691 +DMsTimFactory::DMsTimFactory()
1.692 +//
1.693 +// Constructor
1.694 +//
1.695 + {
1.696 + iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
1.697 + //iParseMask=0;//No units, no info, no PDD
1.698 + //iUnitsMask=0;//Only one thing
1.699 + }
1.700 +
1.701 +TInt DMsTimFactory::Create(DLogicalChannelBase*& aChannel)
1.702 +//
1.703 +// Create a new DMsTim on this logical device
1.704 +//
1.705 + {
1.706 + aChannel=new DMsTim;
1.707 + return aChannel?KErrNone:KErrNoMemory;
1.708 + }
1.709 +
1.710 +const TInt KDMsTimThreadPriority = 27;
1.711 +_LIT(KDMsTimThread,"DMsTimThread");
1.712 +
1.713 +TInt DMsTimFactory::Install()
1.714 +//
1.715 +// Install the LDD - overriding pure virtual
1.716 +//
1.717 + {
1.718 + // Allocate a kernel thread to run the DFC
1.719 + TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMsTimThreadPriority, KDMsTimThread);
1.720 +
1.721 +#ifdef CPU_AFFINITY_ANY
1.722 + NKern::ThreadSetCpuAffinity((NThread*)(gDfcQ->iThread), KCpuAffinityAny);
1.723 +#endif
1.724 +
1.725 + if (r != KErrNone)
1.726 + return r;
1.727 +
1.728 + return SetName(&KMsTimerLddName);
1.729 + }
1.730 +
1.731 +void DMsTimFactory::GetCaps(TDes8& aDes) const
1.732 +//
1.733 +// Get capabilities - overriding pure virtual
1.734 +//
1.735 + {
1.736 + TCapsMsTimV01 b;
1.737 + b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
1.738 + Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
1.739 + }
1.740 +
1.741 +/**
1.742 + Destructor
1.743 +*/
1.744 +DMsTimFactory::~DMsTimFactory()
1.745 + {
1.746 + if (gDfcQ)
1.747 + gDfcQ->Destroy();
1.748 + }
1.749 +
1.750 +DMsTim::DMsTim()
1.751 +//
1.752 +// Constructor
1.753 +//
1.754 + {
1.755 + iThread=&Kern::CurrentThread();
1.756 + iThread->Open();
1.757 + TInt i;
1.758 + for (i=0; i<KMaxMsTim; i++)
1.759 + {
1.760 + iMsTim[i].iLdd=this;
1.761 + iMsTim[i].iId=i;
1.762 + }
1.763 + for (i=0; i<KMaxMsTimR; i++)
1.764 + {
1.765 + iMsTimR[i].iLdd=this;
1.766 + }
1.767 + iSeed[0]=NTimerQTest::MsCount();
1.768 + iSeed[1]=0;
1.769 + }
1.770 +
1.771 +TInt DMsTim::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
1.772 +//
1.773 +// Create channel
1.774 +//
1.775 + {
1.776 + if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
1.777 + return KErrNotSupported;
1.778 + InitTimer();
1.779 + SetDfcQ(gDfcQ);
1.780 + for (TInt i = 0 ; i < KMaxMsTim ; ++i)
1.781 + {
1.782 + TInt r = iMsTim[i].Create();
1.783 + if (r != KErrNone)
1.784 + return r;
1.785 + }
1.786 + iMsgQ.Receive();
1.787 +#ifdef __SMP__
1.788 + NKern::ThreadSetCpuAffinity(NKern::CurrentThread(), NKern::NumberOfCpus() - 1); // Try and avoid the cpu the test app is running on
1.789 +#endif
1.790 + return KErrNone;
1.791 + }
1.792 +
1.793 +DMsTim::~DMsTim()
1.794 +//
1.795 +// Destructor
1.796 +//
1.797 + {
1.798 +#if defined(__MI920__) || defined(__NI1136__)
1.799 +#if !defined(USE_CM920_FRC)
1.800 + TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EDisable);
1.801 +#endif
1.802 +#endif
1.803 +#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
1.804 + TOmapTimer::SetTimer3Ctrl( 0 ); // disable the timer
1.805 +#endif
1.806 + Kern::SafeClose((DObject*&)iThread, NULL);
1.807 + }
1.808 +
1.809 +void DMsTim::HandleMsg(TMessageBase* aMsg)
1.810 + {
1.811 + TInt r=KErrNone;
1.812 + TThreadMessage& m=*(TThreadMessage*)aMsg;
1.813 + TInt id=m.iValue;
1.814 + if (id==(TInt)ECloseMsg)
1.815 + {
1.816 + NTimerQTest::Stop();
1.817 + TInt i;
1.818 + for (i=0; i<KMaxMsTim; i++)
1.819 + {
1.820 + iMsTim[i].Cancel();
1.821 + iMsTim[i].iCompletionDfc.Cancel();
1.822 + iMsTim[i].CompleteClient(KErrCancel);
1.823 + }
1.824 + for (i=0; i<KMaxMsTimR; i++)
1.825 + {
1.826 + iMsTimR[i].Cancel();
1.827 + iMsTimR[i].FillWithGarbage(0x01);
1.828 + }
1.829 + m.Complete(KErrNone,EFalse);
1.830 + iMsgQ.CompleteAll(KErrServerTerminated);
1.831 + return;
1.832 + }
1.833 + else if (id<0)
1.834 + {
1.835 + TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
1.836 + r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
1.837 + }
1.838 + else
1.839 + {
1.840 + r=DoControl(id,m.Ptr0(),m.Ptr1());
1.841 + }
1.842 + m.Complete(r,ETrue);
1.843 + }
1.844 +
1.845 +TInt DMsTim::DoControl(TInt aFunction, TAny* a1, TAny* a2)
1.846 + {
1.847 + TInt r=KErrNone;
1.848 + TInt id=(TInt)a1;
1.849 + TMsTim& m=iMsTim[id];
1.850 + TInt interval=(TInt)a2;
1.851 + switch (aFunction)
1.852 + {
1.853 + case RMsTim::EControlStartPeriodicInt:
1.854 + r=m.Start(TMsTim::EIntAgain,interval,0);
1.855 + break;
1.856 + case RMsTim::EControlStartPeriodicDfc:
1.857 + r=m.Start(TMsTim::EDfcAgain,interval,0);
1.858 + break;
1.859 + case RMsTim::EControlStopPeriodic:
1.860 + m.Cancel();
1.861 + m.iCompletionDfc.Cancel();
1.862 + break;
1.863 + case RMsTim::EControlGetInfo:
1.864 + {
1.865 + SMsTimerInfo info;
1.866 + info.iCount=m.iCount;
1.867 + Int64 avg=m.iTotal/m.iCount;
1.868 + info.iAvg=TicksToMicroseconds((TInt)avg);
1.869 +#ifdef __SMP__
1.870 + info.iMin=info.iAvg;
1.871 + info.iMax=info.iAvg;
1.872 +#else
1.873 + info.iMin=TicksToMicroseconds(m.iMin);
1.874 + info.iMax=TicksToMicroseconds(m.iMax);
1.875 +#endif
1.876 +
1.877 + r=Kern::ThreadRawWrite(iThread,a2,&info,sizeof(info));
1.878 + break;
1.879 + }
1.880 + case RMsTim::EControlBeginRandomTest:
1.881 + {
1.882 + iRandMin=KMaxTInt;
1.883 + iRandMax=KMinTInt;
1.884 + iXferC=0;
1.885 + iCritC=0;
1.886 + iStartFail=0;
1.887 + iCallBacks=0;
1.888 + iCompletions=0;
1.889 + NTimerQTest::Setup(this);
1.890 + break;
1.891 + }
1.892 + case RMsTim::EControlEndRandomTest:
1.893 + {
1.894 + NTimerQTest::Stop();
1.895 + TInt i;
1.896 + for (i=0; i<KMaxMsTimR; i++)
1.897 + {
1.898 + iMsTimR[i].Cancel();
1.899 + iMsTimR[i].FillWithGarbage(0x35);
1.900 + }
1.901 + break;
1.902 + }
1.903 + case RMsTim::EControlGetRandomTestInfo:
1.904 + {
1.905 + SRandomTestInfo info;
1.906 + info.iMin=iRandMin;
1.907 + info.iMax=iRandMax;
1.908 + info.iXferC=iXferC;
1.909 + info.iCritC=iCritC;
1.910 + info.iStartFail=iStartFail;
1.911 + info.iCallBacks=iCallBacks;
1.912 + info.iCompletions=iCompletions;
1.913 + r=Kern::ThreadRawWrite(iThread,a1,&info,sizeof(info));
1.914 + break;
1.915 + }
1.916 + case RMsTim::EControlGetIdleTime:
1.917 + {
1.918 + TInt irq=NKern::DisableAllInterrupts();
1.919 + r=NTimerQ::IdleTime();
1.920 + NKern::RestoreInterrupts(irq);
1.921 + break;
1.922 + }
1.923 + default:
1.924 + r=KErrNotSupported;
1.925 + break;
1.926 + }
1.927 + return r;
1.928 + }
1.929 +
1.930 +TInt DMsTim::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
1.931 + {
1.932 + TInt id=(TInt)a1;
1.933 + TMsTim& m=iMsTim[aFunction == RMsTim::ERequestIntCancel ? 7 : id];
1.934 + TInt interval=(TInt)a2;
1.935 + TInt r=KErrNone;
1.936 + switch (aFunction)
1.937 + {
1.938 + case RMsTim::ERequestOneShotInt:
1.939 + r=m.Start(TMsTim::EIntAfter,interval,0);
1.940 + break;
1.941 + case RMsTim::ERequestOneShotDfc:
1.942 + r=m.Start(TMsTim::EDfcAfter,interval,0);
1.943 + break;
1.944 + case RMsTim::ERequestIntCancel:
1.945 + r=m.Start(TMsTim::EIntCancel,interval,id);
1.946 + break;
1.947 + case RMsTim::ERequestOneShotIntAgain:
1.948 + r=m.Start(TMsTim::EIntAgainOnce,interval,0);
1.949 + break;
1.950 + case RMsTim::ERequestOneShotUserDfc:
1.951 + r=m.Start(TMsTim::EUserDfcAfter,interval,0);
1.952 + break;
1.953 + case RMsTim::ERequestOneShotUserDfcAgain:
1.954 + r=m.Start(TMsTim::EUserDfcAgainOnce,interval,0);
1.955 + break;
1.956 + default:
1.957 + r=KErrNotSupported;
1.958 + break;
1.959 + }
1.960 + m.iRequest->SetStatus(aStatus);
1.961 + if (r!=KErrNone)
1.962 + Kern::QueueRequestComplete(iThread,m.iRequest,r);
1.963 + return r;
1.964 + }
1.965 +
1.966 +void DMsTim::TimerExpired(TInt anId)
1.967 + {
1.968 + TMsTim& m=iMsTim[anId];
1.969 + switch (m.iMode)
1.970 + {
1.971 + case TMsTim::EIntAfter:
1.972 + case TMsTim::EDfcAfter:
1.973 + case TMsTim::EUserDfcAfter:
1.974 + m.CompleteClient(KErrNone);
1.975 + break;
1.976 + case TMsTim::EIntAgain:
1.977 + case TMsTim::EDfcAgain:
1.978 + break;
1.979 + case TMsTim::EIntCancel:
1.980 + case TMsTim::EDfcCancel:
1.981 + {
1.982 + TMsTim& cancelled=iMsTim[m.iParam];
1.983 + cancelled.CompleteClient(KErrAbort);
1.984 + m.CompleteClient(KErrNone);
1.985 + break;
1.986 + }
1.987 + }
1.988 + }
1.989 +