os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4rng.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /*
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 /**
    20  @file
    21  @internalComponent
    22  @released
    23 */
    24 #include <kernel/kern_priv.h>
    25 #include "cryptodriver.h"
    26 #ifdef __MARM__
    27 #include <omap_hrp/assp/shared/omap_reg.h>
    28 #include <omap_hrp/assp/shared/omap_interrupt.h>
    29 #endif
    30 //#include "cryptoh4.h"
    31 #include "cryptoldd.h"
    32 #include "cryptoh4rng.h"
    33 
    34 inline void CryptoH4JobRandom::EnableIsr()
    35 	{
    36 	TRACE_FUNCTION("EnableIsr");
    37 	//	Kern::Printf("EI");
    38 	SetRunning(ETrue);
    39 #ifdef __MARM__
    40 	// Enable RNG interrupt. This interrupt will then queue the
    41 	// "random number ready" DFC
    42 	TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask);
    43 	tmp |= 4;
    44 	TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp);
    45 #else
    46 	// Not on real h/w so just queue the DFC...
    47 	// Queue the "random number ready" DFC
    48 	iRandomDfc.Enque(); // Queue from task level
    49 #endif
    50 	}
    51 
    52 inline void CryptoH4JobRandom::DisableIsr()
    53 	{
    54 	TRACE_FUNCTION("DisableIsr");
    55 	//	Kern::Printf("DI");
    56 #ifdef __MARM__
    57 	TInt32 tmp = TOmap::Register32(KHwBaseRngReg + KHoRng_Mask);
    58 	tmp &= ~4;
    59 	TOmap::SetRegister32(KHwBaseRngReg + KHoRng_Mask, tmp);
    60 #endif
    61 	}
    62 
    63 
    64 
    65 CryptoH4JobRandom::CryptoH4JobRandom(DLddChanRandom &aLddChanRandom)
    66 	: iLddChanRandom(aLddChanRandom),
    67 	  iJobSizeInBytes(0),
    68 	  iSwReadByteOffset(0),
    69 	  iHw32Index(0),
    70 	  iIsrHooked(EFalse),
    71 	  iRandomDfc(RandomDfc, this, 1) // DFC is priority '1'
    72 	{
    73 	TRACE_FUNCTION("CryptoH4JobRandom");
    74 	//	Kern::Printf("CryptoH4JobRandom::CryptoH4JobRandom %x", this);
    75 	}
    76 
    77 CryptoH4JobRandom::~CryptoH4JobRandom()
    78 	{
    79 	TRACE_FUNCTION("~CryptoH4JobRandom");
    80 	//	Kern::Printf("CryptoH4JobRandom::~CryptoH4JobRandom %x", this);
    81 	UnHookIsr();
    82 	}
    83 
    84 
    85 void CryptoH4JobRandom::SetDfcQ(TDfcQue *aDfcQue)
    86 	{
    87 	TRACE_FUNCTION("SetDfcQ");
    88 	iRandomDfc.SetDfcQ(aDfcQue);
    89 	}
    90 
    91 void CryptoH4JobRandom::SetDetails(DCryptoJobScheduler *aJobScheduler, 
    92 								   MCryptoJobCallbacks *aCallbacks,
    93 								   TUint32 aNumOfBytes)
    94 	{
    95 	TRACE_FUNCTION("SetDetails");
    96 	//	Kern::Printf("CryptoH4JobRandom::SetDetails");
    97 	iJobScheduler = aJobScheduler;
    98 	iCallbacks = aCallbacks;
    99 	iJobSizeInBytes = aNumOfBytes;
   100 	}
   101 
   102 void CryptoH4JobRandom::GetToPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
   103 	{
   104 	TRACE_FUNCTION("GetToPddBuffer");
   105 	aBuf = 0;
   106 	aBufLen = 0;
   107 	aMore = EFalse;
   108 	}
   109 
   110 void CryptoH4JobRandom::BytesWrittenToPdd(TUint32)
   111 	{
   112 	TRACE_FUNCTION("BytesWrittenToPdd");
   113 	}
   114 
   115 void CryptoH4JobRandom::GetFromPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
   116 	{
   117 	TRACE_FUNCTION("GetFromPddBuffer");
   118 	
   119 	TInt hw8Index = iHw32Index * 4;
   120 	TUint8 *p = (TUint8 *) iRandomBuffer;
   121 	aBuf = &p[iSwReadByteOffset];
   122 
   123 	TInt len = hw8Index - iSwReadByteOffset;
   124 	if(len >= 0)
   125 		{
   126 		aBufLen = len;
   127 		aMore = EFalse;
   128 		}
   129 	else
   130 		{
   131 		// Wrap round condition, but can only return contiguous bytes
   132 		aBufLen = sizeof(iRandomBuffer) - iSwReadByteOffset;
   133 		aMore = ETrue;
   134 		return;
   135 		}
   136 	}
   137 
   138 void CryptoH4JobRandom::BytesReadFromPdd(TUint32 aBytes)
   139 	{
   140 	TRACE_FUNCTION("BytesReadFromPdd");
   141 	iSwReadByteOffset += aBytes;
   142 	if(iSwReadByteOffset >= sizeof(iRandomBuffer))
   143 		{
   144 		iSwReadByteOffset -= sizeof(iRandomBuffer);
   145 		}
   146 	iJobSizeInBytes -= aBytes;
   147 	}
   148 
   149 
   150 
   151 void CryptoH4JobRandom::DoSlice(TBool aFirstSlice)
   152 	{
   153 	TRACE_FUNCTION("DoSlice");
   154 	//	Kern::Printf("DoSlice(%d)", aFirstSlice);
   155 	if(aFirstSlice)
   156 		{
   157 		HookIsr();
   158 		}
   159 	
   160 	// Enable RNG interrupt. The interrupt will then queue the
   161 	// "random number ready" DFC when the h/w is ready.
   162 	// (when not on h/w, this immediately queues a DFC)
   163 	EnableIsr();
   164 	}
   165 
   166 TBool CryptoH4JobRandom::DoSaveState()
   167 	{
   168 	TRACE_FUNCTION("DoSaveState");
   169 	UnHookIsr();
   170 	return ETrue; // We want DoRestoreState to be called
   171 	}
   172 
   173 void CryptoH4JobRandom::DoRestoreState()
   174 	{
   175 	TRACE_FUNCTION("DoRestoreState");
   176 	HookIsr();
   177 	}
   178 
   179 void CryptoH4JobRandom::DoReleaseHw()
   180 	{
   181 	TRACE_FUNCTION("DoReleaseHw");
   182 	// Disable RNG interrupt
   183 	DisableIsr();
   184 
   185 	// Disable/unhook ISR
   186 	UnHookIsr();
   187 
   188 	// Cancel DFC
   189 	iRandomDfc.Cancel();
   190 	
   191 	}
   192 
   193 TInt CryptoH4JobRandom::BytesAvailable() const
   194 	{
   195 	TRACE_FUNCTION("BytesAvailable");
   196 	TInt hw8Index = iHw32Index * 4;
   197 	TInt available = hw8Index - iSwReadByteOffset;
   198 	if(available < 0)
   199 		{
   200 		available += sizeof(iRandomBuffer);
   201 		}
   202 	return available;	
   203 	}
   204 
   205 void CryptoH4JobRandom::RegionsAvailable(TUint8 * &aPtr1, TInt &aLen1, 
   206 										 TUint8 * &aPtr2, TInt &aLen2) const
   207 	{
   208 	TRACE_FUNCTION("RegionsAvailable");
   209 	TInt hw8Index = iHw32Index * 4;
   210 	TUint8 *p = (TUint8 *) iRandomBuffer;
   211 	aPtr1 = &p[iSwReadByteOffset];
   212 
   213 	TInt len = hw8Index - iSwReadByteOffset;
   214 	if(len < 0)
   215 		{
   216 		// Available data crosses buffer end so return two regions
   217 		aLen1 = sizeof(iRandomBuffer) - iSwReadByteOffset;
   218 		aPtr2 = &p[0];
   219 		aLen2 = hw8Index;
   220 		}
   221 	else
   222 		{
   223 		// Available buffer is contiguous
   224 		aLen1 = len;
   225 		aPtr2 = 0;
   226 		aLen2 = 0;
   227 		}
   228 	}
   229 
   230 
   231 
   232 void CryptoH4JobRandom::HookIsr()
   233 	{
   234 	TRACE_FUNCTION("HookIsr");
   235 	//	Kern::Printf("CryptoH4JobRandom::HookIsr iIsrHooked=%d this=%x", iIsrHooked, this);
   236 #ifdef __MARM__
   237 	if(!iIsrHooked)
   238 		{
   239 		TInt r = Interrupt::Bind(EIrqRng, Isr, this);
   240 		if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Bind failed", r);
   241 		r = Interrupt::Enable(EIrqRng);
   242 		if(r != KErrNone) Kern::Fault("CryptoH4JobRandom::HookIsr Enable failed", r);
   243 		iIsrHooked = ETrue;
   244 		}
   245 #endif
   246 	}
   247 
   248 void CryptoH4JobRandom::UnHookIsr()
   249 	{
   250 	TRACE_FUNCTION("UnHookIsr");
   251 	//	Kern::Printf("CryptoH4JobRandom::UnHookIsr iIsrHooked=%d this=%x", iIsrHooked, this);
   252 #ifdef __MARM__
   253 	if(iIsrHooked)
   254 		{
   255 		Interrupt::Disable(EIrqRng);
   256 		Interrupt::Unbind(EIrqRng);
   257 		iIsrHooked = EFalse;
   258 		}
   259 #endif
   260 	}
   261 
   262 
   263 
   264 #ifdef __MARM__
   265 void CryptoH4JobRandom::Isr(TAny *aPtr)
   266 	{
   267 	TRACE_FUNCTION("Isr");
   268 	CryptoH4JobRandom *p = static_cast<CryptoH4JobRandom *>(aPtr);
   269 	// Disable RNG interrupt so DFC can run.
   270 	p->DisableIsr();
   271 	// Queue DFC to read the RNG
   272 	p->iRandomDfc.Add();
   273 	}
   274 #endif
   275 
   276 /**
   277   Called when the current h/w opperation is complete
   278 */
   279 void CryptoH4JobRandom::RandomDfc(TAny* aPtr)
   280     {
   281     ((CryptoH4JobRandom*)aPtr)->DoRandomDfc();
   282     }
   283 
   284 void CryptoH4JobRandom::DoRandomDfc()
   285 	{
   286 	TRACE_FUNCTION("DoRandomDfc");
   287 	// Set state to not using hw, if we continue using the h/w we will
   288 	// call EnableIsr which will change the state back to ERunning.
   289 	SetRunning(EFalse);
   290 	//	Kern::Printf("DoRandomDfc");
   291 #ifdef __MARM__
   292 	// Read h/w
   293 	iRandomBuffer[iHw32Index] = TOmap::Register32(KHwBaseRngReg + KHoRng_Out);
   294 #else
   295 	static TUint32 n = 0;
   296 	iRandomBuffer[iHw32Index]= n++;
   297 #endif
   298 
   299 	++iHw32Index;
   300 	if(iHw32Index >= sizeof(iRandomBuffer)/sizeof(iRandomBuffer[0]))
   301 		{
   302 		iHw32Index = 0;
   303 		}
   304 
   305 	TInt outputAvailable = BytesAvailable();
   306 	TInt space = sizeof(iRandomBuffer) - outputAvailable - 4;
   307 	if((outputAvailable >= iJobSizeInBytes) || (space <= 0))
   308 		{
   309 		// Either have enough data to finish job, or out of buffer
   310 		// space to read more.  We pass available data to the LDD, and
   311 		// declare the slice/job done and return.
   312 
   313 		//
   314 		// Pass available data to LDD
   315 		//
   316 		// LDD will call GetFromPddBuffer/BytesReadFromPdd to read the data.
   317 		iLddChanRandom.DataAvailable();
   318 		}
   319 	
   320 	// Are we done yet?
   321 	if(iJobSizeInBytes <= 0)
   322 		{
   323 		// Tell the scheduler that this slice is done
   324 		iJobScheduler->JobComplete(this, KErrNone);
   325 		return;
   326 		}
   327 
   328 	// Re-calculate output available and space
   329 	outputAvailable = BytesAvailable();
   330 	space = sizeof(iRandomBuffer) - outputAvailable - 4;
   331 
   332 	if((space != 0) && (iJobSizeInBytes-outputAvailable > 0))
   333 		{
   334 		// We have some space and we need more data
   335 		
   336 		// Enable RNG interrupt. The interrupt will then queue the
   337 		// "random number ready" DFC when the h/w is ready.
   338 		// (when not on h/w, this immediately queues a DFC)
   339 		EnableIsr();
   340 		}
   341 	else
   342 		{
   343 		// Job stalled - either out of space or already have enough
   344 		// data but LDD has not take it
   345 		Stalled();
   346 		}
   347 		
   348 	return;
   349 	}
   350 
   351 	
   352 
   353 
   354 // End of file