sl@0: // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // \e32test\benchmark\bm_mcot_pdd.cpp sl@0: // PDD to provide OS timer services to benchmark programs sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: sl@0: sl@0: #include "k32bm.h" sl@0: sl@0: class DBMMcotDevice : public DPhysicalDevice sl@0: { sl@0: public: sl@0: DBMMcotDevice(); sl@0: virtual TInt Install(); sl@0: virtual void GetCaps(TDes8& aDes) const; sl@0: virtual TInt Create(DBase*& aChannel, TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); sl@0: virtual TInt Validate(TInt aUnit, const TDesC8* anInfo, const TVersion& aVer); sl@0: }; sl@0: sl@0: class DBMMcotChannel : public DBMPChannel sl@0: { sl@0: public: sl@0: DBMMcotChannel(); sl@0: ~DBMMcotChannel(); sl@0: sl@0: // Report timing spec sl@0: virtual TBMTicks TimerPeriod(); sl@0: // Get current OST tick time sl@0: virtual TBMTicks TimerStamp(); sl@0: // Tick/nS conversions sl@0: virtual TBMNs TimerTicksToNs(TBMTicks); sl@0: virtual TBMTicks TimerNsToTicks(TBMNs); sl@0: // Pass in client ISRs to invoke sl@0: virtual TInt BindInterrupt(MBMIsr*); sl@0: virtual TInt BindInterrupt(MBMInterruptLatencyIsr*); sl@0: // Invoke an ISR sl@0: virtual void RequestInterrupt(); sl@0: virtual void CancelInterrupt(); sl@0: sl@0: private: sl@0: sl@0: // Attach to OST interrupt sl@0: TInt BindInterrupt(); sl@0: sl@0: static const TInt KBMMcotInterruptDelayTicks = KHwOscFreqHz / 1000; // ie. delay ~ 1 ms timer tick! sl@0: static const TBMTicks KBMMcotPeriod = (((TBMTicks) 1) << 32); sl@0: static const TBMNs KBMMcotNsPerTick = (1000*1000*1000) / KHwOscFreqHz; sl@0: sl@0: // Real ISR (calls out to client) sl@0: static void Isr(TAny*); sl@0: sl@0: MBMIsr* iIsr; sl@0: MBMInterruptLatencyIsr* iInterruptLatencyIsr; sl@0: }; sl@0: sl@0: // Standard boiler plate PDD factory object sl@0: sl@0: DECLARE_STANDARD_PDD() sl@0: // sl@0: // Create a new device sl@0: // sl@0: { sl@0: __ASSERT_CRITICAL; sl@0: return new DBMMcotDevice; sl@0: } sl@0: sl@0: DBMMcotDevice::DBMMcotDevice() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: //iUnitsMask=0; sl@0: iVersion = TVersion(1,0,1); sl@0: } sl@0: sl@0: TInt DBMMcotDevice::Install() sl@0: // sl@0: // Install the device driver. sl@0: // sl@0: { sl@0: TInt r = SetName(&KBMPdName); sl@0: return r; sl@0: } sl@0: sl@0: void DBMMcotDevice::GetCaps(TDes8& aDes) const sl@0: // sl@0: // Return the Comm capabilities. sl@0: // sl@0: { sl@0: } sl@0: sl@0: TInt DBMMcotDevice::Create(DBase*& aChannel, TInt /*aUnit*/, const TDesC8* /*aInfo*/, const TVersion& /*aVer*/) sl@0: // sl@0: // Create a channel on the device. sl@0: // sl@0: { sl@0: __ASSERT_CRITICAL; sl@0: aChannel = new DBMMcotChannel; sl@0: return aChannel?KErrNone:KErrNoMemory; sl@0: } sl@0: sl@0: TInt DBMMcotDevice::Validate(TInt /*aUnit*/, const TDesC8* /*anInfo*/, const TVersion& aVer) sl@0: { sl@0: if (!Kern::QueryVersionSupported(iVersion,aVer)) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: // Actual device channel functions, called by LDD sl@0: sl@0: // Clear saved ISR members sl@0: DBMMcotChannel::DBMMcotChannel() sl@0: { sl@0: // iIsr = NULL; sl@0: // iInterruptLatencyIsr = NULL; sl@0: } sl@0: sl@0: // If we ever initialised the timers to generate ISRs, clear sl@0: DBMMcotChannel::~DBMMcotChannel() sl@0: { sl@0: if (iIsr || iInterruptLatencyIsr) sl@0: { sl@0: TCotulla::DisableOstInterrupt(KHwOstMatchGeneral); sl@0: TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); sl@0: Interrupt::Disable(KIntIdOstMatchGeneral); sl@0: TCotulla::ModifyIntLevels(KHtIntsOstMatchGeneral,0); sl@0: Interrupt::Unbind(KIntIdOstMatchGeneral); sl@0: } sl@0: } sl@0: sl@0: TBMTicks DBMMcotChannel::TimerPeriod() sl@0: { sl@0: return KBMMcotPeriod; sl@0: } sl@0: sl@0: // Read OST and return tick count sl@0: TBMTicks DBMMcotChannel::TimerStamp() sl@0: { sl@0: return TUint(TCotulla::OstData()); sl@0: } sl@0: sl@0: TBMNs DBMMcotChannel::TimerTicksToNs(TBMTicks ticks) sl@0: { sl@0: return ticks * KBMMcotNsPerTick; sl@0: } sl@0: sl@0: TBMTicks DBMMcotChannel::TimerNsToTicks(TBMNs ns) sl@0: { sl@0: return ns / KBMMcotNsPerTick; sl@0: } sl@0: sl@0: // Actual ISR called when benchmark timer fires sl@0: void DBMMcotChannel::Isr(TAny* ptr) sl@0: { sl@0: DBMMcotChannel* mCh = (DBMMcotChannel*) ptr; sl@0: BM_ASSERT(mCh->iIsr || mCh->iInterruptLatencyIsr); sl@0: if (mCh->iIsr) sl@0: { sl@0: // Call the handler with the current OST time sl@0: mCh->iIsr->Isr(TUint(TCotulla::OstData())); sl@0: } sl@0: else sl@0: { sl@0: // Call the handler with the difference between NOW and the time the match timer was set for sl@0: // ie. the latency between the timer interrupt set and when it was called. sl@0: mCh->iInterruptLatencyIsr->InterruptLatencyIsr(TCotulla::OstData() - TCotulla::OstMatch(KHwOstMatchGeneral)); sl@0: } sl@0: TCotulla::DisableOstInterrupt(KHwOstMatchGeneral); sl@0: TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); sl@0: } sl@0: sl@0: sl@0: // Bind the OST match interrupt to a FIQ ISR - it will interrupt running IRQ service sl@0: // routines. sl@0: TInt DBMMcotChannel::BindInterrupt() sl@0: { sl@0: TInt r = Interrupt::Bind(KIntIdOstMatchGeneral, Isr, this); sl@0: if (r != KErrNone) sl@0: { sl@0: return r; sl@0: } sl@0: TCotulla::ModifyIntLevels(0, KHtIntsOstMatchGeneral); // route new timer interrupt to FIQ sl@0: TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); sl@0: Interrupt::Enable(KIntIdOstMatchGeneral); sl@0: return KErrNone; sl@0: } sl@0: sl@0: // NB! Only one of these is ever used per channel opening, ie. the sl@0: // channel must be closed and re-opened between installing client ISR sl@0: TInt DBMMcotChannel::BindInterrupt(MBMIsr* aIsr) sl@0: { sl@0: BM_ASSERT(!iIsr); sl@0: BM_ASSERT(!iInterruptLatencyIsr); sl@0: iIsr = aIsr; sl@0: return BindInterrupt(); sl@0: } sl@0: sl@0: TInt DBMMcotChannel::BindInterrupt(MBMInterruptLatencyIsr* aIsr) sl@0: { sl@0: BM_ASSERT(!iIsr); sl@0: BM_ASSERT(!iInterruptLatencyIsr); sl@0: iInterruptLatencyIsr = aIsr; sl@0: return BindInterrupt(); sl@0: } sl@0: sl@0: // Called by client to request an interrupt (ISR/latency ISR) invocation in ~1mS. sl@0: void DBMMcotChannel::RequestInterrupt() sl@0: { sl@0: BM_ASSERT(iIsr || iInterruptLatencyIsr); sl@0: TCotulla::SetOstMatch(TCotulla::OstData()+KBMMcotInterruptDelayTicks,KHwOstMatchGeneral); sl@0: TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); sl@0: TCotulla::EnableOstInterrupt(KHwOstMatchGeneral); sl@0: } sl@0: sl@0: // Called to cancel if client dies/killed after ISR scheduled ??? sl@0: void DBMMcotChannel::CancelInterrupt() sl@0: { sl@0: if (iIsr || iInterruptLatencyIsr) sl@0: { sl@0: TCotulla::DisableOstInterrupt(KHwOstMatchGeneral); sl@0: TCotulla::SetOstMatchEOI(KHwOstMatchGeneral); sl@0: } sl@0: } sl@0: