--- /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 <kernel/kern_priv.h>
+#include <cryptodriver.h>
+#ifdef __MARM__
+#include <omap_hrp/assp/shared/omap_reg.h>
+#include <omap_hrp/assp/shared/omap_interrupt.h>
+#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<CryptoH4JobRandom *>(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