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