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