333 lines
11 KiB
C
333 lines
11 KiB
C
|
|
/****************************************************************************
|
|
* sec2_cha.c - Channel/CHA operations code for SEC2 Driver
|
|
****************************************************************************
|
|
* Copyright (c) Certicom Corp. 1996-2002. All rights reserved
|
|
* Copyright (c) 2003, 2004 Freescale Semiconductor
|
|
* All Rights Reserved. Proprietary and Confidential.
|
|
*
|
|
* NOTICE: The information contained in this file is proprietary
|
|
* to Freescale Semiconductor, and is being made available to
|
|
* Freescale's customers under strict license agreements.
|
|
* Use or disclosure of this information is permissible only
|
|
* under the terms of the existing license agreement.
|
|
***************************************************************************/
|
|
|
|
|
|
/* Revision History:
|
|
* 1.0 Aug 24,2003 dgs adapted from the final version of mpc18x
|
|
* 1.1.0 Nov 15,2004 sec - merge linux changes from prior versions
|
|
* 1.2 Jan 27,2005
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "Sec2Driver.h"
|
|
|
|
/* Interpeak begin */
|
|
#undef NUM_CHANNELS
|
|
#define NUM_CHANNELS (num_channels)
|
|
extern int num_channels;
|
|
/* Interpeak end */
|
|
|
|
|
|
int ReleaseCha(unsigned long channelCha, int callingTaskId, BOOLEAN locked);
|
|
|
|
|
|
|
|
/****************************************************************/
|
|
/* Function Name: ChaNumToType */
|
|
/* Purpose: To translate the the CHA number to the CHA chaType */
|
|
/* Input: cha - CHA Number */
|
|
/* Output: ChaType */
|
|
/****************************************************************/
|
|
int ChaNumToType(int cha)
|
|
{
|
|
switch (cha)
|
|
{
|
|
case CHA_AFHA:
|
|
return (CHA_AFHA);
|
|
case CHA_DES:
|
|
return (CHA_DES);
|
|
case CHA_MDHA:
|
|
return (CHA_MDHA);
|
|
case CHA_RNG:
|
|
return (CHA_RNG);
|
|
case CHA_PKHA:
|
|
return (CHA_PKHA);
|
|
case CHA_AESA:
|
|
return (CHA_AESA);
|
|
default:
|
|
return (SEC2_INVALID_CHA_TYPE);
|
|
}
|
|
} /* End of ChaNumToType */
|
|
|
|
/* this should only be called with channel assignments locked */
|
|
/********************************************************************/
|
|
/* Function Name: CheckChas */
|
|
/* Purpose: Check to see if the CHA is available (at least one of */
|
|
/* this type of CHA is available) */
|
|
/* Input: The opId requested */
|
|
/* Output: SEC2_SUCCESS if this type of CHA is available */
|
|
/* otherwise the error code */
|
|
/********************************************************************/
|
|
int CheckChas(unsigned long OpId)
|
|
{
|
|
unsigned int chaType = 0;
|
|
switch (OpId & 0xf000)
|
|
{
|
|
case 0x1000: /* RNG Group */
|
|
chaType |= CHA_RNGA_BITMASK;
|
|
break;
|
|
case 0x2000: /* Des Groups */
|
|
chaType |= CHA_DESA_BITMASK;
|
|
break;
|
|
case 0x3000: /* RC4 Groups */
|
|
chaType |= CHA_AFHA_BITMASK;
|
|
break;
|
|
case 0x4000: /* MD Groups */
|
|
chaType |= CHA_MDHA_BITMASK;
|
|
break;
|
|
case 0x5000: /* PK Groups */
|
|
chaType |= CHA_PKHA_BITMASK;
|
|
break;
|
|
case 0x6000: /* AES Groups */
|
|
chaType |= CHA_AESA_BITMASK;
|
|
break;
|
|
case 0x7000: /* ipsec Des + MD Groups */
|
|
chaType |= (CHA_MDHA_BITMASK | CHA_DESA_BITMASK);
|
|
break;
|
|
case 0x8000: /* ipsec aes + md groups */
|
|
chaType |= (CHA_MDHA_BITMASK | CHA_AESA_BITMASK);
|
|
break;
|
|
default:
|
|
/* invalid opId */
|
|
return (SEC2_INVALID_OPERATION_ID);
|
|
}
|
|
if (((chaType & CHA_AFHA_BITMASK) != 0) && (FreeAfhas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
else if (((chaType & CHA_DESA_BITMASK) != 0) && (FreeDesas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
else if (((chaType & CHA_MDHA_BITMASK) != 0) && (FreeMdhas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
else if (((chaType & CHA_RNGA_BITMASK) != 0) && (FreeRngas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
else if (((chaType & CHA_PKHA_BITMASK) != 0) && (FreePkhas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
else if (((chaType & CHA_AESA_BITMASK) != 0) && (FreeAesas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
else if (((chaType & CHA_KEA_BITMASK) != 0) && (FreeKeas == 0))
|
|
{
|
|
return (SEC2_CHA_NOT_AVAILABLE);
|
|
}
|
|
|
|
/* CHA(s) are available, return OK */
|
|
return (SEC2_SUCCESS);
|
|
}
|
|
/********************************************************************/
|
|
/* Function Name: ReleaseChannel */
|
|
/* Purpose: To free a reserved channel */
|
|
/* */
|
|
/* Input: channel - the channel number (1-4) */
|
|
/* callingTaskId - the task id */
|
|
/* locked - TRUE or FALSE */
|
|
/* Return: SEC2_SUCCESS if success otherwise the error code */
|
|
/********************************************************************/
|
|
int ReleaseChannel(unsigned long channel, int callingTaskId, BOOLEAN locked)
|
|
{
|
|
int cha, chaType;
|
|
|
|
SEC2Dump(DBGTXT_SVCRQ, ("ReleaseChannel(%ld, taskID=0x%8x, lock=%d)\n", channel, callingTaskId, locked));
|
|
/* check channel value */
|
|
if ((channel == 0) || (channel > NUM_CHANNELS)) return (SEC2_INVALID_CHANNEL);
|
|
|
|
if (!locked)
|
|
IOLockChannelAssignment();
|
|
|
|
/* check that calling task is the channel's owner */
|
|
if (ChannelAssignments[channel - 1].ownerTaskId != callingTaskId)
|
|
{
|
|
/* error, caller is not the channel owner */
|
|
if (!locked)
|
|
IOUnLockChannelAssignment();
|
|
return (SEC2_INVALID_CHANNEL);
|
|
}
|
|
|
|
/* release all cha's assigned to this channel */
|
|
for (cha=0; cha<NUM_CHAS; cha++)
|
|
{
|
|
if (ChaAssignments[cha] == (unsigned char) channel)
|
|
{
|
|
/* determine cha type from cha number */
|
|
chaType = ChaNumToType(cha);
|
|
/* release the cha */
|
|
ReleaseCha((channel << 8) | chaType, callingTaskId, TRUE);
|
|
}
|
|
}
|
|
|
|
FreeChannels++;
|
|
|
|
/* release the channel */
|
|
ChannelAssignments[channel - 1].assignment = CHANNEL_FREE;
|
|
|
|
if (!locked)
|
|
{
|
|
IOUnLockChannelAssignment();
|
|
|
|
/* schedule queued requests on any freed channels */
|
|
ScheduleNext();
|
|
}
|
|
|
|
return (SEC2_SUCCESS);
|
|
} /* end of ReleaseChannel */
|
|
/**************************************************************************/
|
|
/* Function Name: ReleaseCha */
|
|
/* Purpose: To release a specific CHA */
|
|
/* or a manual channel. */
|
|
/* Input: channelCha - the bottom eight bits is the CHA chaType */
|
|
/* the next eight bits is the channel number (1-4) */
|
|
/* callingTaskId - the task id */
|
|
/* locked - TRUE or FALSE */
|
|
/* Return: SEC2_SUCCESS if success otherwise the error code */
|
|
/**************************************************************************/
|
|
int ReleaseCha(unsigned long channelCha, int callingTaskId, BOOLEAN locked)
|
|
{
|
|
unsigned char channel = (unsigned char)((channelCha >> 8) & 0xFF);
|
|
unsigned char chaType = (unsigned char)(channelCha & 0xFF);
|
|
unsigned long chaStatus[2] = {0,0};
|
|
/* unsigned long temp[2] = {0,0}; */
|
|
int cha;
|
|
int numChas;
|
|
|
|
SEC2Dump(DBGTXT_SVCRQ, ("ReleaseCha(%ld, taskID=0x%8x, lock=%d)\n", channelCha, callingTaskId, locked));
|
|
/* check chaType value */
|
|
if ((chaType != CHA_AFHA) && (chaType != CHA_DES) && (chaType != CHA_MDHA)
|
|
&& (chaType != CHA_RNG) && (chaType != CHA_PKHA)
|
|
&& (chaType != CHA_AESA)
|
|
)
|
|
return (SEC2_INVALID_CHA_TYPE);
|
|
|
|
if (!locked)
|
|
IOLockChannelAssignment();
|
|
|
|
/* check that callingTaskId matches the channel owner */
|
|
if (ChannelAssignments[channel - 1].ownerTaskId != callingTaskId)
|
|
{
|
|
/* error, cha owner is not current task */
|
|
if (!locked)
|
|
IOUnLockChannelAssignment();
|
|
return (SEC2_INVALID_CHANNEL);
|
|
}
|
|
|
|
/* determine number of CHAs for the chaType */
|
|
switch (chaType)
|
|
{
|
|
case CHA_AFHA:
|
|
numChas = NUM_AFHAS;
|
|
break;
|
|
case CHA_DES:
|
|
numChas = NUM_DESAS;
|
|
break;
|
|
case CHA_MDHA:
|
|
numChas = NUM_MDHAS;
|
|
break;
|
|
case CHA_RNG:
|
|
numChas = NUM_RNGAS;
|
|
break;
|
|
case CHA_PKHA:
|
|
numChas = NUM_PKHAS;
|
|
break;
|
|
case CHA_AESA:
|
|
numChas = NUM_AESAS;
|
|
break;
|
|
}
|
|
|
|
/* find the CHA to release */
|
|
for (cha=chaType; cha<(chaType+numChas); cha++)
|
|
{
|
|
/* see if the CHA is assigned to the given channel */
|
|
if (ChaAssignments[cha] == channel)
|
|
{
|
|
/* found a CHA assigned to the given channel */
|
|
/* release the CHA */
|
|
chaStatus[0] = *(unsigned long *)(ChaAssignmentStatusRegister);
|
|
chaStatus[1] = *(unsigned long *)(ChaAssignmentStatusRegister + 1);
|
|
|
|
if (cha < 4)
|
|
{
|
|
chaStatus[0] &= (~(0xF << (cha * 8)));
|
|
ChaAssignments[cha] = CHA_DYNAMIC;
|
|
}
|
|
else
|
|
{
|
|
chaStatus[1] &= (~(0xF << ((cha - 4) * 8)) << 16);
|
|
ChaAssignments[cha] = CHA_DYNAMIC;
|
|
}
|
|
|
|
*(ChaAssignmentControlRegister) = chaStatus[0];
|
|
*(ChaAssignmentControlRegister + 1) = chaStatus[1];
|
|
|
|
/* reset the CHA */
|
|
*(ChaResetControlRegister[cha_idx[cha]]) = CHA_SOFTWARE_RESET;
|
|
*(ChaResetControlRegister[cha_idx[cha]] + 1) = 0;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* see if we found a CHA to release */
|
|
if (cha >= (chaType + numChas))
|
|
{
|
|
/* we didn't find a CHA to release, return an error */
|
|
if (!locked)
|
|
IOUnLockChannelAssignment();
|
|
return (SEC2_INVALID_CHA_TYPE);
|
|
}
|
|
|
|
/* update free CHA counts */
|
|
switch (chaType)
|
|
{
|
|
case CHA_AFHA:
|
|
FreeAfhas++;
|
|
break;
|
|
case CHA_DES:
|
|
FreeDesas++;
|
|
break;
|
|
case CHA_MDHA:
|
|
FreeMdhas++;
|
|
break;
|
|
case CHA_RNG:
|
|
FreeRngas++;
|
|
break;
|
|
case CHA_PKHA:
|
|
FreePkhas++;
|
|
break;
|
|
case CHA_AESA:
|
|
FreeAesas++;
|
|
break;
|
|
}
|
|
|
|
if (!locked)
|
|
{
|
|
IOUnLockChannelAssignment();
|
|
|
|
/* schedule queued requests on any freed CHAs */
|
|
ScheduleNext();
|
|
}
|
|
|
|
return (SEC2_SUCCESS);
|
|
} /* End of ReleaseCha */
|