os/security/cryptoplugins/cryptospiplugins/test/h4drv/crypto_h4/cryptoh4aes.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 "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