kerneltest/e32test/nkernsa/nirqx.cpp
changeset 0 a41df078684a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32test/nkernsa/nirqx.cpp	Mon Oct 19 15:55:17 2009 +0100
@@ -0,0 +1,151 @@
+// Copyright (c) 2007-2009 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\nkernsa\nirqx.cpp
+// 
+//
+
+#include <nk_irq.h>
+
+#ifdef __X86__
+#include <apic.h>
+#endif
+
+class NIrqXTest : public NIrqX
+	{
+public:
+	NIrqXTest();
+	void Kick();
+	void Set(TBool aLevel);
+public:
+	static void DoEoi(NIrq* aIrq);
+	static void DoEnable(NIrq* aIrq);
+	static void DoDisable(NIrq* aIrq);
+	static void DoSetCpu(NIrq* aIrq, TUint32 aMask);
+	static void DoInit(NIrq* aIrq);
+	static TBool DoPending(NIrq* aIrq);
+	static void DoWait(NIrq* aIrq);
+public:
+	TSpinLock			iLock;
+	NIrq*				iIrq;
+	TUint32				iCpuMask;
+	TUint8				iEnabled;
+	TUint8				iPending;
+	TUint8				iLevel;
+	};
+
+NIrqXTest::NIrqXTest()
+	{
+	iIrq = 0;
+	iCpuMask = 0x1;
+	iEnabled = 0;
+	iPending = 0;
+	iLevel = 0;
+	}
+
+void NIrqXTest::Set(TBool aLevel)
+	{
+	TBool active = FALSE;
+	TInt irq = __SPIN_LOCK_IRQSAVE(iLock);
+	TUint32 f = iIrq->iStaticFlags;
+	if (f & NIrq::ELevel)
+		{
+		if (f & NIrq::EPolarity)
+			{
+			active = aLevel;
+			}
+		else
+			{
+			active = !aLevel;
+			}
+		}
+	else
+		{
+		if (f & NIrq::EPolarity)
+			{
+			active = aLevel && !iLevel;
+			}
+		else
+			{
+			active = !aLevel && iLevel;
+			}
+		}
+	iLevel = (TUint8)(aLevel ? 1 : 0);
+	if (active && iEnabled)
+		Kick();
+	__SPIN_UNLOCK_IRQRESTORE(iLock,irq);
+	}
+
+#if defined (__X86__)
+__NAKED__ void NIrqXTest::Kick()
+	{
+	_asm mov al, 1
+	_asm lock xchg al, [ecx]NIrqXTest.iPending
+	_asm cmp al, 0
+	_asm jne short kick0
+	_asm mov eax, [ecx]NIrqXTest.iCpuMask
+	_asm shl eax, 24
+	_asm jz short kick0	// no CPUs, so nothing to do
+	_asm mov ds:[X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRH], eax
+	_asm mov eax, [ecx]NIrqXTest.iIrq
+	_asm mov eax, [eax]NIrq.iVector
+	_asm or eax, 0x4800
+	_asm mov ds:[X86_LOCAL_APIC_BASE + X86_LOCAL_APIC_OFFSET_ICRL], eax
+	_asm kick0:
+	_asm ret
+	}
+#endif
+
+void NIrqXTest::DoEoi(NIrq* aIrq)
+	{
+	NIrqXTest* pX = (NIrqXTest*)iX;
+	TInt irq = __SPIN_LOCK_IRQSAVE(pX->iLock);
+	if (pX->iPending)
+		{
+		pX->iPending = 0;
+		TUint32 f = aIrq->iStaticFlags;
+		if (f & NIrq::ELevel)
+			{
+			TUint active_level = (f & NIrq::EPolarity) ? 1 : 0;
+			if (pX->iLevel==active_level && pX->iEnabled)
+				pX->Kick();
+			}
+		}
+	__SPIN_UNLOCK_IRQRESTORE(pX->iLock,irq);
+	}
+
+void NIrqXTest::DoEnable(NIrq* aIrq)
+	{
+	}
+
+void NIrqXTest::DoDisable(NIrq* aIrq)
+	{
+	}
+
+void NIrqXTest::DoSetCpu(NIrq* aIrq, TUint32 aMask)
+	{
+	}
+
+void NIrqXTest::DoInit(NIrq* aIrq)
+	{
+	iIrq = aIrq;
+	}
+
+TBool NIrqXTest::DoPending(NIrq* aIrq)
+	{
+	}
+
+void NIrqXTest::DoWait(NIrq* aIrq)
+	{
+	}
+