kerneltest/e32test/realtime/d_latncy.cpp
changeset 0 a41df078684a
child 4 56f325a607ea
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     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 	iMsDfc.SetDfcQ(iRtDfcQ);
       
   251 	iClient=&Kern::CurrentThread();
       
   252 	iClient->Open();
       
   253 	Kern::SetThreadPriority(KNumPriorities-2);
       
   254 	return KErrNone;
       
   255 	}
       
   256 
       
   257 #if defined(__MISA__) 
       
   258 // For SA1100/SA1110 use a separate timer on a FIQ interrupt (OST match 0)
       
   259 TInt DLatency::StartTimer()
       
   260 	{
       
   261 	TInt r=Interrupt::Bind(KIntIdOstMatchGeneral,MsCallBack,this);
       
   262 	if (r==KErrNone)
       
   263 		{
       
   264 		TSa1100::ModifyIntLevels(0,KHtIntsOstMatchGeneral);	// route new timer interrupt to FIQ
       
   265 		TSa1100::SetOstMatchEOI(KHwOstMatchGeneral);
       
   266 		TUint oscr=TSa1100::OstData();
       
   267 		iTriggerTime=oscr+KOstTicks*KFudgeFactor;
       
   268 		TSa1100::SetOstMatch(KHwOstMatchGeneral,iTriggerTime);
       
   269 		TSa1100::EnableOstInterrupt(KHwOstMatchGeneral);
       
   270 		Interrupt::Enable(KIntIdOstMatchGeneral);
       
   271 		}
       
   272 	return r;
       
   273 	}
       
   274 #elif defined(__MCOT__)
       
   275 // For Cotulla use a separate timer on a FIQ interrupt (OST match 0)
       
   276 TInt DLatency::StartTimer()
       
   277 	{
       
   278 	TInt r=Interrupt::Bind(KIntIdOstMatchGeneral,MsCallBack,this);
       
   279 	if (r==KErrNone)
       
   280 		{
       
   281 		TCotulla::ModifyIntLevels(0,KHtIntsOstMatchGeneral);	// route new timer interrupt to FIQ
       
   282 		TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
       
   283 		TUint oscr=TCotulla::OstData();
       
   284 		iTriggerTime=oscr+KOstTicks*KFudgeFactor;
       
   285 		TCotulla::SetOstMatch(iTriggerTime,KHwOstMatchGeneral);
       
   286 		TCotulla::EnableOstInterrupt(KHwOstMatchGeneral);
       
   287 		Interrupt::Enable(KIntIdOstMatchGeneral);
       
   288 		}
       
   289 	return r;
       
   290 	}
       
   291 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   292 TInt DLatency::StartTimer()
       
   293 /* 
       
   294  *  For OMAP2420 initialise a new timer to generate an interrupt every 1ms
       
   295  */
       
   296 	{
       
   297 	__ASSERT_ALWAYS(!iTimerInfo.iAddress, Kern::Fault("D_Latncy: timer allocated twice.",
       
   298 													 iTimerInfo.iAddress));
       
   299 
       
   300 	// Get an available Timer from the system
       
   301     TInt r = OmapTimerMgr::GetTimer(iGPTimerId, iTimerInfo);
       
   302     if (KErrNone != r)
       
   303     	{
       
   304     	return r;
       
   305     	}
       
   306     	
       
   307     // Configure the timer
       
   308     r = ConfigureTimer();
       
   309     if (KErrNone != r)
       
   310     	{
       
   311     	DisableTimer();
       
   312     	return r;
       
   313     	}
       
   314     
       
   315     // Bind to timer interrupt
       
   316     r = Interrupt::Bind(iTimerInfo.iInterruptId, MsCallBack, this);
       
   317     if (KErrNone != r)
       
   318         {
       
   319         DisableTimer();
       
   320         return r;
       
   321         }
       
   322               
       
   323     // Unmask timer IT in interrupt controller
       
   324     r = Interrupt::Enable(iTimerInfo.iInterruptId);
       
   325     if (KErrNone != r)
       
   326 		{
       
   327 		Interrupt::Unbind(iTimerInfo.iInterruptId);
       
   328 		DisableTimer();
       
   329     	return r;
       
   330     	}
       
   331     
       
   332     // Start timer
       
   333     TOmap::ModifyRegister32(iTimerInfo.iAddress + KHoGpTimer_TCLR, KClear32,
       
   334                         KHtGpTimer_TCLR_St);
       
   335         
       
   336     return KErrNone;
       
   337 	}
       
   338 
       
   339 void DLatency::DisableTimer()
       
   340 /*
       
   341  *	Disable the interface and functional clock and mark the timer as available 
       
   342  */
       
   343 	{
       
   344 	  // Stop timer
       
   345     TOmap::ModifyRegister32(iTimerInfo.iAddress + KHoGpTimer_TCLR,
       
   346                         KHtGpTimer_TCLR_St, KClear32);
       
   347 
       
   348 #if defined(__WAKEUP_3430__)
       
   349     // Disable Timer clocks using Timer framework instead of using TPRcm direct calls for 3430
       
   350     TInt r = OmapTimerMgr::DisableClocks(iGPTimerId);
       
   351     if (r != KErrNone)
       
   352         __ASSERT_ALWAYS(r, Kern::Fault("Timer clocks disable failed", 0)) ;
       
   353 #else
       
   354 	// Disable timer interface clock in PRCM
       
   355 	TPrcm::InterfaceClkCtrl(iTimerInfo.iPrcmDeviceId, EFalse);
       
   356 	
       
   357 	// Disable timer functional clock in PRCM
       
   358 	TPrcm::FunctionalClkCtrl(iTimerInfo.iPrcmDeviceId, EFalse);
       
   359 #endif
       
   360 
       
   361 	// Release the timer
       
   362 	OmapTimerMgr::ReleaseTimer(iGPTimerId);
       
   363 	
       
   364 	iTimerInfo.iAddress = 0;
       
   365 	}
       
   366 
       
   367 
       
   368 TInt DLatency::ConfigureTimer()
       
   369 /*
       
   370  *	This method will configure a timer to:
       
   371  *		-	run at the system clock (12Mhz)
       
   372  *		-	no prescaler (disable TCLR[PRE])
       
   373  *		-   autoreload and overflow interrupt enabled (TLDR will contain a
       
   374  *			value to generate an interrupt every 1000microsec)
       
   375  */
       
   376 	{
       
   377 
       
   378 #if defined(__WAKEUP_3430__)
       
   379 	// Enable Timer clocks using timer framework instead of TPrcm direct calls for 3430
       
   380     TInt r = OmapTimerMgr::EnableClocks(iGPTimerId);
       
   381     if (r != KErrNone)
       
   382         __ASSERT_ALWAYS(r, Kern::Fault("Timer Clocks enable failed", 0)) ;
       
   383 
       
   384 	// Select the input clock to be system clock 
       
   385     r = OmapTimerMgr::SetTimerClkSrc(iGPTimerId, ESysClk);
       
   386 #else
       
   387 	// Enable timer interface clock in PRCM  
       
   388 	TPrcm::InterfaceClkCtrl(iTimerInfo.iPrcmDeviceId, ETrue, ETrue);
       
   389 	// Enable timer functional clock in PRCM
       
   390 	TPrcm::FunctionalClkCtrl(iTimerInfo.iPrcmDeviceId, ETrue, ETrue);
       
   391 
       
   392 	// Select the input clock to be system clock 
       
   393     TInt r = OmapTimerMgr::SetTimerClkSrc(iGPTimerId, ESysClk);
       
   394 #endif
       
   395 
       
   396     if (KErrNone != r)	
       
   397     	return r;
       
   398 
       
   399     // Timer OCP configuration: - software reset
       
   400     TOmap::SetRegister32( iTimerInfo.iAddress + KHoGpTimerTIOCP_CFG,
       
   401                           KHtGpTimer_TIOCP_CFG_SoftReset);
       
   402 
       
   403     // Wait for reset to be complete
       
   404     TUint16 timeOut = 1000;
       
   405     while ( !(TOmap::Register32(iTimerInfo.iAddress + KHoGpTimer_TISTAT) & 
       
   406     			KHtGpTimer_TISTAT_ResetComplete)
       
   407     			&& --timeOut);
       
   408     
       
   409    // Check if the timer has been reset or we hit the timeout
       
   410    __ASSERT_ALWAYS((TOmap::Register32(iTimerInfo.iAddress + KHoGpTimer_TISTAT) & 
       
   411     			KHtGpTimer_TISTAT_ResetComplete), Kern::Fault("D_Latncy: failed to reset timer.",
       
   412 													 iGPTimerId));
       
   413 	
       
   414     // Set PRE to be 0, PTV value is ignored, AutoReload is enabled
       
   415     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TCLR, KHtGpTimer_TCLR_AR );
       
   416 
       
   417 	//PTV argument is 0 because of TCLR[PRE] = 0 (prescaling disabled)
       
   418 	TInt timerPTV = 0;
       
   419 	
       
   420 	// Calculate clock frequence from the ticks per ms
       
   421 	TInt timerClkSrcFreq = KTicksPerMillisecond * 1000;
       
   422     
       
   423     iTimerLoadValue = OmapTimerMgr::TimerLoadValue(/*microsecs*/1000, timerClkSrcFreq, timerPTV);                          
       
   424 
       
   425 	// First, load value in TCRR and TLDR registers
       
   426     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TCRR, iTimerLoadValue);
       
   427     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TLDR, iTimerLoadValue);
       
   428 
       
   429     // Enable overflow interrupt
       
   430     TOmap::SetRegister32(iTimerInfo.iAddress + KHoGpTimer_TIER,
       
   431                          KHtGpTimer_TIER_OverFlow);
       
   432 
       
   433     return KErrNone;
       
   434 	}
       
   435 #else
       
   436 TInt DLatency::StartTimer()
       
   437 	{
       
   438 	iMsCallBack.OneShot(KTickPeriodMs*KFudgeFactor);
       
   439 	return KErrNone;
       
   440 	}
       
   441 #endif
       
   442 
       
   443 #if defined(__MISA__) 
       
   444 // For SA1100/SA1110 use a separate timer on a FIQ interrupt (OST match 0)
       
   445 void DLatency::StopTimer()
       
   446 	{
       
   447 	TSa1100::ModifyIntLevels(KHtIntsOstMatchGeneral,0);
       
   448 	TSa1100::DisableOstInterrupt(KHwOstMatchGeneral);
       
   449 	Interrupt::Disable(KIntIdOstMatchGeneral);
       
   450 	Interrupt::Unbind(KIntIdOstMatchGeneral);
       
   451 	TSa1100::SetOstMatchEOI(KHwOstMatchGeneral);
       
   452 	}
       
   453 #elif defined(__MCOT__)
       
   454 // For Cotulla use a separate timer on a FIQ interrupt (OST match 0)
       
   455 void DLatency::StopTimer()
       
   456 	{
       
   457 	TCotulla::ModifyIntLevels(KHtIntsOstMatchGeneral,0);
       
   458 	TCotulla::DisableOstInterrupt(KHwOstMatchGeneral);
       
   459 	Interrupt::Disable(KIntIdOstMatchGeneral);
       
   460 	Interrupt::Unbind(KIntIdOstMatchGeneral);
       
   461 	TCotulla::SetOstMatchEOI(KHwOstMatchGeneral);
       
   462 	}
       
   463 #elif defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   464 void DLatency::StopTimer()
       
   465 	{
       
   466 	Interrupt::Disable(iTimerInfo.iInterruptId);
       
   467 	Interrupt::Unbind(iTimerInfo.iInterruptId);
       
   468 	DisableTimer();
       
   469 	}
       
   470 #else
       
   471 void DLatency::StopTimer()
       
   472 	{
       
   473 	iMsCallBack.Cancel();
       
   474 	}
       
   475 #endif
       
   476 
       
   477 TInt DLatency::Request(TInt aFunction, TAny* a1, TAny* a2)
       
   478 //
       
   479 // Client requests
       
   480 //
       
   481 	{
       
   482 	// Kern::Printf("DLatency::Request() 0x%x)\n", aFunction);
       
   483 	TInt r=KErrNone;
       
   484 	switch (aFunction)
       
   485 		{
       
   486 		case RLatency::EControlStart:
       
   487 			iStarted = (TUint8)ETrue;
       
   488 			StartTimer();
       
   489 			break;
       
   490 		case RLatency::EControlTicksPerMs:
       
   491 			r=KTicksPerMillisecond;
       
   492 			break;
       
   493 		case RLatency::EControlGetResults:
       
   494 			iResults.iUserThreadTicks = Ticks();
       
   495 			kumemput32(a1, &iResults, sizeof(SLatencyResults));
       
   496 			break;
       
   497 		default:
       
   498 			r = KErrNotSupported;
       
   499 			break;
       
   500 		}
       
   501 	return(r);
       
   502 	}
       
   503 
       
   504 #ifdef __CAPTURE_EXTRAS
       
   505 extern void CaptureExtras(SLatencyResults&);
       
   506 #endif
       
   507 
       
   508 #if !defined(__MISA__) && !defined(__MCOT__)
       
   509 void DLatency::MsCallBack(TAny* aPtr)
       
   510 	{
       
   511 	DLatency* pL = (DLatency*)aPtr;
       
   512 #if defined(__IS_OMAP2420__) || defined(__WAKEUP_3430__)
       
   513 	pL->iResults.iIntTicks = pL->Ticks();
       
   514 	TOmap::SetRegister32(pL->iTimerInfo.iAddress + KHoGpTimer_TISR, KHtGpTimer_TISR_OverFlow);
       
   515 #else
       
   516 	pL->iResults.iIntTicks = Ticks();
       
   517 #endif
       
   518 #ifdef __CAPTURE_EXTRAS
       
   519 	CaptureExtras(pL->iResults);
       
   520 #endif
       
   521 #if defined(__EPOC32__) && defined(__CPU_X86)
       
   522 	pL->iResults.iIntRetAddr = X86::IrqReturnAddress();
       
   523 #elif defined(__CPU_ARM) && defined(__SMP__)
       
   524 	pL->iResults.iIntRetAddr = Arm::IrqReturnAddress();
       
   525 #else
       
   526 	pL->iResults.iIntRetAddr=(pL->iIntStackTop)[-1];
       
   527 #endif
       
   528 	if (!pL->iOff)
       
   529 		{
       
   530 		pL->iMsCallBack.Again(KTickPeriodMs*KFudgeFactor);
       
   531 		pL->iMsDfc.Add();
       
   532 		}
       
   533 	}
       
   534 #endif
       
   535 
       
   536 void DLatency::MsDfc(TAny* aPtr)
       
   537 	{
       
   538 	DLatency* pL = (DLatency*)aPtr;
       
   539 	pL->iResults.iKernThreadTicks=pL->Ticks();
       
   540 	NKern::ThreadRequestSignal(&pL->iClient->iNThread);
       
   541 	}
       
   542 
       
   543 DLatencyPowerHandler::DLatencyPowerHandler(DLatency* aChannel)
       
   544 	:	DPowerHandler(KLddName), 
       
   545 		iChannel(aChannel)
       
   546 	{
       
   547 	}
       
   548 
       
   549 void DLatencyPowerHandler::PowerUp()
       
   550 	{
       
   551 	iChannel->iOff = (TUint8)EFalse;
       
   552 	if (iChannel->iStarted)
       
   553 		iChannel->StartTimer();
       
   554 	PowerUpDone();
       
   555 	}
       
   556 
       
   557 void DLatencyPowerHandler::PowerDown(TPowerState)
       
   558 	{
       
   559 	iChannel->iOff = (TUint8)ETrue;
       
   560 	iChannel->StopTimer();
       
   561 	PowerDownDone();
       
   562 	}
       
   563 
       
   564 
       
   565