diff -r 000000000000 -r 96e5fb8b040d kerneltest/e32test/system/d_mstim.cpp --- /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 +#elif defined(__MAWD__) +#include +#elif defined(__MISA__) +#include +#elif defined(__MCOT__) +#include +#elif defined(__IS_OMAP1510__) || defined(__IS_OMAP1610__) +#include +#include +#elif defined(__MI920__) || defined(__NI1136__) +#ifdef __MI920__ +#define USE_CM920_FRC +#endif +#ifdef USE_CM920_FRC +#include +#else +#include +#endif +#elif defined(__RVEMUBOARD__) +#include +#elif defined(__NE1_TB__) +#include +#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 (timem.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 (timem.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 (erroriRandMin) + 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; iSetStatus(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; + } + } + } +