We need a way to pass flags to rombuilds in Raptor via extension flm interfaces, so that the CPP pass
of the rom input files can be informed what toolchain we are building with and conditionally
include or exclude files depending on whether the toolchain could build them.
// Copyright (c) 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:
// d_timestamp.cpp
//
#include <kern_priv.h>
#include <kernel.h>
#include "d_timestamp.h"
#include "d_timestamp_dev.h"
// time stamp test defaults
static const TInt KTimerDurationS = 5; // time interval for NTimer
static const TInt KNErrPercent = 1; // percent error acceptable
static const TInt KIterations = 5; // required number of valid runs (with LPM entry)
static const TInt KRetries = 4; // retries are reset on every succesful run
//
// DTimestampTestFactory
//
/**
Standard export function for LDDs. This creates a DLogicalDevice derived object,
in this case, our DTimestampTestFactory
*/
DECLARE_STANDARD_LDD()
{
return new DTimestampTestFactory;
}
/**
Constructor
*/
DTimestampTestFactory::DTimestampTestFactory()
{
// Set version number for this device
iVersion=RTimestampTest::VersionRequired();
// Indicate that we work with a PDD
iParseMask=KDeviceAllowPhysicalDevice;
}
/**
Second stage constructor for DTimestampTestFactory.
This must at least set a name for the driver object.
@return KErrNone if successful, otherwise one of the other system wide error codes.
*/
TInt DTimestampTestFactory::Install()
{
return SetName(&RTimestampTest::Name());
}
/**
Destructor
*/
DTimestampTestFactory::~DTimestampTestFactory()
{
}
/**
Return the drivers capabilities.
Called in the response to an RDevice::GetCaps() request.
@param aDes User-side descriptor to write capabilities information into
*/
void DTimestampTestFactory::GetCaps(TDes8& aDes) const
{
// Create a capabilities object
RTimestampTest::TCaps caps;
caps.iVersion = iVersion;
// Write it back to user memory
Kern::InfoCopy(aDes,(TUint8*)&caps,sizeof(caps));
}
/**
Called by the kernel's device driver framework to create a Logical Channel.
This is called in the context of the user thread (client) which requested the creation of a Logical Channel
(E.g. through a call to RBusLogicalChannel::DoCreate)
The thread is in a critical section.
@param aChannel Set to point to the created Logical Channel
@return KErrNone if successful, otherwise one of the other system wide error codes.
*/
TInt DTimestampTestFactory::Create(DLogicalChannelBase*& aChannel)
{
aChannel=new DTimestampTestChannel;
if(!aChannel)
{
return KErrNoMemory;
}
return KErrNone;
}
//
// Logical Channel
//
/**
Constructor
*/
DTimestampTestChannel::DTimestampTestChannel()
:iTimer(timerExpire,this),iDfc(dfcFn,this,7),iStarted(EFalse)
{
// Get pointer to client threads DThread object
iClient=&Kern::CurrentThread();
// Open a reference on client thread so it's control block can't dissapear until
// this driver has finished with it.
// Note, this call to Open can't fail since its the thread we are currently running in
iClient->Open();
}
/**
Second stage constructor called by the kernel's device driver framework.
This is called in the context of the user thread (client) which requested the creation of a Logical Channel
(E.g. through a call to RBusLogicalChannel::DoCreate)
The thread is in a critical section.
@param aUnit The unit argument supplied by the client to RBusLogicalChannel::DoCreate
@param aInfo The info argument supplied by the client to RBusLogicalChannel::DoCreate
@param aVer The version argument supplied by the client to RBusLogicalChannel::DoCreate
@return KErrNone if successful, otherwise one of the other system wide error codes.
*/
TInt DTimestampTestChannel::DoCreate(TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& aVer)
{
// Check version
if (!Kern::QueryVersionSupported(RTimestampTest::VersionRequired(),aVer))
return KErrNotSupported;
// Setup LDD for receiving client messages
TInt r = Kern::CreateClientRequest(iStartRequest);
if (r != KErrNone) return r;
r = Kern::CreateClientDataRequest(iWaitOnTimerRequest);
if (r != KErrNone) return r;
r = Kern::DynamicDfcQCreate(iQue,Kern::DfcQue0()->iThread->iPriority,RTimestampTest::Name());
if (KErrNone!=r) return r;
iDfc.SetDfcQ(iQue);
SetDfcQ(iQue);
iMsgQ.Receive();
// Done
return KErrNone;
}
/**
Destructor
*/
DTimestampTestChannel::~DTimestampTestChannel()
{
// Cancel all processing that we may be doing
DoCancel(TUint(RTimestampTest::EAllRequests));
Kern::DestroyClientRequest(iWaitOnTimerRequest);
Kern::DestroyClientRequest(iStartRequest);
iQue->Destroy();
// Close our reference on the client thread
Kern::SafeClose((DObject*&)iClient,NULL);
}
/**
Called when a user thread requests a handle to this channel.
*/
TInt DTimestampTestChannel::RequestUserHandle(DThread* aThread, TOwnerType aType)
{
// Make sure that only our client can get a handle
if (aType!=EOwnerThread || aThread!=iClient)
return KErrAccessDenied;
return KErrNone;
}
/**
override SendMsg method to allow pinning data in the context of the client thread
*/
TInt DTimestampTestChannel::SendMsg(TMessageBase* aMsg)
{
TThreadMessage& m=*(TThreadMessage*)aMsg;
TInt id = m.iValue;
// we only support one client
if (id != (TInt)ECloseMsg && m.Client() != iClient)
return KErrAccessDenied;
TInt r = KErrNone;
if (id != (TInt)ECloseMsg && id != KMaxTInt)
{
if (id<0)
{
TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
r = SendRequest(aMsg);
if (r != KErrNone)
Kern::RequestComplete(pS,r);
}
else
r = SendControl(aMsg);
}
else
r = DLogicalChannel::SendMsg(aMsg);
return r;
}
/**
Process a message for this logical channel.
This function is called in the context of a DFC thread.
@param aMessage The message to process.
The iValue member of this distinguishes the message type:
iValue==ECloseMsg, channel close message
iValue==KMaxTInt, a 'DoCancel' message
iValue>=0, a 'DoControl' message with function number equal to iValue
iValue<0, a 'DoRequest' message with function number equal to ~iValue
*/
void DTimestampTestChannel::HandleMsg(TMessageBase* aMsg)
{
TThreadMessage& m=*(TThreadMessage*)aMsg;
// Get message type
TInt id=m.iValue;
// Decode the message type and dispatch it to the relevent handler function...
if (id==(TInt)ECloseMsg)
{
// Channel Close
DoCancel(TUint(RTimestampTest::EAllRequests));
iMsgQ.CompleteAll(KErrServerTerminated);
m.Complete(KErrNone, EFalse);
return;
}
if (id==KMaxTInt)
{
// DoCancel
DoCancel(m.Int0());
m.Complete(KErrNone,ETrue);
return;
}
if (id<0)
{
// DoRequest
TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
DoRequest(~id,pS,m.Ptr1(),m.Ptr2());
m.Complete(KErrNone,ETrue);
}
else
{
// DoControl
TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
m.Complete(r,ETrue);
}
}
/**
Preprocess synchronous 'control' requests
*/
TInt DTimestampTestChannel::SendControl(TMessageBase* aMsg)
{
TThreadMessage& m=*(TThreadMessage*)aMsg;
TInt id=m.iValue;
switch (id)
{
case RTimestampTest::EConfig:
{
STimestampTestConfig info;
#ifdef __SMP__
info.iFreq = NKern::TimestampFrequency();
#else
info.iFreq = NKern::FastCounterFrequency();
#endif
info.iIterations = KIterations;
info.iRetries = KRetries;
info.iTimerDurationS = KTimerDurationS;
info.iErrorPercent = KNErrPercent;
// Allow PDD to override defaults
Pdd().TestConfig(info);
kumemput(m.Ptr0(),&info,sizeof(STimestampTestConfig));
return KErrNone;
}
}
TInt r = DLogicalChannel::SendMsg(aMsg);
if (r != KErrNone)
return r;
// switch (id)
// {
// }
return r;
}
/**
Process synchronous 'control' requests
*/
TInt DTimestampTestChannel::DoControl(TInt aFunction, TAny* a1, TAny* a2)
{
(void)a2;
(void)a1;
(void) aFunction;
// TInt r = KErrNone;
// switch (aFunction)
// {
// default:
// r = KErrNotSupported;
// }
return KErrNotSupported;
}
/**
Preprocess asynchronous requests.
*/
TInt DTimestampTestChannel::SendRequest(TMessageBase* aMsg)
{
TThreadMessage& m=*(TThreadMessage*)aMsg;
TInt function = ~m.iValue;
TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
TInt r = KErrNotSupported;
switch (function)
{
case RTimestampTest::EStart:
if (!iStarted)
{
r = iStartRequest->SetStatus(pS);
}
else
{
r = KErrInUse;
}
break;
case RTimestampTest::EWaitOnTimer:
if (iStarted)
{
iWaitOnTimerRequest->SetDestPtr(m.Ptr1());
r = iWaitOnTimerRequest->SetStatus(pS);
}
else
{
r = KErrNotReady;
}
break;
default:
r = KErrNotSupported;
}
if (r == KErrNone)
r = DLogicalChannel::SendMsg(aMsg);
return r;
}
/**
Process asynchronous requests.
*/
void DTimestampTestChannel::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)
{
(void)a2;
(void)a1;
(void)aStatus;
TInt r = KErrNone;
switch(aReqNo)
{
case RTimestampTest::EStart:
iNTicks = (TInt) a1;
r = iTimer.OneShot(0);
if (KErrNone!=r) Kern::QueueRequestComplete(iClient,iStartRequest,r);
break;
case RTimestampTest::EWaitOnTimer:
Pdd().StartLPMEntryCheck(); // PDD will start checking if we have entered LPM
r = iTimer.Again(iNTicks);
if (KErrNone!=r) Kern::QueueRequestComplete(iClient,iWaitOnTimerRequest,r);
break;
}
}
/**
Process cancelling of asynchronous requests.
*/
void DTimestampTestChannel::DoCancel(TUint aMask)
{
(void)aMask;
iTimer.Cancel(); // no real guarantees on SMP systems
iDfc.Cancel();
}
/**
* process timer expiry
*/
void DTimestampTestChannel::DoTimerExpire()
{
#ifdef __SMP__
TUint64 ts = NKern::Timestamp();
#else
TUint64 ts = NKern::FastCounter();
#endif
iTimestampDelta = ts-iLastTimestamp;
iLastTimestamp = ts;
iDfc.Add();
}
void DTimestampTestChannel::timerExpire(TAny* aParam)
{
DTimestampTestChannel* pD = (DTimestampTestChannel*) aParam;
pD->DoTimerExpire();
}
void DTimestampTestChannel::DoDfcFn()
{
if (!iStarted)
{
iStarted = ETrue;
Kern::QueueRequestComplete(iClient,iStartRequest,KErrNone);
}
else
{
iWaitOnTimerRequest->Data().iDelta = iTimestampDelta;
// PDD will return ETrue here if we have entered LPM
iWaitOnTimerRequest->Data().iLPMEntered = Pdd().EndLPMEntryCheck();
Kern::QueueRequestComplete(iClient,iWaitOnTimerRequest,KErrNone);
}
}
void DTimestampTestChannel::dfcFn(TAny* aParam)
{
DTimestampTestChannel* pD = (DTimestampTestChannel*) aParam;
pD->DoDfcFn();
}