sl@0: // Copyright (c) 2007-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: // e32\include\nkernsmp\nk_irq.h sl@0: // sl@0: // WARNING: This file contains some APIs which are internal and are subject sl@0: // to change without notice. Such APIs should therefore not be used sl@0: // outside the Kernel and Hardware Services package. sl@0: // sl@0: sl@0: /** sl@0: @file sl@0: @internalTechnology sl@0: */ sl@0: sl@0: #ifndef __NK_IRQ_H__ sl@0: #define __NK_IRQ_H__ sl@0: sl@0: #ifndef NK_MAX_IRQS sl@0: #if defined(__CPU_ARM) sl@0: #define NK_MAX_IRQS 96 // 32-127 on GIC sl@0: #else sl@0: #define NK_MAX_IRQS 32 sl@0: #endif sl@0: #endif sl@0: sl@0: #ifndef NK_MAX_IRQ_HANDLERS sl@0: #if defined(__CPU_ARM) sl@0: #define NK_MAX_IRQ_HANDLERS (1*NK_MAX_IRQS) sl@0: #else sl@0: #define NK_MAX_IRQ_HANDLERS (2*NK_MAX_IRQS) sl@0: #endif sl@0: #endif sl@0: sl@0: #include sl@0: #include sl@0: sl@0: class NSchedulable; sl@0: class NThreadBase; sl@0: class NThread; sl@0: class NFastSemaphore; sl@0: class NFastMutex; sl@0: sl@0: /****************************************************************************** sl@0: * Class per peripheral interrupt sl@0: ******************************************************************************/ sl@0: class NIrqHandler; sl@0: class NIrqX; sl@0: class NIrq sl@0: { sl@0: public: sl@0: NIrq(); sl@0: public: sl@0: // client services sl@0: TInt BindRaw(NIsr aIsr, TAny* aPtr); sl@0: TInt UnbindRaw(); sl@0: TInt DisableRaw(TBool aUnbind); sl@0: TInt EnableRaw(); sl@0: TInt Bind(NIrqHandler* aH); sl@0: static TInt FromHandle(TInt& aHandle, NIrq*& aIrq, NIrqHandler*& aHandler); sl@0: public: sl@0: // HW access sl@0: void HwIsr(); sl@0: void HwEoi(); sl@0: void HwEnable(); sl@0: void HwDisable(); sl@0: void HwSetCpu(TInt aCpu); sl@0: void HwSetCpuMask(TUint32 aMask); sl@0: void HwInit(); sl@0: static void HwInit0(); sl@0: static void HwInit1(); sl@0: static void HwInit2AP(); sl@0: TBool HwPending(); sl@0: void HwWaitCpus(); sl@0: public: sl@0: // functions to manipulate iIState sl@0: TUint32 EnterIsr(); // wait for EWait clear, increment run count, return original iIState sl@0: TBool IsrDone(); // decrement run count, return TRUE if still not zero sl@0: void Wait(); // wait until run count is zero and we can transition EWait from 0 to 1 sl@0: void Done(); // set EWait back to 0 sl@0: public: sl@0: enum { // iStaticFlags sl@0: ELevel=0x01, // set for level triggered, clear for edge sl@0: EPolarity=0x02, // set for active high, clear for active low sl@0: EShared=0x10, // set if interrupt can be shared sl@0: }; sl@0: enum { // iIState bits 0-7 sl@0: EWait=0x01, sl@0: ERaw=0x02, // raw ISR with no processing, can't be shared sl@0: ECount=0x04, // if set count all interrupts else limit pending count to 1 sl@0: EUnbind=0x08, // raw ISR being unbound sl@0: }; sl@0: public: sl@0: TSpinLock iNIrqLock; sl@0: SDblQue iHandlers; sl@0: volatile TUint32 iIState; // bits 0-7=flags, bits 8-15=CPU on which it is running, bits 16-31=run count sl@0: TUint16 iStaticFlags; sl@0: TUint16 iIndex; sl@0: volatile TUint32 iEventsPending; sl@0: volatile TUint32 iEnabledEvents; // bits 1-31 = count of enabled handlers, bit 0 = 1 if temporarily disabled sl@0: volatile TUint32 iGeneration; // incremented on unbind raw or enable while bound as raw sl@0: TUint32 iHwId; sl@0: TUint32 iVector; sl@0: NIrqX* iX; sl@0: TUint32 iNIrqSpare[16-10-sizeof(TSpinLock)/sizeof(TUint32)]; sl@0: }; sl@0: sl@0: __ASSERT_COMPILE(!(_FOFF(NIrq,iNIrqLock)&7)); sl@0: __ASSERT_COMPILE(sizeof(NIrq)==64); sl@0: sl@0: class NIrqX sl@0: { sl@0: public: sl@0: typedef void (*TEoiFn)(NIrq*); sl@0: typedef void (*TEnableFn)(NIrq*); sl@0: typedef void (*TDisableFn)(NIrq*); sl@0: typedef void (*TSetCpuFn)(NIrq*, TUint32); sl@0: typedef void (*TInitFn)(NIrq*); sl@0: typedef TBool (*TPendingFn)(NIrq*); sl@0: typedef void (*TWaitFn)(NIrq*); sl@0: public: sl@0: TEoiFn iEoiFn; sl@0: TEnableFn iEnableFn; sl@0: TDisableFn iDisableFn; sl@0: TSetCpuFn iSetCpuFn; sl@0: TInitFn iInitFn; sl@0: TPendingFn iPendingFn; sl@0: TWaitFn iWaitFn; sl@0: }; sl@0: sl@0: /****************************************************************************** sl@0: * Class per interrupt handler sl@0: ******************************************************************************/ sl@0: typedef NEventFn NIsr; sl@0: class TSubScheduler; sl@0: class NIrqHandler : public NEventHandler sl@0: { sl@0: public: sl@0: NIrqHandler(); sl@0: static NIrqHandler* Alloc(); sl@0: void Free(); sl@0: void Activate(TInt aCount); sl@0: TInt Enable(TInt aHandle); sl@0: TInt Disable(TBool aUnbind, TInt aHandle); sl@0: TInt Unbind(TInt aId, NSchedulable* aTied); sl@0: void DoUnbind(); sl@0: public: sl@0: // functions to manipulate iHState sl@0: TUint32 DoSetEnabled(); // if EUnbound clear, clear EDisable. Return original iHState sl@0: TUint32 DoActivate(TInt); sl@0: TUint32 EventBegin(); sl@0: TUint32 EventDone(); sl@0: public: sl@0: enum { // iHState bits 8-31 sl@0: EDisable =0x00000100u, sl@0: EUnbind =0x00000200u, // this handler is being unbound sl@0: EBind =0x00000400u, // this handler has been bound but not enabled sl@0: ENotReady =0x00000800u, // this handler is being bound sl@0: ECount =0x00001000u, // if set count all interrupts else limit pending count to 1 sl@0: EActive =0x00002000u, // handler is running or about to run sl@0: EExclusive =0x00004000u, // exclusive access to shared interrupt sl@0: ERunCountMask =0xffff0000u sl@0: }; sl@0: public: sl@0: SDblQueLink iIrqLink; // link to NIrq sl@0: NIrq* volatile iIrq; sl@0: volatile TUint32 iGeneration; // incremented on enable or bind sl@0: volatile TUint32 iHandle; // bits 0-15 = array index, bits 16-30 = cookie, 1-32767 sl@0: TUint32 iNIrqHandlerSpare[3]; // round to power of 2 sl@0: public: sl@0: static NIrqHandler* FirstFree; // protected by NEventHandler::TiedLock sl@0: }; sl@0: sl@0: __ASSERT_COMPILE(sizeof(NIrqHandler)==64); sl@0: sl@0: sl@0: #if 0 sl@0: #include sl@0: #define IRQ_TRACE_CAT 253 // FIXME sl@0: #define TRACE_IRQ0(n) BTraceContextPc0(IRQ_TRACE_CAT, n) sl@0: #define TRACE_IRQ4(n,a) BTraceContextPc4(IRQ_TRACE_CAT, n, a) sl@0: #define TRACE_IRQ8(n,a,b) BTraceContextPc8(IRQ_TRACE_CAT, n, a, b) sl@0: #define TRACE_IRQ12(n,a,b,c) BTraceContextPc12(IRQ_TRACE_CAT, n, a, b, c) sl@0: #else sl@0: #define TRACE_IRQ0(n) sl@0: #define TRACE_IRQ4(n,a) sl@0: #define TRACE_IRQ8(n,a,b) sl@0: #define TRACE_IRQ12(n,a,b,c) sl@0: #endif sl@0: sl@0: #endif // __NK_IRQ_H__