root/sys/dev/pms/RefTisa/sallsdk/spc/saport.c
/*******************************************************************************
*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved. 
*
*Redistribution and use in source and binary forms, with or without modification, are permitted provided 
*that the following conditions are met: 
*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
*following disclaimer. 
*2. Redistributions in binary form must reproduce the above copyright notice, 
*this list of conditions and the following disclaimer in the documentation and/or other materials provided
*with the distribution. 
*
*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED 
*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE

********************************************************************************/
/*******************************************************************************/
/*! \file saport.c
 *  \brief The file implements the functions to handle port
 *
 */
/******************************************************************************/
#include <sys/cdefs.h>
#include <dev/pms/config.h>

#include <dev/pms/RefTisa/sallsdk/spc/saglobal.h>
#ifdef SA_ENABLE_TRACE_FUNCTIONS
#ifdef siTraceFileID
#undef siTraceFileID
#endif
#define siTraceFileID 'L'
#endif


extern bit32 gFPGA_TEST;
/******************************************************************************/
/*! \brief Add a SAS device to the discovery list of the port
 *
 *  Add a SAS device from the discovery list of the port
 *
 *  \param agRoot handles for this instance of SAS/SATA LLL
 *  \param pPort
 *  \param sasIdentify
 *  \param sasInitiator
 *  \param smpTimeout
 *  \param itNexusTimeout
 *  \param firstBurstSize
 *  \param dTypeSRate -- device type and link rate
 *  \param flag
 *
 *  \return -the device descriptor-
 */
/*******************************************************************************/
GLOBAL agsaDeviceDesc_t *siPortSASDeviceAdd(
  agsaRoot_t        *agRoot,
  agsaPort_t        *pPort,
  agsaSASIdentify_t sasIdentify,
  bit32             sasInitiator,
  bit32             smpTimeout,
  bit32             itNexusTimeout,
  bit32             firstBurstSize,
  bit8              dTypeSRate,
  bit32             flag
  )
{
  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  agsaDeviceDesc_t      *pDevice;

  SA_DBG3(("siPortSASDeviceAdd: start\n"));

  smTraceFuncEnter(hpDBG_VERY_LOUD, "23");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  SA_ASSERT((agNULL != pPort), "");

  /* Acquire Device Lock */
  ossaSingleThreadedEnter(agRoot, LL_DEVICE_LOCK);

  /* Try to Allocate from device list */
  pDevice = (agsaDeviceDesc_t *) saLlistGetHead(&(saRoot->freeDevicesList));

  /* If device handle available */
  if ( agNULL != pDevice)
  {
    int i;

    /* Remove from free device list */
    saLlistRemove(&(saRoot->freeDevicesList), &(pDevice->linkNode));

    /* Initialize device descriptor */
    if ( agTRUE == sasInitiator )
    {
      pDevice->initiatorDevHandle.sdkData = pDevice;
      pDevice->targetDevHandle.sdkData = agNULL;
    }
    else
    {
      pDevice->initiatorDevHandle.sdkData = agNULL;
      pDevice->targetDevHandle.sdkData = pDevice;
    }

    pDevice->initiatorDevHandle.osData = agNULL;
    pDevice->targetDevHandle.osData = agNULL;

    /* setup device type */
    pDevice->deviceType = (bit8)((dTypeSRate & 0x30) >> SHIFT4);
    SA_DBG3(("siPortSASDeviceAdd: Device Type 0x%x, Port Context %p\n", pDevice->deviceType, pPort));
    pDevice->pPort = pPort;
    saLlistInitialize(&(pDevice->pendingIORequests));

    /* setup sasDeviceInfo */
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.smpTimeout = (bit16)smpTimeout;
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.it_NexusTimeout = (bit16)itNexusTimeout;
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.firstBurstSize = (bit16)firstBurstSize;
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate = dTypeSRate;
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.flag = flag;
    for (i = 0; i < 4; i++)
    {
      pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[i] = sasIdentify.sasAddressHi[i];
      pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[i] = sasIdentify.sasAddressLo[i];
    }
    pDevice->devInfo.sasDeviceInfo.initiator_ssp_stp_smp = sasIdentify.initiator_ssp_stp_smp;
    pDevice->devInfo.sasDeviceInfo.target_ssp_stp_smp = sasIdentify.target_ssp_stp_smp;
    pDevice->devInfo.sasDeviceInfo.phyIdentifier = sasIdentify.phyIdentifier;

    /* Add to discoverd device for the port */
    saLlistAdd(&(pPort->listSASATADevices), &(pDevice->linkNode));

    /* Release Device Lock */
    ossaSingleThreadedLeave(agRoot, LL_DEVICE_LOCK);

    /* Log Messages */
    SA_DBG3(("siPortSASDeviceAdd: sasIdentify addrHI 0x%x\n", SA_IDFRM_GET_SAS_ADDRESSHI(&sasIdentify)));
    SA_DBG3(("siPortSASDeviceAdd: sasIdentify addrLO 0x%x\n", SA_IDFRM_GET_SAS_ADDRESSLO(&sasIdentify)));

  }
  else
  {
    /* Release Device Lock */
    ossaSingleThreadedLeave(agRoot, LL_DEVICE_LOCK);
    SA_ASSERT((agNULL != pDevice), "");
    SA_DBG1(("siPortSASDeviceAdd: device allocation failed\n"));
  }
  SA_DBG3(("siPortSASDeviceAdd: end\n"));

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "23");
  return pDevice;
}

/******************************************************************************/
/*! \brief The function to remove a device descriptor
 *
 *  The function to remove a device descriptor
 *
 *  \param agRoot handles for this instance of SAS/SATA hardware
 *  \param pPort  The pointer to the port
 *  \param pDevice The pointer to the device
 *
 *  \return -void-
 */
/*******************************************************************************/
GLOBAL void siPortDeviceRemove(
  agsaRoot_t        *agRoot,
  agsaPort_t        *pPort,
  agsaDeviceDesc_t  *pDevice,
  bit32             unmap
  )
{
  agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  bit32        deviceIdx;

  smTraceFuncEnter(hpDBG_VERY_LOUD, "24");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  SA_ASSERT((agNULL != pPort), "");
  SA_ASSERT((agNULL != pDevice), "");
  SA_ASSERT((SAS_SATA_UNKNOWN_DEVICE != pDevice->deviceType), "");

  /* remove the device from discovered list */
  SA_DBG3(("siPortDeviceRemove(SAS/SATA): DeviceIndex %d Device Context %p\n", pDevice->DeviceMapIndex, pDevice));

  ossaSingleThreadedEnter(agRoot, LL_DEVICE_LOCK);
  saLlistRemove(&(pPort->listSASATADevices), &(pDevice->linkNode));

  /* Reset the device data structure */
  pDevice->pPort = agNULL;
  pDevice->initiatorDevHandle.osData = agNULL;
  pDevice->initiatorDevHandle.sdkData = agNULL;
  pDevice->targetDevHandle.osData = agNULL;
  pDevice->targetDevHandle.sdkData = agNULL;

  saLlistAdd(&(saRoot->freeDevicesList), &(pDevice->linkNode));

  if(unmap)
  {
    /* remove the DeviceMap and MapIndex */
    deviceIdx = pDevice->DeviceMapIndex & DEVICE_ID_BITS;
    OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");

    saRoot->DeviceMap[deviceIdx].DeviceIdFromFW = 0;
    saRoot->DeviceMap[deviceIdx].DeviceHandle = agNULL;
    pDevice->DeviceMapIndex = 0;
  }
  ossaSingleThreadedLeave(agRoot, LL_DEVICE_LOCK);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "24");

  return;
}

/******************************************************************************/
/*! \brief Add a SATA device to the discovery list of the port
 *
 *  Add a SATA device from the discovery list of the port
 *
 *  \param agRoot handles for this instance of SAS/SATA hardware
 *  \param pPort
 *  \param pSTPBridge
 *  \param pSignature
 *  \param pm
 *  \param pmField
 *  \param smpReqTimeout
 *  \param itNexusTimeout
 *  \param firstBurstSize
 *  \param dTypeSRate
 *
 *  \return -the device descriptor-
 */
/*******************************************************************************/
GLOBAL agsaDeviceDesc_t *siPortSATADeviceAdd(
  agsaRoot_t              *agRoot,
  agsaPort_t              *pPort,
  agsaDeviceDesc_t        *pSTPBridge,
  bit8                    *pSignature,
  bit8                    pm,
  bit8                    pmField,
  bit32                   smpReqTimeout,
  bit32                   itNexusTimeout,
  bit32                   firstBurstSize,
  bit8                    dTypeSRate,
  bit32                   flag
  )
{
  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  agsaDeviceDesc_t      *pDevice;

  smTraceFuncEnter(hpDBG_VERY_LOUD, "25");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  SA_ASSERT((agNULL != pPort), "");

  /* Acquire Device Lock */
  ossaSingleThreadedEnter(agRoot, LL_DEVICE_LOCK);

  /* Try to Allocate from device list */
  pDevice = (agsaDeviceDesc_t *) saLlistGetHead(&(saRoot->freeDevicesList));

  /* If device handle available */
  if ( agNULL != pDevice)
  {
    int i;

    /* Remove from free device list */
    saLlistRemove(&(saRoot->freeDevicesList), &(pDevice->linkNode));

    /* Initialize the device descriptor */
    pDevice->initiatorDevHandle.sdkData = agNULL;
    pDevice->targetDevHandle.sdkData = pDevice;
    pDevice->initiatorDevHandle.osData = agNULL;
    pDevice->targetDevHandle.osData = agNULL;

    pDevice->deviceType = (bit8)((dTypeSRate & 0x30) >> SHIFT4);
    SA_DBG3(("siPortSATADeviceAdd: DeviceType 0x%x Port Context %p\n", pDevice->deviceType, pPort));

    /* setup device common infomation */
    pDevice->devInfo.sataDeviceInfo.commonDevInfo.smpTimeout = (bit16)smpReqTimeout;
    pDevice->devInfo.sataDeviceInfo.commonDevInfo.it_NexusTimeout = (bit16)itNexusTimeout;
    pDevice->devInfo.sataDeviceInfo.commonDevInfo.firstBurstSize = (bit16)firstBurstSize;
    pDevice->devInfo.sataDeviceInfo.commonDevInfo.devType_S_Rate = dTypeSRate;
    pDevice->devInfo.sataDeviceInfo.commonDevInfo.flag = flag;
    for (i = 0; i < 4; i++)
    {
      pDevice->devInfo.sataDeviceInfo.commonDevInfo.sasAddressHi[i] = 0;
      pDevice->devInfo.sataDeviceInfo.commonDevInfo.sasAddressLo[i] = 0;
    }
    /* setup SATA device information */
    pDevice->devInfo.sataDeviceInfo.connection = pm;
    pDevice->devInfo.sataDeviceInfo.portMultiplierField = pmField;
    pDevice->devInfo.sataDeviceInfo.stpPhyIdentifier = 0;
    pDevice->pPort = pPort;

    /* Add to discoverd device for the port */
    saLlistAdd(&(pPort->listSASATADevices), &(pDevice->linkNode));

    /* Release Device Lock */
    ossaSingleThreadedLeave(agRoot, LL_DEVICE_LOCK);
  }
  else
  {
    /* Release Device Lock */
    ossaSingleThreadedLeave(agRoot, LL_DEVICE_LOCK);
    SA_ASSERT((agNULL != pDevice), "");
    SA_DBG1(("siPortSATADeviceAdd: device allocation failed\n"));
  }
  SA_DBG3(("siPortSATADeviceAdd: end\n"));

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "25");
  return pDevice;
}

/******************************************************************************/
/*! \brief Invalid a port
 *
 *  Invalid a port
 *
 *  \param agRoot handles for this instance of SAS/SATA hardware
 *  \param pPort
 *
 *  \return -void-
 */
/*******************************************************************************/
GLOBAL void siPortInvalid(
  agsaRoot_t  *agRoot,
  agsaPort_t  *pPort
  )
{
  agsaLLRoot_t    *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  smTraceFuncEnter(hpDBG_VERY_LOUD, "26");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  SA_ASSERT((agNULL != pPort), "");

  /* set port's status to invalidating */
  pPort->status |= PORT_INVALIDATING;

  /* Remove from validPort and add the port back to the free port link list */
  ossaSingleThreadedEnter(agRoot, LL_PORT_LOCK);
  saLlistRemove(&(saRoot->validPorts), &(pPort->linkNode));
  saLlistAdd(&(saRoot->freePorts), &(pPort->linkNode));
  pPort->tobedeleted = agFALSE;
  ossaSingleThreadedLeave(agRoot, LL_PORT_LOCK);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "26");

  /* return */
}

/******************************************************************************/
/*! \brief The function to remove a device descriptor
 *
 *  The function to remove a device descriptor
 *
 *  \param agRoot handles for this instance of SAS/SATA hardware
 *  \param pPort  The pointer to the port
 *  \param pDevice The pointer to the device
 *
 *  \return -void-
 */
/*******************************************************************************/
GLOBAL void siPortDeviceListRemove(
  agsaRoot_t        *agRoot,
  agsaPort_t        *pPort,
  agsaDeviceDesc_t  *pDevice
  )
{
  agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);

  smTraceFuncEnter(hpDBG_VERY_LOUD, "27");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  SA_ASSERT((agNULL != pPort), "");
  SA_ASSERT((agNULL != pDevice), "");
  SA_ASSERT((SAS_SATA_UNKNOWN_DEVICE != pDevice->deviceType), "");

  /* remove the device from discovered list */
  SA_DBG3(("siPortDeviceListRemove(SAS/SATA): PortID %d Device Context %p\n", pPort->portId, pDevice));

  ossaSingleThreadedEnter(agRoot, LL_DEVICE_LOCK);
  saLlistRemove(&(pPort->listSASATADevices), &(pDevice->linkNode));

  /* Reset the device data structure */
  pDevice->pPort = agNULL;
  pDevice->initiatorDevHandle.osData = agNULL;
  pDevice->initiatorDevHandle.sdkData = agNULL;
  pDevice->targetDevHandle.osData = agNULL;
  pDevice->targetDevHandle.sdkData = agNULL;

  saLlistAdd(&(saRoot->freeDevicesList), &(pDevice->linkNode));
  ossaSingleThreadedLeave(agRoot, LL_DEVICE_LOCK);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "27");
  return;
}

/******************************************************************************/
/*! \brief Initiate a Port COntrol IOMB command
 *
 *  This function is called to initiate a Port COntrol command to the SPC.
 *  The completion of this function is reported in ossaPortControlCB().
 *
 *  \param agRoot        handles for this instance of SAS/SATA hardware
 *  \param agContext     the context of this API
 *  \param queueNum      queue number
 *  \param agPortContext point to the event source structure
 *  \param param0        parameter 0
 *  \param param1        parameter 1
 *
 *  \return - successful or failure
 */
/*******************************************************************************/
GLOBAL bit32 saPortControl(
  agsaRoot_t            *agRoot,
  agsaContext_t         *agContext,
  bit32                 queueNum,
  agsaPortContext_t     *agPortContext,
  bit32                 portOperation,
  bit32                 param0,
  bit32                 param1
  )
{
  agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  agsaIORequestDesc_t  *pRequest;
  agsaPort_t           *pPort;
  bit32                ret = AGSA_RC_SUCCESS;
  bit32                opportId;
  agsaPortControlCmd_t payload;
  bit32               using_reserved = agFALSE;


  /* sanity check */
  SA_ASSERT((agNULL !=saRoot ), "");
  SA_ASSERT((agNULL != agPortContext), "");
  if(saRoot == agNULL)
  {
    SA_DBG1(("saPortControl: saRoot == agNULL\n"));
    return(AGSA_RC_FAILURE);
  }
  smTraceFuncEnter(hpDBG_VERY_LOUD, "28");

  SA_DBG1(("saPortControl: portContext %p portOperation 0x%x param0 0x%x param1 0x%x\n", agPortContext, portOperation, param0, param1));

  /* Get request from free IORequests */
  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); /**/
  /* If no LL Control request entry available */
  if ( agNULL == pRequest )
  {
    pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests));
    /* If no LL Control request entry available */
    if(agNULL != pRequest)
    {
      using_reserved = agTRUE;
      SA_DBG2(("saPortControl, using saRoot->freeReservedRequests\n"));
    }
    else
    {
      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
      SA_DBG1(("saPortControl, No request from free list Not using saRoot->freeReservedRequests\n"));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "28");
      return AGSA_RC_BUSY;
    }
  }

  /* If LL Control request entry avaliable */
  if( using_reserved )
  {
    saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
  }
  else
  {
    /* Remove the request from free list */
    saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
  }
  SA_ASSERT((!pRequest->valid), "The pRequest is in use");
  saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
  saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
  saRoot->IOMap[pRequest->HTag].agContext = agContext;
  pRequest->valid = agTRUE;
  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  /* build IOMB command and send to SPC */
  /* set payload to zeros */
  si_memset(&payload, 0, sizeof(agsaPortControlCmd_t));

  /* find port id */
  pPort = (agsaPort_t *) (agPortContext->sdkData);
  opportId = (pPort->portId & PORTID_MASK) | (portOperation << SHIFT8);
  /* set tag */
  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPortControlCmd_t, tag), pRequest->HTag);
  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPortControlCmd_t, portOPPortId), opportId);
  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPortControlCmd_t, Param0), param0);
  OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPortControlCmd_t, Param1), param1);

  SA_DBG1(("saPortControl: portId 0x%x portOperation 0x%x\n", (pPort->portId & PORTID_MASK),portOperation));

  /* build IOMB command and send to SPC */
  ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PORT_CONTROL, IOMB_SIZE64, queueNum);
  if (AGSA_RC_SUCCESS != ret)
  {
    /* remove the request from IOMap */
    saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
    saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
    saRoot->IOMap[pRequest->HTag].agContext = agNULL;
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    if (saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("saPortControl: saving pRequest (%p) for later use\n", pRequest));
      saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
    }
    else
    {
      /* return the request to free pool */
      saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    }
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    SA_DBG1(("saPortControl, sending IOMB failed\n" ));
  }
  else
  {
    if (portOperation == AGSA_PORT_HARD_RESET)
    {
      SA_DBG1(("saPortControl,0x%x AGSA_PORT_HARD_RESET 0x%x param0 0x%x\n",
                pPort->portId, param0, param0 & AUTO_HARD_RESET_DEREG_FLAG));
      saRoot->autoDeregDeviceflag[pPort->portId & PORTID_MASK] = param0 & AUTO_HARD_RESET_DEREG_FLAG;
    }
    else if (portOperation == AGSA_PORT_CLEAN_UP)
    {
      SA_DBG1(("saPortControl, 0x%x AGSA_PORT_CLEAN_UP param0 0x%x %d\n", pPort->portId, param0,((param0 & AUTO_FW_CLEANUP_DEREG_FLAG) ? 0:1)));
      saRoot->autoDeregDeviceflag[pPort->portId & PORTID_MASK] = ((param0 & AUTO_FW_CLEANUP_DEREG_FLAG) ? 0:1);
    }
    SA_DBG1(("saPortControl, sending IOMB SUCCESS, portId 0x%x autoDeregDeviceflag=0x%x\n", pPort->portId,saRoot->autoDeregDeviceflag[pPort->portId & PORTID_MASK]));
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "28");

  return ret;
}

/**
 * saEncryptGetMode()
 *
 *     Returns the status, working state and sector size
 *     registers of the encryption engine
 *
 * @param saRoot
 * @param encryptInfo
 *
 * @return
 */
GLOBAL bit32 saEncryptGetMode(agsaRoot_t        *agRoot,
                              agsaContext_t     *agContext,
                              agsaEncryptInfo_t *encryptInfo)
{
    bit32 ret = AGSA_RC_NOT_SUPPORTED;

    smTraceFuncEnter(hpDBG_VERY_LOUD,"29");
    agContext = agContext; /* Lint*/
    SA_DBG4(("saEncryptGetMode, encryptInfo %p\n",encryptInfo ));
    if(smIS_SPCV(agRoot))
    {
      bit32 ScratchPad1 =0;
      bit32 ScratchPad3 =0;

      encryptInfo->status = 0;
      encryptInfo->encryptionCipherMode = 0;
      encryptInfo->encryptionSecurityMode = 0;
      encryptInfo->flag = 0;

      ScratchPad1 = ossaHwRegRead(agRoot,V_Scratchpad_1_Register);
      ScratchPad3 = ossaHwRegRead(agRoot,V_Scratchpad_3_Register);
      if((ScratchPad1 & SCRATCH_PAD1_V_RAAE_MASK) ==  SCRATCH_PAD1_V_RAAE_MASK)
      {
        if((ScratchPad3 & SCRATCH_PAD3_V_ENC_MASK) == SCRATCH_PAD3_V_ENC_READY ) /* 3 */
        {
          if( ScratchPad3 & SCRATCH_PAD3_V_XTS_ENABLED)
          {
            encryptInfo->encryptionCipherMode = agsaEncryptCipherModeXTS;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMF_ENABLED )
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMF;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMA_ENABLED)
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMA;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMB_ENABLED )
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMB;
          }
          encryptInfo->status = AGSA_RC_SUCCESS;
          ret = AGSA_RC_SUCCESS;
        }
        else if((ScratchPad3 & SCRATCH_PAD3_V_ENC_READY) == SCRATCH_PAD3_V_ENC_DISABLED) /* 0 */
        {
          SA_DBG1(("saEncryptGetMode, SCRATCH_PAD3_V_ENC_DISABLED 1 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
          encryptInfo->status = 0xFFFF;
          encryptInfo->encryptionCipherMode = 0;
          encryptInfo->encryptionSecurityMode = 0;
          ret = AGSA_RC_NOT_SUPPORTED;
        }
        else if((ScratchPad3 & SCRATCH_PAD3_V_ENC_MASK ) == SCRATCH_PAD3_V_ENC_DIS_ERR) /* 1 */
        {
          SA_DBG1(("saEncryptGetMode, SCRATCH_PAD3_V_ENC_DIS_ERR 1 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
          encryptInfo->status = (ScratchPad3 & SCRATCH_PAD3_V_ERR_CODE ) >> SHIFT16;
          if( ScratchPad3 & SCRATCH_PAD3_V_XTS_ENABLED)
          {
            encryptInfo->encryptionCipherMode = agsaEncryptCipherModeXTS;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMF_ENABLED )
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMF;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMA_ENABLED)
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMA;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMB_ENABLED )
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMB;
          }
          ret = AGSA_RC_FAILURE;
        }
        else if((ScratchPad3 & SCRATCH_PAD3_V_ENC_MASK ) == SCRATCH_PAD3_V_ENC_ENA_ERR) /* 2 */
        {

          SA_DBG1(("saEncryptGetMode, SCRATCH_PAD3_V_ENC_ENA_ERR 1 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
          encryptInfo->status = (ScratchPad3 & SCRATCH_PAD3_V_ERR_CODE ) >> SHIFT16;
          if( ScratchPad3 & SCRATCH_PAD3_V_XTS_ENABLED)
          {
            encryptInfo->encryptionCipherMode = agsaEncryptCipherModeXTS;
            SA_DBG1(("saEncryptGetMode, SCRATCH_PAD3_V_ENC_ENA_ERR 2 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMF_ENABLED )
          {
            SA_DBG1(("saEncryptGetMode, SCRATCH_PAD3_V_ENC_ENA_ERR 3 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
            encryptInfo->encryptionSecurityMode = agsaEncryptSMF;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMA_ENABLED)
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMA;
          }
          if( (ScratchPad3 & SCRATCH_PAD3_V_SM_MASK ) == SCRATCH_PAD3_V_SMB_ENABLED )
          {
            encryptInfo->encryptionSecurityMode = agsaEncryptSMB;
          }

          SA_DBG1(("saEncryptGetMode,encryptInfo status 0x%08X CipherMode 0x%X SecurityMode 0x%X\n" ,
              encryptInfo->status,
              encryptInfo->encryptionCipherMode,
              encryptInfo->encryptionSecurityMode));

#ifdef CCFLAGS_SPCV_FPGA_REVB /*The FPGA platform hasn't EEPROM*/
          ret = AGSA_RC_SUCCESS;
#else
          ret = AGSA_RC_FAILURE;
#endif
        }
      }
      else  if((ScratchPad1 & SCRATCH_PAD1_V_RAAE_MASK) ==  SCRATCH_PAD1_V_RAAE_ERR)
      {
        SA_DBG1(("saEncryptGetMode, SCRATCH_PAD1_V_RAAE_ERR 1 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
        ret = AGSA_RC_FAILURE;
      }
      else  if((ScratchPad1 & SCRATCH_PAD1_V_RAAE_MASK) == 0x0 )
      {
        SA_DBG1(("saEncryptGetMode, RAAE not ready AGSA_RC_BUSY 1 0x%08X 3 0x%08X\n",ScratchPad1,ScratchPad3 ));
        ret = AGSA_RC_BUSY;
      }
      if(ScratchPad3 & SCRATCH_PAD3_V_AUT)
      {
        encryptInfo->flag |= OperatorAuthenticationEnable_AUT;
      }
      if(ScratchPad3 & SCRATCH_PAD3_V_ARF)
      {
        encryptInfo->flag |= ReturnToFactoryMode_ARF;
      }

      SA_DBG2(("saEncryptGetMode, encryptionCipherMode 0x%x encryptionSecurityMode 0x%x flag 0x%x status 0x%x\n",
                encryptInfo->encryptionCipherMode,
                encryptInfo->encryptionSecurityMode,
                encryptInfo->flag,
                encryptInfo->status));
      SA_DBG2(("saEncryptGetMode, ScratchPad3 0x%x returns 0x%x\n",ScratchPad3, ret));

    }
    else
    {
      SA_DBG1(("saEncryptGetMode, SPC AGSA_RC_NOT_SUPPORTED\n"));
    }

    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "29");
    return ret;
}

/**/
GLOBAL bit32 saEncryptSetMode (
                      agsaRoot_t        *agRoot,
                      agsaContext_t     *agContext,
                      bit32             queueNum,
                      agsaEncryptInfo_t *mode
                      )

{
  bit32 ret = AGSA_RC_NOT_SUPPORTED;
  agsaSetControllerConfigCmd_t agControllerConfig;
  agsaSetControllerConfigCmd_t *pagControllerConfig = &agControllerConfig;
  bit32 smode = 0;

  if(smIS_SPCV(agRoot))
  {
    bit32 ScratchPad1 =0;

    ScratchPad1 = ossaHwRegRead(agRoot,V_Scratchpad_1_Register);
    if((ScratchPad1 & SCRATCH_PAD1_V_RAAE_MASK) ==  SCRATCH_PAD1_V_RAAE_MASK)
    {
      si_memset(pagControllerConfig,0,sizeof(agsaSetControllerConfigCmd_t));

      SA_DBG2(("saEncryptSetMode, encryptionCipherMode 0x%x encryptionSecurityMode 0x%x status 0x%x\n",
                                          mode->encryptionCipherMode,
                                          mode->encryptionSecurityMode,
                                          mode->status
                                          ));

      smode = mode->encryptionSecurityMode;

      if( mode->encryptionCipherMode & agsaEncryptCipherModeXTS)
      {
        smode |= 1 << SHIFT22;
      }


      pagControllerConfig->pageCode = AGSA_ENCRYPTION_CONTROL_PARM_PAGE | smode;
      pagControllerConfig->tag =0;

      SA_DBG2(("saEncryptSetMode,tag 0x%x pageCode 0x%x\n",
                                          pagControllerConfig->tag,
                                          pagControllerConfig->pageCode
                                          ));

      SA_DBG2(("saEncryptSetMode, 0x%x 0x%x 0x%x 0x%x\n",
                                          pagControllerConfig->configPage[0],
                                          pagControllerConfig->configPage[1],
                                          pagControllerConfig->configPage[2],
                                          pagControllerConfig->configPage[3]
                                          ));

      SA_DBG2(("saEncryptSetMode, 0x%x 0x%x 0x%x 0x%x\n",
                                          pagControllerConfig->configPage[4],
                                          pagControllerConfig->configPage[5],
                                          pagControllerConfig->configPage[6],
                                          pagControllerConfig->configPage[7]
                                          ));

      SA_DBG2(("saEncryptSetMode, 0x%x 0x%x 0x%x 0x%x\n",
                                          pagControllerConfig->configPage[8],
                                          pagControllerConfig->configPage[9],
                                          pagControllerConfig->configPage[10],
                                          pagControllerConfig->configPage[11]
                                          ));

      ret = mpiSetControllerConfigCmd(agRoot,agContext,pagControllerConfig,queueNum,agTRUE);

      SA_DBG2(("saEncryptSetMode,  pageCode 0x%x tag 0x%x status 0x%x\n",
                                        pagControllerConfig->pageCode,
                                        pagControllerConfig->tag,
                                        ret
                                        ));
    }
    else
    {
      SA_DBG2(("saEncryptSetMode,ScratchPad1 not ready %08X\n",ScratchPad1 ));
      ret = AGSA_RC_BUSY;
    }

  }
  return ret;
}



/**
 * saEncryptKekUpdate()
 *
 *     Replace a KEK within the controller
 *
 * @param saRoot
 * @param flags
 * @param newKekIndex
 * @param wrapperKekIndex
 * @param encryptKekBlob
 *
 * @return
 */
GLOBAL bit32 saEncryptKekUpdate(
                    agsaRoot_t         *agRoot,
                    agsaContext_t      *agContext,
                    bit32              queueNum,
                    bit32              flags,
                    bit32              newKekIndex,
                    bit32              wrapperKekIndex,
                    bit32              blobFormat,
                    agsaEncryptKekBlob_t *encryptKekBlob
                    )
{
  agsaKekManagementCmd_t     payload;
  bit32 ret, i;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"30");

  SA_DBG2(("saEncryptKekUpdate, flags 0x%x newKekIndex 0x%x wrapperKekIndex 0x%x encryptKekBlob %p\n",flags,newKekIndex,wrapperKekIndex,encryptKekBlob));
  SA_DBG2(("saEncryptKekUpdate, 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
                                encryptKekBlob->kekBlob[0],encryptKekBlob->kekBlob[1],
                                encryptKekBlob->kekBlob[2],encryptKekBlob->kekBlob[3],
                                encryptKekBlob->kekBlob[4],encryptKekBlob->kekBlob[5],
                                encryptKekBlob->kekBlob[6],encryptKekBlob->kekBlob[7]));
  SA_DBG2(("saEncryptKekUpdate, 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
                                encryptKekBlob->kekBlob[ 8],encryptKekBlob->kekBlob[ 9],
                                encryptKekBlob->kekBlob[10],encryptKekBlob->kekBlob[11],
                                encryptKekBlob->kekBlob[12],encryptKekBlob->kekBlob[13],
                                encryptKekBlob->kekBlob[14],encryptKekBlob->kekBlob[15]));
  SA_DBG2(("saEncryptKekUpdate, 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
                                encryptKekBlob->kekBlob[16],encryptKekBlob->kekBlob[17],
                                encryptKekBlob->kekBlob[18],encryptKekBlob->kekBlob[19],
                                encryptKekBlob->kekBlob[20],encryptKekBlob->kekBlob[21],
                                encryptKekBlob->kekBlob[22],encryptKekBlob->kekBlob[23]));
  SA_DBG2(("saEncryptKekUpdate, 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
                                encryptKekBlob->kekBlob[24],encryptKekBlob->kekBlob[25],
                                encryptKekBlob->kekBlob[26],encryptKekBlob->kekBlob[27],
                                encryptKekBlob->kekBlob[28],encryptKekBlob->kekBlob[29],
                                encryptKekBlob->kekBlob[30],encryptKekBlob->kekBlob[31]));
  SA_DBG2(("saEncryptKekUpdate, 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
                                encryptKekBlob->kekBlob[32],encryptKekBlob->kekBlob[33],
                                encryptKekBlob->kekBlob[34],encryptKekBlob->kekBlob[35],
                                encryptKekBlob->kekBlob[36],encryptKekBlob->kekBlob[37],
                                encryptKekBlob->kekBlob[38],encryptKekBlob->kekBlob[39]));
  SA_DBG2(("saEncryptKekUpdate, 0x%02X%02X%02X%02X 0x%02X%02X%02X%02X\n",
                                encryptKekBlob->kekBlob[40],encryptKekBlob->kekBlob[41],
                                encryptKekBlob->kekBlob[42],encryptKekBlob->kekBlob[43],
                                encryptKekBlob->kekBlob[44],encryptKekBlob->kekBlob[45],
                                encryptKekBlob->kekBlob[46],encryptKekBlob->kekBlob[47]));
  /* create payload for IOMB */
  si_memset(&payload, 0, sizeof(agsaKekManagementCmd_t));

  OSSA_WRITE_LE_32(agRoot,
                   &payload,
                   OSSA_OFFSET_OF(agsaKekManagementCmd_t, NEWKIDX_CURKIDX_KBF_Reserved_SKNV_KSOP),
                   (newKekIndex << SHIFT24) | (wrapperKekIndex << SHIFT16) | blobFormat << SHIFT14 | (flags << SHIFT8) | KEK_MGMT_SUBOP_UPDATE);
  for (i = 0; i < 12; i++)
  {

    OSSA_WRITE_LE_32(agRoot,
                    &payload,
                    OSSA_OFFSET_OF(agsaKekManagementCmd_t, kekBlob[i ]),
                    (bit32)*(bit32*)&encryptKekBlob->kekBlob[i * sizeof(bit32)] );
/**/
    }

  ret = mpiKekManagementCmd(agRoot, agContext, &payload, queueNum );

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "30");
  return ret;
}


#ifdef HIALEAH_ENCRYPTION

GLOBAL bit32 saEncryptHilUpdate(
                    agsaRoot_t         *agRoot,
                    agsaContext_t      *agContext,
                    bit32              queueNum
                    )
{
    agsaKekManagementCmd_t     payload;

    bit32 ScratchPad1 =0;
    bit32 ScratchPad3 =0;
    bit32 ret =0;

    ScratchPad1 = ossaHwRegRead(agRoot,V_Scratchpad_1_Register);
    ScratchPad3 = ossaHwRegRead(agRoot,V_Scratchpad_3_Register);


    smTraceFuncEnter(hpDBG_VERY_LOUD,"xxx");

    SA_DBG2(("saEncryptHilUpdate ScratchPad1 0x08%x ScratchPad3 0x08%x\n",ScratchPad1,ScratchPad3));
    /* create payload for IOMB */
    si_memset(&payload, 0, sizeof(agsaKekManagementCmd_t));

    OSSA_WRITE_LE_32(agRoot, 
                     &payload, 
                     OSSA_OFFSET_OF(agsaKekManagementCmd_t, NEWKIDX_CURKIDX_KBF_Reserved_SKNV_KSOP), 
                     (1 << SHIFT24) | (1 << SHIFT16) | (1 << SHIFT8) | KEK_MGMT_SUBOP_KEYCARDUPDATE);
/**/

    ret = mpiKekManagementCmd(agRoot, agContext, &payload, queueNum );

    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xxx");
    return ret;
}
#endif /* HIALEAH_ENCRYPTION */

/**
 * saEncryptKekInvalidate()
 *
 *     Remove a KEK from the controller
 *
 * @param saRoot
 * @param flags
 * @param newKekIndex
 * @param wrapperKekIndex
 * @param encryptKekBlob
 *
 * @return
 */
GLOBAL bit32 saEncryptKekInvalidate(
                     agsaRoot_t        *agRoot,
                     agsaContext_t     *agContext,
                     bit32             queueNum,
                     bit32             kekIndex
                     )
{
    agsaKekManagementCmd_t     payload;
    bit32 ret;

    smTraceFuncEnter(hpDBG_VERY_LOUD,"31");

    SA_DBG2(("saEncryptKekInvalidate, kekIndex 0x%x \n",kekIndex));


    /* create payload for IOMB */
    si_memset(&payload, 0, sizeof(agsaDekManagementCmd_t));

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaKekManagementCmd_t, NEWKIDX_CURKIDX_KBF_Reserved_SKNV_KSOP),
                     kekIndex << SHIFT16 | KEK_MGMT_SUBOP_INVALIDATE);

    ret = mpiKekManagementCmd(agRoot, agContext, &payload,  queueNum );

    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "31");
    return ret;
}

/**
 * saEncryptDekCacheUpdate()
 *
 *     Replace a DEK within the controller cache
 *
 * @param saRoot
 * @param kekIndex
 * @param dekTableSelect
 * @param dekAddrHi
 * @param dekAddrLo
 * @param dekIndex
 * @param dekNumberOfEntries
 *
 * @return
 */
GLOBAL bit32 saEncryptDekCacheUpdate(
                     agsaRoot_t        *agRoot,
                     agsaContext_t     *agContext,
                     bit32             queueNum,
                     bit32             kekIndex,
                     bit32             dekTableSelect,
                     bit32             dekAddrHi,
                     bit32             dekAddrLo,
                     bit32             dekIndex,
                     bit32             dekNumberOfEntries,
                     bit32             dekBlobFormat,
                     bit32             dekTableKeyEntrySize
                     )
{
    agsaDekManagementCmd_t    payload;
    bit32 ret;

    smTraceFuncEnter(hpDBG_VERY_LOUD,"32");

    SA_DBG2(("saEncryptDekCacheUpdate, kekIndex 0x%x dekTableSelect 0x%x dekAddrHi 0x%x dekAddrLo 0x%x\n",
                     kekIndex,
                     dekTableSelect,
                     dekAddrHi,
                     dekAddrLo ));
    SA_DBG2(("saEncryptDekCacheUpdate, dekIndex 0x%x dekNumberOfEntries 0x%x dekBlobFormat 0x%x dekTableKeyEntrySize 0x%x\n",
                     dekIndex,
                     dekNumberOfEntries,
                     dekBlobFormat,
                     dekTableKeyEntrySize));

    /* create payload for IOMB */
    si_memset(&payload, 0, sizeof(agsaDekManagementCmd_t));

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, KEKIDX_Reserved_TBLS_DSOP),
                     (kekIndex << SHIFT24) | (dekTableSelect << SHIFT8) | DEK_MGMT_SUBOP_UPDATE);

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, dekIndex),
                     dekIndex);

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, tableAddrLo),
                     dekAddrLo);

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, tableAddrHi),
                     dekAddrHi);

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, tableEntries),
                     dekNumberOfEntries);

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, Reserved_DBF_TBL_SIZE),
                     dekBlobFormat << SHIFT8 | dekTableKeyEntrySize );

    ret = mpiDekManagementCmd(agRoot, agContext, &payload, queueNum);

    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "32");
    return ret;
}

/**
 * saEncryptDekCacheInvalidate()
 *
 *     Remove a DEK from the controller cache
 *
 * @param saRoot
 * @param kekIndex
 * @param dekTable
 * @param dekAddrHi
 * @param dekAddrLo
 * @param dekIndex
 * @param dekNumberOfEntries
 *
 * @return
 */
GLOBAL bit32 saEncryptDekCacheInvalidate(
                    agsaRoot_t         *agRoot,
                    agsaContext_t      *agContext,
                    bit32              queueNum,
                    bit32              dekTable,
                    bit32              dekIndex
                    )
{
    agsaDekManagementCmd_t     payload;
    bit32 ret;

    smTraceFuncEnter(hpDBG_VERY_LOUD,"33");

    SA_DBG2(("saEncryptDekCacheInvalidate,dekTable  0x%x dekIndex 0x%x\n",dekTable,dekIndex));

    /* create payload for IOMB */
    si_memset(&payload, 0, sizeof(agsaDekManagementCmd_t));

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, KEKIDX_Reserved_TBLS_DSOP),
                     (dekTable << SHIFT8) | DEK_MGMT_SUBOP_INVALIDATE);

    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, dekIndex),
                     dekIndex);

    /* Assume all DEKs are 80 bytes*/
    OSSA_WRITE_LE_32(agRoot,
                     &payload,
                     OSSA_OFFSET_OF(agsaDekManagementCmd_t, Reserved_DBF_TBL_SIZE),
                     4);

    ret = mpiDekManagementCmd(agRoot, agContext, &payload, queueNum);

    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "33");
    return ret;
}

/**
 * saDIFEncryptionOffloadStart()
 *
 *     initiate the SPCv controller offload function 
 *
 * @param saRoot
 * @param agContext
 * @param queueNum
 * @param op
 * @param agsaDifEncPayload
 * @param agCB
 *
 * @return
 */
GLOBAL bit32 saDIFEncryptionOffloadStart(
                          agsaRoot_t         *agRoot,
                          agsaContext_t      *agContext,
                          bit32               queueNum,
                          bit32               op,
                          agsaDifEncPayload_t *agsaDifEncPayload,
                          ossaDIFEncryptionOffloadStartCB_t agCB)
{
  bit32 ret = AGSA_RC_FAILURE;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3I");
  SA_DBG1(("saDIFEncryptionOffloadStart: start op=%d, agsaDifEncPayload=%p\n", op, agsaDifEncPayload));

  if(smIS_SPCV(agRoot))
  {
    ret = mpiDIFEncryptionOffloadCmd(agRoot, agContext, queueNum, op, agsaDifEncPayload, agCB);
  }
  else
  {
    SA_DBG1(("saDIFEncryptionOffloadStart: spcv only AGSA_RC_FAILURE \n"));
  }

  SA_DBG1(("saDIFEncryptionOffloadStart: end status 0x%x\n",ret));
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3I");
  return ret;
}

/**
 * saSetControllerConfig()
 *
 *     Update a controller mode page
 *
 * @param saRoot
 * @param modePage
 * @param length
 * @param buffer
 * @param agContext
 *
 * @return
 */
GLOBAL bit32 saSetControllerConfig(
                      agsaRoot_t        *agRoot,
                      bit32             queueNum,
                      bit32             modePage,
                      bit32             length,
                      void              *buffer,
                      agsaContext_t     *agContext
                      )
{
    agsaSetControllerConfigCmd_t agControllerConfig;
    bit32 *src;
    bit32 i, ret;

    smTraceFuncEnter(hpDBG_VERY_LOUD,"34");


    if(smIS_SPCV(agRoot))
    {

      SA_DBG2(("saSetControllerConfig: queueNum %d modePage 0x%x length %d\n",queueNum,modePage,length ));

      /* If the page is well known, validate the size of the buffer */
      if (((modePage == AGSA_INTERRUPT_CONFIGURATION_PAGE)   && (length != sizeof(agsaInterruptConfigPage_t )))    ||
           ((modePage == AGSA_ENCRYPTION_DEK_CONFIG_PAGE)    && (length != sizeof(agsaEncryptDekConfigPage_t)))     ||
           ((modePage == AGSA_ENCRYPTION_CONTROL_PARM_PAGE)  && (length != sizeof(agsaEncryptControlParamPage_t ))) ||
           ((modePage == AGSA_ENCRYPTION_HMAC_CONFIG_PAGE)   && (length != sizeof(agsaEncryptHMACConfigPage_t )))   ||
           ((modePage == AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE) && (length != sizeof(agsaSASProtocolTimerConfigurationPage_t )))  )
      {
        SA_DBG1(("saSetControllerConfig: AGSA_RC_FAILURE queueNum %d modePage 0x%x length %d\n",queueNum,modePage,length ));
        ret = AGSA_RC_FAILURE;
      }
      else if(modePage == AGSA_ENCRYPTION_GENERAL_CONFIG_PAGE)
      {
        SA_DBG1(("saSetControllerConfig: Warning!!!!GENERAL_CONFIG_PAGE cannot be set\n"));
        ret = AGSA_RC_FAILURE;
      }
      else
      {
        /* Copy the raw mode page data into something that can be wrapped in an IOMB. */
        si_memset(&agControllerConfig, 0, sizeof(agsaSetControllerConfigCmd_t));

        agControllerConfig.tag = 0;  /*HTAG */

        src = (bit32 *) buffer;

        for (i = 0; i < (length / 4); i++)
        {
          OSSA_WRITE_LE_32(agRoot,
                           &agControllerConfig,
                           OSSA_OFFSET_OF(agsaSetControllerConfigCmd_t, pageCode) + (i * 4),
                           *src);

          src++;
        }
        ret = mpiSetControllerConfigCmd(agRoot, agContext, &agControllerConfig, queueNum,agFALSE);
        if(ret)
        {
          SA_DBG1(("saSetControllerConfig: AGSA_RC_FAILURE (sending) queueNum %d modePage 0x%x length %d\n",queueNum,modePage,length ));
        }

      }
    }
    else
    {
      SA_DBG1(("saSetControllerConfig: spcv only AGSA_RC_FAILURE queueNum %d modePage 0x%x length %d\n",queueNum,modePage,length ));
      ret = AGSA_RC_FAILURE;
    }
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "34");
    return ret;
}


/**
 * saGetControllerConfig()
 *
 *     Retrieve the contents of a controller mode page
 *
 * @param saRoot
 * @param modePage
 * @param agContext
 *
 * @return
 */
GLOBAL bit32 saGetControllerConfig(
                      agsaRoot_t        *agRoot,
                      bit32             queueNum,
                      bit32             modePage,
                      bit32             flag0,
                      bit32             flag1,
                      agsaContext_t     *agContext
                      )
{
    bit32 ret;
    agsaGetControllerConfigCmd_t agControllerConfig;

    smTraceFuncEnter(hpDBG_VERY_LOUD,"35");

    SA_DBG2(("saGetControllerConfig, modePage 0x%x  agContext %p flag0 0x%08x flag1 0x%08x\n",modePage,agContext, flag0, flag1 ));
    if(smIS_SPCV(agRoot))
    {
      si_memset(&agControllerConfig, 0, sizeof(agsaGetControllerConfigCmd_t));

      agControllerConfig.pageCode = modePage;
      if(modePage == AGSA_INTERRUPT_CONFIGURATION_PAGE)
      {
        agControllerConfig.INT_VEC_MSK0 = flag0;
        agControllerConfig.INT_VEC_MSK1 = flag1;
      }
      ret = mpiGetControllerConfigCmd(agRoot, agContext, &agControllerConfig, queueNum);
    }
    else
    {
      SA_DBG1(("saGetControllerConfig: spcv only AGSA_RC_FAILURE queueNum %d modePage 0x%x flag0 0x%08x flag1 0x%08x\n",queueNum,modePage, flag0, flag1 ));
      ret = AGSA_RC_FAILURE;
    }

    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "35");
    return ret;
}

GLOBAL bit32 saEncryptSelftestExecute (
                        agsaRoot_t    *agRoot,
                        agsaContext_t *agContext,
                        bit32          queueNum,
                        bit32          type,
                        bit32          length,
                        void          *TestDescriptor)
{
  bit32 ret = AGSA_RC_SUCCESS;

  agsaEncryptBist_t bist;
  smTraceFuncEnter(hpDBG_VERY_LOUD,"2e");
  si_memset(&bist, 0, (sizeof(agsaEncryptBist_t)));

  SA_DBG1(("saEncryptSelftestExecute, enter\n" ));
  bist.r_subop = (type & 0xFF);

  si_memcpy(&bist.testDiscption,TestDescriptor,length );

  /* setup IOMB payload */
  ret = mpiEncryptBistCmd( agRoot, queueNum, agContext, &bist );

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2e");

  return (ret);
}
GLOBAL bit32 saOperatorManagement(
                        agsaRoot_t           *agRoot,
                        agsaContext_t        *agContext,
                        bit32                 queueNum,
                        bit32                 flag,
                        bit8                  role,
                        agsaID_t             *id,
                        agsaEncryptKekBlob_t *kblob)
{
  bit32 ret = AGSA_RC_SUCCESS;
  agsaOperatorMangmentCmd_t opmcmd;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2i");

  SA_DBG1(("saOperatorManagement, enter\n" ));

  si_memset(&opmcmd, 0, sizeof(agsaOperatorMangmentCmd_t));
  /*role = ((flag & SA_OPR_MGMNT_FLAG_MASK) >> SA_OPR_MGMNT_FLAG_SHIFT);*/

  flag = (flag & ~SA_OPR_MGMNT_FLAG_MASK);

  opmcmd.OPRIDX_AUTIDX_R_KBF_PKT_OMO = flag;

  opmcmd.IDString_Role[0] = (bit8)role;
  SA_DBG1(("saOperatorManagement, role 0x%X flags 0x%08X\n", role, opmcmd.OPRIDX_AUTIDX_R_KBF_PKT_OMO ));

  si_memcpy(&opmcmd.IDString_Role[1], id->ID, AGSA_ID_SIZE);
  si_memcpy(&opmcmd.Kblob, kblob, sizeof(agsaEncryptKekBlob_t));

  /* setup IOMB payload */
  ret = mpiOperatorManagementCmd(agRoot, queueNum, agContext, &opmcmd);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2i");

  return (ret);
}

/*
    The command is for an operator to login to/logout from SPCve.
    Only when all IOs are quiesced, can an operator logout.

    flag:
      Access type (ACS) [4 bits]
        0x1: login
        0x2: logout
        Others: reserved
      KEYopr pinned in the KEK RAM (PIN) [1 bit]
        0: not pinned, operator ID table will be searched during authentication.
        1: pinned, OPRIDX is referenced to unwrap the certificate.
      KEYopr Index in the KEK RAM (OPRIDX) [8 bits]
        If KEYopr is pinned in the KEK RAM, OPRIDX is to reference to the KEK for authentication

    cert
      Operator Certificate (CERT) [40 bytes]
  
    response calls ossaSetOperatorCB
*/

GLOBAL bit32
saSetOperator(
  agsaRoot_t     *agRoot,
  agsaContext_t  *agContext,
  bit32           queueNum,
  bit32           flag,
  void           *cert
  )
{
  bit32 ret = AGSA_RC_SUCCESS;
  agsaSetOperatorCmd_t  SetOperatorCmd;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3c");
  SA_DBG1(("saSetOperator, flag 0x%x cert %p\n",flag, cert));

  /* initialize set operator IOMB */
  si_memset(&SetOperatorCmd, 0, sizeof(agsaSetOperatorCmd_t));
  SetOperatorCmd.OPRIDX_PIN_ACS = flag;
  si_memcpy((bit8*)SetOperatorCmd.cert, (bit8*)cert, 40);

  /* setup IOMB payload */
  ret = mpiSetOperatorCmd(agRoot, queueNum, agContext, &SetOperatorCmd);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3c");
  return (ret);
}

/*
    The command is to get role and ID of either current or all operators from SPCve.
    Option
        0x1: current operator
        0x2: all operators
        Others: reserved

    OprBufAddr
        the host buffer address to store the role and ID of all operators. Valid only when option == 0x2.
        Buffer size must be 1KB to store max 32 operators's role and ID.
    response calls ossaGetOperatorCB
*/
GLOBAL bit32
saGetOperator(
  agsaRoot_t     *agRoot,
  agsaContext_t  *agContext,
  bit32           queueNum,
  bit32           option,
  bit32           AddrHi,
  bit32           AddrLo
  )
{
  bit32 ret = AGSA_RC_SUCCESS;
  agsaGetOperatorCmd_t  GetOperatorCmd;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3d");
  SA_DBG1(("saGetOperator, option 0x%x 0x%08x_%08x\n",option,AddrHi,AddrLo ));

  /* initialize get operator IOMB */
  si_memset(&GetOperatorCmd, 0, sizeof(agsaGetOperatorCmd_t));
  GetOperatorCmd.option = option;
  GetOperatorCmd.OprBufAddrLo = AddrLo;
  GetOperatorCmd.OprBufAddrHi = AddrHi;

  /* setup IOMB payload */
  ret = mpiGetOperatorCmd(agRoot, queueNum, agContext, &GetOperatorCmd);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3d");

  return (ret);
}