kerneltest/e32test/realtime/d_latncy.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\realtime\d_latncy.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "platform.h"
       
    19 
       
    20 #if defined(__MEIG__)
       
    21 #include <cl7211.h>
       
    22 #elif defined(__MAWD__)
       
    23 #include <windermere.h>
       
    24 #elif defined(__MISA__)
       
    25 #include <sa1100.h>
       
    26 #elif defined(__MCOT__)
       
    27 #include <cotulla.h>
       
    28 #elif defined(__MI920__) || defined(__NI1136__)
       
    29 #include <integratorap.h>
       
    30 //#define FREE_RUNNING_MODE			// runs the millisecond timer in free running mode
       
    31 #elif defined(__IS_OMAP1610__)
       
    32 #include <omap_timer.h>
       
    33 #include <omap_plat.h>
       
    34 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
    35 #include <omap_hw.h>
       
    36 #include <shared_instrtimer.h>
       
    37 #elif defined(__EPOC32__) && defined(__CPU_X86)
       
    38 #include <x86.h>
       
    39 #include <x86pc.h>
       
    40 #elif defined(__RVEMUBOARD__)
       
    41 #include <rvemuboard.h>
       
    42 #elif defined(__NE1_TB__)
       
    43 #include <upd35001_timer.h>
       
    44 #endif
       
    45 
       
    46 #ifdef __CPU_ARM
       
    47 #include <arm.h>
       
    48 #endif
       
    49 
       
    50 #include <kernel/kern_priv.h>		//temporary
       
    51 #include "d_latncy.h"
       
    52 
       
    53 _LIT(KLddName,"Latency");
       
    54 _LIT(KThreadName,"LatencyThreadK");
       
    55 
       
    56 #if defined(__MEIG__)
       
    57 const TInt KTickPeriodMs=2;
       
    58 const TInt KTicksPerMillisecond=512;
       
    59 #elif defined(__MAWD__)
       
    60 const TInt KTickPeriodMs=1;
       
    61 const TInt KTicksPerMillisecond=512;
       
    62 #elif defined(__MISA__) || defined(__MCOT__)
       
    63 const TInt KTicksPerMillisecond=3686;
       
    64 const TInt KOstTicks=3685;	// not quite 1ms, so it goes in and out of phase with ms timer
       
    65 TUint TriggerTime;
       
    66 #elif defined(__MI920__) || defined(__NI1136__)
       
    67 const TInt KTickPeriodMs=1;
       
    68 #if defined(__MI920__) || defined(__NI1136__)
       
    69 #ifdef FREE_RUNNING_MODE	
       
    70 const TInt KTicksPerMillisecond=1500;
       
    71 #else
       
    72 const TInt KTicksPerMillisecond=24000;
       
    73 #endif
       
    74 #endif
       
    75 #elif defined(__IS_OMAP1610__)
       
    76 const TInt KTickPeriodMs=1;
       
    77 TInt KTicksPerMillisecond = TOmapPlat::GetInputClk()/32000;
       
    78 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
    79 const TInt KTickPeriodMs=1;					// defined for compatibility but not used (ignored)
       
    80 const TInt KTicksPerMillisecond = 12000; 	// Hard coded (12Mhz)
       
    81 #elif defined(__EPOC32__) && defined(__CPU_X86)
       
    82 const TInt KTickPeriodMs=1;
       
    83 const TInt KTicksPerMillisecond=1193;
       
    84 #elif defined(__RVEMUBOARD__)
       
    85 const TInt KTickPeriodMs=1;
       
    86 const TInt KTicksPerMillisecond=1000;
       
    87 #elif defined(__NE1_TB__)
       
    88 const TInt KTickPeriodMs=1;
       
    89 const TInt KTicksPerMillisecond=66667;
       
    90 #endif
       
    91 
       
    92 #ifdef _DEBUG
       
    93 const TInt KFudgeFactor=1;
       
    94 #else
       
    95 const TInt KFudgeFactor=1;
       
    96 #endif
       
    97 
       
    98 class DDeviceLatency : public DLogicalDevice
       
    99 	{
       
   100 public:
       
   101 	DDeviceLatency();
       
   102 	virtual TInt Install();
       
   103 	virtual void GetCaps(TDes8& aDes) const;
       
   104 	virtual TInt Create(DLogicalChannelBase*& aChannel);
       
   105 	};
       
   106 
       
   107 class DLatencyPowerHandler : public DPowerHandler
       
   108 	{
       
   109 public: // from DPOwerHandler
       
   110 	void PowerUp();
       
   111 	void PowerDown(TPowerState);
       
   112 public:
       
   113 	DLatencyPowerHandler(DLatency* aChannel);
       
   114 public:
       
   115 	DLatency* iChannel;
       
   116 	};
       
   117 
       
   118 
       
   119 
       
   120 inline TUint DLatency::Ticks()
       
   121 	{
       
   122 #if defined(__MEIG__)
       
   123 	return KTicksPerMillisecond-(*(volatile TUint*)(KEigerTimer2Data16+KEigerBaseAddress)&0xffff);
       
   124 #elif defined(__MAWD__)
       
   125 	return KTicksPerMillisecond-(*(volatile TUint*)(KWindTimer2Value16+KWindBaseAddress)&0xffff);
       
   126 #elif defined(__MISA__) || defined(__MCOT__)
       
   127 	return *(volatile TUint*)KHwRwOstOscr-iTriggerTime;
       
   128 #elif defined(__MI920__) || defined(__NI1136__)
       
   129 	return KTicksPerMillisecond-(*(volatile TUint*)(KHwCounterTimer2+KHoTimerValue)&0xffff);
       
   130 #elif defined(__IS_OMAP1610__)
       
   131 	return KTicksPerMillisecond - *(volatile TUint*)(KHwBaseOSTimer1Reg+KHoOSTimer_READ_TIM);
       
   132 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   133 	return (*(volatile TUint*)(iTimerInfo.iAddress + KHoGpTimer_TCRR)) - iTimerLoadValue;
       
   134 #elif defined(__X86PC__)
       
   135 	return 1194 - __HwTimer();
       
   136 #elif defined(__RVEMUBOARD__)
       
   137 	return KTicksPerMillisecond-(*(volatile TUint*)(KHwCounterTimer1+KHoTimerValue)&0xffff);
       
   138 #elif defined(__NE1_TB__)
       
   139 	return NETimer::Timer(0).iTimerCount;	// counts up, reset timer + interrupt on match
       
   140 #endif
       
   141 	}
       
   142 
       
   143 #if !defined(__SMP__)
       
   144 #if !defined(__EPOC32__) || !defined(__CPU_X86)
       
   145 extern TUint IntStackPtr();
       
   146 #endif
       
   147 #endif
       
   148 
       
   149 DECLARE_STANDARD_LDD()
       
   150 	{
       
   151 	return new DDeviceLatency;
       
   152 	}
       
   153 
       
   154 DDeviceLatency::DDeviceLatency()
       
   155 //
       
   156 // Constructor
       
   157 //
       
   158 	{
       
   159 	//iParseMask=0;
       
   160 	//iUnitsMask=0;
       
   161 	iVersion=TVersion(1,0,1);
       
   162 	}
       
   163 
       
   164 TInt DDeviceLatency::Install()
       
   165 //
       
   166 // Install the device driver.
       
   167 //
       
   168 	{
       
   169 	TInt r=SetName(&KLddName);
       
   170 	return r;
       
   171 	}
       
   172 
       
   173 void DDeviceLatency::GetCaps(TDes8& aDes) const
       
   174 //
       
   175 // Return the Comm capabilities.
       
   176 //
       
   177 	{
       
   178 	}
       
   179 
       
   180 TInt DDeviceLatency::Create(DLogicalChannelBase*& aChannel)
       
   181 //
       
   182 // Create a channel on the device.
       
   183 //
       
   184 	{
       
   185 	aChannel=new DLatency;
       
   186 	return aChannel?KErrNone:KErrNoMemory;
       
   187 	}
       
   188 
       
   189 DLatency::DLatency()
       
   190 	:	iMsCallBack(MsCallBack,this),
       
   191 		iMsDfc(MsDfc,this,NULL,1)
       
   192 //
       
   193 // Constructor
       
   194 //
       
   195 	{
       
   196 #if !defined(__SMP__)
       
   197 #if !defined(__EPOC32__) || !defined(__CPU_X86)
       
   198 	iIntStackTop=(TUint*)IntStackPtr();
       
   199 #endif
       
   200 #endif
       
   201 #if defined(__MISA__) || defined(__MCOT__)
       
   202 	iTickIncrement=KOstTicks*KFudgeFactor;
       
   203 #endif
       
   204 #if defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   205 	iTimerInfo.iAddress = 0;
       
   206 #endif
       
   207 	}
       
   208 
       
   209 DLatency::~DLatency()
       
   210 //
       
   211 // Destructor
       
   212 //
       
   213 	{
       
   214 	iOff = (TUint8)ETrue;
       
   215 	StopTimer();
       
   216 	iMsDfc.Cancel();
       
   217 
       
   218 	if (iRtDfcQ)
       
   219 		iRtDfcQ->Destroy();
       
   220 
       
   221 	if (iPowerHandler)
       
   222 		{
       
   223 		iPowerHandler->Remove();
       
   224 		delete iPowerHandler;
       
   225 		}
       
   226 
       
   227 	Kern::SafeClose((DObject*&)iClient, NULL);
       
   228 	}
       
   229 
       
   230 TInt DLatency::DoCreate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer)
       
   231 //
       
   232 // Create the channel from the passed info.
       
   233 //
       
   234 	{
       
   235 	if (!Kern::QueryVersionSupported(TVersion(1,0,1),aVer))
       
   236 		return KErrNotSupported;
       
   237 
       
   238 	// create the power handler
       
   239 	iPowerHandler = new DLatencyPowerHandler(this);
       
   240 	if (!iPowerHandler)
       
   241 		return KErrNoMemory;
       
   242 	iPowerHandler->Add();
       
   243 
       
   244 	// Allocate a kernel thread to run the DFC 
       
   245 	TInt r = Kern::DynamicDfcQCreate(iRtDfcQ, KNumPriorities-1,KThreadName);
       
   246 
       
   247 	if (r != KErrNone)
       
   248 		return r;
       
   249 	
       
   250 #ifdef CPU_AFFINITY_ANY
       
   251 	NKern::ThreadSetCpuAffinity((NThread*)(iRtDfcQ->iThread), KCpuAffinityAny);			
       
   252 #endif
       
   253 
       
   254 	iMsDfc.SetDfcQ(iRtDfcQ);
       
   255 	iClient=&Kern::CurrentThread();
       
   256 	iClient->Open();
       
   257 	Kern::SetThreadPriority(KNumPriorities-2);
       
   258 	return KErrNone;
       
   259 	}
       
   260 
       
   261 #if defined(__MISA__) 
       
   262 // For SA1100/SA1110 use a separate timer on a FIQ interrupt (OST match 0)
       
   263 TInt DLatency::StartTimer()
       
   264 	{
       
   265 	TInt r=Interrupt::Bind(KIntIdOstMatchGeneral,MsCallBack,this);
       
   266 	if (r==KErrNone)
       
   267 		{
       
   268 		TSa1100::ModifyIntLevels(0,KHtIntsOstMatchGeneral);	// route new timer interrupt to FIQ
       
   269 		TSa1100::SetOstMatchEOI(KHwOstMatchGeneral);
       
   270 		TUint oscr=TSa1100::OstData();
       
   271 		iTriggerTime=oscr+KOstTicks*KFudgeFactor;
       
   272 		TSa1100::SetOstMatch(KHwOstMatchGeneral,iTriggerTime);
       
   273 		TSa1100::EnableOstInterrupt(KHwOstMatchGeneral);
       
   274 		Interrupt::Enable(KIntIdOstMatchGeneral);
       
   275 		}
       
   276 	return r;
       
   277 	}
       
   278 #elif defined(__MCOT__)
       
   279 // For Cotulla use a separate timer on a FIQ interrupt (OST match 0)
       
   280 TInt DLatency::StartTimer()
       
   281 	{
       
   282 	TInt r=Interrupt::Bind(KIntIdOstMatchGeneral,MsCallBack,this);
       
   283 	if (r==KErrNone)
       
   284 		{
       
   285 		TCotulla::ModifyIntLevels(0,KHtIntsOstMatchGeneral);	// route new timer interrupt to FIQ
       
   286 		TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
       
   287 		TUint oscr=TCotulla::OstData();
       
   288 		iTriggerTime=oscr+KOstTicks*KFudgeFactor;
       
   289 		TCotulla::SetOstMatch(iTriggerTime,KHwOstMatchGeneral);
       
   290 		TCotulla::EnableOstInterrupt(KHwOstMatchGeneral);
       
   291 		Interrupt::Enable(KIntIdOstMatchGeneral);
       
   292 		}
       
   293 	return r;
       
   294 	}
       
   295 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   296 TInt DLatency::StartTimer()
       
   297 /* 
       
   298  *  For OMAP2420 initialise a new timer to generate an interrupt every 1ms
       
   299  */
       
   300 	{
       
   301 	__ASSERT_ALWAYS(!iTimerInfo.iAddress, Kern::Fault("D_Latncy: timer allocated twice.",
       
   302 													 iTimerInfo.iAddress));
       
   303 
       
   304 	// Get an available Timer from the system
       
   305     TInt r = OmapTimerMgr::GetTimer(iGPTimerId, iTimerInfo);
       
   306     if (KErrNone != r)
       
   307     	{
       
   308     	return r;
       
   309     	}
       
   310     	
       
   311     // Configure the timer
       
   312     r = ConfigureTimer();
       
   313     if (KErrNone != r)
       
   314     	{
       
   315     	DisableTimer();
       
   316     	return r;
       
   317     	}
       
   318     
       
   319     // Bind to timer interrupt
       
   320     r = Interrupt::Bind(iTimerInfo.iInterruptId, MsCallBack, this);
       
   321     if (KErrNone != r)
       
   322         {
       
   323         DisableTimer();
       
   324         return r;
       
   325         }
       
   326               
       
   327     // Unmask timer IT in interrupt controller
       
   328     r = Interrupt::Enable(iTimerInfo.iInterruptId);
       
   329     if (KErrNone != r)
       
   330 		{
       
   331 		Interrupt::Unbind(iTimerInfo.iInterruptId);
       
   332 		DisableTimer();
       
   333     	return r;
       
   334     	}
       
   335     
       
   336     // Start timer
       
   337     TOmap::ModifyRegister32(iTimerInfo.iAddress + KHoGpTimer_TCLR, KClear32,
       
   338                         KHtGpTimer_TCLR_St);
       
   339         
       
   340     return KErrNone;
       
   341 	}
       
   342 
       
   343 void DLatency::DisableTimer()
       
   344 /*
       
   345  *	Disable the interface and functional clock and mark the timer as available 
       
   346  */
       
   347 	{
       
   348 	  // Stop timer
       
   349     TOmap::ModifyRegister32(iTimerInfo.iAddress + KHoGpTimer_TCLR,
       
   350                         KHtGpTimer_TCLR_St, KClear32);
       
   351 
       
   352 #if defined(__WAKEUP_3430__)
       
   353     // Disable Timer clocks using Timer framework instead of using TPRcm direct calls for 3430
       
   354     TInt r = OmapTimerMgr::DisableClocks(iGPTimerId);
       
   355     if (r != KErrNone)
       
   356         __ASSERT_ALWAYS(r, Kern::Fault("Timer clocks disable failed", 0)) ;
       
   357 #else
       
   358 	// Disable timer interface clock in PRCM
       
   359 	TPrcm::InterfaceClkCtrl(iTimerInfo.iPrcmDeviceId, EFalse);
       
   360 	
       
   361 	// Disable timer functional clock in PRCM
       
   362 	TPrcm::FunctionalClkCtrl(iTimerInfo.iPrcmDeviceId, EFalse);
       
   363 #endif
       
   364 
       
   365 	// Release the timer
       
   366 	OmapTimerMgr::ReleaseTimer(iGPTimerId);
       
   367 	
       
   368 	iTimerInfo.iAddress = 0;
       
   369 	}
       
   370 
       
   371 
       
   372 TInt DLatency::ConfigureTimer()
       
   373 /*
       
   374  *	This method will configure a timer to:
       
   375  *		-	run at the system clock (12Mhz)
       
   376  *		-	no prescaler (disable TCLR[PRE])
       
   377  *		-   autoreload and overflow interrupt enabled (TLDR will contain a
       
   378  *			value to generate an interrupt every 1000microsec)
       
   379  */
       
   380 	{
       
   381 
       
   382 #if defined(__WAKEUP_3430__)
       
   383 	// Enable Timer clocks using timer framework instead of TPrcm direct calls for 3430
       
   384     TInt r = OmapTimerMgr::EnableClocks(iGPTimerId);
       
   385     if (r != KErrNone)
       
   386         __ASSERT_ALWAYS(r, Kern::Fault("Timer Clocks enable failed", 0)) ;
       
   387 
       
   388 	// Select the input clock to be system clock 
       
   389     r = OmapTimerMgr::SetTimerClkSrc(iGPTimerId, ESysClk);
       
   390 #else
       
   391 	// Enable timer interface clock in PRCM  
       
   392 	TPrcm::InterfaceClkCtrl(iTimerInfo.iPrcmDeviceId, ETrue, ETrue);
       
   393 	// Enable timer functional clock in PRCM
       
   394 	TPrcm::FunctionalClkCtrl(iTimerInfo.iPrcmDeviceId, ETrue, ETrue);
       
   395 
       
   396 	// Select the input clock to be system clock 
       
   397     TInt r = OmapTimerMgr::SetTimerClkSrc(iGPTimerId, ESysClk);
       
   398 #endif
       
   399 
       
   400     if (KErrNone != r)	
       
   401     	return r;
       
   402 
       
   403     // Timer OCP configuration: - software reset
       
   404     TOmap::SetRegister32( iTimerInfo.iAddress + KHoGpTimerTIOCP_CFG,
       
   405                           KHtGpTimer_TIOCP_CFG_SoftReset);
       
   406 
       
   407     // Wait for reset to be complete
       
   408     TUint16 timeOut = 1000;
       
   409     while ( !(TOmap::Register32(iTimerInfo.iAddress + KHoGpTimer_TISTAT) & 
       
   410     			KHtGpTimer_TISTAT_ResetComplete)
       
   411     			&& --timeOut);
       
   412     
       
   413    // Check if the timer has been reset or we hit the timeout
       
   414    __ASSERT_ALWAYS((TOmap::Register32(iTimerInfo.iAddress + KHoGpTimer_TISTAT) & 
       
   415     			KHtGpTimer_TISTAT_ResetComplete), Kern::Fault("D_Latncy: failed to reset timer.",
       
   416 													 iGPTimerId));
       
   417 	
       
   418     // Set PRE to be 0, PTV value is ignored, AutoReload is enabled
       
   419     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TCLR, KHtGpTimer_TCLR_AR );
       
   420 
       
   421 	//PTV argument is 0 because of TCLR[PRE] = 0 (prescaling disabled)
       
   422 	TInt timerPTV = 0;
       
   423 	
       
   424 	// Calculate clock frequence from the ticks per ms
       
   425 	TInt timerClkSrcFreq = KTicksPerMillisecond * 1000;
       
   426     
       
   427     iTimerLoadValue = OmapTimerMgr::TimerLoadValue(/*microsecs*/1000, timerClkSrcFreq, timerPTV);                          
       
   428 
       
   429 	// First, load value in TCRR and TLDR registers
       
   430     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TCRR, iTimerLoadValue);
       
   431     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TLDR, iTimerLoadValue);
       
   432 
       
   433     // Enable overflow interrupt
       
   434     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TIER,
       
   435                          KHtGpTimer_TIER_OverFlow);
       
   436 
       
   437     return KErrNone;
       
   438 	}
       
   439 #else
       
   440 TInt DLatency::StartTimer()
       
   441 	{
       
   442 	iMsCallBack.OneShot(KTickPeriodMs*KFudgeFactor);
       
   443 	return KErrNone;
       
   444 	}
       
   445 #endif
       
   446 
       
   447 #if defined(__MISA__) 
       
   448 // For SA1100/SA1110 use a separate timer on a FIQ interrupt (OST match 0)
       
   449 void DLatency::StopTimer()
       
   450 	{
       
   451 	TSa1100::ModifyIntLevels(KHtIntsOstMatchGeneral,0);
       
   452 	TSa1100::DisableOstInterrupt(KHwOstMatchGeneral);
       
   453 	Interrupt::Disable(KIntIdOstMatchGeneral);
       
   454 	Interrupt::Unbind(KIntIdOstMatchGeneral);
       
   455 	TSa1100::SetOstMatchEOI(KHwOstMatchGeneral);
       
   456 	}
       
   457 #elif defined(__MCOT__)
       
   458 // For Cotulla use a separate timer on a FIQ interrupt (OST match 0)
       
   459 void DLatency::StopTimer()
       
   460 	{
       
   461 	TCotulla::ModifyIntLevels(KHtIntsOstMatchGeneral,0);
       
   462 	TCotulla::DisableOstInterrupt(KHwOstMatchGeneral);
       
   463 	Interrupt::Disable(KIntIdOstMatchGeneral);
       
   464 	Interrupt::Unbind(KIntIdOstMatchGeneral);
       
   465 	TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
       
   466 	}
       
   467 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   468 void DLatency::StopTimer()
       
   469 	{
       
   470 	Interrupt::Disable(iTimerInfo.iInterruptId);
       
   471 	Interrupt::Unbind(iTimerInfo.iInterruptId);
       
   472 	DisableTimer();
       
   473 	}
       
   474 #else
       
   475 void DLatency::StopTimer()
       
   476 	{
       
   477 	iMsCallBack.Cancel();
       
   478 	}
       
   479 #endif
       
   480 
       
   481 TInt DLatency::Request(TInt aFunction, TAny* a1, TAny* a2)
       
   482 //
       
   483 // Client requests
       
   484 //
       
   485 	{
       
   486 	// Kern::Printf("DLatency::Request() 0x%x)\n", aFunction);
       
   487 	TInt r=KErrNone;
       
   488 	switch (aFunction)
       
   489 		{
       
   490 		case RLatency::EControlStart:
       
   491 			iStarted = (TUint8)ETrue;
       
   492 			StartTimer();
       
   493 			break;
       
   494 		case RLatency::EControlTicksPerMs:
       
   495 			r=KTicksPerMillisecond;
       
   496 			break;
       
   497 		case RLatency::EControlGetResults:
       
   498 			iResults.iUserThreadTicks = Ticks();
       
   499 			kumemput32(a1, &iResults, sizeof(SLatencyResults));
       
   500 			break;
       
   501 		default:
       
   502 			r = KErrNotSupported;
       
   503 			break;
       
   504 		}
       
   505 	return(r);
       
   506 	}
       
   507 
       
   508 #ifdef __CAPTURE_EXTRAS
       
   509 extern void CaptureExtras(SLatencyResults&);
       
   510 #endif
       
   511 
       
   512 #if !defined(__MISA__) && !defined(__MCOT__)
       
   513 void DLatency::MsCallBack(TAny* aPtr)
       
   514 	{
       
   515 	DLatency* pL = (DLatency*)aPtr;
       
   516 #if defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   517 	pL->iResults.iIntTicks = pL->Ticks();
       
   518 	TOmap::SetRegister32(pL->iTimerInfo.iAddress + KHoGpTimer_TISR, KHtGpTimer_TISR_OverFlow);
       
   519 #else
       
   520 	pL->iResults.iIntTicks = Ticks();
       
   521 #endif
       
   522 #ifdef __CAPTURE_EXTRAS
       
   523 	CaptureExtras(pL->iResults);
       
   524 #endif
       
   525 #if defined(__EPOC32__) && defined(__CPU_X86)
       
   526 	pL->iResults.iIntRetAddr = X86::IrqReturnAddress();
       
   527 #elif defined(__CPU_ARM) && defined(__SMP__)
       
   528 	pL->iResults.iIntRetAddr = Arm::IrqReturnAddress();
       
   529 #else
       
   530 	pL->iResults.iIntRetAddr=(pL->iIntStackTop)[-1];
       
   531 #endif
       
   532 	if (!pL->iOff)
       
   533 		{
       
   534 		pL->iMsCallBack.Again(KTickPeriodMs*KFudgeFactor);
       
   535 		pL->iMsDfc.Add();
       
   536 		}
       
   537 	}
       
   538 #endif
       
   539 
       
   540 void DLatency::MsDfc(TAny* aPtr)
       
   541 	{
       
   542 	DLatency* pL = (DLatency*)aPtr;
       
   543 	pL->iResults.iKernThreadTicks=pL->Ticks();
       
   544 	NKern::ThreadRequestSignal(&pL->iClient->iNThread);
       
   545 	}
       
   546 
       
   547 DLatencyPowerHandler::DLatencyPowerHandler(DLatency* aChannel)
       
   548 	:	DPowerHandler(KLddName), 
       
   549 		iChannel(aChannel)
       
   550 	{
       
   551 	}
       
   552 
       
   553 void DLatencyPowerHandler::PowerUp()
       
   554 	{
       
   555 	iChannel->iOff = (TUint8)EFalse;
       
   556 	if (iChannel->iStarted)
       
   557 		iChannel->StartTimer();
       
   558 	PowerUpDone();
       
   559 	}
       
   560 
       
   561 void DLatencyPowerHandler::PowerDown(TPowerState)
       
   562 	{
       
   563 	iChannel->iOff = (TUint8)ETrue;
       
   564 	iChannel->StopTimer();
       
   565 	PowerDownDone();
       
   566 	}
       
   567 
       
   568 
       
   569