Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h)
Have multiple extension sections in the bld.inf, one for each version
of the compiler. The RVCT version building the tools will build the
runtime libraries for its version, but make sure we extract all the other
versions from zip archives. Also add the archive for RVCT4.
// 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.iCount=m.iCount;
Int64 avg=m.iTotal/m.iCount;
info.iAvg=TicksToMicroseconds((TInt)avg);
#ifdef __SMP__
info.iMin=info.iAvg;
info.iMax=info.iAvg;
#else
info.iMin=TicksToMicroseconds(m.iMin);
info.iMax=TicksToMicroseconds(m.iMax);
#endif
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;
}
}
}