cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4aes.cpp
changeset 8 35751d3474b7
child 15 da2ae96f639b
equal deleted inserted replaced
2:675a964f4eb5 8:35751d3474b7
       
     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 "cryptoh4aes.h"
       
    31 
       
    32 #if 0
       
    33 #undef __MARM__
       
    34 #ifndef __MARM__
       
    35 #warning "h/w disabled"
       
    36 #endif
       
    37 #endif
       
    38 
       
    39 #ifdef DUMPBUFFER
       
    40 LOCAL_D void dumpBuffer(const char *aName, TUint32 *aBuf, TUint32 aLen);
       
    41 #else
       
    42 #define dumpBuffer(aName, aBuf, aLen)
       
    43 #endif
       
    44 
       
    45 CryptoH4JobAes::CryptoH4JobAes(DLddChanAes &aLddChanAes)
       
    46 	: iLddChanAes(aLddChanAes),
       
    47 	  iEncrypt(EFalse),
       
    48 	  iKeyLengthBytes(0),
       
    49 	  iSwWriteByteOffset(0),
       
    50 	  iHwReadIndex(0),
       
    51 	  iHwWriteIndex(0),
       
    52 	  iSwReadByteOffset(0),
       
    53 	  iHwRunning(EFalse),
       
    54 	  iDmaToHwPending(0),
       
    55 	  iDmaFromHwPending(0),
       
    56 #ifdef FAKE_DMA
       
    57 	  iFakeDmaToHwQueued(0),
       
    58 	  iFakeDmaFromHwQueued(0),
       
    59 #endif
       
    60 	  iDmaToHwCompleteDfc(DmaToHwCompleteDfc, this, 1), // DFC is priority '1'
       
    61 	  iDmaFromHwCompleteDfc(DmaFromHwCompleteDfc, this, 1)
       
    62 	{
       
    63 	TRACE_FUNCTION("CryptoH4JobAes");
       
    64 	}
       
    65 
       
    66 CryptoH4JobAes::~CryptoH4JobAes()
       
    67 	{
       
    68 	TRACE_FUNCTION("~CryptoH4JobAes");
       
    69 	StopHw();
       
    70 	}
       
    71 
       
    72 
       
    73 void CryptoH4JobAes::SetDfcQ(TDfcQue *aDfcQue)
       
    74 	{
       
    75 	TRACE_FUNCTION("SetDfcQ");
       
    76 	iDmaToHwCompleteDfc.SetDfcQ(aDfcQue);
       
    77 	iDmaFromHwCompleteDfc.SetDfcQ(aDfcQue);
       
    78 	}
       
    79 
       
    80 TUint8 *CryptoH4JobAes::GetKeyBuffer()
       
    81 	{
       
    82 	TRACE_FUNCTION("GetKeyBuffer");
       
    83 	return (TUint8 *) &iKey;
       
    84 	}
       
    85 
       
    86 TUint8 *CryptoH4JobAes::GetIVBuffer()
       
    87 	{
       
    88 	TRACE_FUNCTION("GetIVBuffer");
       
    89 	return (TUint8 *) &iIV;
       
    90 	}
       
    91 	
       
    92 TUint32 CryptoH4JobAes::MaxBytes() const
       
    93 	{
       
    94 	TRACE_FUNCTION("MaxBytes");
       
    95 	return sizeof(iAesBuffer); // return size in bytes
       
    96 	}
       
    97 
       
    98 TUint8 *CryptoH4JobAes::GetIOBuffer()
       
    99 	{
       
   100 	TRACE_FUNCTION("GetIOBuffer");
       
   101 	return (TUint8 *) &iAesBuffer;
       
   102 	}
       
   103 
       
   104 void CryptoH4JobAes::GetToPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
       
   105 	{
       
   106 	TRACE_FUNCTION("GetToPddBuffer");
       
   107 	CheckIndexes();
       
   108 	TUint8 *p = (TUint8 *) iAesBuffer;
       
   109 	aBuf = &p[iSwWriteByteOffset];
       
   110 
       
   111 	if(iSwReadByteOffset > iSwWriteByteOffset)
       
   112 		{
       
   113 		// Available buffer is contiguous
       
   114 		aBufLen = iSwReadByteOffset - iSwWriteByteOffset;
       
   115 		if(aBufLen) --aBufLen; // Never use all space to stop index collision
       
   116 		aMore = EFalse;
       
   117 		return;
       
   118 		}
       
   119 	else
       
   120 		{
       
   121 		// Available data crosses buffer end so return two regions
       
   122 		// OR indexes are equal
       
   123 		aBufLen = sizeof(iAesBuffer) - iSwWriteByteOffset;
       
   124 		if(iSwReadByteOffset == 0)
       
   125 			{
       
   126 			// Do not fill to end of buffer because index would wrap and collid
       
   127 			--aBufLen;
       
   128 			aMore = EFalse;
       
   129 			return;
       
   130 			}
       
   131 		aMore = (iSwReadByteOffset != iSwWriteByteOffset); // Another region to read
       
   132 		return;
       
   133 		}
       
   134 	// Never gets here
       
   135 	}
       
   136 
       
   137 void CryptoH4JobAes::BytesWrittenToPdd(TUint32 aBytes)
       
   138 	{
       
   139 	TRACE_FUNCTION("BytesWrittenToPdd");
       
   140 	CheckIndexes();
       
   141 	iSwWriteByteOffset += aBytes;
       
   142 	if(iSwWriteByteOffset >= sizeof(iAesBuffer))
       
   143 		{
       
   144 		iSwWriteByteOffset -= sizeof(iAesBuffer);
       
   145 		}
       
   146 		
       
   147 	CheckIndexes();
       
   148 	}
       
   149 
       
   150 void CryptoH4JobAes::GetFromPddBuffer(TUint8 * &aBuf, TUint32 &aBufLen, TBool &aMore)
       
   151 	{
       
   152 	TRACE_FUNCTION("GetFromPddBuffer");
       
   153 	CheckIndexes();
       
   154 	TInt hwWrite8Index = iHwWriteIndex * 4;
       
   155 	TUint8 *p = (TUint8 *) iAesBuffer;
       
   156 	aBuf = &p[iSwReadByteOffset];
       
   157 
       
   158 	TInt len = hwWrite8Index - iSwReadByteOffset;
       
   159 	if(len >= 0)
       
   160 		{
       
   161 		aBufLen = len;
       
   162 		aMore = EFalse;
       
   163 		}
       
   164 	else
       
   165 		{
       
   166 		// Wrap round condition, but can only return contiguous bytes
       
   167 		aBufLen = sizeof(iAesBuffer) - iSwReadByteOffset;
       
   168 		aMore = (hwWrite8Index != 0);
       
   169 		}
       
   170 	CheckIndexes();
       
   171 	}
       
   172 
       
   173 void CryptoH4JobAes::BytesReadFromPdd(TUint32 aBytes)
       
   174 	{
       
   175 	TRACE_FUNCTION("BytesReadFromPdd");
       
   176 	CheckIndexes();
       
   177 	iSwReadByteOffset += aBytes;
       
   178 	if(iSwReadByteOffset >= sizeof(iAesBuffer))
       
   179 		{
       
   180 		iSwReadByteOffset -= sizeof(iAesBuffer);
       
   181 		}
       
   182 	CheckIndexes();
       
   183 	iReadRequestLength -= aBytes;
       
   184 	}
       
   185 
       
   186 
       
   187 
       
   188 TInt CryptoH4JobAes::SetDetails(DCryptoJobScheduler *aJobScheduler, 
       
   189 								MCryptoJobCallbacks *aCallbacks,
       
   190 								TBool aEncrypt, 
       
   191 								TInt aKeyLengthBytes,
       
   192 								RCryptoDriver::TChainingMode aMode)
       
   193 	{
       
   194 	TRACE_FUNCTION("TChainingMode");
       
   195 	//	Kern::Printf("AES Details %s: Key len %d, Mode %s (%d)",
       
   196 	//				 aEncrypt?"Encrypt":"Decrypt", aKeyLengthBytes, (aMode == RCryptoDriver::ECbcMode)?"CBC":"ECB", aMode);
       
   197 
       
   198 	if(State() != ECreated)
       
   199 		{
       
   200         return KErrArgument;
       
   201 		}
       
   202 	
       
   203 	iJobScheduler = aJobScheduler;
       
   204 	iCallbacks = aCallbacks;
       
   205 	iEncrypt = aEncrypt;
       
   206 	iKeyLengthBytes = aKeyLengthBytes;
       
   207 
       
   208 	if((aMode != RCryptoDriver::EEcbMode) && (aMode != RCryptoDriver::ECbcMode))
       
   209 		{
       
   210 		return KErrArgument;
       
   211 		}
       
   212 	iMode = aMode;
       
   213 	if(iMode == RCryptoDriver::ECbcMode)
       
   214 		{
       
   215 		// For CBC we need to save the IV incase we need to
       
   216 		// re-initialise the h/w mid-job
       
   217 		TUint32 *from;
       
   218 		TUint32 *to;
       
   219 		if(iEncrypt)
       
   220 			{
       
   221 			// For encryption - DoSaveState saves the last encrypted
       
   222 			// block. We set this to the IV to handle the case where
       
   223 			// we do not encrypt any blocks before being suspended.
       
   224 			from = &iIV[0];
       
   225 			to = &iAesBuffer[((sizeof(iAesBuffer)-16)/4)];
       
   226 			}
       
   227 		else
       
   228 			{
       
   229 			// For decryption - MaybeSetupWriteDmaToHw maintains
       
   230 			// iSavedState as a copy of the last ciphertext
       
   231 			// (pre-decryption) so DoSaveState does not need to do
       
   232 			// anything.
       
   233 			//
       
   234 			// To cover the case where we do not decrypt any blocks
       
   235 			// before being suspended, we initialise iSavedState to the IV.
       
   236 			from = &iIV[0];
       
   237 			to = &iSavedState[0];
       
   238 			}
       
   239 		// Save the IV
       
   240 		*to++ = *from++;
       
   241 		*to++ = *from++;
       
   242 		*to++ = *from++;
       
   243 		*to++ = *from++;
       
   244 		if(iEncrypt)
       
   245 			{
       
   246 			dumpBuffer("SetDetails - end of iAesBuffer", to-4, 4);
       
   247 			}
       
   248 		else
       
   249 			{
       
   250 			dumpBuffer("SetDetails - iSavedState", iSavedState, 4);
       
   251 			}
       
   252 		}
       
   253 
       
   254 	// Reset indexes
       
   255 	iSwWriteByteOffset = 0;
       
   256 	iHwReadIndex = 0,
       
   257 	iHwWriteIndex = 0,
       
   258 	iSwReadByteOffset = 0;
       
   259 
       
   260 	return KErrNone;
       
   261 	}
       
   262 
       
   263 void CryptoH4JobAes::DoSlice(TBool aFirstSlice)
       
   264 	{
       
   265 	TRACE_FUNCTION("DoSlice");
       
   266 	//	Kern::Printf("DoSlice %s", aFirstSlice?"FIRST":"");
       
   267 	if(aFirstSlice)
       
   268 		{
       
   269 		SetupHw(EFalse);
       
   270 		}
       
   271 	
       
   272 	// Push any available data to user
       
   273 	TInt r = iCallbacks->DataAvailable();
       
   274 	if(r != KErrNone)
       
   275 		{
       
   276 		iJobScheduler->JobComplete(this,r);
       
   277 		return;
       
   278 		}
       
   279 	// Read available data from user
       
   280 	r = iCallbacks->DataRequired();
       
   281 	if(r != KErrNone)
       
   282 		{
       
   283 		iJobScheduler->JobComplete(this,r);
       
   284 		return;
       
   285 		}
       
   286 	
       
   287 	// Setup to read data (if enough is available).
       
   288 	// 	Kern::Printf("DoSlice - calling MaybeSetupWriteDmaToHw");
       
   289 	MaybeSetupWriteDmaToHw();
       
   290 
       
   291 	FAKE_DMA();
       
   292 
       
   293 	if(!iDmaToHwPending && !iDmaFromHwPending)
       
   294 		{
       
   295 		Stalled();
       
   296 		}
       
   297 
       
   298 	return;
       
   299 	}
       
   300 
       
   301 TBool CryptoH4JobAes::DoSaveState()
       
   302 	{
       
   303 	TRACE_FUNCTION("DoSaveState");
       
   304 
       
   305 	if((iMode == RCryptoDriver::ECbcMode) && iEncrypt)
       
   306 		{
       
   307 		// Doing CBC encryption - Need to save a copy of the last
       
   308 		// ciphertext block (after encryption) so we can use it as the
       
   309 		// IV if we are later resumed.
       
   310 		//
       
   311 		// Last block processed by h/w just BEFORE iHwWriteIndex. If
       
   312 		// we have not processed any data, then SetDetails will have
       
   313 		// initialised this to the IV
       
   314 		TInt32 fromIndex = (iHwWriteIndex!=0) ? (iHwWriteIndex-4) : ((sizeof(iAesBuffer)-16)/4);
       
   315 		TUint32 *from = &iAesBuffer[fromIndex];
       
   316 		TUint32 *to = &iSavedState[0];
       
   317 		*to++ = *from++;
       
   318 		*to++ = *from++;
       
   319 		*to++ = *from++;
       
   320 		*to++ = *from++;
       
   321 		dumpBuffer("DoSaveState - iSavedState", iSavedState, 4);
       
   322 		}
       
   323 
       
   324 	StopHw();
       
   325 	return ETrue; // We want DoRestoreState to be called
       
   326 	}
       
   327 
       
   328 void CryptoH4JobAes::DoRestoreState()
       
   329 	{
       
   330 	TRACE_FUNCTION("DoRestoreState");
       
   331 	SetupHw(ETrue);
       
   332 	}
       
   333 
       
   334 void CryptoH4JobAes::DoReleaseHw()
       
   335 	{
       
   336 	TRACE_FUNCTION("DoReleaseHw");
       
   337 	StopHw();
       
   338 #ifndef FAKE_DMA
       
   339 	// Cancel DFCs - Doesn't work for FAKE_DMA case....
       
   340 	iDmaToHwCompleteDfc.Cancel();
       
   341 	iDmaFromHwCompleteDfc.Cancel();
       
   342 #endif
       
   343 	}
       
   344 
       
   345 void CryptoH4JobAes::MaybeSetupWriteDmaToHw()
       
   346 	{
       
   347 	TRACE_FUNCTION("MaybeSetupWriteDmaToHw");
       
   348 	if(!iDmaToHwPending)
       
   349 		{
       
   350 		// Calculate space between H/W read index and S/W write index or end of buffer
       
   351 		TInt hwReadIndex8 = iHwReadIndex*4;
       
   352 		TInt avail = (iSwWriteByteOffset >= hwReadIndex8) ? (iSwWriteByteOffset - hwReadIndex8) : (sizeof(iAesBuffer) - hwReadIndex8);
       
   353 		
       
   354 		if(avail >= 16)
       
   355 			{
       
   356 			// At least another block of data is available.
       
   357 			if((avail <= 31) && (iMode == RCryptoDriver::ECbcMode) && !iEncrypt)
       
   358 				{
       
   359 				// Only one complete block is available
       
   360 
       
   361 				// Doing CBC decryption, so need to save a copy of the
       
   362 				// last ciphertext block (before it is decrypted) so we
       
   363 				// can use it as the IV if we are kicked off the h/w
       
   364 				// and have to reconfigure.
       
   365 				// Last block available for h/w is at hwReadIndex8
       
   366 				TUint32 *from = &iAesBuffer[iHwReadIndex];
       
   367 				TUint32 *to = &iSavedState[0];
       
   368 				*to++ = *from++;
       
   369 				*to++ = *from++;
       
   370 				*to++ = *from++;
       
   371 				*to++ = *from++;
       
   372 				dumpBuffer("MaybeSetupWriteDmaToHw - iSavedState", iSavedState, 4);
       
   373 				}
       
   374 			SetupDma((TUint32)&iAesBuffer[iHwReadIndex], ETrue);
       
   375 			}
       
   376 		}
       
   377 	}
       
   378 
       
   379 
       
   380 #ifdef FAKE_DMA
       
   381 void CryptoH4JobAes::FakeDma()
       
   382 	{
       
   383 	TRACE_FUNCTION("FakeDma");
       
   384 	if(iFakeDmaToHwQueued < iDmaToHwPending)
       
   385 		{
       
   386 		// Calculate number of 32 bit values in the h/w
       
   387 		TInt inHw32 = iHwReadIndex - iHwWriteIndex;
       
   388 		if(inHw32 < 0)
       
   389 			{
       
   390 			inHw32 += sizeof(iAesBuffer)/sizeof(iAesBuffer[0]);
       
   391 			}
       
   392 		// Convert to number of 16 byte blocks in h/w
       
   393 		TInt inHwBlocks = inHw32/4;
       
   394 
       
   395 		if((inHwBlocks + iFakeDmaToHwQueued) < 2)
       
   396 			{
       
   397 			// Pipeline is not full, so the next DMA to complete would be a "to h/w"
       
   398 			// Wait for h/w to be ready
       
   399 #ifdef __MARM__
       
   400 			//		Kern::Printf("CryptoH4JobAes::FakeDma - Start waiting for h/w input ready (%x)", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   401 			while(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlInputReady))
       
   402 				{
       
   403 				Kern::Printf("CryptoH4JobAes::FakeDma - Waiting for h/w input ready (%x)", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   404 				}
       
   405 #endif			
       
   406 			// Queue the fake "to dma" complete DFC
       
   407 			iDmaToHwCompleteDfc.Enque();
       
   408 			++iFakeDmaToHwQueued;
       
   409 			return;
       
   410 			}
       
   411 		}
       
   412 
       
   413 	// Either pipeline is full, or we are out of input data.
       
   414 
       
   415 	// Check for output
       
   416 	if(iFakeDmaFromHwQueued < iDmaFromHwPending)
       
   417 		{
       
   418 #ifdef __MARM__
       
   419 		//		Kern::Printf("CryptoH4JobAes::FakeDma - Start waiting for output ready (%x)", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   420 		while(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlOutputReady))
       
   421 			{
       
   422 			Kern::Printf("CryptoH4JobAes::FakeDma - waiting for output ready (%x)",TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   423 			}
       
   424 #endif
       
   425 		// Queue the fake "from dma" complete DFC
       
   426 		iDmaFromHwCompleteDfc.Enque();
       
   427 		++iFakeDmaFromHwQueued;
       
   428 		return;
       
   429 		}
       
   430 
       
   431 	return;
       
   432 	}
       
   433 #endif
       
   434 
       
   435 
       
   436 
       
   437 
       
   438 void CryptoH4JobAes::SetupHw(TBool aUseSavedState)
       
   439 	{
       
   440 	TRACE_FUNCTION("SetupHw");
       
   441 	//	Kern::Printf("SetupHw");
       
   442 #ifdef __MARM__
       
   443 	// AES_MASK
       
   444 #ifdef FAKE_DMA
       
   445 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, KHtAesMaskAutoIdle);
       
   446 #else
       
   447 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, 
       
   448 						 KHtAesMaskDmaReqIn | KHtAesMaskDmaReqOut | KHtAesMaskAutoIdle);
       
   449 #endif
       
   450 	iHwRunning = EFalse; // Previous MASK register write cleared the start bit.
       
   451 	
       
   452 	TUint32 ctrl = 0;
       
   453 	if(iEncrypt)
       
   454 		{
       
   455 			ctrl |= KHtAesCtrlDirection;
       
   456 		}
       
   457 
       
   458 	switch(iKeyLengthBytes)
       
   459 		{
       
   460 		case 32:
       
   461 			// KEYS
       
   462 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_L, iKey[0]);
       
   463 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_H, iKey[1]);
       
   464 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_L, iKey[2]);
       
   465 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_H, iKey[3]);
       
   466 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_L, iKey[4]);
       
   467 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_H, iKey[5]);
       
   468 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY4_L, iKey[6]);
       
   469 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY4_H, iKey[7]);
       
   470 			ctrl |= KHtAesCtrlKeySize256;
       
   471 			break;
       
   472 		case 24:
       
   473 			// KEYS
       
   474 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_L, iKey[0]);
       
   475 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_H, iKey[1]);
       
   476 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_L, iKey[2]);
       
   477 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_H, iKey[3]);
       
   478 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_L, iKey[4]);
       
   479 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY3_H, iKey[5]);
       
   480 			ctrl |= KHtAesCtrlKeySize192;
       
   481 			break;
       
   482 		case 16:
       
   483 			// KEYS
       
   484 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_L, iKey[0]);
       
   485 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY1_H, iKey[1]);
       
   486 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_L, iKey[2]);
       
   487 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_KEY2_H, iKey[3]);
       
   488 			ctrl |= KHtAesCtrlKeySize128;
       
   489 			break;
       
   490 		}
       
   491 	
       
   492 			
       
   493 	
       
   494 	// IV (CBC only)
       
   495 	if(iMode == RCryptoDriver::ECbcMode)
       
   496 		{
       
   497 		if(!aUseSavedState)
       
   498 			{
       
   499 			//		Kern::Printf("Setting IV");
       
   500 			// Set IV
       
   501 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_1, iIV[0]);
       
   502 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_2, iIV[1]);
       
   503 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_3, iIV[2]);
       
   504 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_4, iIV[3]);
       
   505 			dumpBuffer("SetupHw(EFalse) - iIV", iIV, 4);
       
   506 			}
       
   507 		else
       
   508 			{
       
   509 			// Set IV to saved state
       
   510 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_1, iSavedState[0]);
       
   511 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_2, iSavedState[1]);
       
   512 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_3, iSavedState[2]);
       
   513 			TOmap::SetRegister32(KHwBaseAesReg + KHoAES_IV_4, iSavedState[3]);
       
   514 			dumpBuffer("SetupHw(ETrue) - iSavedState", iSavedState, 4);
       
   515 			}
       
   516 		
       
   517 		ctrl |= KHsAesCtrlCBC;
       
   518 		}
       
   519 	
       
   520 	// AES_CTRL
       
   521 	//	Kern::Printf("Setting crtl to %x", ctrl);
       
   522 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_CTRL, ctrl);
       
   523 
       
   524 	// AES_MASK START bit to start DMA
       
   525 	// This is done by SetupDma
       
   526 #else
       
   527 	(void)aUseSavedState;
       
   528 
       
   529 #endif
       
   530 	}
       
   531 
       
   532 void CryptoH4JobAes::SetupDma(TUint32 aPtr, TBool aToHw)
       
   533 	{
       
   534 	TRACE_FUNCTION("SetupDma");
       
   535 	//	Kern::Printf("\t\tSetupDMA - %s, iHwReadIndex %d iHwWriteIndex %d", 
       
   536 	//				 aToHw?"toHw":"fromHw", iHwReadIndex, iHwWriteIndex);
       
   537 	// Start the h/w
       
   538 	if(!iHwRunning)
       
   539 		{
       
   540 		//		Kern::Printf("SetupDma - starting h/w");
       
   541 #ifdef __MARM__
       
   542 		// If h/w is not enabled yet, then set the start bit. This is
       
   543 		// required even when NOT using DMA...
       
   544 		TUint32 mask = TOmap::Register32(KHwBaseAesReg + KHoAES_MASK);
       
   545 		//		Kern::Printf("mask is %x", mask);
       
   546 		mask |= KHtDesMaskDmaReqStart;
       
   547 		TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, mask);
       
   548 		//		Kern::Printf("changed to %x", TOmap::Register32(KHwBaseAesReg + KHoAES_MASK));
       
   549 #else
       
   550 		(void)aPtr;
       
   551 #endif
       
   552 		iHwRunning = ETrue;
       
   553 		}
       
   554 
       
   555 	if(aToHw)
       
   556 		{
       
   557 		++iDmaToHwPending;
       
   558 		SetRunning(ETrue);
       
   559 		}
       
   560 	else
       
   561 		{
       
   562 		++iDmaFromHwPending;
       
   563 		SetRunning(ETrue);
       
   564 		}
       
   565 	
       
   566 	}
       
   567 
       
   568 
       
   569 void CryptoH4JobAes::StopHw()
       
   570 	{
       
   571 	TRACE_FUNCTION("StopHw");
       
   572 #ifdef __MARM__
       
   573 	// Disable h/w
       
   574 	TUint32 mask = TOmap::Register32(KHwBaseAesReg + KHoAES_MASK);
       
   575 	mask &= ~KHtDesMaskDmaReqStart;
       
   576 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, mask);
       
   577 #endif
       
   578 	iHwRunning = EFalse;
       
   579 	}
       
   580 
       
   581 
       
   582 
       
   583 /**
       
   584   Called when the current h/w opperation is complete
       
   585 */
       
   586 void CryptoH4JobAes::DmaComplete(DDmaRequest::TResult aResult, TAny *aPtr)
       
   587 	{
       
   588 	TRACE_FUNCTION("TResult");
       
   589 	(void)aResult;
       
   590 	// Queue our DFC to action the DMA complete notification in our thread.
       
   591 	reinterpret_cast<TDfc *>(aPtr)->Enque();
       
   592 	}
       
   593 
       
   594 
       
   595 
       
   596 
       
   597 void CryptoH4JobAes::DmaToHwCompleteDfc(TAny* aPtr)
       
   598     {
       
   599     ((CryptoH4JobAes*)aPtr)->DoDmaToHwCompleteDfc();
       
   600     }
       
   601 
       
   602 
       
   603 void CryptoH4JobAes::DoDmaToHwCompleteDfc()
       
   604 	{
       
   605 	TRACE_FUNCTION("DoDmaToHwCompleteDfc");
       
   606 	//	Kern::Printf("**DoDmaToHwCompleteDfc iHwReadIndex %d, iHwWriteIndex %d",iHwReadIndex, iHwWriteIndex);
       
   607 	--iDmaToHwPending;
       
   608 	if(iDmaToHwPending < 0) Kern::Fault("DoDmaToHwCompleteDfc - iDmaToHwPending is negative",1);
       
   609 
       
   610 #ifdef FAKE_DMA
       
   611 	--iFakeDmaToHwQueued;
       
   612 	if(iFakeDmaToHwQueued < 0) Kern::Fault("DoDmaToHwCompleteDfc - iFakeDmaToHwQueued is negative",2);
       
   613 #endif
       
   614 
       
   615 	CheckIndexes();
       
   616 
       
   617 #ifdef __MARM__
       
   618 	if(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlInputReady))
       
   619 		{
       
   620 		Kern::Fault("DoDmaToHwCompleteDfc - h/w not ready for input!",3);
       
   621 		}
       
   622 	//		Kern::Printf("DoDmaToHwCompleteDfc - Writing data into h/w index %d (%x)", iHwReadIndex, TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   623 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_1, iAesBuffer[iHwReadIndex]);
       
   624 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_2, iAesBuffer[iHwReadIndex+1]);
       
   625 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_3, iAesBuffer[iHwReadIndex+2]);
       
   626 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_4, iAesBuffer[iHwReadIndex+3]);
       
   627 #endif
       
   628 
       
   629 	// Update index to point at next block to be passed to the h/w
       
   630 	iHwReadIndex += 4; // 4x32bit == 16bytes == block length
       
   631 	if(iHwReadIndex == sizeof(iAesBuffer)/sizeof(TUint32))
       
   632 		{
       
   633 		iHwReadIndex = 0;
       
   634 		}
       
   635 
       
   636 	if(!iDmaFromHwPending)
       
   637 		{
       
   638 		SetupDma((TUint32)&iAesBuffer[iHwWriteIndex], EFalse);
       
   639 		}
       
   640 	
       
   641 	CheckIndexes();
       
   642 	
       
   643 	// Setup to read data (if enough is available).
       
   644 	MaybeSetupWriteDmaToHw();
       
   645 	
       
   646 	FAKE_DMA();
       
   647 	}
       
   648 
       
   649 void CryptoH4JobAes::DmaFromHwCompleteDfc(TAny* aPtr)
       
   650     {
       
   651     ((CryptoH4JobAes*)aPtr)->DoDmaFromHwCompleteDfc();
       
   652     }
       
   653 
       
   654 
       
   655 void CryptoH4JobAes::DoDmaFromHwCompleteDfc()
       
   656 	{
       
   657 	TRACE_FUNCTION("DoDmaFromHwCompleteDfc");
       
   658 	//	Kern::Printf("**DoDmaFromHwCompleteDfc iHwReadIndex %d, iHwWriteIndex %d", iHwReadIndex, iHwWriteIndex);
       
   659 
       
   660 	--iDmaFromHwPending;
       
   661 	if(iDmaFromHwPending < 0) Kern::Fault("DoDmaFromHwCompleteDfc - iDmaFromHwPending is negative",1);
       
   662 
       
   663 #ifdef FAKE_DMA
       
   664 	--iFakeDmaFromHwQueued;
       
   665 	if(iFakeDmaFromHwQueued < 0) Kern::Fault("iFakeDmaFromHwQueued - iFakeDmaFromHwQueued is negative",2);
       
   666 #endif
       
   667 
       
   668 	CheckIndexes();
       
   669 
       
   670 #ifdef __MARM__
       
   671 	if(! (TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlOutputReady))
       
   672 		{
       
   673 		Kern::Fault("DoDmaToHwCompleteDfc - h/w not ready for output!",3);
       
   674 		}
       
   675 
       
   676 	//	Kern::Printf("DoDmaFromHwCompleteDfc - Reading data from h/w index %d (%x)", iHwWriteIndex, TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   677 	iAesBuffer[iHwWriteIndex] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_1);
       
   678 	iAesBuffer[iHwWriteIndex+1] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_2);
       
   679 	iAesBuffer[iHwWriteIndex+2] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_3);
       
   680 	iAesBuffer[iHwWriteIndex+3] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_4);
       
   681 #endif
       
   682 
       
   683 	// Update index to point at next block to be read from the h/w
       
   684 	iHwWriteIndex += 4; // 4x32bit == 16bytes == block length
       
   685 	if(iHwWriteIndex == sizeof(iAesBuffer)/sizeof(TUint32))
       
   686 		{
       
   687 		iHwWriteIndex= 0;
       
   688 		}
       
   689 
       
   690 	CheckIndexes();
       
   691 
       
   692 
       
   693 
       
   694 	TInt hwWrite8Index = iHwWriteIndex * 4;
       
   695 	TInt hwRead8Index = iHwReadIndex * 4;
       
   696 
       
   697 	// Check if we either have enough data to finish the current LDD
       
   698 	// user read request, or if we are running out of space
       
   699 	//
       
   700 	// Calculate data available for xfer to user
       
   701 	TInt availableForUser = hwWrite8Index - iSwReadByteOffset;
       
   702 	if(availableForUser < 0)
       
   703 		{
       
   704 		availableForUser += sizeof(iAesBuffer);
       
   705 		}
       
   706 
       
   707 	if((availableForUser >= sizeof(iAesBuffer) - 32) ||
       
   708 	   (availableForUser >= iReadRequestLength))
       
   709 		{
       
   710 		// Pass available data to user
       
   711 		TInt r = iCallbacks->DataAvailable();
       
   712 		if(r != KErrNone)
       
   713 			{
       
   714 			iJobScheduler->JobComplete(this,r);
       
   715 			return;
       
   716 			}
       
   717 		}
       
   718 
       
   719 	// Are we running short of data?
       
   720 	TInt availableForHw = iSwWriteByteOffset - hwRead8Index;
       
   721 	if(availableForHw < 0)
       
   722 		{
       
   723 		availableForHw += sizeof(iAesBuffer);
       
   724 		}
       
   725 	
       
   726 	if(availableForHw < 16)
       
   727 		{
       
   728 		TInt r = iCallbacks->DataRequired();
       
   729 		if(r != KErrNone)
       
   730 			{
       
   731 			iJobScheduler->JobComplete(this,r);
       
   732 			return;
       
   733 			}
       
   734 		}
       
   735 
       
   736 	// Kick off a new to h/w DMA if one is not already running
       
   737 	MaybeSetupWriteDmaToHw();
       
   738 		
       
   739 	// Current h/w -> iAesBuffer DMA request has completed
       
   740 	if(iHwWriteIndex != iHwReadIndex)
       
   741 		{
       
   742 		SetupDma((TUint32)&iAesBuffer[iHwWriteIndex], EFalse);
       
   743 		}
       
   744 
       
   745 	if(!iDmaToHwPending && ! iDmaFromHwPending)
       
   746 		{
       
   747 		//		Kern::Printf("\t\tDoDmaFromHwCompleteDfc STALLED (underrun), iHwReadIndex %d iHwWriteIndex %d",
       
   748 		//					 iHwReadIndex, iHwWriteIndex);
       
   749 		// Run out of data to process!
       
   750 		// Tell the scheduler that we are stalled & therefore this slice is done
       
   751 		Stalled();
       
   752 		return;
       
   753 		}
       
   754 
       
   755 
       
   756 	CheckIndexes();
       
   757 
       
   758 	FAKE_DMA();
       
   759 	}
       
   760 
       
   761 void CryptoH4JobAes::CheckIndexes() const
       
   762 	{
       
   763 	TRACE_FUNCTION("CheckIndexes");
       
   764 	if(iSwWriteByteOffset < 0 || iSwWriteByteOffset > sizeof(iAesBuffer)) Kern::Fault("CryptoH4JobAes::checkIndexes", 1);
       
   765 
       
   766 	if(iHwReadIndex < 0 || iHwReadIndex > sizeof(iAesBuffer)/sizeof(iAesBuffer[0])) Kern::Fault("CryptoH4JobAes::checkIndexes", 2);
       
   767 
       
   768 	if(iHwWriteIndex < 0 || iHwWriteIndex > sizeof(iAesBuffer)/sizeof(iAesBuffer[0])) Kern::Fault("CryptoH4JobAes::checkIndexes", 3);
       
   769 
       
   770 	if(iSwReadByteOffset < 0 || iSwReadByteOffset > sizeof(iAesBuffer)) Kern::Fault("CryptoH4JobAes::checkIndexes", 4);
       
   771 	
       
   772 	
       
   773 	TInt32 d = iSwWriteByteOffset;
       
   774 	TInt32 c = iHwReadIndex * 4;
       
   775 	TInt32 b = 	iHwWriteIndex * 4;
       
   776 	TInt32 a = 	iSwReadByteOffset;
       
   777 
       
   778 	//	Kern::Printf("%d %d %d %d", a, b, c, d);
       
   779 	
       
   780 	TInt32 offset = 0;
       
   781 	if(b < a) offset = sizeof(iAesBuffer);
       
   782 	b += offset;
       
   783 	if(c < b) offset = sizeof(iAesBuffer);
       
   784 	c += offset;
       
   785 	if(d < c) offset = sizeof(iAesBuffer);
       
   786 	d += offset;
       
   787 	
       
   788 	if(a>b) Kern::Fault("CryptoH4JobAes::CheckIndexes", 5);
       
   789 	if(b>c) Kern::Fault("CryptoH4JobAes::CheckIndexes", 6);
       
   790 	if(c>d) Kern::Fault("CryptoH4JobAes::CheckIndexes", 7);
       
   791 	}
       
   792 
       
   793 
       
   794 void CryptoH4JobAes::NotifyReadRequestLength(TUint32 aReadRequestLength)
       
   795 	{
       
   796 	TRACE_FUNCTION("NotifyReadRequestLength");
       
   797 	iReadRequestLength = aReadRequestLength;
       
   798 	}
       
   799 
       
   800 /**
       
   801    HwPerfCheck
       
   802 
       
   803    This function uses 100% of the CPU power to attempt to drive
       
   804    the AES h/w as fast as possible.
       
   805 
       
   806    This will give some indication of the maximum achievable speed of the h/w
       
   807    excluding the overhead of (almost all of) the driver framework.
       
   808  */
       
   809 void CryptoH4JobAes::HwPerfCheck()
       
   810 	{
       
   811 	TRACE_FUNCTION("HwPerfCheck");
       
   812 	SetupHw(EFalse);
       
   813 
       
   814 	// Start h/w
       
   815 #ifdef __MARM__
       
   816 	TUint32 mask = TOmap::Register32(KHwBaseAesReg + KHoAES_MASK);
       
   817 	mask |= KHtDesMaskDmaReqStart;
       
   818 	TOmap::SetRegister32(KHwBaseAesReg + KHoAES_MASK, mask);
       
   819 #endif
       
   820 
       
   821 	// Reset indexes
       
   822 	iSwWriteByteOffset = 0;
       
   823 	iHwReadIndex = 0,
       
   824 	iHwWriteIndex = 0,
       
   825 	iSwReadByteOffset = 0;
       
   826 
       
   827 	// Read data
       
   828 	iCallbacks->DataRequired();
       
   829 	// Process all data
       
   830 	while(iHwWriteIndex*4 < iSwWriteByteOffset)
       
   831 		{
       
   832 #ifdef __MARM__
       
   833 		//		Kern::Printf("Ctrl %08x", TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL));
       
   834 #endif
       
   835 		// Have we got more data to write to h/w?
       
   836 		if(iHwReadIndex < iSwWriteByteOffset/4)
       
   837 			{
       
   838 			// Yes, but is h/w ready for it?
       
   839 #ifdef __MARM__
       
   840 			if(TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlInputReady)
       
   841 				{
       
   842 				//				Kern::Printf("toHw iHwReadIndex=%d", iHwReadIndex);
       
   843 				// ok, write data to h/w
       
   844 				TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_1, iAesBuffer[iHwReadIndex]);
       
   845 				TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_2, iAesBuffer[iHwReadIndex+1]);
       
   846 				TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_3, iAesBuffer[iHwReadIndex+2]);
       
   847 				TOmap::SetRegister32(KHwBaseAesReg + KHoAES_DATA_4, iAesBuffer[iHwReadIndex+3]);
       
   848 				iHwReadIndex += 4;
       
   849 				}
       
   850 #else
       
   851 			iHwReadIndex += 4;
       
   852 #endif
       
   853 			}
       
   854 		// Do we expect more data from the h/w?
       
   855 		if(iHwWriteIndex < iSwWriteByteOffset/4)
       
   856 			{
       
   857 			// Yes, but is h/w ready?
       
   858 #ifdef __MARM__
       
   859 			if(TOmap::Register32(KHwBaseAesReg + KHoAES_CTRL) & KHtAesCtrlOutputReady)
       
   860 				{
       
   861 				//				Kern::Printf("ReadHw to iHwWriteIndex=%d", iHwWriteIndex);
       
   862 				iAesBuffer[iHwWriteIndex] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_1);
       
   863 				iAesBuffer[iHwWriteIndex+1] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_2);
       
   864 				iAesBuffer[iHwWriteIndex+2] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_3);
       
   865 				iAesBuffer[iHwWriteIndex+3] = TOmap::Register32(KHwBaseAesReg + KHoAES_DATA_4);
       
   866 				iHwWriteIndex += 4;
       
   867 				}
       
   868 #else
       
   869 			iHwWriteIndex += 4;
       
   870 #endif
       
   871 			}
       
   872 		}
       
   873 	
       
   874 	// Write data back to user
       
   875 	iCallbacks->DataAvailable();
       
   876 	}
       
   877 
       
   878 
       
   879 
       
   880 	
       
   881 #ifdef TDFC_WRAPPER
       
   882 TDfcWrapper::TDfcWrapper(const TDfcWrapper &aOrig)
       
   883 	: TDfc(DfcWrapperFunc, this, aOrig.iPriority)
       
   884 	{
       
   885 	TRACE_FUNCTION("TDfcWrapper");
       
   886 	iRealFunction = aOrig.iRealFunction,
       
   887 	iRealPtr = aOrig.iRealPtr;
       
   888 	SetDfcQ(aOrig.iDfcQ);
       
   889 	}
       
   890 
       
   891 
       
   892 TDfcWrapper::TDfcWrapper(TDfcFn aFunction, TAny* aPtr, TInt aPriority)
       
   893 	: TDfc(DfcWrapperFunc, this, aPriority),
       
   894 	  iRealFunction(aFunction),
       
   895 	  iRealPtr(aPtr)
       
   896 	{
       
   897 	TRACE_FUNCTION("TDfcWrapper");
       
   898 	}
       
   899 
       
   900 void TDfcWrapper::Enque()
       
   901 	{
       
   902 	TRACE_FUNCTION("Enque");
       
   903 	// Clone self and queue the clone
       
   904 	TDfcWrapper *p = new TDfcWrapper(*this);
       
   905 	p->BaseEnque();
       
   906 	}
       
   907 
       
   908 void TDfcWrapper::BaseEnque()
       
   909 	{
       
   910 	TRACE_FUNCTION("BaseEnque");
       
   911 	TDfc::Enque();
       
   912 	}
       
   913 
       
   914 
       
   915 void TDfcWrapper::DfcWrapperFunc(TAny* aPtr)
       
   916 	{
       
   917 	TRACE_FUNCTION("DfcWrapperFunc");
       
   918 	TDfcWrapper *p = (TDfcWrapper *) aPtr;
       
   919 	p->iRealFunction(p->iRealPtr);
       
   920 	delete p;
       
   921 	}
       
   922 #endif
       
   923 
       
   924 #ifdef DUMPBUFFER
       
   925 LOCAL_D void dumpBuffer(const char *aName, TUint32 *aBuf, TUint32 aLen)
       
   926 	{
       
   927 	Kern::Printf("%s =", aName);
       
   928 	TUint8 *buf8 = reinterpret_cast<TUint8 *>(aBuf);
       
   929 	for(TInt i = 0 ; i < aLen*4; ++i)
       
   930 		{
       
   931 		if(i%16 == 0)
       
   932 			{
       
   933 			Kern::Printf("\n    ");
       
   934 			}
       
   935 		Kern::Printf("%02x ", buf8[i]);
       
   936 		}
       
   937 	Kern::Printf("\n");
       
   938 	}
       
   939 #endif
       
   940 
       
   941 // End of file