diff -r c1f20ce4abcf -r 3e88ff8f41d5 kerneltest/e32test/power/d_frqchg.cpp --- a/kerneltest/e32test/power/d_frqchg.cpp Tue Aug 31 16:34:26 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,421 +0,0 @@ -// Copyright (c) 2010-2010 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\power\d_frqchg.cpp -// LDD for testing frequency changing -// -// - -#include -#include "d_frqchg.h" - -#if defined(__EPOC32__) && defined(__SMP__) && defined(__MARM__) -#define __SUPPORT_LOCAL_TIMER_PRESCALE__ - -#include -#include -#endif - - -#ifdef __PLATFORM_SUPPORTS_DVFS__ -/** - Baseport needs to supply this function to disable DVFS whilst test is running. - The test relies on changing prescalers in local and global timer directly rather than - actually changing frequency. Consequently DVFS must be disabled when the test is running - - This function when driver is loaded. - @return KErrNone if succesful - */ -extern TInt DisableDvfs(); - -/** - if plaftorm supports DVFS this function will be called when the driver is unloaded - */ -extern void RestoreDvfs(); -#endif - - - -#if defined(__SUPPORT_LOCAL_TIMER_PRESCALE__) -TInt Multiply(SRatio& aDest, const SRatio& aSrc) - { - TUint64 x = aDest.iM; - TUint64 y = aSrc.iM; - x *= y; - if (x==0) - { - aDest.iM = 0; - aDest.iX = 0; - return KErrNone; - } - TInt exp = aDest.iX + aSrc.iX + 32; - if (TInt64(x) >= 0) - x<<=1, --exp; - aDest.iM = I64HIGH(x); - if (I64LOW(x) & 0x80000000u) - { - if (++aDest.iM == 0) - aDest.iM = 0x80000000u, ++exp; - } - if (exp > 32767) - { - aDest.iM = 0xffffffffu; - aDest.iX = 32767; - return KErrOverflow; - } - if (exp < -32768) - { - aDest.iM = 0; - aDest.iX = 0; - return KErrUnderflow; - } - aDest.iX = (TInt16)exp; - return KErrNone; - } - -// Calculate frequency ratio for specified prescale value -// Ratio = (default+1)/(current+1) -void PrescaleRatio(SRatio& aR, TInt aDefault, TInt aCurrent) - { - SRatio df; - df.Set(TUint32(aDefault+1)); - aR.Set(TUint32(aCurrent+1)); - aR.Reciprocal(); - Multiply(aR, df); - } -#endif - -class DFrqChgFactory : public DLogicalDevice -// -// Test LDD factory -// - { -public: - DFrqChgFactory(); - virtual ~DFrqChgFactory(); - virtual TInt Install(); //overriding pure virtual - virtual void GetCaps(TDes8& aDes) const; //overriding pure virtual - virtual TInt Create(DLogicalChannelBase*& aChannel); //overriding pure virtual - }; - -class DFrqChg : public DLogicalChannelBase -// -// Test logical channel -// - { -public: - virtual ~DFrqChg(); -protected: - virtual TInt DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); - virtual TInt Request(TInt aReqNo, TAny* a1, TAny* a2); -#if defined(__SUPPORT_LOCAL_TIMER_PRESCALE__) - void PopulateDefaultPrescaleList(); - void SetLocalTimerPrescaler(TUint32 aCpus, TInt aPrescale); - TScheduler* iS; - TInt iDefaultPrescale[KMaxCpus]; -#if defined(__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK) && defined( __NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__) - void SetGlobalTimerPrescaler(TInt aPrescale); - TInt iDefaultGTPrescale; -#endif -#endif - - }; - - - -DECLARE_STANDARD_LDD() - { - return new DFrqChgFactory; - } - -// -// Constructor -// -DFrqChgFactory::DFrqChgFactory() - { - } - -// -// Destructor, called on unload -// -DFrqChgFactory::~DFrqChgFactory() - { -#ifdef __PLATFORM_SUPPORTS_DVFS__ - RestoreDvfs(); -#endif - } - - - -// -// Create new channel -// -TInt DFrqChgFactory::Create(DLogicalChannelBase*& aChannel) - { - aChannel=new DFrqChg; - return aChannel?KErrNone:KErrNoMemory; - } - - -// -// Install the LDD - overriding pure virtual -// -TInt DFrqChgFactory::Install() - { -#ifdef __PLATFORM_SUPPORTS_DVFS__ - TInt r = DisableDvfs(); - if (KErrNone != r) return r; -#endif - return SetName(&KLddName); - } - - -// -// Get capabilities - overriding pure virtual -// -void DFrqChgFactory::GetCaps(TDes8& /*aDes*/) const - { - } - - -// -// Create channel -// -TInt DFrqChg::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/) - { -#if defined(__SUPPORT_LOCAL_TIMER_PRESCALE__) - iS = (TScheduler*)TScheduler::Ptr(); - PopulateDefaultPrescaleList(); -#endif - return KErrNone; - } - - -// -// Destructor -// -DFrqChg::~DFrqChg() - { -#if defined(__SUPPORT_LOCAL_TIMER_PRESCALE__) - // restore prescalers - SetLocalTimerPrescaler((TUint32) -1, -1); -#if defined(__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK) && defined( __NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__) - SetGlobalTimerPrescaler(-1); -#endif -#endif - } - - -TInt DFrqChg::Request(TInt aReqNo, TAny* a1, TAny* a2) - { - SRatioInv ri; - TInt r = KErrNone; - switch (aReqNo) - { - case RFrqChg::EControl_RatioSet: - { - kumemget32(&ri.iR, a1, sizeof(SRatio)); - ri.iR.Set(ri.iR.iM, (TUint32)a2); - kumemput32(a1, &ri.iR, sizeof(SRatio)); - break; - } - case RFrqChg::EControl_RatioReciprocal: - { - kumemget32(&ri.iR, a1, sizeof(SRatio)); - r = ri.iR.Reciprocal(); - kumemput32(a1, &ri.iR, sizeof(SRatio)); - break; - } - case RFrqChg::EControl_RatioMult: - { - kumemget32(&ri.iR, a1, sizeof(SRatio)); - kumemget32(&ri.iI.iM, a2, sizeof(TUint32)); - r = ri.iR.Mult(ri.iI.iM); - kumemput32(a2, &ri.iI.iM, sizeof(TUint32)); - break; - } - case RFrqChg::EControl_RatioInvSet: - { - SRatio ratio; - const SRatio* p = 0; - if (a2) - { - kumemget32(&ratio, a2, sizeof(SRatio)); - p = ∶ - } - ri.Set(p); - kumemput32(a1, &ri, sizeof(SRatioInv)); - break; - } -#if defined(__EPOC32__) && defined(__SMP__) && defined(__MARM__) - case RFrqChg::EControl_FrqChgTestPresent: - break; - case RFrqChg::EControl_SetCurrentThreadPriority: - NKern::ThreadSetPriority(NKern::CurrentThread(), (TInt)a1); - break; - case RFrqChg::EControl_SetCurrentThreadCpu: - { - TUint32 old = 0; - old = NKern::ThreadSetCpuAffinity(NKern::CurrentThread(), (TUint32)a1); - if (a2) - { - kumemput32(a2, &old, sizeof(TUint32)); - } - - old = NKern::ThreadSetCpuAffinity(NKern::CurrentThread(), (TUint32)a1); - } - - break; - case RFrqChg::EControl_SetCurrentThreadTimeslice: - { - TInt ts = NKern::TimesliceTicks((TUint32)a1); - NKern::ThreadSetTimeslice(NKern::CurrentThread(), ts); - NKern::YieldTimeslice(); - break; - } -#endif -#if defined(__SUPPORT_LOCAL_TIMER_PRESCALE__) - case RFrqChg::EControl_SetLocalTimerPrescaler: - { - TUint32 cpus = (TUint32)a1; - TInt prescale = (TInt)a2; - SetLocalTimerPrescaler(cpus, prescale); - break; - } -#if defined(__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK) && defined( __NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__) - case RFrqChg::EControl_ReadGlobalTimerAndTimestamp: - { - ArmGlobalTimer* tmr = iS->iSX.iGlobalTimerAddr; - TUint32 highlow[2]; - do - { - highlow[1] = tmr->iTimerCountHigh; - highlow[0] = tmr->iTimerCountLow; - } while(highlow[1]!=tmr->iTimerCountHigh); - TUint64 ts = NKern::Timestamp(); - kumemput32(a1,&highlow[0],sizeof(TUint64)); - kumemput32(a2,&ts,sizeof(TUint64)); - break; - } - case RFrqChg::EControl_SetGlobalTimerPrescaler: - { - SetGlobalTimerPrescaler((TInt)a1); - break; - } -#endif -#endif - default: - r = KErrNotSupported; - break; - } - return r; - } - - -#if defined(__SUPPORT_LOCAL_TIMER_PRESCALE__) -void DFrqChg::PopulateDefaultPrescaleList() - { - TInt nc = NKern::NumberOfCpus(); - NThread* nt = NKern::CurrentThread(); - TUint32 aff0 = NKern::ThreadSetCpuAffinity(nt, 0); - TInt i; - for (i=0; iiSX.iLocalTimerAddr; - TInt pv = (tmr->iTimerCtrl & E_ArmTmrCtrl_PrescaleMask) >> E_ArmTmrCtrl_PrescaleShift; - iDefaultPrescale[i] = pv; - } - NKern::ThreadSetCpuAffinity(nt, aff0); -#if defined(__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK) && defined( __NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__) - ArmGlobalTimer* tmr = iS->iSX.iGlobalTimerAddr; - TInt pv = (tmr->iTimerCtrl & E_ArmGTmrCtrl_PrescaleMask) >> E_ArmGTmrCtrl_PrescaleShift; - iDefaultGTPrescale = pv; -#endif - } - -void DFrqChg::SetLocalTimerPrescaler(TUint32 aCpus, TInt aPrescale) - { - TInt nc = NKern::NumberOfCpus(); - NThread* nt = NKern::CurrentThread(); - TUint32 aff0 = NKern::ThreadSetCpuAffinity(nt, 0); - TInt i; - for (i=0; iiSX.iLocalTimerAddr; - tmr->iTimerCtrl = (tmr->iTimerCtrl &~ E_ArmTmrCtrl_PrescaleMask) | ((pv << E_ArmTmrCtrl_PrescaleShift) & E_ArmTmrCtrl_PrescaleMask); - __e32_io_completion_barrier(); - NKern::RestoreInterrupts(irq); - } - } - NKern::ThreadSetCpuAffinity(nt, aff0); - if (aCpus & 0x80000000u) - { - // notify nanokernel of frequency changes - SVariantInterfaceBlock* vib = iS->iVIB; - SRatio ratio[KMaxCpus]; - for (i=0; iiTimerFreqR[i] = &ratio[i]; - } - } - (*vib->iFrqChgFn)(); - } - } - -#if defined(__CPU_ARM_HAS_GLOBAL_TIMER_BLOCK) && defined( __NKERN_TIMESTAMP_USE_SCU_GLOBAL_TIMER__) -void DFrqChg::SetGlobalTimerPrescaler(TInt aPrescale) - { - TInt pv = aPrescale; - if (pv <= 0) - pv = iDefaultGTPrescale; - - ArmGlobalTimer* tmr = iS->iSX.iGlobalTimerAddr; - // TInt irq = NKern::DisableAllInterrupts(); - tmr->iTimerCtrl = (tmr->iTimerCtrl &~ E_ArmGTmrCtrl_PrescaleMask) | ((pv << E_ArmGTmrCtrl_PrescaleShift) & E_ArmGTmrCtrl_PrescaleMask); - __e32_io_completion_barrier(); - // NKern::RestoreInterrupts(irq); - - // notify nanokernel of frequency changes - SVariantInterfaceBlock* vib = iS->iVIB; - SRatio ratio; - - if (aPrescale<=0) - ratio.Set(1); - else - PrescaleRatio(ratio, iDefaultGTPrescale, aPrescale); - - vib->iGTimerFreqR = ∶ - (*vib->iFrqChgFn)(); - } - -#endif -#endif -