diff -r 000000000000 -r a41df078684a kernel/eka/nkernsmp/arm/ncutils.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/nkernsmp/arm/ncutils.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,311 @@ +// Copyright (c) 2008-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: +// e32\nkernsmp\arm\ncutils.cpp +// +// + +#include +#include +#include +#include +#include + +extern "C" { +extern SVariantInterfaceBlock* VIB; +} + +/****************************************************************************** + * Spin lock + ******************************************************************************/ +/** Create a spin lock + + @publishedPartner + @released +*/ +EXPORT_C TSpinLock::TSpinLock(TUint aOrder) + { + (void)aOrder; + __NK_ASSERT_DEBUG( (aOrder==EOrderNone) || ((aOrder&0x7f)<0x20) ); + if (aOrder>=0x80 && aOrder!=EOrderNone) + aOrder -= 0x60; + aOrder |= 0xFF00u; + iLock = TUint64(aOrder)<<48; // byte 6 = 00-1F for interrupt, 20-3F for preemption + // byte 7 = FF if not held + } + + +/****************************************************************************** + * Read/Write Spin lock + ******************************************************************************/ +/** Create a spin lock + + @publishedPartner + @released +*/ +EXPORT_C TRWSpinLock::TRWSpinLock(TUint aOrder) + { + (void)aOrder; + __NK_ASSERT_DEBUG( (aOrder==TSpinLock::EOrderNone) || ((aOrder&0x7f)<0x20) ); + if (aOrder>=0x80 && aOrder!=TSpinLock::EOrderNone) + aOrder -= 0x60; + aOrder |= 0xFF00u; + iLock = TUint64(aOrder)<<48; // byte 6 = 00-1F for interrupt, 20-3F for preemption + // byte 7 = FF if not held + } + + + +#ifdef _DEBUG +void FastMutexNestAttempt() + { + FAULT(); + } + +void FastMutexSignalError() + { + FAULT(); + } +#endif + +void NKern::Init0(TAny* a) + { + __KTRACE_OPT(KBOOT,DEBUGPRINT("VIB=%08x", a)); + VIB = (SVariantInterfaceBlock*)a; + __NK_ASSERT_ALWAYS(VIB && VIB->iVer==0 && VIB->iSize==sizeof(SVariantInterfaceBlock)); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iVer=%d iSize=%d", VIB->iVer, VIB->iSize)); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxCpuClock=%08x %08x", I64HIGH(VIB->iMaxCpuClock), I64LOW(VIB->iMaxCpuClock))); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iMaxTimerClock=%u", VIB->iMaxTimerClock)); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iScuAddr=%08x", VIB->iScuAddr)); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iGicDistAddr=%08x", VIB->iGicDistAddr)); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iGicCpuIfcAddr=%08x", VIB->iGicCpuIfcAddr)); + __KTRACE_OPT(KBOOT,DEBUGPRINT("iLocalTimerAddr=%08x", VIB->iLocalTimerAddr)); + + TScheduler& s = TheScheduler; + s.i_ScuAddr = (TAny*)VIB->iScuAddr; + s.i_GicDistAddr = (TAny*)VIB->iGicDistAddr; + s.i_GicCpuIfcAddr = (TAny*)VIB->iGicCpuIfcAddr; + s.i_LocalTimerAddr = (TAny*)VIB->iLocalTimerAddr; + s.i_TimerMax = (TAny*)(VIB->iMaxTimerClock / 1); // use prescaler value of 1 + + TInt i; + for (i=0; iiTimerMult[i] = (volatile STimerMult*)&ss.i_TimerMultF; + VIB->iCpuMult[i] = (volatile TUint32*)&ss.i_CpuMult; + } + InterruptInit0(); + } + +/** Register the global IRQ handler + Called by the base port at boot time to bind the top level IRQ dispatcher + to the ARM IRQ vector. Should not be called at any other time. + + The handler specified will be called in mode_irq with IRQs disabled and + FIQs enabled. R0-R3, R12 and the return address from the interrupt will + be on the top of the mode_irq stack. R14_irq will point to the kernel's + IRQ postamble routine, which will run IDFCs and reschedule if necessary. + R13_irq will point to the top of the mode_irq stack and will be 8-byte aligned. + The handler should preserve all registers other than R0-R3, R12, R14_irq + and should return to the address in R14_irq. + + @param aHandler The address of the top level IRQ dispatcher routine + */ +EXPORT_C void Arm::SetIrqHandler(TLinAddr aHandler) + { + ArmInterruptInfo.iIrqHandler=aHandler; + } + +/** Register the global FIQ handler + Called by the base port at boot time to bind the top level FIQ dispatcher + to the ARM FIQ vector. Should not be called at any other time. + + The handler specified will be called in mode_fiq with both IRQs and FIQs + disabled. The return address from the interrupt will be on the top of the + mode_fiq stack. R14_fiq will point to the kernel's FIQ postamble routine, + which will run IDFCs and reschedule if necessary. + R13_fiq will point to the top of the mode_fiq stack and will be 4 modulo 8. + The handler should preserve all registers other than R8_fiq-R12_fiq and + R14_fiq and should return to the address in R14_fiq. + + @param aHandler The address of the top level FIQ dispatcher routine + */ +EXPORT_C void Arm::SetFiqHandler(TLinAddr aHandler) + { + ArmInterruptInfo.iFiqHandler=aHandler; + } + +extern void initialiseState(TInt aCpu, TSubScheduler* aSS); + +void Arm::Init1Interrupts() +// +// Initialise the interrupt and exception vector handlers. +// + { + __KTRACE_OPT(KBOOT,DEBUGPRINT(">Arm::Init1Interrupts()")); + + TSubScheduler* ss = &TheSubSchedulers[0]; + initialiseState(0, ss); + + ArmLocalTimer& T = LOCAL_TIMER; + T.iWatchdogDisable = E_ArmTmrWDD_1; + T.iWatchdogDisable = E_ArmTmrWDD_2; + T.iTimerCtrl = 0; + T.iTimerIntStatus = E_ArmTmrIntStatus_Event; + T.iWatchdogCtrl = 0; + T.iWatchdogIntStatus = E_ArmTmrIntStatus_Event; + + NIrq::HwInit1(); + + __KTRACE_OPT(KBOOT,DEBUGPRINT(" TUint64(TInt(KMaxTInt))) + return KMaxTInt; + else + return (TInt)ticks; + } + + +/** Get the frequency of counter queried by NKern::Timestamp(). + +@publishedPartner +@prototype +*/ +EXPORT_C TUint32 NKern::TimestampFrequency() + { + return (TUint32)TheScheduler.i_TimerMax; + } +