--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/system/d_mstim.cpp Thu Dec 17 09:24:54 2009 +0200
@@ -0,0 +1,981 @@
+// Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the License "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// e32test\system\d_mstim.cpp
+// LDD for testing millisecond timer
+//
+//
+
+#include "plat_priv.h"
+#if defined(__MEIG__)
+#include <cl7211.h>
+#elif defined(__MAWD__)
+#include <windermere.h>
+#elif defined(__MISA__)
+#include <sa1100.h>
+#elif defined(__MCOT__)
+#include <cotulla.h>
+#elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+#include <omap.h>
+#include <omap_timer.h>
+#elif defined(__MI920__) || defined(__NI1136__)
+#ifdef __MI920__
+#define USE_CM920_FRC
+#endif
+#ifdef USE_CM920_FRC
+#include <iolines.h>
+#else
+#include <integratorap.h>
+#endif
+#elif defined(__RVEMUBOARD__)
+#include <rvemuboard.h>
+#elif defined(__NE1_TB__)
+#include <upd35001_timer.h>
+#endif
+#include "d_mstim.h"
+#include "../misc/prbs.h"
+
+#if defined(__WINS__)
+typedef Int64 TCounter;
+typedef Int64 TDelta;
+const TDelta KMaxDelta = 0x7fffffffffffffff;
+const TDelta KMinDelta = 0x8000000000000000;
+#else
+typedef TUint TCounter;
+typedef TInt TDelta;
+const TDelta KMaxDelta = KMaxTInt;
+const TDelta KMinDelta = KMinTInt;
+#endif
+
+#ifdef __MISA__
+inline TCounter TIMER()
+ { return *(volatile TUint*)KHwRwOstOscr; }
+#endif
+#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+inline TCounter TIMER()
+ { return TOmapTimer::Timer3Value(); }
+#endif
+#ifdef __MCOT__
+inline TCounter TIMER()
+ { return *(volatile TUint*)KHwRwOstOscr; }
+#endif
+#ifdef __MAWD__
+inline TCounter TIMER()
+ { return *(volatile TUint*)(KWindBaseAddress+KWindTimer1Value16)&0xffff; }
+#endif
+#ifdef __MEIG__
+inline TCounter TIMER()
+{ return *(volatile TUint*)(KEigerBaseAddress+KEigerTimer1Data16)&0xffff;}
+#endif
+#if defined(__MI920__) || defined(__NI1136__)
+inline TCounter TIMER()
+#ifdef USE_CM920_FRC
+ { return *(volatile TUint*)(KHwRwCoreClkCounter);} // 32-bit Core module counter inc's at 24MHz
+#else
+ { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
+#endif
+#endif
+#if defined(__RVEMUBOARD__)
+inline TCounter TIMER()
+ { return *(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff;}
+#endif
+#ifdef __NE1_TB__
+inline TCounter TIMER()
+ { return NETimer::Timer(2).iTimerCount; }
+#endif
+#if defined(__EPOC32__) && defined(__CPU_X86)
+TCounter TIMER();
+void SetUpTimerChannel2();
+#endif
+
+#ifdef __WINS__
+inline TCounter TIMER()
+ {
+ LARGE_INTEGER c;
+ QueryPerformanceCounter(&c);
+ return c.QuadPart;
+ }
+#endif
+
+#if defined(__MISA__) || (defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__)))
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return final-initial; } // SA1100 timer counts up
+#endif
+#if defined(__MCOT__)
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return final-initial; } // Cotulla timer counts up
+#endif
+#if defined(__MAWD__) || defined(__MEIG__) || (!defined(USE_CM920_FRC) && (defined(__MI920__) || defined(__NI1136__)))
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return (initial-final)&0xffff; } // Eiger/Windermere/Integrator timer counts down
+#endif
+#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return (initial-final);} // OMAP timer counts down
+#endif
+#if defined(__EPOC32__) && defined(__CPU_X86)
+TDelta TimeDelta(TUint initial, TUint final)
+ {
+ TUint tickdiff=(initial-final)&0xffff;
+ TUint msdiff=((final>>16)-(initial>>16))&0xffff;
+ msdiff=1193*msdiff-tickdiff;
+ msdiff=(msdiff+32768)&~0xffff;
+ return msdiff+tickdiff;
+ }
+#endif
+#ifdef __NE1_TB__
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return final - initial; }
+#endif
+#ifdef __WINS__
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return final-initial; } // counts up
+#endif
+#if defined(__RVEMUBOARD__)
+inline TDelta TimeDelta(TCounter initial, TCounter final)
+ { return (initial-final)&0xffff; } // Timer counts down
+#endif
+
+const TInt KMajorVersionNumber=0;
+const TInt KMinorVersionNumber=1;
+const TInt KBuildVersionNumber=1;
+
+const TInt KMaxMsTim=9;
+const TInt KMaxMsTimR=9;
+
+TInt TicksToMicroseconds(TDelta aTicks)
+ {
+#if defined(__MISA__) || defined(__MCOT__)
+ Int64 ticks(aTicks);
+ ticks*=(1000000);
+ ticks+=KHwOscFreqHz/2; // 3.6864MHz tick
+ ticks/=KHwOscFreqHz;
+ return (TInt)ticks;
+#endif
+#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+ // Timer runs at 12Mhz/32 = 375kHz. Each tick is 2.66...us which is 16/6us
+ aTicks<<=4; // * 16
+ aTicks+=3; // rounding to the closest number of us
+ return (TInt)(aTicks/6); // us = (ticks*16+3)/6
+#endif
+#if defined(__MI920__) || defined(__NI1136__)
+#if defined(USE_CM920_FRC)
+ Int64 ticks(aTicks);
+ ticks*=(1000000);
+ ticks+=24000000/2;
+ ticks/=24000000;
+ return (TInt)ticks;
+#else
+ aTicks<<=14; // 1 tick = 32/3 us
+ aTicks+=768; // round
+ return (TInt)(aTicks/1536);
+#endif
+#endif
+#if defined(__RVEMUBOARD__)
+ return (TInt)(aTicks*256); // 1 tick = 256 us
+#endif
+#if defined(__MAWD__) || defined(__MEIG__)
+ return aTicks*500; // 2kHz tick
+#endif
+#if defined(__NE1_TB__)
+ NETimer& T2 = NETimer::Timer(2);
+ TUint prescale = __e32_find_ms1_32(T2.iPrescaler & 0x3f);
+ TInt f = 66666667 >> prescale;
+ TInt64 x = I64LIT(1000000);
+ x *= TInt64(aTicks);
+ x += TInt64(f>>1);
+ x /= TInt64(f);
+ return (TInt)x;
+#endif
+#if defined(__EPOC32__) && defined(__CPU_X86)
+ TInt x = aTicks;
+ TInt y = x;
+ y -= ((3*x)>>4); // * 0.D
+ y += (aTicks>>12); // * 0.D00D
+ TInt z = (6*x)>>8; // * 0.06
+ y += z; // * 0.D60D
+ y += (x>>9); // * 0.D68D
+ y += (z>>16); // * 0.D68D6
+ y += (z>>20); // * 0.D68D66
+ return y;
+#endif
+#ifdef __WINS__
+ LARGE_INTEGER f;
+ QueryPerformanceFrequency(&f);
+ aTicks*=1000000;
+ aTicks+=f.QuadPart-1;
+ aTicks/=f.QuadPart;
+ return (TInt)aTicks;
+#endif
+ }
+
+
+void InitTimer()
+ {
+#ifdef __MAWD__
+ // Set up timer 1 as free running 2kHz clock
+ TWind::SetBuzzerControl(0); // disable buzzer
+ TWind::SetTimer1Control(KWindTimer1ControlTimerEnable);
+ TWind::SetTimer1Load(0);
+#endif
+#ifdef __MEIG__
+ // Set up timer 1 as free running 2kHz clock
+ TEiger::ModifyControl21(KEigerControlTimer1PreOrFree|KEigerControlTimer1K512OrK2|
+ KEigerControlBuzzerToggle|KEigerControlBuzzerTimer1OrToggle,0);
+ TEiger::SetTimer1Data(0);
+#endif
+#if defined(__MISA__)
+ // MISA free running counter is always active - no initialisation required
+#endif
+#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+ // Set up Timer3 as a free-running timer at 12Mhz/32 = 375kHz
+ TOmapTimer::SetTimer3Ctrl( TOmapTimer::KHtOSTimer_Cntl_Ar
+ | TOmapTimer::KHtOSTimer_Cntl_Free
+ | TOmapTimer::KHtOSTimer_Cntl_ClkEnable );
+ TOmapTimer::SetTimer3Prescale( TOmapTimer::EPrescaleBy32 );
+ // Autoreload 0xFFFFFFFF to effectively wrap from zero back to 0xFFFFFFFF
+ TOmapTimer::SetTimer3LoadTim( 0xFFFFFFFF );
+ TOmapTimer::StartTimer3();
+#endif
+#if defined(__MI920__) || defined(__NI1136__)
+#if !defined(USE_CM920_FRC)
+ TIntegratorAP::SetTimerMode(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerModeFreeRunning);
+ TIntegratorAP::SetTimerPreScale(TIntegratorAP::ECounterTimer1, TIntegratorAP::ETimerPreScaleDiv256); // 93.75kHz wrap 699ms
+ TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EEnable);
+#endif
+#endif
+#if defined(__RVEMUBOARD__)
+ // Switch timer 1 to a 1MHz clock in the system controller Ctrl register
+ TRvEmuBoard::SetSCCtrl(KTimer1EnSel);
+
+ // Set up timer 1 as free running 3.90625kHz clock
+ TRvEmuBoard::SetTimerMode(KHwCounterTimer1, TRvEmuBoard::ETimerModeFreeRunning);
+ TRvEmuBoard::SetTimerPreScale(KHwCounterTimer1, TRvEmuBoard::ETimerPreScaleDiv256);// 3.90625kHz wrap 16.777s
+ TRvEmuBoard::EnableTimer(KHwCounterTimer1, TRvEmuBoard::EEnable);
+#endif
+#if defined(__NE1_TB__)
+ // nothing to do since variant has already set up timer
+#endif
+#if defined(__EPOC32__) && defined(__CPU_X86)
+ // Set up timer channel 2 as free running counter at 14318180/12 Hz
+ SetUpTimerChannel2();
+#endif
+ }
+
+// global Dfc Que
+TDynamicDfcQue* gDfcQ;
+
+class NTimerQTest
+ {
+public:
+ static inline NTimerQ& Timer()
+ { return *(NTimerQ*)NTimerQ::TimerAddress(); }
+ static inline TUint32 MsCount()
+ { return Timer().iMsCount; }
+ static inline void Setup(TAny* aPtr)
+ { NTimerQ& m=Timer(); m.iDebugFn=Test; m.iDebugPtr=aPtr; }
+ static inline void Stop()
+ { NTimerQ& m=Timer(); m.iDebugFn=NULL; m.iDebugPtr=NULL; }
+ static inline TBool XferC()
+ { return Timer().iTransferringCancelled; }
+ static inline TBool CritC()
+ { return Timer().iCriticalCancelled; }
+ static void Test(TAny* aPtr, TInt aPos);
+ };
+
+class DMsTim;
+
+class TMsTim : public NTimer
+ {
+public:
+ enum TMode
+ {
+ EIntAfter,
+ EDfcAfter,
+ EIntAgain,
+ EDfcAgain,
+ EIntCancel,
+ EDfcCancel,
+ EUserDfcAfter
+ };
+
+ enum TModeX
+ {
+ EIntAgainOnce=7,
+ EUserDfcAgainOnce
+ };
+public:
+ TMsTim();
+ ~TMsTim();
+ TInt Create();
+ TInt Start(TInt aMode, TInt aInterval, TInt aParam);
+ static void MsCallBack(TAny* aPtr);
+ static void IDfcFn(TAny* aPtr);
+ static void DfcFn(TAny* aPtr);
+ void CompleteClient(TInt aValue);
+public:
+ TMode iMode;
+ TInt iInterval;
+ TInt iParam;
+ TCounter iStartTime;
+ TDelta iMin;
+ TDelta iMax;
+ Int64 iTotal;
+ TInt iCount;
+ DMsTim* iLdd;
+ TInt iId;
+ TClientRequest* iRequest;
+ TDfc iIDfc;
+ TDfc iCompletionDfc;
+ };
+
+class TMsTimRand : public NTimer
+ {
+public:
+ TMsTimRand();
+#ifdef __SMP__
+ ~TMsTimRand();
+#endif
+ TInt Start(TInt aInterval, DMsTim* aLdd, TInt aPos);
+ static void MsCallBack(TAny* aPtr);
+ void FillWithGarbage(TUint aFillValue);
+public:
+ TInt iInterval;
+ TCounter iStartTime;
+ DMsTim* iLdd;
+ };
+
+class DMsTimFactory : public DLogicalDevice
+//
+// Millisecond timer LDD factory
+//
+ {
+public:
+ DMsTimFactory();
+ ~DMsTimFactory();
+ virtual TInt Install(); //overriding pure virtual
+ virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual
+ virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual
+ };
+
+class DMsTim : public DLogicalChannel
+//
+// Millisecond timer LDD channel
+//
+ {
+public:
+ DMsTim();
+ ~DMsTim();
+protected:
+ virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer);
+ TInt DoControl(TInt aFunction, TAny* a1, TAny* a2);
+ TInt DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2);
+ virtual void HandleMsg(TMessageBase* aMsg);
+public:
+ void TimerExpired(TInt anId);
+ inline DThread* Client() { return iThread; }
+public:
+ DThread* iThread;
+ TMsTim iMsTim[KMaxMsTim];
+ TMsTimRand iMsTimR[KMaxMsTimR];
+ TInt iRandMin;
+ TInt iRandMax;
+ TInt iXferC;
+ TInt iCritC;
+ TInt iStartFail;
+ TInt iCallBacks;
+ TInt iCompletions;
+ TUint iSeed[2];
+ };
+
+TMsTim::TMsTim()
+ : NTimer(MsCallBack,this),
+ iMode(EIntAfter),
+ iInterval(0),
+ iParam(0),
+ iStartTime(0),
+ iMin(KMaxDelta),
+ iMax(KMinDelta),
+ iTotal(0),
+ iCount(0),
+ iRequest(NULL),
+ iIDfc(IDfcFn,this),
+ iCompletionDfc(DfcFn,this,gDfcQ,1)
+ {
+ }
+
+TMsTim::~TMsTim()
+ {
+ Kern::DestroyClientRequest(iRequest);
+#ifdef __SMP__
+ NTimer* nt = STATIC_CAST(NTimer*,this);
+ new (nt) NTimer(&MsCallBack, this); // so NTimer destructor doesn't kill us
+#endif
+ }
+
+TInt TMsTim::Create()
+ {
+ return Kern::CreateClientRequest(iRequest);
+ }
+
+void TMsTim::IDfcFn(TAny* aPtr)
+ {
+ TMsTim& m=*(TMsTim*)aPtr;
+ TInt c = NKern::CurrentContext();
+ __NK_ASSERT_ALWAYS(c == NKern::EIDFC);
+ __NK_ASSERT_ALWAYS(NKern::KernelLocked(1));
+ m.iCompletionDfc.DoEnque();
+ }
+
+void TMsTim::DfcFn(TAny* aPtr)
+ {
+ TMsTim& m=*(TMsTim*)aPtr;
+ if (m.iMode==EUserDfcAfter)
+ {
+ TCounter timer_val=TIMER();
+ TDelta time=TimeDelta(m.iStartTime, timer_val);
+ ++m.iCount;
+ if (time<m.iMin)
+ m.iMin=time;
+ if (time>m.iMax)
+ m.iMax=time;
+ m.iTotal+=time;
+ }
+ m.iLdd->TimerExpired(m.iId);
+ }
+
+void TestThreadContext()
+ {
+ TInt c1 = NKern::CurrentContext();
+ NKern::Lock();
+ TInt c2 = NKern::CurrentContext();
+ NKern::Unlock();
+ __NK_ASSERT_ALWAYS((c1 == NKern::EThread) && (c2 == NKern::EThread));
+ }
+
+void TMsTim::MsCallBack(TAny* aPtr)
+ {
+ TInt c = NKern::CurrentContext();
+ TCounter timer_val=TIMER();
+ TMsTim& m=*(TMsTim*)aPtr;
+ TDelta time=TimeDelta(m.iStartTime, timer_val);
+ if (++m.iCount>0 || (m.iMode!=EIntAgain && m.iMode!=EDfcAgain))
+ {
+ if (time<m.iMin)
+ m.iMin=time;
+ if (time>m.iMax)
+ m.iMax=time;
+ m.iTotal+=time;
+ }
+ switch (m.iMode)
+ {
+ case EIntAfter:
+ __NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
+ m.iIDfc.Add();
+ break;
+ case EDfcAfter:
+ TestThreadContext();
+ m.iCompletionDfc.Enque();
+ break;
+ case EIntAgain:
+ __NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
+ m.iStartTime=TIMER();
+ m.Again(m.iInterval);
+ break;
+ case EDfcAgain:
+ TestThreadContext();
+ m.iStartTime=TIMER();
+ m.Again(m.iInterval);
+ break;
+ case EIntCancel:
+ __NK_ASSERT_ALWAYS(c == NKern::EInterrupt);
+ m.iLdd->iMsTim[m.iParam].Cancel();
+ m.iIDfc.Add();
+ break;
+ case EDfcCancel:
+ TestThreadContext();
+ m.iLdd->iMsTim[m.iParam].Cancel();
+ m.iCompletionDfc.Enque();
+ break;
+ case EUserDfcAfter:
+ __NK_ASSERT_ALWAYS(EFalse);
+ break;
+ }
+ }
+
+TInt TMsTim::Start(TInt aMode, TInt aInterval, TInt aParam)
+ {
+ TInt r=KErrGeneral;
+ TInt c=0;
+ TCounter holder=TIMER(); // holds the start value of timer
+ switch (aMode)
+ {
+ case EIntAgain:
+ c=-1;
+ case EIntAfter:
+ case EIntCancel:
+ r=OneShot(aInterval);
+ break;
+ case EDfcAgain:
+ c=-1;
+ case EDfcAfter:
+ case EDfcCancel:
+ r=OneShot(aInterval,ETrue);
+ break;
+ case EIntAgainOnce:
+ case EUserDfcAgainOnce:
+#ifdef __SMP__
+ i8888.iHState2=FALSE;
+#else
+ iCompleteInDfc=FALSE;
+#endif
+ r=Again(aInterval);
+ if (aMode==EUserDfcAgainOnce)
+ aMode=EUserDfcAfter;
+ else
+ aMode=EIntAfter;
+ break;
+ case EUserDfcAfter:
+ r=OneShot(aInterval, iCompletionDfc);
+ break;
+ }
+ if (r!=KErrNone)
+ return r;
+ iStartTime=holder;
+ iMode=TMode(aMode);
+ iInterval=aInterval;
+ iParam=aParam;
+ iMin=KMaxDelta;
+ iMax=KMinDelta;
+ iTotal=0;
+ iCount=c;
+ return KErrNone;
+ }
+
+void TMsTim::CompleteClient(TInt aValue)
+ {
+ Kern::QueueRequestComplete(iLdd->Client(),iRequest,aValue);
+ }
+
+TMsTimRand::TMsTimRand()
+ : NTimer(&MsCallBack,this)
+ {
+ memset(this,0,sizeof(TMsTimRand));
+#ifdef __SMP__
+ NTimer* nt = STATIC_CAST(NTimer*,this);
+ new (nt) NTimer(&MsCallBack,this);
+#else
+ iFunction=MsCallBack; // avoid triggering assertion in NTimer::OneShot()
+#endif
+ }
+
+#ifdef __SMP__
+TMsTimRand::~TMsTimRand()
+ {
+ NTimer* nt = STATIC_CAST(NTimer*,this);
+ new (nt) NTimer(&MsCallBack, this); // so NTimer destructor doesn't kill us
+ }
+#endif
+
+void TMsTimRand::FillWithGarbage(TUint aFill)
+ {
+#ifdef __SMP__
+ TUint32 f = aFill;
+ f |= (f<<8);
+ f |= (f<<16);
+ iNext = (SDblQueLink*)f;
+ iPrev = (SDblQueLink*)f;
+ iDfcQ = (TDfcQue*)f;
+ iPtr = (TAny*)f;
+ iFn = (NEventFn)f;
+ iTiedLink.iNext = (SDblQueLink*)f;
+ iTiedLink.iPrev = (SDblQueLink*)f;
+#else
+ memset(this, (TUint8)aFill, 16);
+#endif
+ }
+
+TInt TMsTimRand::Start(TInt aInterval, DMsTim* aLdd, TInt aPos)
+ {
+ iLdd=aLdd;
+#ifdef __SMP__
+ TUint fill=(aPos<<5)|(i8888.iHState1<<2)|3;
+#else
+ TUint fill=(aPos<<5)|(iState<<2)|3;
+ iPad1 = (TUint8)fill;
+#endif
+ TInt r=OneShot(aInterval,ETrue);
+ if (r==KErrNone)
+ {
+ iPtr=this;
+ iInterval=aInterval;
+ iStartTime=TIMER();
+#ifdef __SMP__
+ iFn=MsCallBack;
+ i8888.iHState0 = (TUint8)fill;
+ if (i8888.iHState1!=EHolding)
+ *(TUint*)0xfcd1fcd1=i8888.iHState1;
+#else
+ iFunction=MsCallBack;
+ iUserFlags = (TUint8)fill;
+ if (iState!=EHolding)
+ *(TUint*)0xfcd1fcd1=iState;
+#endif
+ }
+ return r;
+ }
+
+void TMsTimRand::MsCallBack(TAny* aPtr)
+ {
+ TMsTimRand& m=*(TMsTimRand*)aPtr;
+ TCounter time=TIMER();
+ TDelta elapsed=TimeDelta(m.iStartTime,time);
+ TInt error=TicksToMicroseconds(elapsed)-m.iInterval*1000;
+ if (error<m.iLdd->iRandMin)
+ m.iLdd->iRandMin=error;
+ if (error>m.iLdd->iRandMax)
+ m.iLdd->iRandMax=error;
+ ++m.iLdd->iCompletions;
+ m.FillWithGarbage(0xd9);
+ }
+
+void NTimerQTest::Test(TAny* aPtr, TInt aPos)
+ {
+ DMsTim& ldd=*(DMsTim*)aPtr;
+ ++ldd.iCallBacks;
+ if (aPos==7)
+ return;
+ TUint action=Random(ldd.iSeed)&31;
+ TMsTimRand& m=ldd.iMsTimR[action&7];
+ if (action<8)
+ {
+#ifdef __SMP__
+ TUint fill=(aPos<<5)|(m.i8888.iHState1<<2)|3;
+#else
+ TUint fill=(aPos<<5)|(m.iState<<2)|3;
+#endif
+ m.Cancel();
+ m.FillWithGarbage(fill);
+ }
+ else if (action<16)
+ {
+ TUint iv=(Random(ldd.iSeed)&31)+32;
+ TInt r=m.Start(iv,&ldd,aPos);
+ if (r!=KErrNone)
+ ++ldd.iStartFail;
+ }
+ if (XferC())
+ ++ldd.iXferC;
+ if (CritC())
+ ++ldd.iCritC;
+ }
+
+DECLARE_STANDARD_LDD()
+ {
+ return new DMsTimFactory;
+ }
+
+DMsTimFactory::DMsTimFactory()
+//
+// Constructor
+//
+ {
+ iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
+ //iParseMask=0;//No units, no info, no PDD
+ //iUnitsMask=0;//Only one thing
+ }
+
+TInt DMsTimFactory::Create(DLogicalChannelBase*& aChannel)
+//
+// Create a new DMsTim on this logical device
+//
+ {
+ aChannel=new DMsTim;
+ return aChannel?KErrNone:KErrNoMemory;
+ }
+
+const TInt KDMsTimThreadPriority = 27;
+_LIT(KDMsTimThread,"DMsTimThread");
+
+TInt DMsTimFactory::Install()
+//
+// Install the LDD - overriding pure virtual
+//
+ {
+ // Allocate a kernel thread to run the DFC
+ TInt r = Kern::DynamicDfcQCreate(gDfcQ, KDMsTimThreadPriority, KDMsTimThread);
+
+#ifdef CPU_AFFINITY_ANY
+ NKern::ThreadSetCpuAffinity((NThread*)(gDfcQ->iThread), KCpuAffinityAny);
+#endif
+
+ if (r != KErrNone)
+ return r;
+
+ return SetName(&KMsTimerLddName);
+ }
+
+void DMsTimFactory::GetCaps(TDes8& aDes) const
+//
+// Get capabilities - overriding pure virtual
+//
+ {
+ TCapsMsTimV01 b;
+ b.iVersion=TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber);
+ Kern::InfoCopy(aDes,(TUint8*)&b,sizeof(b));
+ }
+
+/**
+ Destructor
+*/
+DMsTimFactory::~DMsTimFactory()
+ {
+ if (gDfcQ)
+ gDfcQ->Destroy();
+ }
+
+DMsTim::DMsTim()
+//
+// Constructor
+//
+ {
+ iThread=&Kern::CurrentThread();
+ iThread->Open();
+ TInt i;
+ for (i=0; i<KMaxMsTim; i++)
+ {
+ iMsTim[i].iLdd=this;
+ iMsTim[i].iId=i;
+ }
+ for (i=0; i<KMaxMsTimR; i++)
+ {
+ iMsTimR[i].iLdd=this;
+ }
+ iSeed[0]=NTimerQTest::MsCount();
+ iSeed[1]=0;
+ }
+
+TInt DMsTim::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
+//
+// Create channel
+//
+ {
+ if (!Kern::QueryVersionSupported(TVersion(KMajorVersionNumber,KMinorVersionNumber,KBuildVersionNumber),aVer))
+ return KErrNotSupported;
+ InitTimer();
+ SetDfcQ(gDfcQ);
+ for (TInt i = 0 ; i < KMaxMsTim ; ++i)
+ {
+ TInt r = iMsTim[i].Create();
+ if (r != KErrNone)
+ return r;
+ }
+ iMsgQ.Receive();
+#ifdef __SMP__
+ NKern::ThreadSetCpuAffinity(NKern::CurrentThread(), NKern::NumberOfCpus() - 1); // Try and avoid the cpu the test app is running on
+#endif
+ return KErrNone;
+ }
+
+DMsTim::~DMsTim()
+//
+// Destructor
+//
+ {
+#if defined(__MI920__) || defined(__NI1136__)
+#if !defined(USE_CM920_FRC)
+ TIntegratorAP::EnableTimer(TIntegratorAP::ECounterTimer1, TIntegratorAP::EDisable);
+#endif
+#endif
+#if defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__)
+ TOmapTimer::SetTimer3Ctrl( 0 ); // disable the timer
+#endif
+ Kern::SafeClose((DObject*&)iThread, NULL);
+ }
+
+void DMsTim::HandleMsg(TMessageBase* aMsg)
+ {
+ TInt r=KErrNone;
+ TThreadMessage& m=*(TThreadMessage*)aMsg;
+ TInt id=m.iValue;
+ if (id==(TInt)ECloseMsg)
+ {
+ NTimerQTest::Stop();
+ TInt i;
+ for (i=0; i<KMaxMsTim; i++)
+ {
+ iMsTim[i].Cancel();
+ iMsTim[i].iCompletionDfc.Cancel();
+ iMsTim[i].CompleteClient(KErrCancel);
+ }
+ for (i=0; i<KMaxMsTimR; i++)
+ {
+ iMsTimR[i].Cancel();
+ iMsTimR[i].FillWithGarbage(0x01);
+ }
+ m.Complete(KErrNone,EFalse);
+ iMsgQ.CompleteAll(KErrServerTerminated);
+ return;
+ }
+ else if (id<0)
+ {
+ TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
+ r=DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
+ }
+ else
+ {
+ r=DoControl(id,m.Ptr0(),m.Ptr1());
+ }
+ m.Complete(r,ETrue);
+ }
+
+TInt DMsTim::DoControl(TInt aFunction, TAny* a1, TAny* a2)
+ {
+ TInt r=KErrNone;
+ TInt id=(TInt)a1;
+ TMsTim& m=iMsTim[id];
+ TInt interval=(TInt)a2;
+ switch (aFunction)
+ {
+ case RMsTim::EControlStartPeriodicInt:
+ r=m.Start(TMsTim::EIntAgain,interval,0);
+ break;
+ case RMsTim::EControlStartPeriodicDfc:
+ r=m.Start(TMsTim::EDfcAgain,interval,0);
+ break;
+ case RMsTim::EControlStopPeriodic:
+ m.Cancel();
+ m.iCompletionDfc.Cancel();
+ break;
+ case RMsTim::EControlGetInfo:
+ {
+ SMsTimerInfo info;
+ info.iMin=TicksToMicroseconds(m.iMin);
+ info.iMax=TicksToMicroseconds(m.iMax);
+ info.iCount=m.iCount;
+ Int64 avg=m.iTotal/m.iCount;
+ info.iAvg=TicksToMicroseconds((TInt)avg);
+
+ r=Kern::ThreadRawWrite(iThread,a2,&info,sizeof(info));
+ break;
+ }
+ case RMsTim::EControlBeginRandomTest:
+ {
+ iRandMin=KMaxTInt;
+ iRandMax=KMinTInt;
+ iXferC=0;
+ iCritC=0;
+ iStartFail=0;
+ iCallBacks=0;
+ iCompletions=0;
+ NTimerQTest::Setup(this);
+ break;
+ }
+ case RMsTim::EControlEndRandomTest:
+ {
+ NTimerQTest::Stop();
+ TInt i;
+ for (i=0; i<KMaxMsTimR; i++)
+ {
+ iMsTimR[i].Cancel();
+ iMsTimR[i].FillWithGarbage(0x35);
+ }
+ break;
+ }
+ case RMsTim::EControlGetRandomTestInfo:
+ {
+ SRandomTestInfo info;
+ info.iMin=iRandMin;
+ info.iMax=iRandMax;
+ info.iXferC=iXferC;
+ info.iCritC=iCritC;
+ info.iStartFail=iStartFail;
+ info.iCallBacks=iCallBacks;
+ info.iCompletions=iCompletions;
+ r=Kern::ThreadRawWrite(iThread,a1,&info,sizeof(info));
+ break;
+ }
+ case RMsTim::EControlGetIdleTime:
+ {
+ TInt irq=NKern::DisableAllInterrupts();
+ r=NTimerQ::IdleTime();
+ NKern::RestoreInterrupts(irq);
+ break;
+ }
+ default:
+ r=KErrNotSupported;
+ break;
+ }
+ return r;
+ }
+
+TInt DMsTim::DoRequest(TInt aFunction, TRequestStatus* aStatus, TAny* a1, TAny* a2)
+ {
+ TInt id=(TInt)a1;
+ TMsTim& m=iMsTim[aFunction == RMsTim::ERequestIntCancel ? 7 : id];
+ TInt interval=(TInt)a2;
+ TInt r=KErrNone;
+ switch (aFunction)
+ {
+ case RMsTim::ERequestOneShotInt:
+ r=m.Start(TMsTim::EIntAfter,interval,0);
+ break;
+ case RMsTim::ERequestOneShotDfc:
+ r=m.Start(TMsTim::EDfcAfter,interval,0);
+ break;
+ case RMsTim::ERequestIntCancel:
+ r=m.Start(TMsTim::EIntCancel,interval,id);
+ break;
+ case RMsTim::ERequestOneShotIntAgain:
+ r=m.Start(TMsTim::EIntAgainOnce,interval,0);
+ break;
+ case RMsTim::ERequestOneShotUserDfc:
+ r=m.Start(TMsTim::EUserDfcAfter,interval,0);
+ break;
+ case RMsTim::ERequestOneShotUserDfcAgain:
+ r=m.Start(TMsTim::EUserDfcAgainOnce,interval,0);
+ break;
+ default:
+ r=KErrNotSupported;
+ break;
+ }
+ m.iRequest->SetStatus(aStatus);
+ if (r!=KErrNone)
+ Kern::QueueRequestComplete(iThread,m.iRequest,r);
+ return r;
+ }
+
+void DMsTim::TimerExpired(TInt anId)
+ {
+ TMsTim& m=iMsTim[anId];
+ switch (m.iMode)
+ {
+ case TMsTim::EIntAfter:
+ case TMsTim::EDfcAfter:
+ case TMsTim::EUserDfcAfter:
+ m.CompleteClient(KErrNone);
+ break;
+ case TMsTim::EIntAgain:
+ case TMsTim::EDfcAgain:
+ break;
+ case TMsTim::EIntCancel:
+ case TMsTim::EDfcCancel:
+ {
+ TMsTim& cancelled=iMsTim[m.iParam];
+ cancelled.CompleteClient(KErrAbort);
+ m.CompleteClient(KErrNone);
+ break;
+ }
+ }
+ }
+