diff -r 675a964f4eb5 -r 35751d3474b7 cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4rng.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4rng.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -0,0 +1,354 @@ +/* +* 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: +* +*/ + + +/** + @file + @internalComponent + @released +*/ +#include +#include +#ifdef __MARM__ +#include +#include +#endif +//#include "cryptoh4.h" +#include "cryptoldd.h" +#include "cryptoh4rng.h" + +inline void CryptoH4JobRandom::EnableIsr() + { + TRACE_FUNCTION("EnableIsr"); + // Kern::Printf("EI"); + SetRunning(ETrue); +#ifdef __MARM__ + // Enable RNG interrupt. This interrupt will then queue the + // "random number ready" DFC + TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask); + tmp |= 4; + TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp); +#else + // Not on real h/w so just queue the DFC... + // Queue the "random number ready" DFC + iRandomDfc.Enque(); // Queue from task level +#endif + } + +inline void CryptoH4JobRandom::DisableIsr() + { + TRACE_FUNCTION("DisableIsr"); + // Kern::Printf("DI"); +#ifdef __MARM__ + TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask); + tmp &= ~4; + TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp); +#endif + } + + + +CryptoH4JobRandom::CryptoH4JobRandom(DLddChanRandom &aLddChanRandom) + : iLddChanRandom(aLddChanRandom), + iJobSizeInBytes(0), + iSwReadByteOffset(0), + iHw32Index(0), + iIsrHooked(EFalse), + iRandomDfc(RandomDfc, this, 1) // DFC is priority '1' + { + TRACE_FUNCTION("CryptoH4JobRandom"); + // Kern::Printf("CryptoH4JobRandom::CryptoH4JobRandom %x", this); + } + +CryptoH4JobRandom::~CryptoH4JobRandom() + { + TRACE_FUNCTION("~CryptoH4JobRandom"); + // Kern::Printf("CryptoH4JobRandom::~CryptoH4JobRandom %x", this); + UnHookIsr(); + } + + +void CryptoH4JobRandom::SetDfcQ(TDfcQue *aDfcQue) + { + TRACE_FUNCTION("SetDfcQ"); + iRandomDfc.SetDfcQ(aDfcQue); + } + +void CryptoH4JobRandom::SetDetails(DCryptoJobScheduler *aJobScheduler, + MCryptoJobCallbacks *aCallbacks, + TUint32 aNumOfBytes) + { + TRACE_FUNCTION("SetDetails"); + // Kern::Printf("CryptoH4JobRandom::SetDetails"); + iJobScheduler = aJobScheduler; + iCallbacks = aCallbacks; + iJobSizeInBytes = aNumOfBytes; + } + +void CryptoH4JobRandom::GetToPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore) + { + TRACE_FUNCTION("GetToPddBuffer"); + aBuf = 0; + aBufLen = 0; + aMore = EFalse; + } + +void CryptoH4JobRandom::BytesWrittenToPdd(TUint32) + { + TRACE_FUNCTION("BytesWrittenToPdd"); + } + +void CryptoH4JobRandom::GetFromPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore) + { + TRACE_FUNCTION("GetFromPddBuffer"); + + TInt hw8Index = iHw32Index * 4; + TUint8 *p = (TUint8 *) iRandomBuffer; + aBuf = &p[iSwReadByteOffset]; + + TInt len = hw8Index - iSwReadByteOffset; + if(len >= 0) + { + aBufLen = len; + aMore = EFalse; + } + else + { + // Wrap round condition, but can only return contiguous bytes + aBufLen = sizeof(iRandomBuffer) - iSwReadByteOffset; + aMore = ETrue; + return; + } + } + +void CryptoH4JobRandom::BytesReadFromPdd(TUint32 aBytes) + { + TRACE_FUNCTION("BytesReadFromPdd"); + iSwReadByteOffset += aBytes; + if(iSwReadByteOffset >= sizeof(iRandomBuffer)) + { + iSwReadByteOffset -= sizeof(iRandomBuffer); + } + iJobSizeInBytes -= aBytes; + } + + + +void CryptoH4JobRandom::DoSlice(TBool aFirstSlice) + { + TRACE_FUNCTION("DoSlice"); + // Kern::Printf("DoSlice(%d)", aFirstSlice); + if(aFirstSlice) + { + HookIsr(); + } + + // Enable RNG interrupt. The interrupt will then queue the + // "random number ready" DFC when the h/w is ready. + // (when not on h/w, this immediately queues a DFC) + EnableIsr(); + } + +TBool CryptoH4JobRandom::DoSaveState() + { + TRACE_FUNCTION("DoSaveState"); + UnHookIsr(); + return ETrue; // We want DoRestoreState to be called + } + +void CryptoH4JobRandom::DoRestoreState() + { + TRACE_FUNCTION("DoRestoreState"); + HookIsr(); + } + +void CryptoH4JobRandom::DoReleaseHw() + { + TRACE_FUNCTION("DoReleaseHw"); + // Disable RNG interrupt + DisableIsr(); + + // Disable/unhook ISR + UnHookIsr(); + + // Cancel DFC + iRandomDfc.Cancel(); + + } + +TInt CryptoH4JobRandom::BytesAvailable() const + { + TRACE_FUNCTION("BytesAvailable"); + TInt hw8Index = iHw32Index * 4; + TInt available = hw8Index - iSwReadByteOffset; + if(available < 0) + { + available += sizeof(iRandomBuffer); + } + return available; + } + +void CryptoH4JobRandom::RegionsAvailable(TUint8 * &aPtr1, TInt &aLen1, + TUint8 * &aPtr2, TInt &aLen2) const + { + TRACE_FUNCTION("RegionsAvailable"); + TInt hw8Index = iHw32Index * 4; + TUint8 *p = (TUint8 *) iRandomBuffer; + aPtr1 = &p[iSwReadByteOffset]; + + TInt len = hw8Index - iSwReadByteOffset; + if(len < 0) + { + // Available data crosses buffer end so return two regions + aLen1 = sizeof(iRandomBuffer) - iSwReadByteOffset; + aPtr2 = &p[0]; + aLen2 = hw8Index; + } + else + { + // Available buffer is contiguous + aLen1 = len; + aPtr2 = 0; + aLen2 = 0; + } + } + + + +void CryptoH4JobRandom::HookIsr() + { + TRACE_FUNCTION("HookIsr"); + // Kern::Printf("CryptoH4JobRandom::HookIsr iIsrHooked=%d this=%x", iIsrHooked, this); +#ifdef __MARM__ + if(!iIsrHooked) + { + TInt r = Interrupt::Bind(EIrqRng, Isr, this); + if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Bind failed", r); + r = Interrupt::Enable(EIrqRng); + if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Enable failed", r); + iIsrHooked = ETrue; + } +#endif + } + +void CryptoH4JobRandom::UnHookIsr() + { + TRACE_FUNCTION("UnHookIsr"); + // Kern::Printf("CryptoH4JobRandom::UnHookIsr iIsrHooked=%d this=%x", iIsrHooked, this); +#ifdef __MARM__ + if(iIsrHooked) + { + Interrupt::Disable(EIrqRng); + Interrupt::Unbind(EIrqRng); + iIsrHooked = EFalse; + } +#endif + } + + + +#ifdef __MARM__ +void CryptoH4JobRandom::Isr(TAny *aPtr) + { + TRACE_FUNCTION("Isr"); + CryptoH4JobRandom *p = static_cast(aPtr); + // Disable RNG interrupt so DFC can run. + p->DisableIsr(); + // Queue DFC to read the RNG + p->iRandomDfc.Add(); + } +#endif + +/** + Called when the current h/w opperation is complete +*/ +void CryptoH4JobRandom::RandomDfc(TAny* aPtr) + { + ((CryptoH4JobRandom*)aPtr)->DoRandomDfc(); + } + +void CryptoH4JobRandom::DoRandomDfc() + { + TRACE_FUNCTION("DoRandomDfc"); + // Set state to not using hw, if we continue using the h/w we will + // call EnableIsr which will change the state back to ERunning. + SetRunning(EFalse); + // Kern::Printf("DoRandomDfc"); +#ifdef __MARM__ + // Read h/w + iRandomBuffer[iHw32Index] = TOmap::Register32(KHwBaseRngReg + KHoRng_Out); +#else + static TUint32 n = 0; + iRandomBuffer[iHw32Index]= n++; +#endif + + ++iHw32Index; + if(iHw32Index >= sizeof(iRandomBuffer)/sizeof(iRandomBuffer[0])) + { + iHw32Index = 0; + } + + TInt outputAvailable = BytesAvailable(); + TInt space = sizeof(iRandomBuffer) - outputAvailable - 4; + if((outputAvailable >= iJobSizeInBytes) || (space <= 0)) + { + // Either have enough data to finish job, or out of buffer + // space to read more. We pass available data to the LDD, and + // declare the slice/job done and return. + + // + // Pass available data to LDD + // + // LDD will call GetFromPddBuffer/BytesReadFromPdd to read the data. + iLddChanRandom.DataAvailable(); + } + + // Are we done yet? + if(iJobSizeInBytes <= 0) + { + // Tell the scheduler that this slice is done + iJobScheduler->JobComplete(this, KErrNone); + return; + } + + // Re-calculate output available and space + outputAvailable = BytesAvailable(); + space = sizeof(iRandomBuffer) - outputAvailable - 4; + + if((space != 0) && (iJobSizeInBytes-outputAvailable > 0)) + { + // We have some space and we need more data + + // Enable RNG interrupt. The interrupt will then queue the + // "random number ready" DFC when the h/w is ready. + // (when not on h/w, this immediately queues a DFC) + EnableIsr(); + } + else + { + // Job stalled - either out of space or already have enough + // data but LDD has not take it + Stalled(); + } + + return; + } + + + + +// End of file