root/sys/dev/pms/RefTisa/sallsdk/spc/sampirsp.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 sampirsp.c
 *  \brief The file implements the functions of MPI Outbound Response Message
 *
 */
/******************************************************************************/
#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 'J'
#endif

/******************************************************************************/
/* Protoytpes */
void saReturnRequestToFreePool(
                            agsaRoot_t          *agRoot,
                            agsaIORequestDesc_t *pRequest
                            );
                                                        
/******************************************************************************/
/*! \brief Process Outbound IOMB Message
 *
 *  Process Outbound IOMB from SPC
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LL Layer
 *  \param pMsg1        Pointer of Response IOMB message 1
 *  \param category     category of outbpond IOMB header
 *  \param opcode       Opcode of Outbound IOMB header
 *  \param bc           buffer count of IOMB header
 *
 *  \return success or fail
 *
 */
/*******************************************************************************/
#if 0
FORCEINLINE bit32
mpiParseOBIomb(
  agsaRoot_t        *agRoot,
  bit32             *pMsg1,
  mpiMsgCategory_t  category,
  bit16             opcode
  )
{
  agsaLLRoot_t      *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  bit32              ret = AGSA_RC_SUCCESS;
  bit32              parserStatus = AGSA_RC_SUCCESS;

  smTraceFuncEnter(hpDBG_VERY_LOUD, "2f");

  switch (opcode)
  {
    case OPC_OUB_COMBINED_SSP_COMP:
    {
      agsaSSPCoalescedCompletionRsp_t  *pIomb = (agsaSSPCoalescedCompletionRsp_t *)pMsg1;
      agsaIORequestDesc_t              *pRequest = agNULL;
      bit32  tag     = 0;
      bit32  sspTag  = 0;
      bit32  count   = 0;

#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSSPCompleted++;
      SA_DBG3(("mpiParseOBIomb, SSP_COMP Response received IOMB=%p %d\n",
         pMsg1, saRoot->LLCounters.IOCounter.numSSPCompleted));
#else
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_COMBINED_SSP_COMP Response received IOMB=%p\n", pMsg1));
#endif
      /* get Tag */
      for (count = 0; count < pIomb->coalescedCount; count++)
      {
        tag = pIomb->sspComplCxt[count].tag;
        sspTag = pIomb->sspComplCxt[count].SSPTag;
        pRequest = (agsaIORequestDesc_t *)saRoot->IOMap[tag].IORequest;
        SA_ASSERT((pRequest), "pRequest");

        if(pRequest == agNULL)
        {
          SA_DBG1(("mpiParseOBIomb,OPC_OUB_COMBINED_SSP_COMP Resp IOMB tag=0x%x, status=0x%x, param=0x%x, SSPTag=0x%x\n", tag, OSSA_IO_SUCCESS, 0, sspTag));
          return(AGSA_RC_FAILURE);
        }
        SA_ASSERT((pRequest->valid), "pRequest->valid");

        SA_DBG3(("mpiParseOBIomb, OPC_OUB_COMBINED_SSP_COMP IOMB tag=0x%x, status=0x%x, param=0x%x, SSPTag=0x%x\n", tag, OSSA_IO_SUCCESS, 0, sspTag));

        /* Completion of SSP without Response Data */
        siIODone( agRoot, pRequest, OSSA_IO_SUCCESS, sspTag);
      }
    }
    break;

    case OPC_OUB_SSP_COMP:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSSPCompleted++;
      SA_DBG3(("mpiParseOBIomb, SSP_COMP Response received IOMB=%p %d\n",
         pMsg1, saRoot->LLCounters.IOCounter.numSSPCompleted));
#else
      SA_DBG3(("mpiParseOBIomb, SSP_COMP Response received IOMB=%p\n", pMsg1));
#endif
      /* process the SSP IO Completed response message */
      mpiSSPCompletion(agRoot, pMsg1);
      break;
    }
    case OPC_OUB_COMBINED_SATA_COMP:
    {
      agsaSATACoalescedCompletionRsp_t    *pIomb;
      agsaIORequestDesc_t       *pRequest;
      bit32                     tag;
      bit32                     count;

    #ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSSPCompleted++;
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_COMBINED_SATA_COMP Response received IOMB=%p %d\n",
         pMsg1, saRoot->LLCounters.IOCounter.numSSPCompleted));
    #else
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_COMBINED_SATA_COMP Response received IOMB=%p\n", pMsg1));
    #endif

      pIomb = (agsaSATACoalescedCompletionRsp_t *)pMsg1;
      /* get Tag */
      for (count = 0; count < pIomb->coalescedCount; count++)
      {
        tag = pIomb->stpComplCxt[count].tag;
        pRequest = (agsaIORequestDesc_t *)saRoot->IOMap[tag].IORequest;
        SA_ASSERT((pRequest), "pRequest");

        if(pRequest == agNULL)
        {
          SA_DBG1(("mpiParseOBIomb,OPC_OUB_COMBINED_SATA_COMP Resp IOMB tag=0x%x, status=0x%x, param=0x%x\n", tag, OSSA_IO_SUCCESS, 0));
          return(AGSA_RC_FAILURE);
        }
        SA_ASSERT((pRequest->valid), "pRequest->valid");

        SA_DBG3(("mpiParseOBIomb, OPC_OUB_COMBINED_SATA_COMP IOMB tag=0x%x, status=0x%x, param=0x%x\n", tag, OSSA_IO_SUCCESS, 0));

        /* Completion of SATA without Response Data */
        siIODone( agRoot, pRequest, OSSA_IO_SUCCESS, 0);
      }
      break;
    }
    case OPC_OUB_SATA_COMP:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSataCompleted++;
      SA_DBG3(("mpiParseOBIomb, SATA_COMP Response received IOMB=%p %d\n",
             pMsg1, saRoot->LLCounters.IOCounter.numSataCompleted));
#else
      SA_DBG3(("mpiParseOBIomb, SATA_COMP Response received IOMB=%p\n", pMsg1));
#endif
      /* process the response message */
      mpiSATACompletion(agRoot, pMsg1);
      break;
    }
    case OPC_OUB_SSP_ABORT_RSP:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSSPAbortedCB++;
#else
      SA_DBG3(("mpiParseOBIomb, SSP_ABORT Response received IOMB=%p\n", pMsg1));
#endif
      /* process the response message */
      parserStatus = mpiSSPAbortRsp(agRoot, (agsaSSPAbortRsp_t *)pMsg1);
      if(parserStatus !=  AGSA_RC_SUCCESS)
      {
         SA_DBG3(("mpiParseOBIomb, mpiSSPAbortRsp FAIL IOMB=%p\n", pMsg1));
      }

      break;
    }
    case OPC_OUB_SATA_ABORT_RSP:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSataAbortedCB++;
#else
      SA_DBG3(("mpiParseOBIomb, SATA_ABORT Response received IOMB=%p\n", pMsg1));
#endif
      /* process the response message */
      mpiSATAAbortRsp(agRoot, (agsaSATAAbortRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SATA_EVENT:
    {
      SA_DBG3(("mpiParseOBIomb, SATA_EVENT Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSATAEvent(agRoot, (agsaSATAEventRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SSP_EVENT:
    {
      SA_DBG3(("mpiParseOBIomb, SSP_EVENT Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSSPEvent(agRoot, (agsaSSPEventRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SMP_COMP:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSMPCompleted++;
      SA_DBG3(("mpiParseOBIomb, SMP_COMP Response received IOMB=%p, %d\n",
             pMsg1, saRoot->LLCounters.IOCounter.numSMPCompleted));
#else
      SA_DBG3(("mpiParseOBIomb, SMP_COMP Response received IOMB=%p\n", pMsg1));
#endif
      /* process the response message */
      mpiSMPCompletion(agRoot, (agsaSMPCompletionRsp_t *)pMsg1);
      break;
    }
#ifndef BIOS
    case OPC_OUB_ECHO:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numEchoCB++;
      SA_DBG3(("mpiParseOBIomb, ECHO Response received %d\n", saRoot->LLCounters.IOCounter.numEchoCB));
#else
      SA_DBG3(("mpiParseOBIomb, ECHO Response received\n"));
#endif
      /* process the response message */
      mpiEchoRsp(agRoot, (agsaEchoRsp_t *)pMsg1);
      break;
    }
#endif
    case OPC_OUB_GET_NVMD_DATA:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_GET_NVMD_DATA received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetNVMDataRsp(agRoot, (agsaGetNVMDataRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SPC_HW_EVENT:
    {
      SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SPC_HW_EVENT Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiHWevent(agRoot, (agsaHWEvent_SPC_OUB_t *)pMsg1);
      break;
    }
    case OPC_OUB_HW_EVENT:
    {
      SA_DBG3(("mpiParseOBIomb, HW_EVENT Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiHWevent(agRoot, (agsaHWEvent_SPC_OUB_t *)pMsg1);
      break;
    }
    case OPC_OUB_PHY_START_RESPONSE:
    {
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_PHY_START_RESPONSE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiPhyStartEvent( agRoot, (agsaHWEvent_Phy_OUB_t  *)pMsg1  );

      break;
    }
    case OPC_OUB_PHY_STOP_RESPONSE:
    {
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_PHY_STOP_RESPONSE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiPhyStopEvent( agRoot, (agsaHWEvent_Phy_OUB_t  *)pMsg1  );
      break;
    }

    case OPC_OUB_LOCAL_PHY_CNTRL:
    {
      SA_DBG3(("mpiParseOBIomb, PHY CONTROL Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiPhyCntrlRsp(agRoot, (agsaLocalPhyCntrlRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SPC_DEV_REGIST:
    {
      SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SPC_DEV_REGIST Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiDeviceRegRsp(agRoot, (agsaDeviceRegistrationRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_DEV_REGIST:
    {
      SA_DBG2(("mpiParseOBIomb, DEV_REGISTRATION Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiDeviceRegRsp(agRoot, (agsaDeviceRegistrationRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_DEREG_DEV:
    {
      SA_DBG3(("mpiParseOBIomb, DEREGISTRATION DEVICE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiDeregDevHandleRsp(agRoot, (agsaDeregDevHandleRsp_t *)pMsg1);
      break;
    }
#ifndef BIOS
    case OPC_OUB_GET_DEV_HANDLE:
    {
      SA_DBG3(("mpiParseOBIomb, GET_DEV_HANDLE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetDevHandleRsp(agRoot, (agsaGetDevHandleRsp_t *)pMsg1);
      break;
    }
#endif
    case OPC_OUB_SPC_DEV_HANDLE_ARRIV:
    {
      SA_DBG3(("mpiParseOBIomb, SPC_DEV_HANDLE_ARRIV Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiDeviceHandleArrived(agRoot, (agsaDeviceHandleArrivedNotify_t *)pMsg1);
      break;
    }
    case OPC_OUB_DEV_HANDLE_ARRIV:
    {
      SA_DBG3(("mpiParseOBIomb, DEV_HANDLE_ARRIV Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiDeviceHandleArrived(agRoot, (agsaDeviceHandleArrivedNotify_t *)pMsg1);
      break;
    }
#if 0 //Sunitha
        case OPC_OUB_THERM_HW_EVENT:
        {
      SA_DBG3(("mpiParseOBIomb, THERM_HW_EVENT Response received IOMB=%p\n", pMsg1));
      ossaLogThermalEvent(agRoot, (agsaThermal_Hw_Event_Notify_t *)pMsg1);
      break;
        }
#endif //Sunitha
    case OPC_OUB_SSP_RECV_EVENT:
    {
      SA_DBG3(("mpiParseOBIomb, SSP_RECV_EVENT Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSSPReqReceivedNotify(agRoot, (agsaSSPReqReceivedNotify_t *)pMsg1);
      break;
    }
    case OPC_OUB_DEV_INFO:
    {
      SA_ASSERT((smIS_SPCV(agRoot)), "smIS_SPCV");
      SA_DBG3(("mpiParseOBIomb, DEV_INFO Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetDevInfoRsp(agRoot, (agsaGetDevInfoRspV_t *)pMsg1);
      break;
    }
#ifndef BIOS
    case OPC_OUB_GET_PHY_PROFILE_RSP:
    {
      SA_ASSERT((smIS_SPCV(agRoot)), "smIS_SPCV");
      SA_DBG2(("mpiParseOBIomb, OPC_OUB_GET_PHY_PROFILE_RSP Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetPhyProfileRsp(agRoot, (agsaGetPhyProfileRspV_t *)pMsg1);
      break;
    }
    case OPC_OUB_SET_PHY_PROFILE_RSP:
    {
      SA_ASSERT((smIS_SPCV(agRoot)), "smIS_SPCV");
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_PHY_PROFILE_RSP Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSetPhyProfileRsp(agRoot, (agsaSetPhyProfileRspV_t *)pMsg1);
      break;
    }
#endif /* BIOS */
    case OPC_OUB_SPC_DEV_INFO:
    {
      SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
      SA_DBG3(("mpiParseOBIomb, DEV_INFO Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetDevInfoRspSpc(agRoot, (agsaGetDevInfoRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_FW_FLASH_UPDATE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_FW_FLASH_UPDATE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiFwFlashUpdateRsp(agRoot, (agsaFwFlashUpdateRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_FLASH_OP_EXT_RSP:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_FW_FLASH_UPDATE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiFwExtFlashUpdateRsp(agRoot, (agsaFwFlashOpExtRsp_t *)pMsg1);
      break;
    }
#ifndef BIOS
#ifdef SPC_ENABLE_PROFILE
    case OPC_OUB_FW_PROFILE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_FW_PROFILE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiFwProfileRsp(agRoot, (agsaFwProfileRsp_t *)pMsg1);
      break;
    }
#endif
    case OPC_OUB_SET_NVMD_DATA:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_NVMD_DATA received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSetNVMDataRsp(agRoot, (agsaSetNVMDataRsp_t *)pMsg1);
      break;
    }

    case OPC_OUB_GPIO_RESPONSE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_GPIO_RESPONSE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGPIORsp(agRoot, (agsaGPIORsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_GPIO_EVENT:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_GPIO_RESPONSE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGPIOEventRsp(agRoot, (agsaGPIOEvent_t *)pMsg1);
      break;
    }
#endif  /* BIOS */
    case OPC_OUB_GENERAL_EVENT:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_GENERAL_EVENT Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGeneralEventRsp(agRoot, (agsaGeneralEventRsp_t *)pMsg1);
      break;
    }
#ifndef BIOS
    case OPC_OUB_SAS_DIAG_MODE_START_END:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SAS_DIAG_MODE_START_END Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSASDiagStartEndRsp(agRoot, (agsaSASDiagStartEndRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SAS_DIAG_EXECUTE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SAS_DIAG_EXECUTE_RSP Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSASDiagExecuteRsp(agRoot, (agsaSASDiagExecuteRsp_t *)pMsg1);
      break;
    }
#endif /* BIOS */
    case OPC_OUB_GET_TIME_STAMP:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_GET_TIME_STAMP Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetTimeStampRsp(agRoot, (agsaGetTimeStampRsp_t *)pMsg1);
      break;
    }

    case OPC_OUB_SPC_SAS_HW_EVENT_ACK:
    {
      SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
      SA_DBG3(("mpiParseOBIomb,OPC_OUB_SPC_SAS_HW_EVENT_ACK  Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSASHwEventAckRsp(agRoot, (agsaSASHwEventAckRsp_t *)pMsg1);
      break;
    }

    case OPC_OUB_SAS_HW_EVENT_ACK:
    {
      SA_ASSERT((smIS_SPCV(agRoot)), "smIS_SPCV");
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SAS_HW_EVENT_ACK Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSASHwEventAckRsp(agRoot, (agsaSASHwEventAckRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_PORT_CONTROL:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_PORT_CONTROL Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiPortControlRsp(agRoot, (agsaPortControlRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_SMP_ABORT_RSP:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numSMPAbortedCB++;
      SA_DBG3(("mpiParseOBIomb, SMP_ABORT Response received IOMB=%p, %d\n",
             pMsg1, saRoot->LLCounters.IOCounter.numSMPAbortedCB));
#else
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SMP_ABORT_RSP Response received IOMB=%p\n", pMsg1));
#endif
      /* process the response message */
      mpiSMPAbortRsp(agRoot, (agsaSMPAbortRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_DEVICE_HANDLE_REMOVAL:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_DEVICE_HANDLE_REMOVAL received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiDeviceHandleRemoval(agRoot, (agsaDeviceHandleRemoval_t *)pMsg1);
      break;
    }
    case OPC_OUB_SET_DEVICE_STATE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_DEVICE_STATE received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSetDeviceStateRsp(agRoot, (agsaSetDeviceStateRsp_t *)pMsg1);
      break;
    }

#ifndef BIOS
    case OPC_OUB_GET_DEVICE_STATE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_GET_DEVICE_STATE received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetDeviceStateRsp(agRoot, (agsaGetDeviceStateRsp_t *)pMsg1);
      break;
    }
#endif  /* BIOS */

    case OPC_OUB_SET_DEV_INFO:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_DEV_INFO received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSetDevInfoRsp(agRoot, (agsaSetDeviceInfoRsp_t *)pMsg1);
      break;
    }

#ifndef BIOS_DEBUG
    case OPC_OUB_SAS_RE_INITIALIZE:
    {
      SA_ASSERT((smIS_SPC(agRoot)), "smIS_SPC");
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SAS_RE_INITIALIZE received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSasReInitializeRsp(agRoot, (agsaSasReInitializeRsp_t *)pMsg1);
      break;
    }
#endif  /* BIOS */

    case OPC_OUB_SGPIO_RESPONSE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SGPIO_RESPONSE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiSGpioRsp(agRoot, (agsaSGpioRsp_t *)pMsg1);
      break;
    }

#ifndef BIOS
    case OPC_OUB_PCIE_DIAG_EXECUTE:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_PCIE_DIAG_EXECUTE Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiPCIeDiagExecuteRsp(agRoot, (agsaPCIeDiagExecuteRsp_t *)pMsg1);
      break;
    }
    case 2104: //delray start
    {
      if(smIS_SPC6V(agRoot))
      {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_GET_DFE_DATA_RSP Response received IOMB=%p\n", pMsg1));
      /* process the response message */
      mpiGetDFEDataRsp(agRoot, (agsaGetDDEFDataRsp_t *)pMsg1);
      }
      if(smIS_SPC12V(agRoot))
      {
        SA_DBG3(("mpiParseOBIomb, OPC_INB_GET_VIST_CAP Response received IOMB=%p\n", pMsg1));
        mpiGetVisRsp(agRoot, (agsaGetVisCapRsp_t *)pMsg1);
      }  
      else
      {
        SA_DBG1(("mpiParseOBIomb, 2104  Response received IOMB=%p\n", pMsg1));
      }
      break;
    }
#endif   /* BIOS */
    case OPC_OUB_SET_CONTROLLER_CONFIG:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_SET_CONTROLLER_CONFIG Response received IOMB=%p\n", pMsg1));
      mpiSetControllerConfigRsp(agRoot, (agsaSetControllerConfigRsp_t *)pMsg1);
      break;
    }
#ifndef BIOS
    case OPC_OUB_GET_CONTROLLER_CONFIG:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_GET_CONTROLLER_CONFIG Response received IOMB=%p\n", pMsg1));
      mpiGetControllerConfigRsp(agRoot, (agsaGetControllerConfigRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_KEK_MANAGEMENT:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_KEK_MANAGEMENT Response received IOMB=%p\n", pMsg1));
      mpiKekManagementRsp(agRoot, (agsaKekManagementRsp_t *)pMsg1);
      break;
    }
#endif  /* BIOS */
#ifdef UN_USED_FUNC
    case OPC_OUB_DEK_MANAGEMENT:
    {
      SA_DBG3(("mpiParseOBIomb, OPC_OUB_DEK_MANAGEMENT Response received IOMB=%p\n", pMsg1));
      mpiDekManagementRsp(agRoot, (agsaDekManagementRsp_t *)pMsg1);
      break;
    }
#endif
#ifndef BIOS
    case OPC_OUB_OPR_MGMT:
    {
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_OPR_MGMT Response received IOMB=%p\n", pMsg1));
      mpiOperatorManagementRsp(agRoot, (agsaOperatorMangmenRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_ENC_TEST_EXECUTE:
    {
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_ENC_TEST_EXECUTE Response received IOMB=%p\n", pMsg1));
      mpiBistRsp(agRoot, (agsaEncryptBistRsp_t *)pMsg1);
      break;
    }
#endif /* BIOS */
    case OPC_OUB_SET_OPERATOR:
    {
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_SET_OPERATOR Response received IOMB=%p\n", pMsg1));
      mpiSetOperatorRsp(agRoot, (agsaSetOperatorRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_GET_OPERATOR:
    {
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_GET_OPERATOR Response received IOMB=%p\n", pMsg1));
      mpiGetOperatorRsp(agRoot, (agsaGetOperatorRsp_t *)pMsg1);
      break;
    }
    case OPC_OUB_DIF_ENC_OFFLOAD_RSP://delray start
    {
      SA_ASSERT((smIS_SPCV(agRoot)), "smIS_SPCV");
      SA_DBG1(("mpiParseOBIomb, OPC_OUB_DIF_ENC_OFFLOAD_RSP Response received IOMB=%p\n", pMsg1));
      mpiDifEncOffloadRsp(agRoot, (agsaDifEncOffloadRspV_t *)pMsg1);
      break;
    }                   //delray end
    default:
    {
#ifdef SALL_API_TEST
      saRoot->LLCounters.IOCounter.numUNKNWRespIOMB++;
      SA_DBG1(("mpiParseOBIomb, UnKnown Response received IOMB=%p, %d\n",
             pMsg1, saRoot->LLCounters.IOCounter.numUNKNWRespIOMB));
#else
      SA_DBG1(("mpiParseOBIomb, Unknown IOMB Response received opcode 0x%X IOMB=%p\n",opcode, pMsg1));
#endif
      break;
    }
  } /* switch */

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

  return ret;

}
#endif

/******************************************************************************/
/*! \brief ECHO Response
 *
 *  This routine handles the response of ECHO Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiEchoRsp(
  agsaRoot_t          *agRoot,
  agsaEchoRsp_t       *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag;

  smTraceFuncEnter(hpDBG_VERY_LOUD, "2g");

  SA_DBG3(("mpiEchoRsp: HTAG=0x%x\n", pIomb->tag));

  /* get request from IOMap */
  OSSA_READ_LE_32(agRoot, &tag, pIomb, OSSA_OFFSET_OF(agsaEchoRsp_t, tag));

  pRequest = (agsaIORequestDesc_t *)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiEchoRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x\n", tag));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2g");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  ossaEchoCB(agRoot, agContext, (void *)&pIomb->payload[0]);

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiEchoRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2g");
  return ret;
}

/******************************************************************************/
/*! \brief Get NVM Data Response
 *
 *  This routine handles the response of GET NVM Data Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetNVMDataRsp(
  agsaRoot_t          *agRoot,
  agsaGetNVMDataRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               i, dataLen;
  bit32               DlenStatus, tag, iRTdaBnDpsAsNvm;

  smTraceFuncEnter(hpDBG_VERY_LOUD, "2h");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetNVMDataRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &DlenStatus, pIomb, OSSA_OFFSET_OF(agsaGetNVMDataRsp_t, DlenStatus));
  OSSA_READ_LE_32(AGROOT, &iRTdaBnDpsAsNvm, pIomb, OSSA_OFFSET_OF(agsaGetNVMDataRsp_t, iRTdaBnDpsAsNvm));
  OSSA_READ_LE_32(AGROOT, &dataLen, pIomb, OSSA_OFFSET_OF(agsaGetNVMDataRsp_t, NVMData[10])) ;

  SA_DBG1(("mpiGetNVMDataRsp: HTAG=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t *)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetNVMDataRsp: Bad Response IOMB!!! pRequest is NULL.\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2h");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  if (iRTdaBnDpsAsNvm & IRMode)
  {
    /* indirect mode - IR bit set */
    SA_DBG1(("mpiGetNVMDataRsp: OSSA_SUCCESS, IR=1, DataLen=%d\n", dataLen));
    if (((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_CONFIG_SEEPROM) ||
        ((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_VPD_FLASH) ||
        ((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_TWI_DEVICES) ||
        ((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_EXPANSION_ROM) ||
        ((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_IOP_REG_FLASH))
    {
      /* CB for NVMD */
//#ifdef UN_USED_FUNC
      ossaGetNVMDResponseCB(agRoot, agContext, (DlenStatus & NVMD_STAT), INDIRECT_MODE, dataLen, agNULL);
//#endif
    }
    else if (((iRTdaBnDpsAsNvm & NVMD_TYPE) == AAP1_RDUMP) ||
             ((iRTdaBnDpsAsNvm & NVMD_TYPE) == IOP_RDUMP))
    {
#ifdef UN_USED_FUNC
      if ((DlenStatus & NVMD_STAT) == 0)
      {
        /* CB for Register Dump */

        ossaGetRegisterDumpCB(agRoot, agContext, OSSA_SUCCESS);
      }
      else
      {
        /* CB for Register Dump */
        ossaGetRegisterDumpCB(agRoot, agContext, OSSA_FAILURE);
      }
#endif
    }
    else
    {
      /* Should not be happened */
      SA_DBG1(("mpiGetNVMDataRsp: (IR=1)Wrong Device type 0x%x\n", iRTdaBnDpsAsNvm));
    }
  }
  else /* direct mode */
  {
    SA_DBG1(("mpiGetNVMDataRsp: OSSA_SUCCESS, IR=0, DataLen=%d\n", ((DlenStatus & NVMD_LEN) >> SHIFT24)));
    for (i = 0; i < (((DlenStatus & NVMD_LEN) >> SHIFT24)/4); i++)
    {
      SA_DBG1(("mpiGetNVMDataRsp: OSSA_SUCCESS, NVMDATA=0x%x\n", pIomb->NVMData[i]));
    }
    if (((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_CONFIG_SEEPROM) ||
        ((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_VPD_FLASH) ||
        ((iRTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_TWI_DEVICES))
    {
      /* CB for NVMD */
  //    char * safe_type_pun = (char *)(&pIomb->NVMData[0]);
#ifdef UN_USED_FUNC
      ossaGetNVMDResponseCB(agRoot, agContext, (DlenStatus & NVMD_STAT), DIRECT_MODE,
         ((DlenStatus & NVMD_LEN) >> SHIFT24), (agsaFrameHandle_t *)safe_type_pun);
#endif
    }
    else if (((iRTdaBnDpsAsNvm & NVMD_TYPE) == AAP1_RDUMP) ||
             ((iRTdaBnDpsAsNvm & NVMD_TYPE) == IOP_RDUMP))
    {
#ifdef UN_USED_FUNC

      if ((DlenStatus & NVMD_STAT) == 0)
      {
        /* CB for Register Dump */
        ossaGetRegisterDumpCB(agRoot, agContext, OSSA_SUCCESS);
      }
      else
      {
        /* CB for Register Dump */
        ossaGetRegisterDumpCB(agRoot, agContext, OSSA_FAILURE);
      }
#endif
    }
    else
    {
      /* Should not be happened */
      SA_DBG1(("mpiGetNVMDataRsp: (IR=0)Wrong Device type 0x%x\n", iRTdaBnDpsAsNvm));
    }
  }

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetNVMDataRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2h");

  /* return value */
  return ret;
}

/******************************************************************************/
/*! \brief Phy Event Response from SPCv
 *
 *  Process Phy Event from SPC
 *
 *  \param agRoot        Handles for this instance of SAS/SATA LL Layer
 *  \param pIomb         pointer of IOMB
 *
 *  \return success or fail
 *
 */
/*******************************************************************************/

GLOBAL bit32 mpiPhyStartEvent(
  agsaRoot_t        *agRoot,
  agsaHWEvent_Phy_OUB_t  *pIomb
  )
{
  bit32                    ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t             *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);

  bit32                    phyId;
  bit32                    IOMBStatus;
  bit32                    tag;

  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32                HwCBStatus;

  if(saRoot == agNULL)
  {
    SA_DBG1(("mpiPhyStartEvent: saRoot == agNULL\n"));
    return(AGSA_RC_FAILURE);
  }
  smTraceFuncEnter(hpDBG_VERY_LOUD, "2H");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaHWEvent_Phy_OUB_t, tag)) ;

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiPhyStartEvent: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x \n", tag));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2H");
    return AGSA_RC_FAILURE;
  }

  SA_DBG1(("mpiPhyStartEvent: Status 0x%X PhyId 0x%X\n",pIomb->Status,pIomb->ReservedPhyId));

  OSSA_READ_LE_32(AGROOT, &IOMBStatus, pIomb, OSSA_OFFSET_OF(agsaHWEvent_Phy_OUB_t,Status ));
  OSSA_READ_LE_32(AGROOT, &phyId, pIomb, OSSA_OFFSET_OF(agsaHWEvent_Phy_OUB_t,ReservedPhyId ));

  switch (IOMBStatus)
  {
    case OSSA_MPI_IO_SUCCESS:                  /* PhyStart operation completed successfully */
      HwCBStatus = 0;
      saRoot->phys[phyId].linkstatus = 1;
      SA_DBG1(("mpiPhyStartEvent:MPI_IO_SUCCESS IOMBStatus 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      /* Callback with PHY_UP */
      break;
    case OSSA_MPI_ERR_INVALID_PHY_ID:      /* identifier specified in the PHY_START command is invalid i.e out of supported range for this product. */
      HwCBStatus = 1;
      saRoot->phys[phyId].linkstatus = 0;
      SA_DBG1(("mpiPhyStartEvent: MPI_ERR_INVALID_PHY_ID IOMBStatus 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      ret = AGSA_RC_FAILURE;
      break;
    case OSSA_MPI_ERR_PHY_ALREADY_STARTED:
      HwCBStatus = 2;
      saRoot->phys[phyId].linkstatus = 1;
      SA_DBG1(("mpiPhyStartEvent: MPI_ERR_PHY_ALREADY_STARTED IOMBStatus 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      ret = AGSA_RC_FAILURE;
      break;
    case OSSA_MPI_ERR_INVALID_ANALOG_TBL_IDX:
      HwCBStatus = 4;
      saRoot->phys[phyId].linkstatus = 0;
      SA_DBG1(("mpiPhyStartEvent: MPI_ERR_INVALID_ANALOG_TBL_IDX IOMBStatus 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      ret = AGSA_RC_FAILURE;
      break;
    default:
      HwCBStatus = 3;
      saRoot->phys[phyId].linkstatus = 0;
      SA_DBG1(("mpiPhyStartEvent: Unknown IOMBStatus 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      ret = AGSA_RC_FAILURE;
    break;
  }

  ossaHwCB(agRoot,agNULL, OSSA_HW_EVENT_PHY_START_STATUS ,((HwCBStatus << SHIFT8) | phyId) ,agContext, agNULL);

  /* return the request to free pool */
  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiPhyStartEvent: 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);

  return(ret);
}


GLOBAL bit32 mpiPhyStopEvent(
  agsaRoot_t        *agRoot,
  agsaHWEvent_Phy_OUB_t  *pIomb
  )
{
  bit32                    ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t             *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  bit32                    phyId;

  bit32                    IOMBStatus;
  bit32                    HwCBStatus;

  bit32                    tag;

  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;

  agsaPhy_t               *pPhy;
  agsaPort_t              *pPort;


  if(saRoot == agNULL)
  {
    SA_DBG1(("mpiPhyStopEvent: saRoot == agNULL\n"));
    return(AGSA_RC_FAILURE);
  }
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaHWEvent_Phy_OUB_t, tag)) ;

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiPhyStopEvent: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x \n", tag));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2H");
    return AGSA_RC_FAILURE;
  }

  OSSA_READ_LE_32(AGROOT, &IOMBStatus, pIomb, OSSA_OFFSET_OF(agsaHWEvent_Phy_OUB_t,Status ));
  OSSA_READ_LE_32(AGROOT, &phyId, pIomb, OSSA_OFFSET_OF(agsaHWEvent_Phy_OUB_t,ReservedPhyId ));
  SA_DBG1(("mpiPhyStopEvent: Status %08X PhyId %08X\n",IOMBStatus,phyId));

  if(smIS_SPCV(agRoot))
  {
      phyId &= 0xff;  // SPCv PHY_ID is one byte wide
  }

  saRoot->phys[phyId].linkstatus = 0;

  switch (IOMBStatus)
  {
    case OSSA_MPI_IO_SUCCESS:                  /* PhyStart operation completed successfully */
      SA_DBG1(("mpiPhyStopEvent:MPI_IO_SUCCESS  0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      HwCBStatus = 0;
      /* Callback with PHY_DOWN */
      break;
    case OSSA_MPI_ERR_INVALID_PHY_ID:      /* identifier specified in the PHY_START command is invalid i.e out of supported range for this product. */
      SA_DBG1(("mpiPhyStopEvent: MPI_ERR_INVALID_PHY_ID 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      HwCBStatus = 1;
      break;
    case OSSA_MPI_ERR_PHY_NOT_STARTED:  /* An attempt to stop a phy which is not started  */
      HwCBStatus = 4;
      SA_DBG1(("mpiPhyStopEvent:  0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      break;

    case OSSA_MPI_ERR_DEVICES_ATTACHED:  /* All the devices in a port need to be deregistered if the PHY_STOP is for the last phy  */
      HwCBStatus = 2;
      SA_DBG1(("mpiPhyStopEvent:  0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      break;

    default:
      HwCBStatus = 3;
      SA_DBG1(("mpiPhyStopEvent: Unknown Status 0x%x for phyId 0x%x\n",IOMBStatus,phyId));
      break;
  }


  if(HwCBStatus == 0)
  {
    pPhy = &(saRoot->phys[phyId]);
    /* get the port of the phy */
    pPort = pPhy->pPort;
    if ( agNULL != pPort )
    {
      SA_DBG1(("siPhyStopCB: phy%d invalidating port\n", phyId));
      /* invalid port state, remove the port */
      pPort->status |= PORT_INVALIDATING;
      saRoot->PortMap[pPort->portId].PortStatus  |= PORT_INVALIDATING;
      /* invalid the port */
      siPortInvalid(agRoot, pPort);
      /* map out the portmap */
      saRoot->PortMap[pPort->portId].PortContext = agNULL;
      saRoot->PortMap[pPort->portId].PortID = PORT_MARK_OFF;
      saRoot->PortMap[pPort->portId].PortStatus  |= PORT_INVALIDATING;
      ossaHwCB(agRoot,&(pPort->portContext) , OSSA_HW_EVENT_PHY_STOP_STATUS, ((HwCBStatus << SHIFT8) | phyId ),agContext, agNULL);
    }
    else
    {
      SA_DBG1(("siPhyStopCB: phy%d - Port is not established\n", phyId));
      ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_STOP_STATUS, ((HwCBStatus << SHIFT8) | phyId ) , agContext, agNULL);
    }

    /* set PHY_STOPPED status */
    PHY_STATUS_SET(pPhy, PHY_STOPPED);

    /* Exclude the phy from a port */
    if ( agNULL != pPort )
    {
      /* Acquire port list lock */
      ossaSingleThreadedEnter(agRoot, LL_PORT_LOCK);

      /* Delete the phy from the port */
      pPort->phyMap[phyId] = agFALSE;
      saRoot->phys[phyId].pPort = agNULL;

      /* Release port list lock */
      ossaSingleThreadedLeave(agRoot, LL_PORT_LOCK);
    }

  }
  else
  {
    SA_DBG1(("siPhyStopCB: Error phy%d - Port is not established\n", phyId));
    ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_STOP_STATUS, ((HwCBStatus << SHIFT8) | phyId ) , agContext, agNULL);
  }

  /* return the request to free pool */
  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiPhyStartEvent: 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);

  return(ret);
}


/******************************************************************************/
/*! \brief Hardware Event Response from SPC
 *
 *  Process HW Event from SPC
 *
 *  \param agRoot        Handles for this instance of SAS/SATA LL Layer
 *  \param pIomb         pointer of IOMB
 *
 *  \return success or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiHWevent(
  agsaRoot_t            *agRoot,
  agsaHWEvent_SPC_OUB_t *pIomb
  )
{
  bit32                    ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t             *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t      *pRequest;
  agsaPortContext_t        *agPortContext;
  agsaSASIdentify_t        *IDframe;
  agsaFisRegDeviceToHost_t *sataFis;
  agsaContext_t            *agContext;
  agsaPort_t               *pPort = agNULL;
  bit32                    phyId;
  bit32                    portId;
  bit32                    Event;
  bit32                    tag, status;
  bit8                     linkRate;
  bit32                    LREventPhyIdPortId;
  bit32                    npipps, eventParam,npip,port_state;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2j");

  SA_ASSERT((agNULL !=saRoot ), "");
  if(saRoot == agNULL)
  {
    SA_DBG1(("mpiHWevent: saRoot == agNULL\n"));
    return(AGSA_RC_FAILURE);
  }
  if(smIS_SPC(agRoot))
  {
    OSSA_READ_LE_32(AGROOT, &LREventPhyIdPortId, pIomb, OSSA_OFFSET_OF(agsaHWEvent_SPC_OUB_t, LRStatusEventPhyIdPortId));
    OSSA_READ_LE_32(AGROOT, &npipps, pIomb, OSSA_OFFSET_OF(agsaHWEvent_SPC_OUB_t, NpipPortState));
    OSSA_READ_LE_32(AGROOT, &eventParam, pIomb, OSSA_OFFSET_OF(agsaHWEvent_SPC_OUB_t, EVParam));
    SA_DBG2(("mpiHWEvent: S, LREventPhyIdPortId 0x%08x npipps 0x%08x eventParam 0x%08x\n", LREventPhyIdPortId ,npipps ,eventParam ));

    /* get port context */
    portId = LREventPhyIdPortId & PORTID_MASK;
    smTrace(hpDBG_VERY_LOUD,"QK",portId);
    /* TP:QK portId */

    /* get phyId */
    phyId = (LREventPhyIdPortId & PHY_ID_BITS) >> SHIFT4;

    smTrace(hpDBG_VERY_LOUD,"QK",npipps);
    /* TP:QK npipps */
    smTrace(hpDBG_VERY_LOUD,"QL",portId);
    /* TP:QL portId */
    smTrace(hpDBG_VERY_LOUD,"QM",phyId);
    /* TP:QM phyId */

    SA_DBG1(("mpiHWEvent:SPC, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, (npipps & PORT_STATE_MASK)));
  }
  else
  {
    OSSA_READ_LE_32(AGROOT, &LREventPhyIdPortId, pIomb, OSSA_OFFSET_OF(agsaHWEvent_V_OUB_t, LRStatEventPortId));
    OSSA_READ_LE_32(AGROOT, &npipps, pIomb, OSSA_OFFSET_OF(agsaHWEvent_V_OUB_t, RsvPhyIdNpipRsvPortState));
    OSSA_READ_LE_32(AGROOT, &eventParam, pIomb, OSSA_OFFSET_OF(agsaHWEvent_V_OUB_t, EVParam));
    SA_DBG2(("mpiHWEvent: V, LREventPhyIdPortId 0x%08x npipps 0x%08x eventParam 0x%08x\n", LREventPhyIdPortId ,npipps ,eventParam ));

    smTrace(hpDBG_VERY_LOUD,"QN",npipps);
    /* TP:QN npipps */

    /* get port context */
    portId = LREventPhyIdPortId & PORTID_MASK;

    smTrace(hpDBG_VERY_LOUD,"QO",portId);
    /* TP:QO portId */

    /* get phyId */
    phyId = (npipps & PHY_ID_V_BITS) >> SHIFT16;
    smTrace(hpDBG_VERY_LOUD,"QP",phyId);
    /* TP:QP phyId */

    /* get npipps */
    npip =(npipps & 0xFF00 ) >> SHIFT4;
    port_state  =(npipps & 0xF );
    npipps = npip | port_state; // Make it look like SPCs nipps


    SA_DBG1(("mpiHWEvent: V, PhyID 0x%x PortID 0x%x NPIP 0x%x PS 0x%x npipps 0x%x\n",
                phyId, portId,npip,port_state,npipps));
  }

  Event = (LREventPhyIdPortId & HW_EVENT_BITS) >> SHIFT8;

  /* get Link Rate */
  linkRate = (bit8)((LREventPhyIdPortId & LINK_RATE_MASK) >> SHIFT28);
  /* get status byte */
  status = (LREventPhyIdPortId & STATUS_BITS) >> SHIFT24;

  smTrace(hpDBG_VERY_LOUD,"HA",portId);
  /* TP:HA portId */
  smTrace(hpDBG_VERY_LOUD,"HB",linkRate);
  /* TP:HB linkRate */
  smTrace(hpDBG_VERY_LOUD,"HC",phyId);
  /* TP:HC phyId */
  smTrace(hpDBG_VERY_LOUD,"HD",npipps);
  /* TP:HD npipps */
  smTrace(hpDBG_VERY_LOUD,"HE",status);
  /* TP:HE status */

  if (portId > saRoot->phyCount)
  {
    if (OSSA_PORT_NOT_ESTABLISHED == (npipps & PORT_STATE_MASK))
    {
      /* out of range checking for portId */
      SA_DBG1(("mpiHWEvent: PORT_ID is out of range, PhyID %d PortID %d\n",
                phyId, portId));
      /* port is not estiblished */
      agPortContext = agNULL;
    }
    else
    {
      /* portId is bad and state is correct - should not happen */
      SA_DBG1(("mpiHWEvent: PORT_ID is bad with correct Port State, PhyID %d PortID %d\n",
                phyId, portId));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2j");
      return AGSA_RC_FAILURE;
    }
  }
  else
  {
    SA_DBG2(("mpiHWEvent:PortID 0x%x PortStatus 0x%x PortContext %p\n",saRoot->PortMap[portId & PORTID_MASK].PortID,saRoot->PortMap[portId & PORTID_MASK].PortStatus,saRoot->PortMap[portId & PORTID_MASK].PortContext));
    agPortContext = (agsaPortContext_t *)saRoot->PortMap[portId].PortContext;
  }

  if(agPortContext == agNULL)
  {
    SA_DBG1(("mpiHWEvent: agPortContext is NULL, PhyID %d PortID %d\n",
                phyId, portId));
  }

  smTrace(hpDBG_VERY_LOUD,"HF",Event);
  /* TP:HF OSSA_HW_EVENT */

  switch (Event)
  {
    case OSSA_HW_EVENT_SAS_PHY_UP:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_SAS_PHY_UP, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, (npipps & PORT_STATE_MASK)));

      /* get SAS Identify info */
      IDframe = (agsaSASIdentify_t *)&pIomb->sasIdentify;
      /* Callback about SAS link up */
      saRoot->phys[phyId].linkstatus |= 2;
      saRoot->phys[phyId].sasIdentify.phyIdentifier = IDframe->phyIdentifier;
      saRoot->phys[phyId].sasIdentify.deviceType_addressFrameType = IDframe->deviceType_addressFrameType;
    
      si_memcpy(&(saRoot->phys[phyId].sasIdentify.sasAddressHi),&(IDframe->sasAddressHi),4);
      si_memcpy(&(saRoot->phys[phyId].sasIdentify.sasAddressLo),&(IDframe->sasAddressLo),4);
      siEventPhyUpRcvd(agRoot, phyId, IDframe, portId, npipps, linkRate);
      break;
    }
    case OSSA_HW_EVENT_SATA_PHY_UP:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_SATA_PHY_UP, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, (npipps & PORT_STATE_MASK)));

      /* get SATA FIS info */
      saRoot->phys[phyId].linkstatus |= 2;
      sataFis = (agsaFisRegDeviceToHost_t *)&pIomb->sataFis;
      /* Callback about SATA Link Up */
      siEventSATASignatureRcvd(agRoot, phyId, (void *)sataFis, portId, npipps, linkRate);
      break;
    }
    case OSSA_HW_EVENT_SATA_SPINUP_HOLD:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_SATA_SPINUP_HOLD, PhyID %d\n", phyId));
      ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_SATA_SPINUP_HOLD, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PHY_DOWN:
    {
      agsaPhy_t *pPhy = &(saRoot->phys[phyId]);

      if(pPhy) {
                osti_memset(&pPhy->sasIdentify,0,sizeof(agsaSASIdentify_t));
      }
      saRoot->phys[phyId].linkstatus &= 1;
      if (agNULL != agPortContext)
      {
        pPort = (agsaPort_t *) (agPortContext->sdkData);
      }

      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_DOWN, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));

      /* callback */
      if ( agNULL != pPort )
      {
        if (OSSA_PORT_VALID == (npipps & PORT_STATE_MASK))
        {
          pPort->status &= ~PORT_INVALIDATING;
          saRoot->PortMap[portId].PortStatus  &= ~PORT_INVALIDATING;
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_DOWN, PhyID %d  ~PORT_INVALIDATING \n", phyId));
        }
        else
        {
          if (OSSA_PORT_INVALID == (npipps & PORT_STATE_MASK))
          {
            /* set port invalid flag */
            pPort->status |= PORT_INVALIDATING;
            saRoot->PortMap[portId].PortStatus  |= PORT_INVALIDATING;
            SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_DOWN PortInvalid portID %d PortContext %p NPIP 0x%x\n", portId, agPortContext,npipps));
          }
          else
          {
            if (OSSA_PORT_IN_RESET == (npipps & PORT_STATE_MASK))
            {
              SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_DOWN PortInReset portID %d PortContext %p\n", portId, agPortContext));
            }
            else
            {
              SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_DOWN Not PortInReset portID %d PortContext %p\n", portId, agPortContext));
            }
          }
        }

        /* report PhyId, NPIP, PortState */
        phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
        /* Callback with PHY_DOWN */
        ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_DOWN, phyId, agNULL, agNULL);
      }
      else
      {
        /* no portcontext.- error */
        SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_DOWN PhyDown pPort is NULL.\n"));
      }

      /* set PHY_DOWN status */
      PHY_STATUS_SET(pPhy, PHY_DOWN);
      break;
    }
    case OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC:
    {
      agsaPhyErrCountersPage_t errorParam;
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
      errorParam.inboundCRCError = eventParam;
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_ERR_INBOUND_CRC, phyId, (void *)&errorParam, agNULL);
      break;
    }
    case OSSA_HW_EVENT_HARD_RESET_RECEIVED:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_HARD_RESET_RECEIVED, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_HARD_RESET_RECEIVED, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD:
    {
      agsaPhyErrCountersPage_t errorParam;
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_LINK_ERR_INVALID_DWORD, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
      errorParam.invalidDword = eventParam;
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_ERR_INVALID_DWORD, phyId, (void *)&errorParam, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR:
    {
      agsaPhyErrCountersPage_t errorParam;
      SA_DBG3(("mpiHWEvent: OSSA_HW_EVENT_LINK_ERR_DISPARITY_ERROR, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
      errorParam.runningDisparityError = eventParam;
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_ERR_DISPARITY_ERROR, phyId, (void *)&errorParam, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION:
    {
      agsaPhyErrCountersPage_t errorParam;
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_LINK_ERR_CODE_VIOLATION, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
      errorParam.codeViolation = eventParam;
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_ERR_CODE_VIOLATION, phyId, (void *)&errorParam, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH:
    {
      agsaPhyErrCountersPage_t errorParam;
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
      errorParam.lossOfDwordSynch = eventParam;
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_ERR_LOSS_OF_DWORD_SYNCH, phyId, (void *)&errorParam, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
        phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));

      if (agNULL != agPortContext)
      {
        pPort = (agsaPort_t *) (agPortContext->sdkData);
      }
      else
      {
        SA_ASSERT((agPortContext), "agPortContext agNULL was there a PHY UP?");
        return(AGSA_RC_FAILURE);
      }

      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO, phyId, agNULL, agNULL);

      if (OSSA_PORT_VALID == (npipps & PORT_STATE_MASK))
      {
         pPort->status &= ~PORT_INVALIDATING;
         saRoot->PortMap[portId].PortStatus  &= ~PORT_INVALIDATING;
         SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO NOT PORT_INVALIDATING portID %d PortContext %p\n", portId, agPortContext));
      }
      else
      {
        if (OSSA_PORT_INVALID == (npipps & PORT_STATE_MASK))
        {
          /* set port invalid flag */
          pPort->status |= PORT_INVALIDATING;
          saRoot->PortMap[portId].PortStatus  |= PORT_INVALIDATING;
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RECOVERY_TIMER_TMO PORT_INVALIDATING portID %d PortContext %p\n", portId, agPortContext));
         }
        else
        {
          if (OSSA_PORT_IN_RESET == (npipps & PORT_STATE_MASK))
          {
            SA_DBG1(("mpiHWEvent: PortInReset portID %d PortContext %p\n", portId, agPortContext));
          }
        }
      }
      break;
    }
    case OSSA_HW_EVENT_PORT_RECOVER:
    {
      if (agNULL != agPortContext)
      {
        pPort = (agsaPort_t *) (agPortContext->sdkData);
      }

      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RECOVER, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
        phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));

      if (OSSA_PORT_VALID == (npipps & PORT_STATE_MASK))
      {
        if (agNULL != pPort)
        {
          /* reset port invalid flag */
          pPort->status &= ~PORT_INVALIDATING;
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RECOVER NOT PORT_INVALIDATING portID %d PortContext %p\n", portId, agPortContext));
        }
        saRoot->PortMap[portId].PortStatus  &= ~PORT_INVALIDATING;
      }
      /* get SAS Identify info */
      IDframe = (agsaSASIdentify_t *)&pIomb->sasIdentify;
      /* report PhyId, NPIP, PortState and LinkRate */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16) | (linkRate << SHIFT8);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PORT_RECOVER, phyId, agNULL, (void *)IDframe);
      break;
    }
    case OSSA_HW_EVENT_PHY_STOP_STATUS:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS PhyId=0x%x, status=0x%x eventParam=0x%x\n", phyId, status,eventParam));
      OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaHWEvent_SPC_OUB_t, EVParam));

      switch(eventParam)
      {
        case 0:
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS Stopped 0\n" ));
        break;
        case 1:
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS INVALID_PHY 1\n" ));
        break;
        case 2:
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS DEVICES_ATTACHED 2\n" ));
        break;
        case 3:
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS OTHER_FAILURE 3\n" ));
        break;
        case 4:
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS PHY_NOT_ENABLED 4\n" ));
        break;
        default:
          SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS Unknown code 0x%x\n", eventParam));
          break;
      }

      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_STOP_STATUS phyId 0x%x status 0x%x eventParam 0x%x\n", phyId, status,eventParam));
      /* get request from IOMap */
      pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
      SA_ASSERT((pRequest), "pRequest NULL");
      SA_ASSERT((pRequest->valid), "pRequest->valid");

      agContext = saRoot->IOMap[tag].agContext;

      siPhyStopCB(agRoot, phyId, status, agContext, portId, npipps);

      /* remove the request from IOMap */
      saRoot->IOMap[tag].Tag = MARK_OFF;
      saRoot->IOMap[tag].IORequest = agNULL;
      saRoot->IOMap[tag].agContext = agNULL;

      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
      pRequest->valid = agFALSE;
      /* return the request to free pool */
      if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
      {
        SA_DBG1(("mpiHWevent: 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);
      break;
    }
    case OSSA_HW_EVENT_BROADCAST_CHANGE:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_BROADCAST_CHANGE, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_BROADCAST_CHANGE, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_BROADCAST_SES:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_BROADCAST_CHANGE_SES, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_BROADCAST_SES, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_BROADCAST_EXP:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_BROADCAST_EXP, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_BROADCAST_EXP, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_ID_FRAME_TIMEOUT:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_ID_FRAME_TIMEOUT, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_ID_FRAME_TIMEOUT, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PHY_START_STATUS:
    {
      OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaHWEvent_SPC_OUB_t, EVParam)) ;
      /* get request from IOMap */
      pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;

      SA_ASSERT((pRequest), "pRequest");
      if( pRequest == agNULL)
      {
         SA_DBG1(("mpiHWevent: pRequest (%p) NULL\n", pRequest));
         ret = AGSA_RC_FAILURE;
         break;
      }

      agContext = saRoot->IOMap[tag].agContext;

      /* makeup for CB */
      status = (status << 8) | phyId;
      ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_START_STATUS, status, agContext, agNULL);

      /* remove the request from IOMap */
      saRoot->IOMap[tag].Tag = MARK_OFF;
      saRoot->IOMap[tag].IORequest = agNULL;
      saRoot->IOMap[tag].agContext = agNULL;

      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
      SA_ASSERT((pRequest->valid), "pRequest->valid");
      pRequest->valid = agFALSE;
      /* return the request to free pool */
      if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
      {
        SA_DBG1(("mpiHWevent: 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(("mpiHWEvent: OSSA_HW_EVENT_PHY_START_STATUS, PhyID %d\n", phyId));

      break;
    }
    case OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED:
    {
      agsaPhyErrCountersPage_t errorParam;
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED, PhyID %d PortID %d NPIP 0x%x PS 0x%x\n",
                phyId, portId, (npipps & PHY_IN_PORT_MASK) >> SHIFT4, npipps & PORT_STATE_MASK));
      /* report PhyId, NPIP, PortState */
      si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
      errorParam.phyResetProblem = eventParam;
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PHY_ERR_PHY_RESET_FAILED, phyId, (void *)&errorParam, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PORT_RESET_TIMER_TMO:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RESET_TIMER_TMO, PhyID %d PortID %d\n", phyId, portId));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PORT_RESET_TIMER_TMO, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_PORT_RESET_COMPLETE:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_PORT_RESET_COMPLETE, PhyID %d PortID %d\n", phyId, portId));
      /* get SAS Identify info */
      IDframe = (agsaSASIdentify_t *)&pIomb->sasIdentify;
      /* report PhyId, NPIP, PortState and LinkRate */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16) | (linkRate << SHIFT8);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_PORT_RESET_COMPLETE, phyId, agNULL, (void *)IDframe);
      break;
    }
    case OSSA_HW_EVENT_BROADCAST_ASYNCH_EVENT:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_BROADCAST_ASYNCH_EVENT, PhyID %d PortID %d\n", phyId, portId));
      /* report PhyId, NPIP, PortState */
      phyId |= (npipps & PHY_IN_PORT_MASK) | ((npipps & PORT_STATE_MASK) << SHIFT16);
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_BROADCAST_ASYNCH_EVENT, phyId, agNULL, agNULL);
      break;
    }
    case OSSA_HW_EVENT_IT_NEXUS_LOSS:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_IT_NEXUS_LOSS, PhyID %d PortID %d status 0x%X\n", phyId, portId,status));
      break;
    }
    case OSSA_HW_EVENT_OPEN_RETRY_BACKOFF_THR_ADJUSTED:
    {
      SA_DBG1(("mpiHWEvent: OSSA_HW_EVENT_OPEN_RETRY_BACKOFF_THR_ADJUSTED, PhyID %d PortID %d status 0x%X\n", phyId, portId,status));
      ossaHwCB(agRoot, agPortContext, OSSA_HW_EVENT_OPEN_RETRY_BACKOFF_THR_ADJUSTED, phyId, agNULL, agNULL);
      break;
    }

    default:
    {
      SA_DBG1(("mpiHWEvent: Unknown HW Event 0x%x status 0x%X\n", Event ,status));
      break;
    }
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2j");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SMP Completion
 *
 *  This function handles the SMP completion.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA hardware
 *  \param pIomb        pointer of Message1
 *  \param bc           buffer count
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSMPCompletion(
  agsaRoot_t             *agRoot,
  agsaSMPCompletionRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  bit32               status;
  bit32               tag;
  bit32               param;
  agsaIORequestDesc_t *pRequest;

  SA_DBG3(("mpiSMPCompletion: start, HTAG=0x%x\n", pIomb->tag));

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2k");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSMPCompletionRsp_t, tag)) ;
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSMPCompletionRsp_t, status)) ;
  OSSA_READ_LE_32(AGROOT, &param, pIomb, OSSA_OFFSET_OF(agsaSMPCompletionRsp_t, param)) ;
   /* get SMP request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSMPCompletion: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x PARAM=0x%x\n", tag, status, param));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2k");
    return AGSA_RC_FAILURE;
  }

  switch (status)
  {
  case OSSA_IO_SUCCESS:
    SA_DBG3(("mpiSMPCompletion: OSSA_IO_SUCCESS HTAG = 0x%x\n", tag));
    /* process message */
    siSMPRespRcvd(agRoot, pIomb, param, tag);
    break;

  case OSSA_IO_OVERFLOW:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OVERFLOW HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OVERFLOW++;
    /* SMP failed */
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_ABORTED:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_ABORTED HTAG = 0x%x\n", tag));

    saRoot->IoErrorCount.agOSSA_IO_ABORTED++;
#ifdef SA_PRINTOUT_IN_WINDBG
#ifndef DBG
        DbgPrint("agOSSA_IO_ABORTED  %d\n",  saRoot->IoErrorCount.agOSSA_IO_ABORTED);
#endif /* DBG  */
#endif /* SA_PRINTOUT_IN_WINDBG  */
    /* SMP failed */
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_NO_DEVICE:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_NO_DEVICE HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_NO_DEVICE++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_ERROR_HW_TIMEOUT:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_ERROR_HW_TIMEOUT HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_ERROR_HW_TIMEOUT++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_XFER_ERROR_BREAK:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_XFER_ERROR_BREAK HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_XFER_ERROR_BREAK++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_XFER_ERROR_PHY_NOT_READY:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_XFER_ERROR_PHY_NOT_READY HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_XFER_ERROR_PHY_NOT_READY++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_BREAK:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_BREAK HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_BREAK++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_XFER_ERROR_RX_FRAME:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_XFER_ERROR_RX_FRAME HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_XFER_ERROR_RX_FRAME++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_XFER_OPEN_RETRY_TIMEOUT:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_XFER_OPEN_RETRY_TIMEOUT HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_XFER_OPEN_RETRY_TIMEOUT++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_ERROR_INTERNAL_SMP_RESOURCE HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_ERROR_INTERNAL_SMP_RESOURCE++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_PORT_IN_RESET:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_PORT_IN_RESET HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_PORT_IN_RESET++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_DS_NON_OPERATIONAL:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_DS_NON_OPERATIONAL HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_DS_NON_OPERATIONAL++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_DS_IN_RECOVERY:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_DS_IN_RECOVERY HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_DS_IN_RECOVERY++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_HW_RESOURCE_BUSY++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_ABORT_IN_PROGRESS:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_ABORT_IN_PROGRESS HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_ABORT_IN_PROGRESS++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_ABORT_DELAYED:
    SA_DBG1(("mpiSMPCompletion:OSSA_IO_ABORT_DELAYED  HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_ABORT_DELAYED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_INVALID_LENGTH:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_INVALID_LENGTH HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_INVALID_LENGTH++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_DS_INVALID:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_DS_INVALID HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_DS_INVALID++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_XFER_READ_COMPL_ERR:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_XFER_READ_COMPL_ERR HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_XFER_READ_COMPL_ERR++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_MPI_ERR_IO_RESOURCE_UNAVAILABLE:
    SA_DBG1(("mpiSMPCompletion: OSSA_MPI_ERR_IO_RESOURCE_UNAVAILABLE HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_MPI_ERR_IO_RESOURCE_UNAVAILABLE++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_MPI_ERR_OFFLOAD_DIF_OR_ENC_NOT_ENABLED:
    SA_DBG1(("mpiSMPCompletion: OSSA_MPI_ERR_IO_RESOURCE_UNAVAILABLE HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_MPI_ERR_OFFLOAD_DIF_OR_ENC_NOT_ENABLED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  case OSSA_IO_OPEN_CNX_ERROR_OPEN_PREEMPTED:
    SA_DBG1(("mpiSMPCompletion: OSSA_IO_OPEN_CNX_ERROR_OPEN_PREEMPTED HTAG = 0x%x\n", tag));
    saRoot->IoErrorCount.agOSSA_IO_OPEN_CNX_ERROR_OPEN_PREEMPTED++;
    siAbnormal(agRoot, pRequest, status, 0, 0);
    break;

  default:
    SA_DBG1(("mpiSMPCompletion: Unknown Status = 0x%x Tag 0x%x\n", status, tag));
    saRoot->IoErrorCount.agOSSA_IO_UNKNOWN_ERROR++;
    /* not allowed case. Therefore, assert */
    SA_ASSERT((agFALSE), "mpiSMPCompletion: Unknown Status");
    break;
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2k");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI Get Device Handle Command Response
 *
 *  This function handles the response of Get Device Handle Command.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA hardware
 *  \param pIomb        pointer of Message
 *  \param bc           buffer count
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetDevHandleRsp(
  agsaRoot_t             *agRoot,
  agsaGetDevHandleRsp_t  *pIomb
  )
{
  bit32 ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaPortContext_t   *agPortContext;
  agsaContext_t       *agContext;
  agsaDeviceDesc_t    *pDevice;
  bit8 portId;
  bit32 deviceid=0, deviceIdc, i;
  bit32 DeviceIdcPortId, tag;

  SA_DBG3(("mpiGetDevHandleRsp: start, HTAG=0x%x\n", pIomb->tag));

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2m");

  OSSA_READ_LE_32(AGROOT, &DeviceIdcPortId, pIomb, OSSA_OFFSET_OF(agsaGetDevHandleRsp_t, DeviceIdcPortId)) ;
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetDevHandleRsp_t, tag)) ;
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetDevHandleRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x DeviceIdcPortId=0x%x\n", tag, DeviceIdcPortId));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2m");
    return AGSA_RC_FAILURE;
  }

  /* get port context */
  portId = (bit8)(DeviceIdcPortId & PORTID_MASK);
  SA_DBG2(("mpiGetDevHandleRsp:PortID 0x%x PortStatus 0x%x PortContext %p\n",saRoot->PortMap[portId & PORTID_MASK].PortID,saRoot->PortMap[portId & PORTID_MASK].PortStatus,saRoot->PortMap[portId & PORTID_MASK].PortContext));
  agPortContext = (agsaPortContext_t *)saRoot->PortMap[portId].PortContext;

  /* get Device ID count */
  deviceIdc = (bit8)((DeviceIdcPortId & DEVICE_IDC_BITS) >> SHIFT8);

  /* based on the deviceIDC to get all device handles */
  for (i = 0; i < deviceIdc; i++)
  {
    OSSA_READ_LE_32(AGROOT, &deviceid, pIomb, OSSA_OFFSET_OF(agsaGetDevHandleRsp_t, deviceId[i])) ;
    /* find device handle from device index */
    pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle;
    if (pDevice->targetDevHandle.sdkData)
     saRoot->DeviceHandle[i] = &(pDevice->targetDevHandle);
    else
     saRoot->DeviceHandle[i] = &(pDevice->initiatorDevHandle);
  }

  SA_DBG1(("mpiGetDevHandleRsp:deviceid 0x%x  0x%x\n",deviceid, (deviceid & DEVICE_ID_BITS)));
  /* call back oslayer */
  ossaGetDeviceHandlesCB(agRoot, agContext, agPortContext, saRoot->DeviceHandle, deviceIdc);

  /* return the request to free pool */
  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetDevHandleRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2m");

  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI Phy Control Command Response
 *
 *  This function handles the response of PHY Control Command.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA hardware
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiPhyCntrlRsp(
  agsaRoot_t             *agRoot,
  agsaLocalPhyCntrlRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext = agNULL;
  bit32               phyId, operation, status, tag, phyOpId;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2n");

  SA_DBG3(("mpiPhyCntrlRsp: start, HTAG=0x%x,\n", pIomb->tag));

  /* get tag */
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaLocalPhyCntrlRsp_t, tag)) ;
  OSSA_READ_LE_32(AGROOT, &phyOpId, pIomb, OSSA_OFFSET_OF(agsaLocalPhyCntrlRsp_t, phyOpId)) ;
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaLocalPhyCntrlRsp_t, status)) ;
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiPhyCntrlRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x PhyOpId=0x%x\n", tag, status, phyOpId));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2n");
    return AGSA_RC_FAILURE;
  }
  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  phyId = phyOpId & LOCAL_PHY_PHYID;
  operation = (phyOpId & LOCAL_PHY_OP_BITS) >> SHIFT8;


  SA_DBG3(("mpiPhyCntrlRsp: phyId=0x%x Operation=0x%x Status=0x%x\n", phyId, operation, status));

  if( pRequest->completionCB == agNULL )
  {
    /* call back with the status */
    ossaLocalPhyControlCB(agRoot, agContext, phyId, operation, status, agNULL);
  }
  else
  {
    (*(ossaLocalPhyControlCB_t)(pRequest->completionCB))(agRoot, agContext, phyId, operation, status, agNULL );
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiPhyCntrlRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2n");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI Device Register Command Response
 *
 *  This function handles the response of Device Register Command.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA hardware
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiDeviceRegRsp(
  agsaRoot_t    *agRoot,
  agsaDeviceRegistrationRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = agNULL;
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               deviceId;
  agsaDeviceDesc_t    *pDevice = agNULL;
  agsaDeviceDesc_t    *pDeviceRemove = agNULL;
  bit32               deviceIdx,status, tag;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2p");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  SA_ASSERT((agNULL != saRoot), "");

  SA_DBG3(("mpiDeviceRegRsp: start, HTAG=0x%x\n", pIomb->tag));

  SA_ASSERT((NULL != saRoot->DeviceRegistrationCB), "DeviceRegistrationCB can not be NULL");
  OSSA_READ_LE_32(AGROOT, &deviceId, pIomb, OSSA_OFFSET_OF(agsaDeviceRegistrationRsp_t, deviceId)) ;
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaDeviceRegistrationRsp_t, tag)) ;
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaDeviceRegistrationRsp_t, status)) ;

  SA_DBG1(("mpiDeviceRegRsp: deviceID 0x%x \n", deviceId));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiDeviceRegRsp: Bad IOMB!!! pRequest is NULL. TAG=0x%x, STATUS=0x%x DEVICEID=0x%x\n", tag, status, deviceId));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2p");
    return AGSA_RC_FAILURE;
  }

  pDevice = pRequest->pDevice;

  agContext = saRoot->IOMap[tag].agContext;
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  /* get Device Id or status */
  SA_DBG3(("mpiDeviceRegRsp: hosttag 0x%x\n", tag));
  SA_DBG3(("mpiDeviceRegRsp: deviceID 0x%x Device Context %p\n", deviceId, pDevice));

  if (agNULL == pDevice)
  {
    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiDeviceRegRsp: 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(("mpiDeviceRegRsp: warning!!! no device is found\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2p");
    return AGSA_RC_FAILURE;
  }

  if (agNULL == saRoot->DeviceRegistrationCB)
  {
    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiDeviceRegRsp: 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(("mpiDeviceRegRsp: warning!!! no DeviceRegistrationCB is found\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2p");
    return AGSA_RC_FAILURE;
  }


  if(smIS_SPCV(agRoot))
  {
    switch( status)
    {
      case 0:
          status = OSSA_SUCCESS;
          break;
      case MPI_ERR_DEVICE_HANDLE_UNAVAILABLE:
          status = OSSA_FAILURE_OUT_OF_RESOURCE;
          break;
      case MPI_ERR_DEVICE_ALREADY_REGISTERED:
          status = OSSA_FAILURE_DEVICE_ALREADY_REGISTERED;
          break;
      case MPI_ERR_PHY_ID_INVALID:
          status = OSSA_FAILURE_INVALID_PHY_ID;
          break;
      case MPI_ERR_PHY_ID_ALREADY_REGISTERED:
          status = OSSA_FAILURE_PHY_ID_ALREADY_REGISTERED;
          break;
      case MPI_ERR_PORT_INVALID_PORT_ID:
          status = OSSA_FAILURE_PORT_ID_OUT_OF_RANGE;
          break;
      case MPI_ERR_PORT_STATE_NOT_VALID:
          status = OSSA_FAILURE_PORT_NOT_VALID_STATE;
          break;
      case MPI_ERR_DEVICE_TYPE_NOT_VALID:
          status = OSSA_FAILURE_DEVICE_TYPE_NOT_VALID;
          break;
      default:
        SA_ASSERT((0), "DeviceRegistration Unknown status");
        ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
        pRequest->valid = agFALSE;
        /* return the request to free pool */
        if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
        {
          SA_DBG1(("mpiDeviceRegRsp: 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);

        return AGSA_RC_FAILURE;
    }
  }

  switch (status)
  {
  case OSSA_SUCCESS:
    /* mapping the device handle and device id */
    deviceIdx = deviceId & DEVICE_ID_BITS;
    OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");
    saRoot->DeviceMap[deviceIdx].DeviceIdFromFW = deviceId;
    saRoot->DeviceMap[deviceIdx].DeviceHandle = (void *)pDevice;
    pDevice->DeviceMapIndex = deviceId;

    (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                  agContext,
                                                                  OSSA_SUCCESS,
                                                                  &pDevice->targetDevHandle,
                                                                  deviceId
                                                                  );

    break;
  case OSSA_FAILURE_OUT_OF_RESOURCE:
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_OUT_OF_RESOURCE\n"));
    /* remove device from LL device list */
    siPortDeviceRemove(agRoot, pDevice->pPort, pDevice, agFALSE);

    /* call ossaDeviceRegistrationCB_t */
    (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                  agContext,
                                                                  OSSA_FAILURE_OUT_OF_RESOURCE,
                                                                  &pDevice->targetDevHandle,
                                                                  deviceId
                                                                  );


    break;
  case OSSA_FAILURE_DEVICE_ALREADY_REGISTERED:
    /* get original device handle and device id */
    pDeviceRemove = pDevice;
    deviceIdx = deviceId & DEVICE_ID_BITS;
    OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");
    pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceIdx].DeviceHandle;
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_DEVICE_ALREADY_REGISTERED, existing deviceContext %p\n", pDevice));
    /* no auto registration */
    if (pDevice != agNULL)
    {
      /* remove device from LL device list */
      siPortDeviceListRemove(agRoot, pDevice->pPort, pDeviceRemove);

      /* call ossaDeviceRegistrationCB_t */
      (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                    agContext,
                                                                    OSSA_FAILURE_DEVICE_ALREADY_REGISTERED,
                                                                    &pDevice->targetDevHandle,
                                                                    deviceId
                                                                    );
    }
    else
    {
      SA_DBG1(("mpiDeviceRegRsp: pDevice is NULL. TAG=0x%x, STATUS=0x%x DEVICEID=0x%x\n", tag, status, deviceId));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2p");
      return AGSA_RC_FAILURE;
    }

    break;
  case OSSA_FAILURE_INVALID_PHY_ID:
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_INVALID_PHY_ID\n"));
    /* remove device from LL device list */
    siPortDeviceRemove(agRoot, pDevice->pPort, pDevice, agFALSE);

    /* call ossaDeviceRegistrationCB_t */
    (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                  agContext,
                                                                  OSSA_FAILURE_INVALID_PHY_ID,
                                                                  &pDevice->targetDevHandle,
                                                                  deviceId
                                                                  );
    break;
  case OSSA_FAILURE_PHY_ID_ALREADY_REGISTERED:
    /* get original device handle and device id */
    pDeviceRemove = pDevice;
    deviceIdx = deviceId & DEVICE_ID_BITS;
    OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");
    pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceIdx].DeviceHandle;
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_PHY_ID_ALREADY_REGISTERED, existing deviceContext %p\n", pDevice));
    /* no auto registration */
    if (pDevice != agNULL)
    {
      /* remove device from LL device list */
      siPortDeviceListRemove(agRoot, pDevice->pPort, pDeviceRemove);

      /* call ossaDeviceRegistrationCB_t */
      (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                    agContext,
                                                                    OSSA_FAILURE_PHY_ID_ALREADY_REGISTERED,
                                                                    &pDevice->targetDevHandle,
                                                                    deviceId
                                                                    );
    }
    else
    {
      SA_DBG1(("mpiDeviceRegRsp: pDevice is NULL. TAG=0x%x, STATUS=0x%x DEVICEID=0x%x\n", tag, status, deviceId));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2p");
      return AGSA_RC_FAILURE;
    }

    break;
  case OSSA_FAILURE_PORT_ID_OUT_OF_RANGE:
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_OUT_OF_RESOURCE\n"));
    /* remove device from LL device list */
    siPortDeviceRemove(agRoot, pDevice->pPort, pDevice, agFALSE);

    /* call ossaDeviceRegistrationCB_t */
    (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                  agContext,
                                                                  OSSA_FAILURE_PORT_ID_OUT_OF_RANGE,
                                                                  &pDevice->targetDevHandle,
                                                                  deviceId
                                                                  );
    break;
  case OSSA_FAILURE_PORT_NOT_VALID_STATE:
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_PORT_NOT_VALID_STATE\n"));
    /* remove device from LL device list */
    siPortDeviceRemove(agRoot, pDevice->pPort, pDevice, agFALSE);

    /* call ossaDeviceRegistrationCB_t */
    (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                  agContext,
                                                                  OSSA_FAILURE_PORT_NOT_VALID_STATE,
                                                                  &pDevice->targetDevHandle,
                                                                  deviceId
                                                                  );
    break;
  case OSSA_FAILURE_DEVICE_TYPE_NOT_VALID:
    SA_DBG1(("mpiDeviceRegRsp: OSSA_FAILURE_DEVICE_TYPE_NOT_VALID\n"));
    /* remove device from LL device list */
    siPortDeviceRemove(agRoot, pDevice->pPort, pDevice, agFALSE);
    /* call ossaDeviceRegistrationCB_t */
    (*(ossaDeviceRegistrationCB_t)(saRoot->DeviceRegistrationCB))(agRoot,
                                                                  agContext,
                                                                  OSSA_FAILURE_DEVICE_TYPE_NOT_VALID,
                                                                  &pDevice->targetDevHandle,
                                                                  deviceId
                                                                  );
    break;
  default:
    SA_DBG3(("mpiDeviceRegRsp, unknown status in response %d\n", status));
    break;
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiDeviceRegRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "2p");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI Deregister Device Command Response
 *
 *  This function handles the response of Deregister Command.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA hardware
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiDeregDevHandleRsp(
  agsaRoot_t              *agRoot,
  agsaDeregDevHandleRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDevHandle_t     *agDevHandle;
  agsaContext_t       *agContext;
  agsaDeviceDesc_t    *pDevice;
  bit32               deviceIdx, status, tag;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2r");
  SA_ASSERT((NULL != saRoot->DeviceDeregistrationCB), "DeviceDeregistrationCB can not be NULL");

  SA_DBG3(("mpiDeregDevHandleRsp: start, HTAG=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaDeregDevHandleRsp_t, tag)) ;
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaDeregDevHandleRsp_t, status)) ;
  OSSA_READ_LE_32(AGROOT, &deviceIdx, pIomb, OSSA_OFFSET_OF(agsaDeregDevHandleRsp_t, deviceId)) ;
  /* get request from IOMap */

  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiDeregDevHandleRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x deviceIdx 0x%x\n", tag, status,deviceIdx));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2r");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  pDevice = pRequest->pDevice;
  if (pDevice != agNULL)
  {
    if (pDevice->targetDevHandle.sdkData)
    {
      agDevHandle = &(pDevice->targetDevHandle);
    }
    else
    {
      agDevHandle = &(pDevice->initiatorDevHandle);
    }
  }
  else
  {
    SA_DBG1(("mpiDeregDevHandleRsp: pDevice is NULL"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2r");
    return AGSA_RC_FAILURE;
  }

  if (agNULL == agDevHandle)
  {
    SA_DBG1(("mpiDeregDevHandleRsp: warning!!! no deviceHandle is found"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2r");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiDeregDevHandleRsp: 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);

    return AGSA_RC_FAILURE;
  }

  SA_DBG1(("mpiDeregDevHandleRsp: deviceID 0x%x Device Context %p\n", pDevice->DeviceMapIndex, pDevice));

  if (agNULL == saRoot->DeviceDeregistrationCB)
  {
    SA_DBG1(("mpiDeregDevHandleRsp: warning!!! no DeviceDeregistrationCB is found"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2r");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiDeregDevHandleRsp: 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);

    return AGSA_RC_FAILURE;
  }

  switch (status)
  {
    case OSSA_SUCCESS:
     (*(ossaDeregisterDeviceHandleCB_t)(saRoot->DeviceDeregistrationCB))(agRoot,
                                                                agContext,
                                                                agDevHandle,
                                                                OSSA_SUCCESS
                                                                );
      siRemoveDevHandle(agRoot, agDevHandle);
      break;
    case OSSA_ERR_DEVICE_HANDLE_INVALID:
    case OSSA_INVALID_HANDLE:
      (*(ossaDeregisterDeviceHandleCB_t)(saRoot->DeviceDeregistrationCB))(agRoot,
                                                                agContext,
                                                                agDevHandle,
                                                                status
                                                                );
// already removed and no device to remove
//      siRemoveDevHandle(agRoot, agDevHandle);
      SA_DBG1(("mpiDeregDevRegRsp, OSSA_INVALID_HANDLE status in response %d\n", status));
      break;
    case OSSA_ERR_DEVICE_BUSY:
      (*(ossaDeregisterDeviceHandleCB_t)(saRoot->DeviceDeregistrationCB))(agRoot,
                                                                agContext,
                                                                agDevHandle,
                                                                status
                                                                );
      SA_DBG1(("mpiDeregDevRegRsp, OSSA_ERR_DEVICE_BUSY status in response %d\n", status));
      ret = AGSA_RC_BUSY;
      break;
    default:
      SA_DBG1(("mpiDeregDevRegRsp, unknown status in response 0x%X\n", status));
      break;
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiDeregDevHandleRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2r");
  return ret;
}


/******************************************************************************/
/*! \brief Get Phy Profile Response SPCv
 *
 *  This routine handles the response of Get Phy Profile Command Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Message
 *
 *  \return sucess or fail
 *  SPC  only
 */
/*******************************************************************************/

GLOBAL bit32 mpiGetPhyProfileRsp(
  agsaRoot_t             *agRoot,
  agsaGetPhyProfileRspV_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32              status, tag;

  bit32          Reserved_SOP_PHYID;
  bit32          PhyId;
  bit32          SOP;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2J");
  OSSA_READ_LE_32(agRoot, &status, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t, status));
  OSSA_READ_LE_32(agRoot, &tag, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t, tag));
  /* get TAG */
  SA_DBG1(("mpiGetPhyProfileRsp: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetPhyProfileRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2J");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  OSSA_READ_LE_32(agRoot, &Reserved_SOP_PHYID, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,Reserved_Ppc_SOP_PHYID ));

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");
  SA_DBG1(("mpiGetPhyProfileRsp:   %p\n",pIomb));
  SA_DBG1(("mpiGetPhyProfileRsp: completionCB %p\n",pRequest->completionCB ));

  SOP = (Reserved_SOP_PHYID & 0xFF00) >> SHIFT8;
  PhyId = Reserved_SOP_PHYID & 0xFF;

  /* check status success or failure */
  if (status)
  {
    /* status is FAILED */
    SA_DBG1(("mpiGetPhyProfileRsp:AGSA_RC_FAILURE  0x%08X\n", status));
    switch(SOP)
    {
      case AGSA_SAS_PHY_ERR_COUNTERS_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_ERR_COUNTERS_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_SAS_PHY_BW_COUNTERS_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: GET_SAS_PHY_BW_COUNTERS SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_SAS_PHY_GENERAL_STATUS_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_GENERAL_STATUS_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_PHY_SNW3_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_PHY_SNW3_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_PHY_RATE_CONTROL_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_PHY_RATE_CONTROL_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      case AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL );
        break;
      }
      default:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: undefined SOP 0x%x\n", SOP));
        break;
      }
    }
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2J");
    return AGSA_RC_FAILURE;
  }
  else
  {
    SA_DBG1(("mpiGetPhyProfileRsp: SUCCESS type 0x%X\n",SOP ));
    switch(SOP)
    {
      case AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE:
        /* call back with the status */
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE PhyId %d\n",PhyId));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , agNULL);
        break;
      case AGSA_SAS_PHY_ERR_COUNTERS_PAGE:
      {

        agsaPhyErrCountersPage_t Errors;

        OSSA_READ_LE_32(agRoot, &Errors.invalidDword,          pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &Errors.runningDisparityError, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));
        OSSA_READ_LE_32(agRoot, &Errors.codeViolation,         pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[2] ));
        OSSA_READ_LE_32(agRoot, &Errors.lossOfDwordSynch,      pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[3] ));
        OSSA_READ_LE_32(agRoot, &Errors.phyResetProblem,       pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[4] ));
        OSSA_READ_LE_32(agRoot, &Errors.inboundCRCError,       pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[5] ));

        /* call back with the status */
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , &Errors);
        /* status is SUCCESS */

        SA_DBG3(("mpiGetPhyProfileRsp: pIomb %p\n",pIomb));
        SA_DBG1(("mpiGetPhyProfileRsp: Reserved_SOP_PHYID    0x%08X\n",Reserved_SOP_PHYID));
        SA_DBG1(("mpiGetPhyProfileRsp: invalidDword          0x%08X\n",Errors.invalidDword ));
        SA_DBG1(("mpiGetPhyProfileRsp: runningDisparityError 0x%08X\n",Errors.runningDisparityError ));
        SA_DBG1(("mpiGetPhyProfileRsp: codeViolation         0x%08X\n",Errors.codeViolation ));
        SA_DBG1(("mpiGetPhyProfileRsp: lossOfDwordSynch      0x%08X\n",Errors.lossOfDwordSynch ));
        SA_DBG1(("mpiGetPhyProfileRsp: phyResetProblem       0x%08X\n",Errors.phyResetProblem ));
        SA_DBG1(("mpiGetPhyProfileRsp: inboundCRCError       0x%08X\n",Errors.inboundCRCError ));
        break;

      }
      case AGSA_SAS_PHY_BW_COUNTERS_PAGE:
      {

        agsaPhyBWCountersPage_t  bw_counts;
        OSSA_READ_LE_32(agRoot, &bw_counts.TXBWCounter, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &bw_counts.RXBWCounter, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));

        SA_DBG1(("mpiGetPhyProfileRsp: GET_SAS_PHY_BW_COUNTERS TX 0x%08X RX 0x%08X\n",bw_counts.TXBWCounter,bw_counts.RXBWCounter));
        /* call back with the status */
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, &bw_counts);
        break;
      }
      case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
      {
        agsaPhyAnalogSettingsPage_t analog;

        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE 0x%X\n",SOP));
        OSSA_READ_LE_32(agRoot, &analog.Dword0, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword1, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword2, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[2] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword3, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[3] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword4, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[4] ));
          /* call back with the status */
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, &analog);
        break;
      }

      case AGSA_SAS_PHY_GENERAL_STATUS_PAGE:
      {
        agsaSASPhyGeneralStatusPage_t GenStatus;
        OSSA_READ_LE_32(agRoot, &GenStatus.Dword0, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &GenStatus.Dword1, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_GENERAL_STATUS_PAGE SOP 0x%x 0x%x 0x%x\n", SOP,GenStatus.Dword0,GenStatus.Dword1));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , &GenStatus );
        break;
      }
      case AGSA_PHY_SNW3_PAGE:
      {
        agsaPhySNW3Page_t Snw3;
        OSSA_READ_LE_32(agRoot, &Snw3.LSNW3, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &Snw3.RSNW3, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));

        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_PHY_SNW3_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , &Snw3 );
        break;
      }
      case AGSA_PHY_RATE_CONTROL_PAGE:
      {
        agsaPhyRateControlPage_t RateControl;
        OSSA_READ_LE_32(agRoot, &RateControl.Dword0, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &RateControl.Dword1, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));
        OSSA_READ_LE_32(agRoot, &RateControl.Dword2, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[2] ));
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_PHY_RATE_CONTROL_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , &RateControl );
        break;
      }
      case AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE:
      {
        agsaSASPhyOpenRejectRetryBackOffThresholdPage_t Backoff;
        OSSA_READ_LE_32(agRoot, &Backoff.Dword0, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &Backoff.Dword1, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[1] ));
        OSSA_READ_LE_32(agRoot, &Backoff.Dword2, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[2] ));
        OSSA_READ_LE_32(agRoot, &Backoff.Dword3, pIomb, OSSA_OFFSET_OF(agsaGetPhyProfileRspV_t,PageSpecificArea[3] ));
        SA_DBG1(("mpiGetPhyProfileRsp: AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE SOP 0x%x\n", SOP));
        ossaGetPhyProfileCB(agRoot, agContext, status, SOP, PhyId , &Backoff );
        break;
      }
      default:
      {
        SA_DBG1(("mpiGetPhyProfileRsp: undefined successful SOP 0x%x\n", SOP));
        break;
      }

    }
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetPhyProfileRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2J");
  return ret;
}


GLOBAL bit32 mpiSetPhyProfileRsp(
  agsaRoot_t             *agRoot,
  agsaSetPhyProfileRspV_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32                status, tag;

  bit32           Reserved_Ppc_PHYID;
  bit32           PhyId;
  bit16           SOP;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2Q");
  OSSA_READ_LE_32(agRoot, &status, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t, status));
  OSSA_READ_LE_32(agRoot, &tag, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t, tag));
  OSSA_READ_LE_32(agRoot, &Reserved_Ppc_PHYID, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t, Reserved_Ppc_PHYID));
  /* get TAG */
  SA_DBG1(("mpiSetPhyProfileRsp: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSetPhyProfileRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2Q");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_DBG1(("mpiSetPhyProfileRsp:   %p\n",pIomb));

  SOP = pRequest->SOP;
  PhyId = Reserved_Ppc_PHYID & 0xFF;

  /* check status success or failure */
  if (status)
  {
    /* status is FAILED */
    SA_DBG1(("mpiSetPhyProfileRsp:AGSA_RC_FAILURE  0x%08X\n", status));
    switch(SOP)
    {
      case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE SOP 0x%x\n", SOP));
        ossaSetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, agNULL );
        break;
      }
      case AGSA_PHY_SNW3_PAGE:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: AGSA_PHY_SNW3_PAGE SOP 0x%x\n", SOP));
        ossaSetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, agNULL );
        break;
      }

      case AGSA_PHY_RATE_CONTROL_PAGE:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: AGSA_PHY_RATE_CONTROL_PAGE SOP 0x%x\n", SOP));
        ossaSetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, agNULL );
        break;
      }
     case AGSA_SAS_PHY_MISC_PAGE:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: AGSA_SAS_PHY_MISC_PAGE SOP 0x%x\n", SOP));
        ossaSetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, agNULL );
        break;
      }

      default:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: undefined SOP 0x%x\n", SOP));
        break;
      }
    }
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2Q");
    return AGSA_RC_FAILURE;
  }
  else
  {
    SA_DBG1(("mpiSetPhyProfileRsp: SUCCESS type 0x%X\n",SOP ));
    switch(SOP)
    {
      case AGSA_PHY_SNW3_PAGE:
      case AGSA_PHY_RATE_CONTROL_PAGE:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: Status 0x%x SOP 0x%x PhyId %d\n",status, SOP, PhyId));
        ossaSetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, agNULL );
        break;

      }
      case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
      {
        agsaPhyAnalogSettingsPage_t analog;

        SA_DBG1(("mpiSetPhyProfileRsp: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE 0x%X\n",SOP));
        OSSA_READ_LE_32(agRoot, &analog.Dword0, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t,PageSpecificArea[0] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword1, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t,PageSpecificArea[1] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword2, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t,PageSpecificArea[2] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword3, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t,PageSpecificArea[3] ));
        OSSA_READ_LE_32(agRoot, &analog.Dword4, pIomb, OSSA_OFFSET_OF(agsaSetPhyProfileRspV_t,PageSpecificArea[4] ));
          /* call back with the status */
        ossaSetPhyProfileCB(agRoot, agContext, status, SOP, PhyId, &analog );
        break;
      }
      default:
      {
        SA_DBG1(("mpiSetPhyProfileRsp: undefined successful SOP 0x%x\n", SOP));
        break;
      }

    }
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  SA_DBG1(("mpiSetPhyProfileRsp: completionCB %p\n",pRequest->completionCB ));

  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSetPhyProfileRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2Q");
  return ret;
}



/******************************************************************************/
/*! \brief Get Device Information Response
 *
 *  This routine handles the response of Get Device Info Command Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Message
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetDevInfoRsp(
  agsaRoot_t          *agRoot,
  agsaGetDevInfoRspV_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  agsaContext_t       *agContext;
  agsaDeviceInfo_t    commonDevInfo;
  bit32               ARSrateSMPTimeOutPortID, IRMcnITNexusTimeOut, status, tag;
  bit32               deviceid;
  bit32               sasAddrHi;
  bit32               sasAddrLow;
#if defined(SALLSDK_DEBUG)
  bit32               option;
#endif /* SALLSDK_DEBUG */

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2M");
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRspV_t, status));
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRspV_t, tag));
  /* get TAG */
  SA_DBG3(("mpiGetDevInfoRsp: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetDevInfoRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2M");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* check status success or failure */
  if (status)
  {
    /* status is FAILED */
    ossaGetDeviceInfoCB(agRoot, agContext, agNULL, OSSA_DEV_INFO_INVALID_HANDLE, agNULL);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2M");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
#if defined(SALLSDK_DEBUG)
    option = (bit32)pRequest->DeviceInfoCmdOption;
#endif /* SALLSDK_DEBUG */
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiGetDevInfoRsp: 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);

    return AGSA_RC_FAILURE;
  }

  /* status is SUCCESS */
  OSSA_READ_LE_32(AGROOT, &deviceid, pIomb,                OSSA_OFFSET_OF(agsaGetDevInfoRspV_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &ARSrateSMPTimeOutPortID, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRspV_t, ARSrateSMPTimeOutPortID));
  OSSA_READ_LE_32(AGROOT, &IRMcnITNexusTimeOut, pIomb,       OSSA_OFFSET_OF(agsaGetDevInfoRspV_t, IRMcnITNexusTimeOut));
  OSSA_READ_LE_32(AGROOT, &sasAddrHi, pIomb,       OSSA_OFFSET_OF(agsaGetDevInfoRspV_t,sasAddrHi[0] ));
  OSSA_READ_LE_32(AGROOT, &sasAddrLow, pIomb,       OSSA_OFFSET_OF(agsaGetDevInfoRspV_t,sasAddrLow[0] ));

  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle;
  if (pDevice != agNULL)
  {
    if (pDevice->targetDevHandle.sdkData)
    {
      agDevHandle = &(pDevice->targetDevHandle);
    }
    else
    {
      agDevHandle = &(pDevice->initiatorDevHandle);
    }
  }
  else
  {
    SA_DBG1(("mpiGetDevInfoRsp: pDevice is NULL"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2M");
    return AGSA_RC_FAILURE;
  }

  if (agDevHandle == agNULL)
  {
    SA_DBG1(("mpiGetDevInfoRsp: warning!!! no deviceHandle is found"));
    ossaGetDeviceInfoCB(agRoot, agContext, agNULL, OSSA_DEV_INFO_INVALID_HANDLE, agNULL);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2M");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
#if defined(SALLSDK_DEBUG)
    option = (bit32)pRequest->DeviceInfoCmdOption;
#endif /* SALLSDK_DEBUG */
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiGetDevInfoRsp: 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);

    return AGSA_RC_FAILURE;
  }

  /* setup common device information */
  si_memset(&commonDevInfo, 0, sizeof(agsaDeviceInfo_t));
  commonDevInfo.smpTimeout       = (bit16)((ARSrateSMPTimeOutPortID >> SHIFT8 ) & SMPTO_VBITS);
  commonDevInfo.it_NexusTimeout  = (bit16)(IRMcnITNexusTimeOut & NEXUSTO_VBITS);
  commonDevInfo.firstBurstSize   = (bit16)((IRMcnITNexusTimeOut >> SHIFT16) & FIRST_BURST_MCN);
  commonDevInfo.devType_S_Rate   = (bit8)((ARSrateSMPTimeOutPortID >> SHIFT24) & 0x3f);
  commonDevInfo.flag = (bit32)((ARSrateSMPTimeOutPortID >> SHIFT30 ) & FLAG_VBITS);
  commonDevInfo.flag |= IRMcnITNexusTimeOut & 0xf0000;
  if (IRMcnITNexusTimeOut & 0x1000000)
  {
    commonDevInfo.flag |= 0x100000;
  }

  /* check SAS device then copy SAS Address */
  if ( ((ARSrateSMPTimeOutPortID & DEV_TYPE_BITS) >> SHIFT28 == 0x00) ||
       ((ARSrateSMPTimeOutPortID & DEV_TYPE_BITS) >> SHIFT28 == 0x01)) 
  {
    /* copy the sasAddressHi byte-by-byte : no endianness */
    commonDevInfo.sasAddressHi[0] = pIomb->sasAddrHi[0];
    commonDevInfo.sasAddressHi[1] = pIomb->sasAddrHi[1];
    commonDevInfo.sasAddressHi[2] = pIomb->sasAddrHi[2];
    commonDevInfo.sasAddressHi[3] = pIomb->sasAddrHi[3];

    /* copy the sasAddressLow byte-by-byte : no endianness */
    commonDevInfo.sasAddressLo[0] = pIomb->sasAddrLow[0];
    commonDevInfo.sasAddressLo[1] = pIomb->sasAddrLow[1];
    commonDevInfo.sasAddressLo[2] = pIomb->sasAddrLow[2];
    commonDevInfo.sasAddressLo[3] = pIomb->sasAddrLow[3];
  }

  /* copy common device information to SAS and SATA device common header*/
  si_memcpy(&pDevice->devInfo.sasDeviceInfo.commonDevInfo, &commonDevInfo, sizeof(agsaDeviceInfo_t));
  si_memcpy(&pDevice->devInfo.sataDeviceInfo.commonDevInfo, &commonDevInfo, sizeof(agsaDeviceInfo_t));

  /* setup device firstBurstSize infomation */
  pDevice->devInfo.sataDeviceInfo.commonDevInfo.firstBurstSize =
       (bit16)((IRMcnITNexusTimeOut >> SHIFT16) & FIRST_BURST);

  /* Display Device Information */
  SA_DBG3(("mpiGetDevInfoRsp: smpTimeout=0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.smpTimeout));
  SA_DBG3(("mpiGetDevInfoRsp: it_NexusTimeout=0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.it_NexusTimeout));
  SA_DBG3(("mpiGetDevInfoRsp: firstBurstSize=0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.firstBurstSize));
  SA_DBG3(("mpiGetDevInfoRsp: devType_S_Rate=0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate));

  /*
  D518 P2I[15-12]: Disk  HP      DG0146FAMWL     , HPDE, WWID=5000c500:17459a31, 6.0G
  */

  SA_DBG1(("mpiGetDevInfoRsp: Device 0x%08X flag 0x%08X %s WWID= %02x%02x%02x%02x:%02x%02x%02x%02x, %s\n",
    deviceid,
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.flag,
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x20 ? "SATA DA" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x10 ? "SSP/SMP" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x0 ? "  STP  " : "Unknown",

    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[3],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[2],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[1],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[0],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[3],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[2],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[1],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[0],

    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 8  ? " 1.5G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 9  ? " 3.0G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 10 ? " 6.0G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 11 ? "12.0G" : "????" ));

  ossaGetDeviceInfoCB(agRoot, agContext, agDevHandle, OSSA_DEV_INFO_NO_EXTENDED_INFO, &commonDevInfo);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
#if defined(SALLSDK_DEBUG)
  option = (bit32)pRequest->DeviceInfoCmdOption;
#endif /* SALLSDK_DEBUG */
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetDevInfoRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2M");
  return ret;
}

/******************************************************************************/
/*! \brief Get Device Information Response
 *
 *  This routine handles the response of Get Device Info Command Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Message
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetDevInfoRspSpc(
  agsaRoot_t          *agRoot,
  agsaGetDevInfoRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  agsaContext_t       *agContext;
  bit32               dTypeSrateSMPTOPortID, FirstBurstSizeITNexusTimeOut, status, tag;
  bit32               deviceid;
  bit32               sasAddrHi;
  bit32               sasAddrLow;
  bit32               Info_avail = 0;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2t");
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, tag));
  /* get TAG */
  SA_DBG3(("mpiGetDevInfoRspSpc: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetDevInfoRspSpc: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2t");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* check status success or failure */
  if (status)
  {
    /* status is FAILED */
    ossaGetDeviceInfoCB(agRoot, agContext, agNULL, OSSA_DEV_INFO_INVALID_HANDLE, agNULL);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2t");
    return AGSA_RC_FAILURE;
  }

  /* status is SUCCESS */
  OSSA_READ_LE_32(AGROOT, &deviceid, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &dTypeSrateSMPTOPortID, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, dTypeSrateSMPTOArPortID));
  OSSA_READ_LE_32(AGROOT, &FirstBurstSizeITNexusTimeOut, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, FirstBurstSizeITNexusTimeOut));
  OSSA_READ_LE_32(AGROOT, &sasAddrHi, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, sasAddrHi[0]));
  OSSA_READ_LE_32(AGROOT, &sasAddrLow, pIomb, OSSA_OFFSET_OF(agsaGetDevInfoRsp_t, sasAddrLow[0]));


  SA_DBG2(("mpiGetDevInfoRspSpc:deviceid                     0x%08X\n",deviceid));
  SA_DBG2(("mpiGetDevInfoRspSpc:dTypeSrateSMPTOPortID        0x%08X\n",dTypeSrateSMPTOPortID));
  SA_DBG2(("mpiGetDevInfoRspSpc:FirstBurstSizeITNexusTimeOut 0x%08X\n",FirstBurstSizeITNexusTimeOut));
  SA_DBG2(("mpiGetDevInfoRspSpc:sasAddrHi                    0x%08X\n",sasAddrHi));
  SA_DBG2(("mpiGetDevInfoRspSpc:sasAddrLow                   0x%08X\n",sasAddrLow));


  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle;
  if (pDevice != agNULL)
  {
    if (pDevice->targetDevHandle.sdkData)
    {
      agDevHandle = &(pDevice->targetDevHandle);
    }
    else
    {
      agDevHandle = &(pDevice->initiatorDevHandle);
    }
  }
  else
  {
    SA_DBG1(("mpiGetDevInfoRspSpc: pDevice is NULL"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2t");
    return AGSA_RC_FAILURE;
  }

  if (agDevHandle == agNULL)
  {
    SA_DBG1(("mpiGetDevInfoRspSpc: warning!!! no deviceHandle is found"));
    ossaGetDeviceInfoCB(agRoot, agContext, agNULL, OSSA_DEV_INFO_INVALID_HANDLE, agNULL);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2t");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiGetDevInfoRspSpc: 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);

    return AGSA_RC_FAILURE;
  }

  Info_avail = OSSA_DEV_INFO_NO_EXTENDED_INFO;

  /* setup device common infomation */
  pDevice->devInfo.sasDeviceInfo.commonDevInfo.smpTimeout =
    (bit16)((dTypeSrateSMPTOPortID >> SHIFT8 ) & SMPTO_BITS);

  pDevice->devInfo.sataDeviceInfo.commonDevInfo.smpTimeout =
    (bit16)((dTypeSrateSMPTOPortID >> SHIFT8 ) & SMPTO_BITS);

  pDevice->devInfo.sasDeviceInfo.commonDevInfo.it_NexusTimeout =
    (bit16)(FirstBurstSizeITNexusTimeOut & NEXUSTO_BITS);

  pDevice->devInfo.sataDeviceInfo.commonDevInfo.it_NexusTimeout =
    (bit16)(FirstBurstSizeITNexusTimeOut & NEXUSTO_BITS);

  pDevice->devInfo.sasDeviceInfo.commonDevInfo.firstBurstSize =
    (bit16)((FirstBurstSizeITNexusTimeOut >> SHIFT16) & FIRST_BURST);

  pDevice->devInfo.sataDeviceInfo.commonDevInfo.firstBurstSize =
    (bit16)((FirstBurstSizeITNexusTimeOut >> SHIFT16) & FIRST_BURST);

  pDevice->devInfo.sasDeviceInfo.commonDevInfo.flag = (bit32)((dTypeSrateSMPTOPortID >> SHIFT4 ) & FLAG_BITS);

  pDevice->devInfo.sataDeviceInfo.commonDevInfo.flag = (bit32)((dTypeSrateSMPTOPortID >> SHIFT4 ) & FLAG_BITS);

  pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate =
    (bit8)((dTypeSrateSMPTOPortID >> SHIFT24) & LINK_RATE_BITS);

  pDevice->devInfo.sataDeviceInfo.commonDevInfo.devType_S_Rate =
    (bit8)((dTypeSrateSMPTOPortID >> SHIFT24) & LINK_RATE_BITS);

  /* check SAS device then copy SAS Address */
  if ( ((dTypeSrateSMPTOPortID & DEV_TYPE_BITS) >> SHIFT28 == 0x00) ||
       ((dTypeSrateSMPTOPortID & DEV_TYPE_BITS) >> SHIFT28 == 0x01)) 
  {
    /* copy the sasAddressHi byte-by-byte : no endianness */
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[0] = pIomb->sasAddrHi[0];
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[1] = pIomb->sasAddrHi[1];
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[2] = pIomb->sasAddrHi[2];
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[3] = pIomb->sasAddrHi[3];

    /* copy the sasAddressLow byte-by-byte : no endianness */
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[0] = pIomb->sasAddrLow[0];
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[1] = pIomb->sasAddrLow[1];
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[2] = pIomb->sasAddrLow[2];
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[3] = pIomb->sasAddrLow[3];
  }

  /* Display Device Information */
  SA_DBG3(("mpiGetDevInfoRspSpc: smpTimeout=     0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.smpTimeout));
  SA_DBG3(("mpiGetDevInfoRspSpc: it_NexusTimeout=0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.it_NexusTimeout));
  SA_DBG3(("mpiGetDevInfoRspSpc: firstBurstSize= 0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.firstBurstSize));
  SA_DBG3(("mpiGetDevInfoRspSpc: devType_S_Rate= 0x%x\n", pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate));


  SA_DBG1(("Device SPC deviceid 0x%08X flag 0x%08X %s WWID= %02x%02x%02x%02x:%02x%02x%02x%02x, %s\n",
    deviceid,
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.flag,
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x20 ? "SATA DA" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x10 ? "SSP/SMP" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x0 ? "  STP  " : "Unknown",

    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[3],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[2],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[1],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[0],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[3],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[2],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[1],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[0],

    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 8  ? " 1.5G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 9  ? " 3.0G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 10 ? " 6.0G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 11 ? "12.0G" : "????" ));

  ossaGetDeviceInfoCB(agRoot, agContext, agDevHandle, Info_avail, &pDevice->devInfo.sasDeviceInfo.commonDevInfo);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetDevInfoRspSpc: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2t");
  return ret;
}

/******************************************************************************/
/*! \brief Set Device Information Response
 *
 *  This routine handles the response of Set Device Info Command Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Message
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSetDevInfoRsp(
  agsaRoot_t             *agRoot,
  agsaSetDeviceInfoRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  agsaContext_t       *agContext;
  bit32               tag, status, deviceid, option, param;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2v");
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSetDeviceInfoRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSetDeviceInfoRsp_t, tag));
  /* get TAG */
  SA_DBG3(("mpiSetDevInfoRsp: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSetDevInfoRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2v");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");
  /* check status success or failure */
  if (status)
  {
    /* status is FAILED */
    if (pRequest->completionCB == agNULL)
    {
      SA_DBG1(("mpiSetDevInfoRsp: status is FAILED pRequest->completionCB == agNULL\n" ));
      ossaSetDeviceInfoCB(agRoot, agContext, agNULL, status, 0, 0);
    }
    else
    {
      SA_DBG1(("mpiSetDevInfoRsp: status is FAILED use CB\n" ));
      (*(ossaSetDeviceInfoCB_t)(pRequest->completionCB))(agRoot, agContext, agNULL, status, 0, 0);
    }
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2v");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

    return AGSA_RC_FAILURE;
  }

  /* status is SUCCESS */
  OSSA_READ_LE_32(AGROOT, &deviceid, pIomb, OSSA_OFFSET_OF(agsaSetDeviceInfoRsp_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &option, pIomb, OSSA_OFFSET_OF(agsaSetDeviceInfoRsp_t, SA_SR_SI));
  OSSA_READ_LE_32(AGROOT, &param, pIomb, OSSA_OFFSET_OF(agsaSetDeviceInfoRsp_t, A_R_ITNT));

  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle;
  if (pDevice != agNULL)
  {
    if (pDevice->targetDevHandle.sdkData)
    {
      agDevHandle = &(pDevice->targetDevHandle);
    }
    else
    {
      agDevHandle = &(pDevice->initiatorDevHandle);
    }
  }
  else
  {
    SA_DBG1(("mpiSetDevInfoRsp: pDevice is NULL"));
    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "2v");
    return AGSA_RC_FAILURE;
  }

  if (agDevHandle == agNULL)
  {
    SA_DBG1(("mpiSetDevInfoRsp: warning!!! no deviceHandle is found"));
    if (pRequest->completionCB == agNULL)
    {
      ossaSetDeviceInfoCB(agRoot, agContext, agNULL, OSSA_IO_NO_DEVICE, 0, 0);
    }
    else
    {
      (*(ossaSetDeviceInfoCB_t)(pRequest->completionCB))(agRoot, agContext, agNULL, OSSA_IO_NO_DEVICE, 0, 0);
    }
    smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "2v");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

    return AGSA_RC_FAILURE;
  }

  SA_DBG2(("mpiSetDevInfoRsp:, option 0x%X param 0x%X\n", option, param));

  if(smIS_SPCV(agRoot))
  {
    SA_DBG2(("mpiSetDevInfoRsp:was option 0x%X param 0x%X\n", option, param));
    SA_DBG2(("mpiSetDevInfoRsp:pDevice->option 0x%X pDevice->param 0x%X\n", pDevice->option, pDevice->param));
    option |= pDevice->option;
    param |= pDevice->param;
    SA_DBG2(("mpiSetDevInfoRsp:now option 0x%X param 0x%X\n", option, param));
    if (pRequest->completionCB == agNULL)
    {
      ossaSetDeviceInfoCB(agRoot, agContext, agDevHandle, OSSA_SUCCESS, option, param);
    }
    else
    {
      (*(ossaSetDeviceInfoCB_t)(pRequest->completionCB))(agRoot, agContext, agDevHandle, OSSA_SUCCESS, option, param);
    }
  }
  else
  {
    SA_DBG2(("mpiSetDevInfoRsp:, option 0x%X param 0x%X\n", option, param));
    if (pRequest->completionCB == agNULL)
    {
      ossaSetDeviceInfoCB(agRoot, agContext, agDevHandle, OSSA_SUCCESS, option, param);
    }
    else
    {
      (*(ossaSetDeviceInfoCB_t)(pRequest->completionCB))(agRoot, agContext, agDevHandle, OSSA_SUCCESS, option, param);
    }
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "2v");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SSP Event
 *
 *  This function handles the SAS Event.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSSPEvent(
  agsaRoot_t        *agRoot,
  agsaSSPEventRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaPortContext_t   *agPortContext;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  bit32               event,deviceId;
  bit32               deviceIdx, tag, portId_tmp;
  bit32               SSPTag;
  bit16               sspTag;
  bit8                portId;

  agsaDifDetails_t Dif_details;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2u");

  OSSA_READ_LE_32(AGROOT, &event, pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, event));
  OSSA_READ_LE_32(AGROOT, &deviceId, pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &portId_tmp, pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, portId));
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &SSPTag, pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, SSPTag));


  sspTag = (bit16)(SSPTag & SSPTAG_BITS);

  /* get IORequest from IOMap */
  pRequest  = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;

  SA_ASSERT((pRequest), "pRequest");

  if(agNULL == pRequest)
  {
    SA_DBG1(("mpiSSPEvent: agNULL == pRequest event 0x%X\n", event));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2u");
    return AGSA_RC_FAILURE;
  }

  /* get port context */
  portId = (bit8)(portId_tmp & PORTID_MASK);
  SA_DBG2(("mpiSSPEvent:PortID 0x%x PortStatus 0x%x PortContext %p\n",saRoot->PortMap[portId & PORTID_MASK].PortID,saRoot->PortMap[portId & PORTID_MASK].PortStatus,saRoot->PortMap[portId & PORTID_MASK].PortContext));
  agPortContext = (agsaPortContext_t *)saRoot->PortMap[portId].PortContext;
  /* get device Id */
  deviceIdx = deviceId & DEVICE_ID_BITS;
  OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");
  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceIdx].DeviceHandle;

  if( agNULL == pDevice )
  {
    OS_ASSERT(pDevice, "pDevice");
    agDevHandle = agNULL;
  }
  else
  {
    if (pDevice->targetDevHandle.sdkData)
    {
      agDevHandle = &(pDevice->targetDevHandle);
    }
    else
    {
      agDevHandle = &(pDevice->initiatorDevHandle);
    }
  }

  switch (event)
  {
    case  OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH:
    case  OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH:
    case  OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH:
    case  OSSA_IO_XFR_ERROR_DIF_MISMATCH:
    {

      SA_DBG1(("mpiSSPEvent:  DIF Event 0x%x HTAG = 0x%x\n", event, tag));

      OSSA_READ_LE_32(AGROOT, &Dif_details.UpperLBA,           pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, EVT_PARAM0_or_LBAH));
      OSSA_READ_LE_32(AGROOT, &Dif_details.LowerLBA,           pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, EVT_PARAM1_or_LBAL));
      OSSA_READ_LE_32(AGROOT, &Dif_details.sasAddressHi,       pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, SAS_ADDRH));
      OSSA_READ_LE_32(AGROOT, &Dif_details.sasAddressLo,       pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, SAS_ADDRL));
      OSSA_READ_LE_32(AGROOT, &Dif_details.ExpectedCRCUDT01,   pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, UDT1_E_UDT0_E_CRC_E));
      OSSA_READ_LE_32(AGROOT, &Dif_details.ExpectedUDT2345,    pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, UDT5_E_UDT4_E_UDT3_E_UDT2_E));
      OSSA_READ_LE_32(AGROOT, &Dif_details.ActualCRCUDT01,     pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, UDT1_A_UDT0_A_CRC_A));
      OSSA_READ_LE_32(AGROOT, &Dif_details.ActualUDT2345,      pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, UDT5_A_UDT4_A_UDT3_A_UDT2_A));
      OSSA_READ_LE_32(AGROOT, &Dif_details.DIFErrDevID,        pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, HW_DEVID_Reserved_DIF_ERR));
      OSSA_READ_LE_32(AGROOT, &Dif_details.ErrBoffsetEDataLen, pIomb, OSSA_OFFSET_OF(agsaSSPEventRsp_t, EDATA_LEN_ERR_BOFF));

      SA_DBG2(("mpiSSPEvent: UpperLBA.         0x%08X LowerLBA.           0x%08X\n",Dif_details.UpperLBA,         Dif_details.LowerLBA));
      SA_DBG2(("mpiSSPEvent: sasAddressHi.     0x%02X%02X%02X%02X sasAddressLo.       0x%02X%02X%02X%02X\n",
                          Dif_details.sasAddressHi[0],Dif_details.sasAddressHi[1],Dif_details.sasAddressHi[2],Dif_details.sasAddressHi[3],
                          Dif_details.sasAddressLo[0],Dif_details.sasAddressLo[1],Dif_details.sasAddressLo[2],Dif_details.sasAddressLo[3]));
      SA_DBG2(("mpiSSPEvent: ExpectedCRCUDT01. 0x%08X ExpectedUDT2345.    0x%08X\n",Dif_details.ExpectedCRCUDT01, Dif_details.ExpectedUDT2345));
      SA_DBG2(("mpiSSPEvent: ActualCRCUDT01.   0x%08X ActualUDT2345.      0x%08X\n",Dif_details.ActualCRCUDT01,   Dif_details.ActualUDT2345));
      SA_DBG2(("mpiSSPEvent: DIFErrDevID.      0x%08X ErrBoffsetEDataLen. 0x%08X\n",Dif_details.DIFErrDevID,      Dif_details.ErrBoffsetEDataLen));
    }

    default:
    {
      SA_DBG3(("mpiSSPEvent:  Non DIF event"));
      break;
    }
  }


  /* get event */
  switch (event)
  {
    case OSSA_IO_OVERFLOW:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OVERFLOW tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OVERFLOW++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_BREAK:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_BREAK tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_BREAK++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_PHY_NOT_READY:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_PHY_NOT_READY tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_PHY_NOT_READY++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_BREAK:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_BREAK tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_BREAK++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_NAK_RECEIVED:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_NAK_RECEIVED tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_NAK_RECEIVED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_ACK_NAK_TIMEOUT:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_ACK_NAK_TIMEOUT tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_ACK_NAK_TIMEOUT++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_OFFSET_MISMATCH:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_OFFSET_MISMATCH tag 0x%x ssptag 0x%x\n", tag, sspTag));
#ifdef SA_ENABLE_PCI_TRIGGER
      if( saRoot->swConfig.PCI_trigger & PCI_TRIGGER_OFFSET_MISMATCH )
      {
        siPCITriger(agRoot);
      }
#endif /* SA_ENABLE_PCI_TRIGGER */
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_OFFSET_MISMATCH++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_XFER_ZERO_DATA_LEN tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_XFER_ZERO_DATA_LEN++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_OPEN_RETRY_TIMEOUT:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_OPEN_RETRY_TIMEOUT tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_OPEN_RETRY_TIMEOUT++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_CMD_FRAME_ISSUED:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_CMD_FRAME_ISSUED tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_CMD_FRAME_ISSUED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_UNEXPECTED_PHASE:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERROR_UNEXPECTED_PHASE tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_UNEXPECTED_PHASE++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case  OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
    {
      SA_DBG1(("mpiSSPEvent:OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED HTAG = 0x%x sspTag = 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case  OSSA_IO_XFR_ERROR_INTERNAL_CRC_ERROR:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_INTERNAL_CRC_ERROR HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_INTERNAL_CRC_ERROR++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
    case  OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag,sizeof(agsaDifDetails_t),&Dif_details);
      break;
    }
    case  OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag,sizeof(agsaDifDetails_t),&Dif_details);
      break;
    }
    case  OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag,sizeof(agsaDifDetails_t),&Dif_details);
      break;
    }
    case  OSSA_IO_XFR_ERROR_DIF_MISMATCH:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFR_ERROR_DIF_MISMATCH tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DIF_MISMATCH++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag,sizeof(agsaDifDetails_t),&Dif_details);
      break;
    }
    case  OSSA_IO_XFER_ERR_EOB_DATA_OVERRUN:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_ERR_EOB_DATA_OVERRUN tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERR_EOB_DATA_OVERRUN++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_READ_COMPL_ERR:
    {
      SA_DBG1(("mpiSSPEvent: OSSA_IO_XFER_READ_COMPL_ERR tag 0x%x ssptag 0x%x\n", tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_XFER_READ_COMPL_ERR++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0, agNULL);
      break;
    }
    default:
    {
      SA_DBG1(("mpiSSPEvent:  Unknown Event 0x%x tag 0x%x ssptag 0x%x\n", event, tag, sspTag));
      saRoot->IoEventCount.agOSSA_IO_UNKNOWN_ERROR++;
      ossaSSPEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, sspTag, 0,agNULL);
      break;
    }
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2u");
  /* return value */
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SATA Event
 *
 *  This function handles the SATA Event.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSATAEvent(
  agsaRoot_t         *agRoot,
  agsaSATAEventRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest = agNULL;
  agsaPortContext_t   *agPortContext;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  bit32               deviceIdx, portId_tmp, event, tag, deviceId;
  bit8                portId;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2w");

  /* get port context */
  OSSA_READ_LE_32(AGROOT, &portId_tmp, pIomb, OSSA_OFFSET_OF(agsaSATAEventRsp_t, portId));
  OSSA_READ_LE_32(AGROOT, &deviceId, pIomb, OSSA_OFFSET_OF(agsaSATAEventRsp_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &event, pIomb, OSSA_OFFSET_OF(agsaSATAEventRsp_t, event));
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSATAEventRsp_t, tag));

  if (OSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE != event)
  {
    /* get IORequest from IOMap */
    pRequest  = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  }
  /* get port context - only for OSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE */
  portId = (bit8)(portId_tmp & PORTID_MASK);
  SA_DBG2(("mpiSATAEvent:PortID 0x%x PortStatus 0x%x PortContext %p\n",saRoot->PortMap[portId & PORTID_MASK].PortID,saRoot->PortMap[portId & PORTID_MASK].PortStatus,saRoot->PortMap[portId & PORTID_MASK].PortContext));
  agPortContext = (agsaPortContext_t *)saRoot->PortMap[portId].PortContext;
  /* get device Id - only for OSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE*/
  deviceIdx = deviceId & DEVICE_ID_BITS;
  OS_ASSERT(deviceIdx < MAX_IO_DEVICE_ENTRIES, "deviceIdx MAX_IO_DEVICE_ENTRIES");
  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceIdx].DeviceHandle;
  agDevHandle = &(pDevice->targetDevHandle);

  /* get event */
  switch (event)
  {
    case OSSA_IO_OVERFLOW:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OVERFLOW HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OVERFLOW++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_BREAK:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_BREAK HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_BREAK++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_PHY_NOT_READY:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_PHY_NOT_READY HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_PHY_NOT_READY++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_BREAK:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_BREAK HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_BREAK++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }

    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE:
    {
      SA_DBG1(("mpiSATAEvent:  HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED:
    {
      SA_DBG1(("mpiSATAEvent:OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED  HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_NAK_RECEIVED:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_NAK_RECEIVED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_NAK_RECEIVED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE++;
      ossaSATAEvent(agRoot, agNULL, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_OFFSET_MISMATCH:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_OFFSET_MISMATCH HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_OFFSET_MISMATCH++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_XFER_ZERO_DATA_LEN:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_XFER_ZERO_DATA_LEN HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_XFER_ZERO_DATA_LEN++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_OPEN_RETRY_TIMEOUT:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_OPEN_RETRY_TIMEOUT HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_OPEN_RETRY_TIMEOUT++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_PEER_ABORTED:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_PEER_ABORTED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_PEER_ABORTED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_CMD_FRAME_ISSUED:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_CMD_FRAME_ISSUED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_CMD_FRAME_ISSUED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
    {
      SA_DBG1(("mpiSATAEvent, OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_UNEXPECTED_PHASE:
    {
      SA_DBG1(("mpiSATAEvent, OSSA_IO_XFER_ERROR_UNEXPECTED_PHASE HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_UNEXPECTED_PHASE++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN:
    {
      SA_DBG1(("mpiSATAEvent, OSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_XFER_RDY_OVERRUN++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED:
    {
      SA_DBG1(("mpiSATAEvent, OSSA_IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_XFER_RDY_NOT_EXPECTED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_PIO_SETUP_ERROR:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_PIO_SETUP_ERROR HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_PIO_SETUP_ERROR++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFR_ERROR_DIF_MISMATCH:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFR_ERROR_DIF_MISMATCH HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_DIF_MISMATCH++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFR_ERROR_INTERNAL_CRC_ERROR:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFR_ERROR_INTERNAL_CRC_ERROR HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFR_ERROR_INTERNAL_CRC_ERROR++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERR_EOB_DATA_OVERRUN:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERR_EOB_DATA_OVERRUN HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERR_EOB_DATA_OVERRUN++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    case OSSA_IO_XFER_ERROR_DMA_ACTIVATE_TIMEOUT:
    {
      SA_DBG1(("mpiSATAEvent: OSSA_IO_XFER_ERROR_DMA_ACTIVATE_TIMEOUT HTAG = 0x%x\n", tag));
      saRoot->IoEventCount.agOSSA_IO_XFER_ERROR_DMA_ACTIVATE_TIMEOUT++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
    default:
    {
      SA_DBG1(("mpiSATAEvent: Unknown Event 0x%x HTAG = 0x%x\n", event, tag));
      saRoot->IoEventCount.agOSSA_IO_UNKNOWN_ERROR++;
      ossaSATAEvent(agRoot, pRequest->pIORequestContext, agPortContext, agDevHandle, event, 0, agNULL);
      break;
    }
  }

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2w");
  return ret;
}

/******************************************************************************/
/*! \brief Set NVM Data Response
 *
 *  This routine handles the response of SET NVM Data Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSetNVMDataRsp(
  agsaRoot_t          *agRoot,
  agsaSetNVMDataRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag, status, iPTdaBnDpsAsNvm;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2x");

  SA_DBG1(("mpiSetNVMDataRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSetNVMDataRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &iPTdaBnDpsAsNvm, pIomb, OSSA_OFFSET_OF(agsaSetNVMDataRsp_t, iPTdaBnDpsAsNvm));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSetNVMDataRsp_t, status));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSetNVMDataRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2x");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  if (((iPTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_CONFIG_SEEPROM) ||
      ((iPTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_VPD_FLASH) ||
      ((iPTdaBnDpsAsNvm & NVMD_TYPE) == AGSA_NVMD_TWI_DEVICES))
  {
    /* CB for VPD for SEEPROM-0, VPD_FLASH and TWI */
    ossaSetNVMDResponseCB(agRoot, agContext, (status & NVMD_STAT));
  }
  else
  {
    /* should not happend */
    SA_DBG1(("mpiSetNVMDataRsp: NVMD is wrong. TAG=0x%x STATUS=0x%x\n", tag, (iPTdaBnDpsAsNvm & NVMD_TYPE)));
    ret = AGSA_RC_FAILURE;
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2x");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SSP ABORT Response
 *
 *  This function handles the SSP Abort Response.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSSPAbortRsp(
  agsaRoot_t         *agRoot,
  agsaSSPAbortRsp_t  *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDeviceDesc_t    *pDevice;
  bit32               tag, status, scope;
  smTraceFuncEnter(hpDBG_VERY_LOUD,"2y");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSSPAbortRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSSPAbortRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &scope, pIomb, OSSA_OFFSET_OF(agsaSSPAbortRsp_t, scp));
  scope &= 3; 
  /* get IORequest from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;

  if (agNULL == pRequest)
  {
    /* remove the SSP_ABORT or SATA_ABORT request from IOMap */
    saRoot->IOMap[tag].Tag = MARK_OFF;
    saRoot->IOMap[tag].IORequest = agNULL;
    SA_ASSERT((pRequest), "pRequest");
    SA_DBG1(("mpiSSPAbortRsp: the request is NULL. Tag=%x\n", tag));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2y");
    return AGSA_RC_FAILURE;
  }


  if ( agTRUE == pRequest->valid )
  {
    pDevice = pRequest->pDevice;
    SA_ASSERT((pRequest->pDevice), "pRequest->pDevice");

    SA_DBG3(("mpiSSPAbortRsp: request abort is valid Htag 0x%x\n", tag));
    /* remove the SSP_ABORT or SATA_ABORT request from IOMap */
    saRoot->IOMap[tag].Tag = MARK_OFF;
    saRoot->IOMap[tag].IORequest = agNULL;

    if( pRequest->completionCB == agNULL )
    {
      ossaSSPAbortCB(agRoot, pRequest->pIORequestContext, scope, status);
    }
    else
    {
      (*(ossaGenericAbortCB_t)(pRequest->completionCB))(agRoot, pRequest->pIORequestContext, scope, status);
    }

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* Delete the request from the pendingIORequests */
    saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));

    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiSSPAbortRsp: 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));
    }

    if(scope)
    {
      siCountActiveIORequestsOnDevice( agRoot, pDevice->DeviceMapIndex );
    }

    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  }
  else
  {
    ret = AGSA_RC_FAILURE;
    SA_DBG1(("mpiSSPAbortRsp: the request is not valid any more. Tag=%x\n", pRequest->HTag));
  }

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2y");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SATA ABORT Response
 *
 *  This function handles the SATA Event.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSATAAbortRsp(
  agsaRoot_t         *agRoot,
  agsaSATAAbortRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDeviceDesc_t    *pDevice;
  bit32               tag, status, scope;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3B");
  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSATAAbortRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSATAAbortRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &scope, pIomb, OSSA_OFFSET_OF(agsaSATAAbortRsp_t, scp));

  /* get IORequest from IOMap */
  pRequest  = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;

  if (agNULL == pRequest)
  {
    /* remove the SSP_ABORT or SATA_ABORT request from IOMap */
    saRoot->IOMap[tag].Tag = MARK_OFF;
    saRoot->IOMap[tag].IORequest = agNULL;
    SA_DBG1(("mpiSATAAbortRsp: the request is NULL. Tag=%x\n", tag));
    SA_ASSERT((pRequest), "pRequest");
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3B");
    return AGSA_RC_FAILURE;
  }

  if ( agTRUE == pRequest->valid )
  {
    pDevice = pRequest->pDevice;
    SA_ASSERT((pRequest->pDevice), "pRequest->pDevice");

    SA_DBG3(("mpiSATAAbortRsp: request abort is valid Htag 0x%x\n", tag));

    if( pRequest->completionCB == agNULL )
    {
      ossaSATAAbortCB(agRoot, pRequest->pIORequestContext, scope, status);
    }
    else
    {
      (*(ossaGenericAbortCB_t)(pRequest->completionCB))(agRoot, pRequest->pIORequestContext, scope, status);
    }
    /* remove the SATA_ABORT request from IOMap */
    saRoot->IOMap[tag].Tag = MARK_OFF;
    saRoot->IOMap[tag].IORequest = agNULL;
    saRoot->IOMap[tag].agContext = agNULL;

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* Delete the request from the pendingIORequests */
    saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
    /* return the request to free pool */
    saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  }
  else
  {
    ret = AGSA_RC_FAILURE;
    SA_DBG1(("mpiSATAAbortRsp: the request is not valid any more. Tag=%x\n", pRequest->HTag));
  }


  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3B");
  return ret;
}

/******************************************************************************/
/*! \brief Set GPIO Response
 *
 *  This routine handles the response of GPIO Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGPIORsp(
  agsaRoot_t          *agRoot,
  agsaGPIORsp_t       *pIomb
  )
{
  bit32                    ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t             *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaContext_t            *agContext;
  agsaIORequestDesc_t      *pRequest;
  agsaGpioPinSetupInfo_t   pinSetupInfo;
  agsaGpioEventSetupInfo_t eventSetupInfo;
  bit32 GpioIe, OT11_0, OT19_12, GPIEVChange, GPIEVFall, GPIEVRise, GpioRdVal, tag;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"5C");

  SA_DBG3(("mpiGPIORsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGPIORsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x\n", tag));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "5C");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;
  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* set payload to zeros */
  si_memset(&pinSetupInfo, 0, sizeof(agsaGpioPinSetupInfo_t));
  si_memset(&eventSetupInfo, 0, sizeof(agsaGpioEventSetupInfo_t));

  OSSA_READ_LE_32(AGROOT, &GpioIe, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, GpioIe));
  OSSA_READ_LE_32(AGROOT, &OT11_0, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, OT11_0));
  OSSA_READ_LE_32(AGROOT, &OT19_12, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, OT19_12));
  OSSA_READ_LE_32(AGROOT, &GPIEVChange, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, GPIEVChange));
  OSSA_READ_LE_32(AGROOT, &GPIEVFall, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, GPIEVFall));
  OSSA_READ_LE_32(AGROOT, &GPIEVRise, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, GPIEVRise));
  OSSA_READ_LE_32(AGROOT, &GpioRdVal, pIomb, OSSA_OFFSET_OF(agsaGPIORsp_t, GpioRdVal));
  pinSetupInfo.gpioInputEnabled = GpioIe;
  pinSetupInfo.gpioTypePart1 = OT11_0;
  pinSetupInfo.gpioTypePart2 = OT19_12;
  eventSetupInfo.gpioEventLevel = GPIEVChange;
  eventSetupInfo.gpioEventFallingEdge = GPIEVFall;
  eventSetupInfo.gpioEventRisingEdge = GPIEVRise;

  ossaGpioResponseCB(agRoot, agContext, OSSA_IO_SUCCESS, GpioRdVal,
                     &pinSetupInfo,
                     &eventSetupInfo);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGPIORsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "5C");
  return ret;
}

/******************************************************************************/
/*! \brief Set GPIO Event Response
 *
 *  This routine handles the response of GPIO Event
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGPIOEventRsp(
  agsaRoot_t          *agRoot,
  agsaGPIOEvent_t     *pIomb
  )
{
  bit32       ret = AGSA_RC_SUCCESS;
  bit32       GpioEvent;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3D");

  OSSA_READ_LE_32(AGROOT, &GpioEvent, pIomb, OSSA_OFFSET_OF(agsaGPIOEvent_t, GpioEvent));

  ossaGpioEvent(agRoot, GpioEvent);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3D");
  return ret;
}

/******************************************************************************/
/*! \brief SAS Diagnostic Start/End Response
 *
 *  This routine handles the response of SAS Diagnostic Start/End Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSASDiagStartEndRsp(
  agsaRoot_t               *agRoot,
  agsaSASDiagStartEndRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag, Status;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2F");

  SA_DBG3(("mpiSASDiagStartEndRsp: HTAG=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSASDiagStartEndRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &Status, pIomb, OSSA_OFFSET_OF(agsaSASDiagStartEndRsp_t, Status));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSASDiagStartEndRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, Status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2F");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  switch(Status)
  {

    case OSSA_DIAG_SE_SUCCESS:
      SA_DBG3(("mpiSASDiagStartEndRsp: Status OSSA_DIAG_SE_SUCCESS 0x%X \n", Status));
      break;
    case OSSA_DIAG_SE_INVALID_PHY_ID:
      SA_DBG1(("mpiSASDiagStartEndRsp: Status OSSA_DIAG_SE_INVALID_PHY_ID 0x%X \n", Status));
      break;
    case OSSA_DIAG_PHY_NOT_DISABLED:
      SA_DBG1(("mpiSASDiagStartEndRsp: Status OSSA_DIAG_PHY_NOT_DISABLED Status 0x%X \n", Status));
      break;
    case OSSA_DIAG_OTHER_FAILURE:
      if(smIS_SPCV(agRoot))
      {
        SA_DBG1(("mpiSASDiagStartEndRsp: Status OSSA_DIAG_OTHER_FAILURE Status 0x%X \n", Status));
      }
      else
      {
        SA_DBG1(("mpiSASDiagStartEndRsp: Status OSSA_DIAG_OPCODE_INVALID Status 0x%X \n", Status));
      }
      break;
    default:
      SA_DBG1(("mpiSASDiagStartEndRsp:Status UNKNOWN 0x%X \n", Status));
      break;
  }

  ossaSASDiagStartEndCB(agRoot, agContext, Status);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSASDiagStartEndRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2F");
  return ret;
}

/******************************************************************************/
/*! \brief SAS Diagnostic Execute Response
 *
 *  This routine handles the response of SAS Diagnostic Execute Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSASDiagExecuteRsp(
  agsaRoot_t               *agRoot,
  agsaSASDiagExecuteRsp_t  *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag, Status, CmdTypeDescPhyId, ReportData;
  smTraceFuncEnter(hpDBG_VERY_LOUD,"3G");

  SA_DBG3(("mpiSASDiagExecuteRsp: HTAG=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSASDiagExecuteRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &Status, pIomb, OSSA_OFFSET_OF(agsaSASDiagExecuteRsp_t, Status));
  OSSA_READ_LE_32(AGROOT, &CmdTypeDescPhyId, pIomb, OSSA_OFFSET_OF(agsaSASDiagExecuteRsp_t, CmdTypeDescPhyId));
  OSSA_READ_LE_32(AGROOT, &ReportData, pIomb, OSSA_OFFSET_OF(agsaSASDiagExecuteRsp_t, ReportData));
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSASDiagExecuteRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x STATUS=0x%x\n", tag, Status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3G");
    return AGSA_RC_FAILURE;
  }

  switch(Status)
  {

    case OSSA_DIAG_SUCCESS:
      SA_DBG3(("mpiSASDiagExecuteRsp: Status OSSA_DIAG_SUCCESS 0x%X \n", Status));
      break;
    case OSSA_DIAG_INVALID_COMMAND:
      if(smIS_SPCV(agRoot))
      {
        SA_DBG1(("mpiSASDiagExecuteRsp: Status OSSA_DIAG_INVALID_COMMAND Status 0x%X \n", Status));
      }
      else
      {
        SA_DBG1(("mpiSASDiagExecuteRsp: Status OSSA_DIAG_FAIL Status 0x%X \n", Status));
      }
      break;
    case OSSA_REGISTER_ACCESS_TIMEOUT:
      SA_DBG1(("mpiSASDiagExecuteRsp: Status OSSA_REGISTER_ACCESS_TIMEOUT Status 0x%X \n", Status));
      break;
    case OSSA_DIAG_NOT_IN_DIAGNOSTIC_MODE:
      SA_DBG1(("mpiSASDiagExecuteRsp: Status OSSA_DIAG_NOT_IN_DIAGNOSTIC_MODE Status 0x%X \n", Status));
      break;
    case OSSA_DIAG_INVALID_PHY:
      SA_DBG1(("mpiSASDiagExecuteRsp: Status OSSA_DIAG_INVALID_PHY Status 0x%X \n", Status));
      break;
    case OSSA_MEMORY_ALLOC_FAILURE:
      SA_DBG1(("mpiSASDiagExecuteRsp: Status  Status 0x%X \n", Status));
      break;

    default:
      SA_DBG1(("mpiSASDiagExecuteRsp:Status UNKNOWN 0x%X \n", Status));
      break;
  }


  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  ossaSASDiagExecuteCB(agRoot, agContext, Status, CmdTypeDescPhyId, ReportData);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSASDiagExecuteRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3G");

  /* return value */
  return ret;
}

/******************************************************************************/
/*! \brief SAS General Event Notification Response
 *
 *  This routine handles the response of Inbound IOMB Command with error case
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGeneralEventRsp(
  agsaRoot_t               *agRoot,
  agsaGeneralEventRsp_t    *pIomb
  )
{
  bit32                 ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  bit32                 i;
  bit32                 status;
  bit32                 tag;
  agsaIORequestDesc_t   *pRequest;
  agsaDeviceDesc_t      *pDevice;
  agsaContext_t         *agContext = NULL;
  agsaGeneralEventRsp_t GenEventData;
  agsaHWEventEncrypt_t  agEvent;
  bit16                 OpCode = 0;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3H");

  si_memset(&GenEventData,0,sizeof(agsaGeneralEventRsp_t));

  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaGeneralEventRsp_t, status));

  SA_DBG3(("mpiGeneralEventRsp:  %p\n", pIomb));

  SA_DBG1(("mpiGeneralEventRsp: OpCode 0x%X status 0x%x\n",pIomb->inbIOMBpayload[0] & OPCODE_BITS, status));

  for (i = 0; i < GENERAL_EVENT_PAYLOAD; i++)
  {
    OSSA_READ_LE_32(AGROOT, &GenEventData.inbIOMBpayload[i], pIomb, OSSA_OFFSET_OF(agsaGeneralEventRsp_t,inbIOMBpayload[i] ));
  }
  SA_DBG1(("mpiGeneralEventRsp: inbIOMBpayload 0x%08x 0x%08x 0x%08x 0x%08x\n",
                                    GenEventData.inbIOMBpayload[0],GenEventData.inbIOMBpayload[1],
                                    GenEventData.inbIOMBpayload[2],GenEventData.inbIOMBpayload[3] ));
  SA_DBG1(("mpiGeneralEventRsp: inbIOMBpayload 0x%08x 0x%08x 0x%08x 0x%08x\n",
                                    GenEventData.inbIOMBpayload[4],GenEventData.inbIOMBpayload[8],
                                    GenEventData.inbIOMBpayload[6],GenEventData.inbIOMBpayload[7] ));

  switch (status) /*status  */
  {

    case GEN_EVENT_IOMB_V_BIT_NOT_SET:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_IOMB_V_BIT_NOT_SET\n" ));
      break;
    case GEN_EVENT_INBOUND_IOMB_OPC_NOT_SUPPORTED:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_INBOUND_IOMB_OPC_NOT_SUPPORTED\n" ));
      break;
    case GEN_EVENT_IOMB_INVALID_OBID:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_IOMB_INVALID_OBID\n" ));
      break;
    case GEN_EVENT_DS_IN_NON_OPERATIONAL:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_DS_IN_NON_OPERATIONAL\n" ));
      break;
    case GEN_EVENT_DS_IN_RECOVERY:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_DS_IN_RECOVERY\n" ));
      break;
    case GEN_EVENT_DS_INVALID:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_DS_INVALID\n" ));
      break;
    case GEN_EVENT_IO_XFER_READ_COMPL_ERR:
      SA_DBG1(("mpiGeneralEventRsp: GEN_EVENT_IO_XFER_READ_COMPL_ERR 0x%x 0x%x 0x%x\n",
                GenEventData.inbIOMBpayload[0],
                GenEventData.inbIOMBpayload[1],
                GenEventData.inbIOMBpayload[1] ));
      ossaGeneralEvent(agRoot, status, agContext, GenEventData.inbIOMBpayload);
      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3H");
      return(ret);
    default:
      SA_DBG1(("mpiGeneralEventRsp: Unknown General Event status!!! 0x%x\n", status));
      smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3H");
      return AGSA_RC_FAILURE;
  }

  OpCode = (bit16)(GenEventData.inbIOMBpayload[0] & OPCODE_BITS);
  tag = GenEventData.inbIOMBpayload[1];
  SA_DBG1(("mpiGeneralEventRsp:OpCode 0x%X [0] 0x%08x\n" ,OpCode,(bit16)(GenEventData.inbIOMBpayload[0] & OPCODE_BITS)));

  switch (OpCode) /* OpCode */
    {
      case OPC_INB_DEV_HANDLE_ACCEPT:
      case OPC_INB_ECHO:
      case OPC_INB_FW_FLASH_UPDATE:
      case OPC_INB_GET_NVMD_DATA:
      case OPC_INB_SET_NVMD_DATA:
      case OPC_INB_DEREG_DEV_HANDLE:
      case OPC_INB_SPC_GET_DEV_INFO:
      case OPC_INB_GET_DEV_HANDLE:
      case OPC_INB_SPC_REG_DEV:
      case OPC_INB_SAS_DIAG_EXECUTE:
      case OPC_INB_SAS_DIAG_MODE_START_END:
      case OPC_INB_PHYSTART:
      case OPC_INB_PHYSTOP:
      case OPC_INB_LOCAL_PHY_CONTROL:
      case OPC_INB_GPIO:
      case OPC_INB_GET_TIME_STAMP:
      case OPC_INB_PORT_CONTROL:
      case OPC_INB_SET_DEVICE_STATE:
      case OPC_INB_GET_DEVICE_STATE:
      case OPC_INB_SET_DEV_INFO:
//      case OPC_INB_PCIE_DIAG_EXECUTE:
      case OPC_INB_SAS_HW_EVENT_ACK:
      case OPC_INB_SAS_RE_INITIALIZE:
      case OPC_INB_KEK_MANAGEMENT:
      case OPC_INB_SET_OPERATOR:
      case OPC_INB_GET_OPERATOR:
//      case OPC_INB_SGPIO:

#ifdef SPC_ENABLE_PROFILE
      case OPC_INB_FW_PROFILE:
#endif
          /* Uses the tag table, so we have to free it up */

          SA_ASSERT((tag < AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs),
                    "OPC_OUB_GENERAL_EVENT tag out of range");
          SA_ASSERT((saRoot->IOMap[ tag < (AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs) ? tag : 0 ].Tag != MARK_OFF),
                    "OPC_OUB_GENERAL_EVENT tag not in use 1");

#if defined(SALLSDK_DEBUG)
          if (tag > AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs)
          {
            smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "3H");
            return AGSA_RC_FAILURE;
          }
#endif /* SALLSDK_DEBUG */

          SA_DBG1(("mpiGeneralEventRsp:OpCode found 0x%x htag 0x%x\n",OpCode, tag));
          /* get agContext */
          agContext = saRoot->IOMap[tag].agContext;
          /* get request from IOMap */
          pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
          if(pRequest)
          {
            /* remove the request from IOMap */
            saRoot->IOMap[tag].Tag = MARK_OFF;
            saRoot->IOMap[tag].IORequest = agNULL;
            saRoot->IOMap[tag].agContext = agNULL;

            ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
            SA_ASSERT((pRequest->valid), "pRequest->valid");
            pRequest->valid = agFALSE;
            /* return the request to free pool */
            if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
            {
              SA_DBG1(("mpiGeneralEventRsp: 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);
          }
          else
          {
            SA_DBG1(("mpiGeneralEventRsp:pRequest (%p) NULL\n", pRequest));
            ret =  AGSA_RC_FAILURE;
          }
          break;
      /* ????  */
      case OPC_INB_SATA_HOST_OPSTART:
      case OPC_INB_SATA_ABORT:
      case OPC_INB_SSPINIIOSTART:
      case OPC_INB_SSPINITMSTART:
      case OPC_INB_SSPINIEXTIOSTART:
      case OPC_INB_SSPTGTIOSTART:
      case OPC_INB_SSPTGTRSPSTART:
      case OPC_INB_SSP_DIF_ENC_OPSTART:
      case OPC_INB_SATA_DIF_ENC_OPSTART:

      case OPC_INB_SSP_ABORT:
      case OPC_INB_SMP_REQUEST:
      case OPC_INB_SMP_ABORT:
      {
        /* Uses the tag table, so we have to free it up */
        SA_DBG1(("mpiGeneralEventRsp:OpCode found 0x%x htag 0x%x\n",OpCode, tag));

        tag = GenEventData.inbIOMBpayload[1];

        SA_ASSERT((tag < AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs),
                  "OPC_OUB_GENERAL_EVENT tag out of range");
        SA_ASSERT((saRoot->IOMap[ tag < (AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs) ? tag : 0 ].Tag != MARK_OFF),
                  "OPC_OUB_GENERAL_EVENT tag not in use 2");
#if defined(SALLSDK_DEBUG)
        if (tag > AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs)
        {
          smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "3H");
          return AGSA_RC_FAILURE;
        }
#endif
          /* get request from IOMap */
        pRequest  = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
        if(pRequest)
        {
          pDevice   = pRequest->pDevice;
          /* return the request to free pool */
          /* get IORequestContext */
          agContext = (agsaContext_t *)pRequest->pIORequestContext;
          /* remove the request from IOMap */
          saRoot->IOMap[tag].Tag = MARK_OFF;
          saRoot->IOMap[tag].IORequest = agNULL;
          saRoot->IOMap[tag].agContext = agNULL;

          ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
          SA_ASSERT((pRequest->valid), "pRequest->valid");
          pRequest->valid = agFALSE;
          saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
          if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
          {
            SA_DBG1(("mpiGeneralEventRsp: 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);
          break;
        }
        else
        {
          SA_DBG1(("mpiGeneralEventRsp:pRequest (%p) NULL\n", pRequest));
          ret =  AGSA_RC_FAILURE;
        }
      }
    default:
    {
        SA_DBG1(("mpiGeneralEventRsp:OpCode Not found 0x%x htag 0x%x\n",OpCode, tag));
        ret =  AGSA_RC_FAILURE;

        /* Uses the tag table, so we have to free it up */
        tag = GenEventData.inbIOMBpayload[1];

        SA_ASSERT((tag < AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs),
                  "OPC_OUB_GENERAL_EVENT tag out of range");
        SA_ASSERT((saRoot->IOMap[ tag < (AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs) ? tag : 0 ].Tag != MARK_OFF),
                  "OPC_OUB_GENERAL_EVENT tag not in use 3");

#if defined(SALLSDK_DEBUG)
        if (tag > AGSA_MAX_VALID_PORTS * saRoot->swConfig.maxActiveIOs)
        {
          smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "3H");
          return AGSA_RC_FAILURE;
        }
#endif
        /* get agContext */
        agContext = saRoot->IOMap[tag].agContext;
        /* get request from IOMap */
        pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
        if (pRequest == agNULL)
        {
          smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "3H");
          return AGSA_RC_FAILURE;
        }

        /* remove the request from IOMap */
        saRoot->IOMap[tag].Tag = MARK_OFF;
        saRoot->IOMap[tag].IORequest = agNULL;
        saRoot->IOMap[tag].agContext = agNULL;

        ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
        SA_ASSERT((pRequest->valid), "pRequest->valid");
        pRequest->valid = agFALSE;
        /* return the request to free pool */
        if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
        {
          SA_DBG1(("mpiGeneralEventRsp: 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);
        break;
      }
      ret =  AGSA_RC_FAILURE;

    }

  switch (OpCode) /* OpCode */
  {

    case OPC_INB_KEK_MANAGEMENT:
    {  
      bit32 flags = GenEventData.inbIOMBpayload[2];

      SA_DBG1(("mpiGeneralEventRsp: OPC_INB_KEK_MANAGEMENT 0x%x htag 0x%x flags 0x%x\n",OpCode, tag, flags));
      if (flags & 0xFF00) /* update and store*/
      {
        agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE;
        SA_DBG1(("mpiGeneralEventRsp: OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE\n"));
      }
      else /* update */
      {
        agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_UPDATE;
        SA_DBG1(("mpiGeneralEventRsp: OSSA_HW_ENCRYPT_KEK_UPDATE\n"));
      }
      agEvent.status = OSSA_INVALID_ENCRYPTION_SECURITY_MODE;
      si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
      agEvent.status = status;

      SA_DBG1(("mpiGeneralEventRsp: ossaHwCB OSSA_HW_EVENT_ENCRYPTION\n" ));
      ossaHwCB(agRoot, NULL, OSSA_HW_EVENT_ENCRYPTION, 0, (void*)&agEvent, agContext);
      break;
    }
    case OPC_INB_OPR_MGMT:
         si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
         agEvent.status = status;
         agEvent.encryptOperation = OSSA_HW_ENCRYPT_OPERATOR_MANAGEMENT;

         SA_DBG1(("mpiGeneralEventRsp: OSSA_HW_ENCRYPT_OPERATOR_MANAGEMENT\n" ));
         ossaOperatorManagementCB(agRoot, agContext, status, 0);
         break;
    case OPC_INB_SET_OPERATOR:
         SA_DBG1(("mpiGeneralEventRsp: OSSA_HW_ENCRYPT_SET_OPERATOR\n" ));
         ossaSetOperatorCB(agRoot,agContext,0xFF,0xFF );
         break;
    case OPC_INB_GET_OPERATOR:
         SA_DBG1(("mpiGeneralEventRsp: OSSA_HW_ENCRYPT_GET_OPERATOR\n" ));
         ossaGetOperatorCB(agRoot,agContext,0xFF,0xFF,0xFF,0xFF,agNULL );
         break;
    case OPC_INB_ENC_TEST_EXECUTE:
         si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
         agEvent.status = status;
         agEvent.encryptOperation = OSSA_HW_ENCRYPT_TEST_EXECUTE;

         SA_DBG1(("mpiGeneralEventRsp: OSSA_HW_ENCRYPT_TEST_EXECUTE\n" ));
         ossaHwCB(agRoot, NULL, OSSA_HW_EVENT_ENCRYPTION, 0, (void*)&agEvent, agContext);
         break;
    default:
         SA_DBG1(("mpiGeneralEventRsp: MGMNT OpCode Not found 0x%x\n",OpCode ));
         ossaGeneralEvent(agRoot, status, agContext, GenEventData.inbIOMBpayload);
         break;
  }

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "3H");
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SSP Request Received Event (target mode)
 *
 *  This function handles the SSP Request Received Event.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pMsg1        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSSPReqReceivedNotify(
  agsaRoot_t *agRoot,
  agsaSSPReqReceivedNotify_t *pMsg1)
{
  bit32            ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t     *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaDeviceDesc_t *pDevice;
  bit32            deviceid, iniTagSSPIul, frameTypeHssa, TlrHdsa;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3J");
  /* convert endiness if necassary */
  OSSA_READ_LE_32(AGROOT, &deviceid, pMsg1, OSSA_OFFSET_OF(agsaSSPReqReceivedNotify_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &iniTagSSPIul, pMsg1, OSSA_OFFSET_OF(agsaSSPReqReceivedNotify_t, iniTagSSPIul));
  OSSA_READ_LE_32(AGROOT, &frameTypeHssa, pMsg1, OSSA_OFFSET_OF(agsaSSPReqReceivedNotify_t, frameTypeHssa));
  OSSA_READ_LE_32(AGROOT, &TlrHdsa, pMsg1, OSSA_OFFSET_OF(agsaSSPReqReceivedNotify_t, TlrHdsa));
  /* deviceId -> agDeviceHandle */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle;

  if (agNULL == pDevice)
  {
    SA_DBG1(("mpiSSPReqReceivedNotify: warning!!! no deviceHandle is found"));
  }
  else
  {
    /* type punning only safe through char *. See gcc -fstrict_aliasing. */
    char * safe_type_pun = (char *)&(pMsg1->SSPIu[0]);
    if( pDevice->initiatorDevHandle.sdkData != agNULL)
    {
      ossaSSPReqReceived(agRoot, &(pDevice->initiatorDevHandle),
                        (agsaFrameHandle_t *)safe_type_pun,
                        (bit16)((iniTagSSPIul >> SHIFT16) & INITTAG_BITS),
                        ((frameTypeHssa >> SHIFT24) & FRAME_TYPE) |
                       ((TlrHdsa >> SHIFT16) & TLR_BITS),
                        (iniTagSSPIul & SSPIUL_BITS));
    }else if( pDevice->targetDevHandle.sdkData != agNULL)
    {
      ossaSSPReqReceived(agRoot, &(pDevice->targetDevHandle),
                        (agsaFrameHandle_t *)safe_type_pun,
                        (bit16)((iniTagSSPIul >> SHIFT16) & INITTAG_BITS),
                        ((frameTypeHssa >> SHIFT24) & FRAME_TYPE) |
                       ((TlrHdsa >> SHIFT16) & TLR_BITS),
                        (iniTagSSPIul & SSPIUL_BITS));
    }else
    {
      SA_ASSERT(0, "Device handle sdkData not set");
    }
  }

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

/******************************************************************************/
/*! \brief SPC MPI Device Handle Arrived Event (target mode)
 *
 *  This function handles the Device Handle Arrived Event.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pMsg1        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiDeviceHandleArrived(
  agsaRoot_t *agRoot,
  agsaDeviceHandleArrivedNotify_t *pMsg1)
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaDeviceDesc_t    *pDevice;
  agsaPort_t          *pPort;
  agsaSASDeviceInfo_t pDeviceInfo;
  agsaPortContext_t   *agPortContext;
  agsaSASIdentify_t   remoteIdentify;
  bit32               CTag;
  bit32               FwdDeviceId;
  bit32               ProtConrPortId;
  bit32               portId;
  bit32               conRate;
  bit8                i, protocol, dTypeSRate;
  bit32               HostAssignedId;

  if(saRoot == agNULL)
  {
    SA_ASSERT((saRoot != agNULL), "saRoot");
    return AGSA_RC_FAILURE;
  }

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3L");
  /* convert endiness if necassary */
  OSSA_READ_LE_32(AGROOT, &CTag, pMsg1, OSSA_OFFSET_OF(agsaDeviceHandleArrivedNotify_t, CTag));
  OSSA_READ_LE_32(AGROOT, &FwdDeviceId, pMsg1, OSSA_OFFSET_OF(agsaDeviceHandleArrivedNotify_t, HostAssignedIdFwdDeviceId));
  OSSA_READ_LE_32(AGROOT, &ProtConrPortId, pMsg1, OSSA_OFFSET_OF(agsaDeviceHandleArrivedNotify_t, ProtConrPortId));


  if(smIS_SPCV(agRoot))
  {
    portId = ProtConrPortId & PortId_V_MASK;
    conRate = (ProtConrPortId & Conrate_V_MASK ) >> Conrate_V_SHIFT;

    HostAssignedId = (FwdDeviceId & 0xFFFF0000) >> SHIFT16;
    if(HostAssignedId)
    {
      SA_DBG1(("mpiDeviceHandleArrived: HostAssignedId 0x%X\n",HostAssignedId));
    }
  }
  else
  {
    portId = ProtConrPortId & PortId_SPC_MASK;
    conRate = (ProtConrPortId & Conrate_SPC_MASK ) >> Conrate_SPC_SHIFT;
  }
  protocol =(bit8)((ProtConrPortId & PROTOCOL_BITS ) >> PROTOCOL_SHIFT);

  SA_DBG1(("mpiDeviceHandleArrived: New Port portID %d deviceid 0x%X conRate 0x%X protocol 0x%X\n",portId, FwdDeviceId,conRate,protocol));

  /* Port Map */
  agPortContext = saRoot->PortMap[portId].PortContext;
  if (agNULL == agPortContext)
  {
    ossaSingleThreadedEnter(agRoot, LL_PORT_LOCK);
    /* new port */
    /* Acquire port list lock */
    /* Allocate a free port */
    pPort = (agsaPort_t *) saLlistGetHead(&(saRoot->freePorts));
    if (agNULL != pPort)
    {
      saLlistRemove(&(saRoot->freePorts), &(pPort->linkNode));

      /* setup the port data structure */
      pPort->portContext.osData = agNULL;
      pPort->portContext.sdkData = pPort;
      pPort->tobedeleted = agFALSE;
      /* Add to valid port list */
      saLlistAdd(&(saRoot->validPorts), &(pPort->linkNode));
      /* Release port list lock */
      ossaSingleThreadedLeave(agRoot, LL_PORT_LOCK);

      /* Setup portMap based on portId */
      saRoot->PortMap[portId].PortID = portId;
      saRoot->PortMap[portId].PortContext = &(pPort->portContext);
      saRoot->PortMap[portId].PortStatus  &= ~PORT_INVALIDATING;
      pPort->portId = portId;

      pPort->status &= ~PORT_INVALIDATING;
      SA_DBG3(("mpiDeviceHandleArrived: ~PORT_INVALIDATING New Port portID %d PortContext %p\n",saRoot->PortMap[pPort->portId].PortID , &pPort->portContext));
    }
    else
    {
      ossaSingleThreadedLeave(agRoot, LL_PORT_LOCK);
      SA_DBG2(("mpiDeviceHandleArrived:Port NULL\n"));
      /* pPort is agNULL*/
      smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3L");
      return AGSA_RC_FAILURE;
    }
  }
  else
  {
    /* exist port */
    pPort = (agsaPort_t *) (agPortContext->sdkData);
    pPort->status &= ~PORT_INVALIDATING;
    pPort->portId =portId;
    saRoot->PortMap[pPort->portId].PortStatus  &= ~PORT_INVALIDATING;

    SA_DBG1(("mpiDeviceHandleArrived: ~PORT_INVALIDATING Old port portID %d PortContext %p\n", portId, &pPort->portContext));

  }
  /* build Device Information structure */
  si_memset(&pDeviceInfo, 0, sizeof(agsaSASDeviceInfo_t));
  if (ProtConrPortId & PROTOCOL_BITS)
  {
    protocol = SA_IDFRM_SSP_BIT; /* SSP */
    pDeviceInfo.commonDevInfo.devType_S_Rate = (bit8)(conRate | 0x10);

  }
  else
  {
    protocol = SA_IDFRM_SMP_BIT; /* SMP */
    pDeviceInfo.commonDevInfo.devType_S_Rate = (bit8)conRate;
  }
  pDeviceInfo.initiator_ssp_stp_smp = protocol;
  pDeviceInfo.numOfPhys = 1;
  pDeviceInfo.commonDevInfo.sasAddressHi[0] = pMsg1->sasAddrHi[0];
  pDeviceInfo.commonDevInfo.sasAddressHi[1] = pMsg1->sasAddrHi[1];
  pDeviceInfo.commonDevInfo.sasAddressHi[2] = pMsg1->sasAddrHi[2];
  pDeviceInfo.commonDevInfo.sasAddressHi[3] = pMsg1->sasAddrHi[3];
  pDeviceInfo.commonDevInfo.sasAddressLo[0] = pMsg1->sasAddrLow[0];
  pDeviceInfo.commonDevInfo.sasAddressLo[1] = pMsg1->sasAddrLow[1];
  pDeviceInfo.commonDevInfo.sasAddressLo[2] = pMsg1->sasAddrLow[2];
  pDeviceInfo.commonDevInfo.sasAddressLo[3] = pMsg1->sasAddrLow[3];
  pDeviceInfo.commonDevInfo.flag = 0;
  pDeviceInfo.commonDevInfo.it_NexusTimeout = ITL_TO_DEFAULT;

  /* deviceId -> agDeviceHandle */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[FwdDeviceId & DEVICE_ID_BITS].DeviceHandle;

  if (agNULL == pDevice)
  {
    /* new device */
    si_memset(&remoteIdentify, 0, sizeof(agsaSASIdentify_t));
    for (i=0;i<4;i++)
    {
      remoteIdentify.sasAddressHi[i] = pMsg1->sasAddrHi[i];
      remoteIdentify.sasAddressLo[i] = pMsg1->sasAddrLow[i];
    }
    remoteIdentify.deviceType_addressFrameType = (bit8)(pDeviceInfo.commonDevInfo.devType_S_Rate & 0xC0);
    dTypeSRate = pDeviceInfo.commonDevInfo.devType_S_Rate;
    /* get Device from free Device List */
    pDevice = siPortSASDeviceAdd(agRoot, pPort, remoteIdentify, agTRUE, SMP_TO_DEFAULT, ITL_TO_DEFAULT, 0, dTypeSRate, 0);
    if (agNULL == pDevice)
    {
      SA_DBG1(("mpiDeviceHandleArrived: Device Handle is NULL, Out of Resources Error.\n"));
    }
    else
    {
      bit32 AccStatus = 0;
      bit32 SaveId = FwdDeviceId & 0xFFFF;
      /* mapping the device handle and device id */
      saRoot->DeviceMap[FwdDeviceId & DEVICE_ID_BITS].DeviceIdFromFW = FwdDeviceId;
      saRoot->DeviceMap[FwdDeviceId & DEVICE_ID_BITS].DeviceHandle = (void *)pDevice;
      pDevice->DeviceMapIndex = FwdDeviceId;
      SA_DBG2(("mpiDeviceHandleArrived: New deviceID 0x%x Device Context %p DeviceTypeSRate 0x%x\n", FwdDeviceId, pDevice, dTypeSRate));

      /* Call Back */
      AccStatus = ossaDeviceHandleAccept(agRoot, &(pDevice->initiatorDevHandle), &pDeviceInfo, agPortContext,&FwdDeviceId );

      HostAssignedId = (FwdDeviceId & 0xFFFF0000) >> SHIFT16;
      if(HostAssignedId)
      {
        if( SaveId == (FwdDeviceId & 0xFFFF)  )
        {

          saRoot->DeviceMap[FwdDeviceId & DEVICE_ID_BITS].DeviceIdFromFW = FwdDeviceId;
          pDevice->DeviceMapIndex = FwdDeviceId;

          SA_DBG1(("mpiDeviceHandleArrived:FwdDeviceId 0x%x HostAssignedId 0x%x\n",FwdDeviceId,HostAssignedId));
        }
        else
        {
          SA_DBG1(("mpiDeviceHandleArrived:Id mangled expect 0x%x Got 0x%x\n",SaveId, (FwdDeviceId & 0xFFFF)));
          ret = AGSA_RC_FAILURE;
        }
      }

      /* get AWT flag and ITLN_TMO value */

      if(AccStatus == OSSA_RC_ACCEPT )
      {
        /* build DEVICE_HANDLE_ACCEPT IOMB and send to SPC with action=accept */
        mpiDevHandleAcceptCmd(agRoot, agNULL, CTag, FwdDeviceId, 0, pDeviceInfo.commonDevInfo.flag, pDeviceInfo.commonDevInfo.it_NexusTimeout, 0);
      }
      else
      {
        mpiDevHandleAcceptCmd(agRoot, agNULL, CTag, FwdDeviceId, 1, pDeviceInfo.commonDevInfo.flag, pDeviceInfo.commonDevInfo.it_NexusTimeout, 0);
      }
    }
  }

  SA_DBG1(("mpiDeviceHandleArrived Device 0x%08X flag 0x%08X %s WWID= %02x%02x%02x%02x:%02x%02x%02x%02x, %s\n",
    FwdDeviceId,
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.flag,
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x20 ? "SATA DA" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x10 ? "SSP/SMP" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF0) == 0x0 ? "  STP  " : "Unknown",

    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[3],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[2],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[1],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressHi[0],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[3],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[2],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[1],
    pDevice->devInfo.sasDeviceInfo.commonDevInfo.sasAddressLo[0],

    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 8  ? " 1.5G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 9  ? " 3.0G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 10 ? " 6.0G" :
    (pDevice->devInfo.sasDeviceInfo.commonDevInfo.devType_S_Rate & 0xF) == 11 ? "12.0G" : "????" ));

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3L");
  return ret;
}

/******************************************************************************/
/*! \brief Get Time Stamp Response
 *
 *  This routine handles the response of Get Time Stamp Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetTimeStampRsp(
  agsaRoot_t               *agRoot,
  agsaGetTimeStampRsp_t    *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag, timeStampLower, timeStampUpper;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3M");

  SA_DBG3(("mpiGetTimeStampRsp: HTAG=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetTimeStampRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &timeStampLower, pIomb, OSSA_OFFSET_OF(agsaGetTimeStampRsp_t, timeStampLower));
  OSSA_READ_LE_32(AGROOT, &timeStampUpper, pIomb, OSSA_OFFSET_OF(agsaGetTimeStampRsp_t, timeStampUpper));
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetTimeStampRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x\n", tag));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3M");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  SA_DBG3(("mpiGetTimeStampRsp: timeStampLower 0x%x timeStampUpper 0x%x\n", timeStampLower, timeStampUpper));

  ossaGetTimeStampCB(agRoot, agContext, timeStampLower, timeStampUpper);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetTimeStampRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3M");
  return ret;
}

/******************************************************************************/
/*! \brief SAS HW Event Ack Response
 *
 *  This routine handles the response of SAS HW Event Ack Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSASHwEventAckRsp(
  agsaRoot_t               *agRoot,
  agsaSASHwEventAckRsp_t   *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  agsaPort_t          *pPort;
  bit32               tag, status;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2N");

  SA_DBG2(("mpiSASHwEventAckRsp: Htag=0x%x %p\n", pIomb->tag,pIomb));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSASHwEventAckRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSASHwEventAckRsp_t, status));
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSASHwEventAckRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x Status=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2N");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;
  SA_ASSERT((pRequest->valid), "pRequest->valid");

  SA_DBG1(("mpiSASHwEventAckRsp: status 0x%x Htag=0x%x HwAckType=0x%x\n",status,pIomb->tag,pRequest->HwAckType ));

  ossaHwEventAckCB(agRoot, agContext, status);

  pPort = pRequest->pPort;
  if (agNULL != pPort)
  {
    SA_DBG1(("mpiSASHwEventAckRsp: pPort %p tobedeleted %d\n", pPort, pPort->tobedeleted));
    if (pPort->status & PORT_INVALIDATING &&  pPort->tobedeleted )
    {
      SA_DBG1(("mpiSASHwEventAckRsp: PORT_INVALIDATING portInvalid portID %d pPort %p, nulling out PortContext\n", pPort->portId, pPort));
      /* invalid the port */
      siPortInvalid(agRoot, pPort);
      /* map out the portmap */
      saRoot->PortMap[pPort->portId].PortContext = agNULL;
      saRoot->PortMap[pPort->portId].PortID = PORT_MARK_OFF;
      saRoot->PortMap[pPort->portId].PortStatus  |= PORT_INVALIDATING;
    }
    else
    {
      SA_DBG1(("mpiSASHwEventAckRsp:pPort->status 0x%x Htag=0x%x %p\n",pPort->status, pIomb->tag,pIomb));
    }
  }
  else
  {
    SA_DBG1(("mpiSASHwEventAckRsp: pPort is NULL, no portId, HTag=0x%x\n", tag));
  }

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSASHwEventAckRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2N");
  return ret;
}

/******************************************************************************/
/*! \brief Port Control Response
 *
 *  This routine handles the response of SAS HW Event Ack Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiPortControlRsp(
  agsaRoot_t           *agRoot,
  agsaPortControlRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest = agNULL;
  agsaContext_t       *agContext = agNULL;
  agsaPortContext_t   *agPortContext = agNULL;
  bit32               tag;
  bit32               port =0;
  bit32               operation =0;
  bit32               status =0;
  bit32               portState =0;
  bit32               portOperation =0;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3O");

  SA_DBG2(("mpiPortControlRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaPortControlRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &operation, pIomb, OSSA_OFFSET_OF(agsaPortControlRsp_t, portOPPortId));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaPortControlRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &portState, pIomb, OSSA_OFFSET_OF(agsaPortControlRsp_t,rsvdPortState ));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiPortControlRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x Status=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3O");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  if(!pRequest->valid)
  {
    SA_DBG1(("mpiPortControlRsp: pRequest->valid %d not set\n", pRequest->valid));
  }

  SA_DBG2(("mpiPortControlRsp: pRequest->completionCB %p\n", pRequest->completionCB));

  port = operation & PORTID_MASK;

  if(port < AGSA_MAX_VALID_PORTS )
  {
    SA_DBG2(("mpiPortControlRsp: PortID 0x%x PortStatus 0x%x PortContext %p\n",
           saRoot->PortMap[port].PortID,
           saRoot->PortMap[port].PortStatus,
           saRoot->PortMap[port].PortContext));

    agPortContext = (agsaPortContext_t *)saRoot->PortMap[port].PortContext;
  }
  SA_DBG2(("mpiPortControlRsp: PortID 0x%x PortStatus 0x%x PortContext %p\n",saRoot->PortMap[operation & PORTID_MASK].PortID,saRoot->PortMap[operation & PORTID_MASK].PortStatus,saRoot->PortMap[operation & PORTID_MASK].PortContext));
  agPortContext = (agsaPortContext_t *)saRoot->PortMap[operation & PORTID_MASK].PortContext;
  SA_DBG1(("mpiPortControlRsp: agPortContext %p\n",agPortContext ));


  SA_DBG2(("mpiPortControlRsp: portID 0x%x status 0x%x\n", (operation & PORTID_MASK), status));

  SA_DBG1(("mpiPortControlRsp: portID 0x%x status 0x%x agPortContext %p\n",port, status,agPortContext));

  portOperation = (((operation & LOCAL_PHY_OP_BITS) >> SHIFT8) | (portState << SHIFT28) );

  SA_DBG1(("mpiPortControlRsp: portState 0x%x operation 0x%x portOperation 0x%x\n",portState, operation,portOperation ));

  switch(portOperation)
  {
    case AGSA_PORT_SET_SMP_PHY_WIDTH:
      SA_DBG1(("mpiPortControlRsp: AGSA_PORT_SET_SMP_PHY_WIDTH  operation 0x%x\n",operation ));
      break;
    case AGSA_PORT_SET_PORT_RECOVERY_TIME:
      SA_DBG1(("mpiPortControlRsp: AGSA_PORT_SET_PORT_RECOVERY_TIME  operation 0x%x\n",operation ));
      break;
    case AGSA_PORT_IO_ABORT:
      SA_DBG1(("mpiPortControlRsp: AGSA_PORT_IO_ABORT  operation 0x%x\n",operation ));
      break;
    case AGSA_PORT_SET_PORT_RESET_TIME:
      SA_DBG1(("mpiPortControlRsp: AGSA_PORT_SET_PORT_RESET_TIME  operation 0x%x\n",operation ));
      break;
    case AGSA_PORT_HARD_RESET:
      SA_DBG1(("mpiPortControlRsp: AGSA_PORT_HARD_RESET  operation 0x%x\n",operation ));
      break;
    case AGSA_PORT_CLEAN_UP:
      SA_DBG1(("mpiPortControlRsp: AGSA_PORT_CLEAN_UP  operation 0x%x\n",operation ));
      break;
    case AGSA_STOP_PORT_RECOVERY_TIMER:
      SA_DBG1(("mpiPortControlRsp: AGSA_STOP_PORT_RECOVERY_TIMER  operation 0x%x\n",operation ));
      break;
    default:
    {
      SA_DBG1(("mpiPortControlRsp: Unknown  operation 0x%x\n",operation ));
    }
  }

  ossaPortControlCB(agRoot, agContext, agPortContext, portOperation, status);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiPortControlRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3O");
  /* return value */
  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI SMP ABORT Response
 *
 *  This function handles the SMP Abort Response.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSMPAbortRsp(
  agsaRoot_t         *agRoot,
  agsaSMPAbortRsp_t  *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDeviceDesc_t    *pDevice;
  bit32               tag, scp, status;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3P");

  SA_DBG3(("mpiSMPAbortRsp: HTag=0x%x Status=0x%x\n", pIomb->tag, pIomb->status));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSMPAbortRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSMPAbortRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &scp, pIomb, OSSA_OFFSET_OF(agsaSMPAbortRsp_t, scp));

  /* get IORequest from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;

  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSMPAbortRsp: pRequest is NULL, HTag=0x%x Status=0x%x\n", pIomb->tag, pIomb->status));
    SA_ASSERT((pRequest), "pRequest");
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3P");
    return AGSA_RC_FAILURE;
  }

  if ( agTRUE == pRequest->valid )
  {
    pDevice = pRequest->pDevice;
    SA_ASSERT((pRequest->pDevice), "pRequest->pDevice");

    SA_DBG3(("mpiSMPAbortRsp: request abort is valid Htag 0x%x\n", tag));

    /* remove the SSP_ABORT or SATA_ABORT request from IOMap */
    saRoot->IOMap[tag].Tag = MARK_OFF;
    saRoot->IOMap[tag].IORequest = agNULL;
    saRoot->IOMap[tag].agContext = agNULL;

    if( pRequest->completionCB == agNULL )
    {
      SA_DBG1(("mpiSMPAbortRsp: ************************************************* Valid for Expander only tag 0x%x\n", tag));
      ossaSMPAbortCB(agRoot, pRequest->pIORequestContext, scp, status);
    }
    else
    {
      (*(ossaGenericAbortCB_t)(pRequest->completionCB))(agRoot, pRequest->pIORequestContext, scp, status);
    }

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);

    /* Delete the request from the pendingIORequests */
    saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode));
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiSMPAbortRsp: saving pRequest (%p) for later use\n", pRequest));
      saLlistIOAdd(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
    }
    else
    {
      saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    }
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  }
  else
  {
    ret = AGSA_RC_FAILURE;
    SA_DBG1(("mpiSMPAbortRsp: the request is not valid any more. Tag=%x\n", pRequest->HTag));
  }


  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3P");

  return ret;
}

/******************************************************************************/
/*! \brief SPC MPI Device Handle Arrived Event (target mode)
 *
 *  This function handles the Device Handle Arrived Event.
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pMsg1        pointer of Message
 *
 *  \return The read value
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiDeviceHandleRemoval(
  agsaRoot_t *agRoot,
  agsaDeviceHandleRemoval_t *pMsg1)
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaDeviceDesc_t    *pDevice;
  agsaPortContext_t   *agPortContext;
  bit32               portId;
  bit32               deviceid, deviceIdx;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3R");

  /* convert endiness if necassary */
  OSSA_READ_LE_32(AGROOT, &portId, pMsg1, OSSA_OFFSET_OF(agsaDeviceHandleRemoval_t, portId));
  OSSA_READ_LE_32(AGROOT, &deviceid, pMsg1, OSSA_OFFSET_OF(agsaDeviceHandleRemoval_t, deviceId));

  SA_DBG3(("mpiDeviceHandleRemoval: portId=0x%x deviceId=0x%x\n", portId, deviceid));

  pDevice = saRoot->DeviceMap[deviceid & DEVICE_ID_BITS].DeviceHandle;
  SA_DBG2(("mpiDeviceHandleRemoval:PortID 0x%x PortStatus 0x%x PortContext %p\n",
          saRoot->PortMap[portId & PORTID_MASK].PortID,
          saRoot->PortMap[portId & PORTID_MASK].PortStatus,
          saRoot->PortMap[portId & PORTID_MASK].PortContext));
  agPortContext = (agsaPortContext_t *)saRoot->PortMap[portId & PORTID_MASK].PortContext;

  /* Call Back */
  SA_DBG1(("mpiDeviceHandleRemoval: portId=0x%x deviceId=0x%x autoDeregDeviceflag=0x%x\n", portId, deviceid,saRoot->autoDeregDeviceflag[portId & PORTID_MASK]));
  if (pDevice->targetDevHandle.sdkData)
  {
    ossaDeviceHandleRemovedEvent(agRoot, &(pDevice->targetDevHandle), agPortContext);

    if (saRoot->autoDeregDeviceflag[portId & PORTID_MASK])
    {
      /* remove the DeviceMap and MapIndex */
      deviceIdx = pDevice->DeviceMapIndex & DEVICE_ID_BITS;
      SA_DBG1(("mpiDeviceHandleRemoval: A  Freed portId=0x%x deviceId=0x%x\n", portId, deviceid));
      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;

      /* Reset the device data structure */
      pDevice->pPort = agNULL;
      pDevice->targetDevHandle.sdkData = agNULL;
      pDevice->targetDevHandle.osData = agNULL;
      ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
      saLlistAdd(&(saRoot->freeDevicesList), &(pDevice->linkNode));
      SA_DBG1(("mpiDeviceHandleRemoval: portId=0x%x deviceId=0x%x\n", portId, deviceid));

      ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    }
  }
  else
  {
    if (pDevice->initiatorDevHandle.sdkData)
    {
      ossaDeviceHandleRemovedEvent(agRoot, &(pDevice->initiatorDevHandle), agPortContext);

      if (saRoot->autoDeregDeviceflag[portId & PORTID_MASK])
      {
        /* remove the DeviceMap and MapIndex */
        deviceIdx = pDevice->DeviceMapIndex & DEVICE_ID_BITS;
        SA_DBG1(("mpiDeviceHandleRemoval: A  Freed portId=0x%x deviceId=0x%x\n", portId, deviceid));
        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;

        /* Reset the device data structure */
        pDevice->pPort = agNULL;
        pDevice->initiatorDevHandle.sdkData = agNULL;
        pDevice->initiatorDevHandle.osData = agNULL;
        ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
        saLlistAdd(&(saRoot->freeDevicesList), &(pDevice->linkNode));
        ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
      }
    }
    else
    {
      /* no callback because bad device_id */
      SA_DBG1(("mpiDeviceHandleRemoval: Bad Device Handle, deviceId=0x%x\n", deviceid));
    }
  }

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

/******************************************************************************/
/*! \brief Set Device State Response
 *
 *  This routine handles the response of SET Device State Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSetDeviceStateRsp(
  agsaRoot_t             *agRoot,
  agsaSetDeviceStateRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  agsaContext_t       *agContext;
  bit32               tag, status, deviceState, deviceId;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3Q");

  SA_DBG1(("mpiSetDeviceStateRsp: HTag=0x%x, deviceId=0x%x\n", pIomb->tag, pIomb->deviceId));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSetDeviceStateRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &deviceId, pIomb, OSSA_OFFSET_OF(agsaSetDeviceStateRsp_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSetDeviceStateRsp_t, status));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSetDeviceStateRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3Q");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* status is SUCCESS */
  OSSA_READ_LE_32(AGROOT, &deviceState, pIomb, OSSA_OFFSET_OF(agsaSetDeviceStateRsp_t, pds_nds));

  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceId & DEVICE_ID_BITS].DeviceHandle;
  if (agNULL == pDevice)
  {
    SA_DBG1(("mpiSetDeviceStateRsp: DeviceHandle is NULL!!! deviceId=0x%x TAG=0x%x STATUS=0x%x \n", deviceId, tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3Q");
    return AGSA_RC_FAILURE;
  }

  if (pDevice->targetDevHandle.sdkData)
  {
    agDevHandle = &(pDevice->targetDevHandle);
  }
  else
  {
    agDevHandle = &(pDevice->initiatorDevHandle);
  }

  if (agDevHandle == agNULL)
  {
    SA_DBG1(("mpiSetDeviceStateRsp: warning!!! no deviceHandle is found"));
    ossaSetDeviceStateCB(agRoot, agContext, agNULL, OSSA_IO_NO_DEVICE, 0, 0);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "3Q");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiSetDeviceStateRsp: 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);

    return AGSA_RC_FAILURE;
  }

  ossaSetDeviceStateCB(agRoot, agContext, agDevHandle, status, (deviceState & NDS_BITS),
                      (deviceState & PDS_BITS) >> SHIFT4);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSetDeviceStateRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "3Q");
  return ret;
}

/******************************************************************************/
/*! \brief Get Device State Response
 *
 *  This routine handles the response of GET Device State Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetDeviceStateRsp(
  agsaRoot_t             *agRoot,
  agsaGetDeviceStateRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaDevHandle_t     *agDevHandle;
  agsaDeviceDesc_t    *pDevice;
  agsaContext_t       *agContext;
  bit32               tag, status, deviceId, deviceState;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3W");

  SA_DBG1(("mpiGetDeviceStateRsp: HTag=0x%x, deviceId=0x%x\n", pIomb->tag, pIomb->deviceId));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetDeviceStateRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &deviceId, pIomb, OSSA_OFFSET_OF(agsaGetDeviceStateRsp_t, deviceId));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaGetDeviceStateRsp_t, status));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetDeviceStateRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3W");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* status is SUCCESS */
  OSSA_READ_LE_32(AGROOT, &deviceState, pIomb, OSSA_OFFSET_OF(agsaGetDeviceStateRsp_t, ds));

  /* find device handle from device index */
  pDevice = (agsaDeviceDesc_t *)saRoot->DeviceMap[deviceId & DEVICE_ID_BITS].DeviceHandle;
  if (pDevice != agNULL)
  {
    if (pDevice->targetDevHandle.sdkData)
    {
      agDevHandle = &(pDevice->targetDevHandle);
    }
    else
    {
      agDevHandle = &(pDevice->initiatorDevHandle);
    }
  }
  else
  {
    SA_DBG1(("mpiGetDeviceStateRsp: pDevice is NULL"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3W");
    return AGSA_RC_FAILURE;
  }

  if (agDevHandle == agNULL)
  {
    SA_DBG1(("mpiGetDeviceStateRsp: warning!!! no deviceHandle is found"));
    ossaGetDeviceStateCB(agRoot, agContext, agNULL, OSSA_IO_NO_DEVICE, 0);
    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "3W");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
    {
      SA_DBG1(("mpiGetDeviceStateRsp: 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);

    return AGSA_RC_FAILURE;
  }

  ossaGetDeviceStateCB(agRoot, agContext, agDevHandle, status, deviceState);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetDeviceStateRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "3W");
  return ret;
}

/******************************************************************************/
/*! \brief SAS ReInitialize Response
 *
 *  This routine handles the response of SAS Reinitialize Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSasReInitializeRsp(
  agsaRoot_t               *agRoot,
  agsaSasReInitializeRsp_t *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  agsaSASReconfig_t   SASReconfig;
  bit32               tag, status, setFlags, MaxPorts;
  bit32               openRejReCmdData, sataHOLTMO;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3X");

  SA_DBG1(("mpiSasReInitializeRsp: HTag=0x%x, status=0x%x\n", pIomb->tag, pIomb->status));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSasReInitializeRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSasReInitializeRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &setFlags, pIomb, OSSA_OFFSET_OF(agsaSasReInitializeRsp_t, setFlags));
  OSSA_READ_LE_32(AGROOT, &MaxPorts, pIomb, OSSA_OFFSET_OF(agsaSasReInitializeRsp_t, MaxPorts));
  OSSA_READ_LE_32(AGROOT, &openRejReCmdData, pIomb, OSSA_OFFSET_OF(agsaSasReInitializeRsp_t, openRejReCmdData));
  OSSA_READ_LE_32(AGROOT, &sataHOLTMO, pIomb, OSSA_OFFSET_OF(agsaSasReInitializeRsp_t, sataHOLTMO));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSasReInitializeRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3X");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  SASReconfig.flags = setFlags;
  SASReconfig.maxPorts = (bit8)(MaxPorts & 0xFF);
  SASReconfig.openRejectRetriesCmd = (bit16)((openRejReCmdData & 0xFFFF0000) >> SHIFT16);
  SASReconfig.openRejectRetriesData = (bit16)(openRejReCmdData & 0x0000FFFF);
  SASReconfig.sataHolTmo = (bit16)(sataHOLTMO & 0xFFFF);
  ossaReconfigSASParamsCB(agRoot, agContext, status, &SASReconfig);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSasReInitializeRsp: 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);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3X");

  return ret;
}

/******************************************************************************/
/*! \brief serial GPIO Response
 *
 *  This routine handles the response of serial GPIO Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSGpioRsp(
  agsaRoot_t        *agRoot,
  agsaSGpioRsp_t    *pInIomb
  )
{
  bit32                     ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t              *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t       *pRequest = NULL;
  agsaContext_t             *agContext = NULL;
  bit32                     i, tag, resultFunctionFrameType;
  agsaSGpioReqResponse_t    SgpioResponse = {0};

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3Y");

  SA_DBG3(("mpiSGpioRsp: HTAG=0x%x\n", pInIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pInIomb, OSSA_OFFSET_OF(agsaSGpioRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &resultFunctionFrameType, pInIomb, OSSA_OFFSET_OF(agsaSGpioRsp_t, resultFunctionFrameType));
  
  SgpioResponse.smpFrameType = resultFunctionFrameType & 0xFF;
  SgpioResponse.function = (resultFunctionFrameType & 0xFF00) >> 8;
  SgpioResponse.functionResult = (resultFunctionFrameType & 0xFF0000) >> 16;
  
  if (SA_SAS_SMP_READ_GPIO_REGISTER == SgpioResponse.function)
  {
    for (i = 0; i < OSSA_SGPIO_MAX_READ_DATA_COUNT; i++)
    {
      OSSA_READ_LE_32(AGROOT, &SgpioResponse.readWriteData[i], pInIomb, OSSA_OFFSET_OF(agsaSGpioRsp_t, readData) + (i * 4));
    }
  }

  /* Get the request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSGpioRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x STATUS=0x%x\n", tag, SgpioResponse.functionResult));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3Y");
    ret = AGSA_RC_FAILURE;
  }
  else
  {
    agContext = saRoot->IOMap[tag].agContext;
    ossaSGpioCB(agRoot, agContext, &SgpioResponse);

    /* Return the request to free pool */
    saReturnRequestToFreePool(agRoot, pRequest);

    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3Y");
  }
  
  return ret;
}

/******************************************************************************/
/*! \brief PCIE Diagnostics Response
 *
 *  This routine handles the response of PCIE Diagnostics Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiPCIeDiagExecuteRsp(
  agsaRoot_t                *agRoot,
  void                      *pInIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = agNULL;
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag, Status, Command;
  agsaPCIeDiagResponse_t pciediadrsp;
  bit32  *pIomb = (bit32  *)pInIomb;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3Z");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  SA_ASSERT((agNULL != saRoot), "");

  si_memset(&pciediadrsp, 0, sizeof(agsaPCIeDiagResponse_t));

  if(smIS_SPCV(agRoot))
  {
    OSSA_READ_LE_32(AGROOT, &tag,                  pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,tag));
    OSSA_READ_LE_32(AGROOT, &Command,              pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,CmdTypeDesc));
    OSSA_READ_LE_32(AGROOT, &Status,               pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,Status));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.ERR_BLKH, pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,ERR_BLKH ));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.ERR_BLKL, pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,ERR_BLKL ));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.DWord8,   pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,DWord8 ));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.DWord9,   pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,DWord9 ));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.DWord10,  pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,DWord10 ));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.DWord11,  pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,DWord11 ));
    OSSA_READ_LE_32(AGROOT, &pciediadrsp.DIF_ERR,  pIomb, OSSA_OFFSET_OF(agsaPCIeDiagExecuteRsp_t,DIF_ERR ));
    SA_DBG3(("mpiPCIeDiagExecuteRsp: HTAG=0x%x\n",tag));
  }
  else
  {
    OSSA_READ_LE_32(AGROOT, &tag,        pIomb,           OSSA_OFFSET_OF(agsa_SPC_PCIeDiagExecuteRsp_t,tag));
    OSSA_READ_LE_32(AGROOT, &Command,    pIomb,           OSSA_OFFSET_OF(agsa_SPC_PCIeDiagExecuteRsp_t,CmdTypeDesc));
    OSSA_READ_LE_32(AGROOT, &Status,     pIomb,           OSSA_OFFSET_OF(agsa_SPC_PCIeDiagExecuteRsp_t,Status));
    SA_DBG3(("mpiPCIeDiagExecuteRsp: SPC HTAG=0x%x\n",tag));
  }

  switch(Status)
  {
    case OSSA_PCIE_DIAG_SUCCESS:
      SA_DBG3(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_SUCCESS TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_IO_INVALID_LENGTH:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_IO_INVALID_LENGTH TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_INVALID_COMMAND:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_INVALID_COMMAND TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_INTERNAL_FAILURE:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_INTERNAL_FAILURE TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_INVALID_CMD_TYPE:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_INVALID_CMD_TYPE TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_INVALID_CMD_DESC:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_INVALID_CMD_DESC TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_CRC_MISMATCH:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_CRC_MISMATCH TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_INVALID_PCIE_ADDR:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_INVALID_PCIE_ADDR TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_INVALID_BLOCK_SIZE:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_INVALID_BLOCK_SIZE TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_LENGTH_NOT_BLOCK_SIZE_ALIGNED:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_LENGTH_NOT_BLOCK_SIZE_ALIGNED TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_MISMATCH:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_MISMATCH TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    case OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH:
      SA_DBG1(("mpiPCIeDiagExecuteRsp: OSSA_PCIE_DIAG_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
    default:
      SA_DBG1(("mpiPCIeDiagExecuteRsp:  UNKNOWN status TAG=0x%x STATUS=0x%x\n", tag, Status));
      break;
  }
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiPCIeDiagExecuteRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x STATUS=0x%x\n", tag, Status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3Z");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  ossaPCIeDiagExecuteCB(agRoot, agContext, Status, Command,&pciediadrsp);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiPCIeDiagExecuteRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3Z");

  /* return value */
  return ret;
}
/******************************************************************************/
/*! \brief Get DFE Data command Response
 *
 *  This routine handles the response of Get DFE Data command Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetDFEDataRsp(
  agsaRoot_t    *agRoot,
  void          *pIomb
  )
{
  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = agNULL;
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag = 0, status = 0, In_Ln = 0, MCNT = 0, NBT = 0;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2Y");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  SA_ASSERT((agNULL != saRoot), "");

  if(smIS_SPCV(agRoot))
  {
    OSSA_READ_LE_32(AGROOT, &tag,                pIomb, OSSA_OFFSET_OF(agsaGetDDEFDataRsp_t,tag));
    OSSA_READ_LE_32(AGROOT, &status,             pIomb, OSSA_OFFSET_OF(agsaGetDDEFDataRsp_t,status));
    OSSA_READ_LE_32(AGROOT, &In_Ln,              pIomb, OSSA_OFFSET_OF(agsaGetDDEFDataRsp_t,reserved_In_Ln));
    OSSA_READ_LE_32(AGROOT, &MCNT,               pIomb, OSSA_OFFSET_OF(agsaGetDDEFDataRsp_t,MCNT));
    OSSA_READ_LE_32(AGROOT, &NBT,                pIomb, OSSA_OFFSET_OF(agsaGetDDEFDataRsp_t,NBT));
  }
  else
  {
    /* SPC does not support this command */
  }

  switch(status)
  {
    case OSSA_DFE_MPI_IO_SUCCESS:
      SA_DBG3(("mpiGetDFEDataRsp: OSSA_DFE_MPI_IO_SUCCESS TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    case OSSA_DFE_DATA_OVERFLOW:
      SA_DBG1(("mpiGetDFEDataRsp: OSSA_DFE_DATA_OVERFLOW TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    case OSSA_DFE_MPI_ERR_RESOURCE_UNAVAILABLE:
      SA_DBG1(("mpiGetDFEDataRsp: OSSA_DFE_MPI_ERR_RESOURCE_UNAVAILABLE TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    case OSSA_DFE_CHANNEL_DOWN:
      SA_DBG1(("mpiGetDFEDataRsp: OSSA_DFE_CHANNEL_DOWN TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    case OSSA_DFE_MEASUREMENT_IN_PROGRESS:
      SA_DBG1(("mpiGetDFEDataRsp: OSSA_DFE_MEASUREMENT_IN_PROGRESS TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    case OSSA_DFE_CHANNEL_INVALID:
      SA_DBG1(("mpiGetDFEDataRsp: OSSA_DFE_CHANNEL_INVALID TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    case OSSA_DFE_DMA_FAILURE:
      SA_DBG1(("mpiGetDFEDataRsp: OSSA_DFE_DMA_FAILURE TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
    default:
      SA_DBG1(("mpiGetDFEDataRsp:  UNKNOWN status TAG=0x%x STATUS=0x%x\n", tag, status));
      break;
   }

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetDFEDataRsp: Bad Response IOMB!!! pRequest is NULL.TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2Y");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  ossaGetDFEDataCB(agRoot, agContext, status, NBT);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetDFEDataRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2Y");

  return ret;
}


/******************************************************************************/
/*! \brief SAS Set Controller Config Response
 *
 *  This routine handles the response of Set Controller Config Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSetControllerConfigRsp(
  agsaRoot_t                   *agRoot,
  agsaSetControllerConfigRsp_t *pIomb
  )
{
  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t   *pRequest;
  agsaHWEventMode_t     agMode;
  bit32                 status, errorQualifierPage, tag;
  bit32                 errorQualifier;
  bit32                 pagetype;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3a");

  SA_DBG1(("mpiSetControllerConfigRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSetControllerConfigRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSetControllerConfigRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &errorQualifierPage, pIomb, OSSA_OFFSET_OF(agsaSetControllerConfigRsp_t, errorQualifierPage));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSetControllerConfigRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3a");
    return AGSA_RC_FAILURE;
  }

  si_memset(&agMode, 0, sizeof(agsaHWEventMode_t));
  agMode.modePageOperation = agsaModePageSet;
  agMode.status = status;
  agMode.context = saRoot->IOMap[tag].agContext;
  errorQualifier = (errorQualifierPage & 0xFFFF0000) >> SHIFT16;
  pagetype = (errorQualifierPage & 0xFF);

  if(status )
  {
    SA_DBG1(("mpiSetControllerConfigRsp: Error detected tag 0x%x pagetype 0x%x status 0x%x errorQualifier 0x%x\n", 
      tag, pagetype,status, errorQualifier));
  }
  else
  {
    SA_DBG1(("mpiSetControllerConfigRsp: tag 0x%x pagetype 0x%x status 0x%x\n", tag, pagetype,status ));
  }


  switch( pagetype)
  {
    case AGSA_ENCRYPTION_DEK_CONFIG_PAGE:
    case AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE:
    case AGSA_INTERRUPT_CONFIGURATION_PAGE:
    case AGSA_ENCRYPTION_HMAC_CONFIG_PAGE:
    case AGSA_IO_GENERAL_CONFIG_PAGE:
    /*case AGSA_ENCRYPTION_CONTROL_PARM_PAGE:*/
      /* Report the event before freeing the IOMB */
      SA_DBG1(("mpiSetControllerConfigRsp:OSSA_HW_EVENT_MODE\n"));
      ossaHwCB(agRoot,agMode.context, OSSA_HW_EVENT_MODE, errorQualifierPage, (void *) &agMode, 0);
  

      break;

    case AGSA_ENCRYPTION_GENERAL_CONFIG_PAGE:
      SA_DBG1(("mpiSetControllerConfigRsp:warning!!!! GENERAL_CONFIG_PAGE is read only, cannot be set\n"));
      break;

    /* why we need to read the scrach pad register when handling ENCRYPTION_SECURITY_PARM_PAGE??? */
    case AGSA_ENCRYPTION_CONTROL_PARM_PAGE:
    {
      bit32 ScratchPad1 = 0;
      bit32 ScratchPad3 = 0;
      agsaEncryptInfo_t encrypt;
      agsaEncryptInfo_t *encryptInfo = &encrypt;
      SA_DBG1(("mpiSetControllerConfigRsp: AGSA_ENCRYPTION_CONTROL_PARM_PAGE\n" ));

      if( pRequest->modePageContext)
      {
        pRequest->modePageContext = agFALSE;
      }

      si_memset(&encrypt, 0, sizeof(agsaEncryptInfo_t));
      encryptInfo->status = 0;
      encryptInfo->encryptionCipherMode = 0;
      encryptInfo->encryptionSecurityMode = 0;

      ScratchPad1 = ossaHwRegRead(agRoot,V_Scratchpad_1_Register);
      ScratchPad3 = ossaHwRegRead(agRoot,V_Scratchpad_3_Register);
      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;
      }
      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 */
        {
          encryptInfo->status = AGSA_RC_SUCCESS;
        }
        else if((ScratchPad3 & SCRATCH_PAD3_V_ENC_READY) == SCRATCH_PAD3_V_ENC_DISABLED) /* 0 */
        {
          encryptInfo->status = 0xFFFF;
          encryptInfo->encryptionCipherMode = 0;
          encryptInfo->encryptionSecurityMode = 0;
        }
        else if((ScratchPad3 & SCRATCH_PAD3_V_ENC_MASK ) == SCRATCH_PAD3_V_ENC_DIS_ERR) /* 1 */
        {
          encryptInfo->status = (ScratchPad3 & SCRATCH_PAD3_V_ERR_CODE ) >> SHIFT16;
        }
        else if((ScratchPad3 & SCRATCH_PAD3_V_ENC_MASK ) == SCRATCH_PAD3_V_ENC_ENA_ERR) /* 2 */
        {
          encryptInfo->status = (ScratchPad3 & SCRATCH_PAD3_V_ERR_CODE ) >> SHIFT16;
        }
      }
      else  if((ScratchPad1 & SCRATCH_PAD1_V_RAAE_MASK) ==  SCRATCH_PAD1_V_RAAE_ERR)
      {
        SA_DBG1(("mpiSetControllerConfigRsp, RAAE not ready SPC AGSA_RC_FAILURE\n"));
        encryptInfo->status = 0xFFFF;
        encryptInfo->encryptionCipherMode = 0;
        encryptInfo->encryptionSecurityMode = 0;
      }
      else  if((ScratchPad1 & SCRATCH_PAD1_V_RAAE_MASK) == 0x0 )
      {
        SA_DBG2(("mpiSetControllerConfigRsp, RAAE not ready AGSA_RC_BUSY\n"));
      }

      SA_DBG2(("mpiSetControllerConfigRsp, encryptionCipherMode 0x%x encryptionSecurityMode 0x%x status 0x%x\n",
                encryptInfo->encryptionCipherMode,
                encryptInfo->encryptionSecurityMode,
                encryptInfo->status));
      SA_DBG2(("mpiSetControllerConfigRsp, ScratchPad3 0x%x\n",ScratchPad3));
      SA_DBG1(("mpiSetControllerConfigRsp:AGSA_ENCRYPTION_CONTROL_PARM_PAGE 0x%X\n", agMode.modePageOperation));
      ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_SECURITY_MODE, errorQualifier, (void *)encryptInfo, agMode.context);
      break;
    }

    default:
      SA_DBG1(("mpiSetControllerConfigRsp: Unknown page code 0x%X\n", pagetype));
      break;
  }

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSetControllerRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3a");
  return AGSA_RC_SUCCESS;

}

/******************************************************************************/
/*! \brief SAS Get Controller Config Response
 *
 *  This routine handles the response of Get Controller Config Command
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetControllerConfigRsp(
  agsaRoot_t               *agRoot,
  agsaGetControllerConfigRsp_t *pIomb
  )
{
  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t   *pRequest;
  agsaHWEventMode_t     agMode;
  bit32                 status, errorQualifier, tag;
  bit32                 configPage[12];

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3b");

  si_memset(&agMode, 0, sizeof(agsaHWEventMode_t));
  si_memset(configPage, 0, sizeof(configPage));


  SA_DBG2(("mpiGetControllerConfigRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &errorQualifier, pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t, errorQualifier));
  OSSA_READ_LE_32(AGROOT, &configPage[0],  pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t,configPage[0] ));
  OSSA_READ_LE_32(AGROOT, &configPage[1],  pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t,configPage[1] ));
  OSSA_READ_LE_32(AGROOT, &configPage[2],  pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t,configPage[2] ));
  OSSA_READ_LE_32(AGROOT, &configPage[3],  pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t,configPage[3] ));
  OSSA_READ_LE_32(AGROOT, &configPage[4],  pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t,configPage[4] ));
  OSSA_READ_LE_32(AGROOT, &configPage[5],  pIomb, OSSA_OFFSET_OF(agsaGetControllerConfigRsp_t,configPage[5] ));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetControllerConfigRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3b");
    return AGSA_RC_FAILURE;
  }

  si_memset(&agMode, 0, sizeof(agsaHWEventMode_t));
  agMode.modePageOperation = agsaModePageGet;
  agMode.status = status;

  SA_DBG1(("mpiGetControllerConfigRsp: page 0x%x status 0x%x errorQualifier 0x%x \n", (pIomb->configPage[0] & 0xFF),status, errorQualifier));

  switch (pIomb->configPage[0] & 0xFF)
  {
  case AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE:
      agMode.modePageLen = sizeof(agsaSASProtocolTimerConfigurationPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE page len 0x%x \n",agMode.modePageLen));
      break;
  case AGSA_INTERRUPT_CONFIGURATION_PAGE:
      agMode.modePageLen = sizeof(agsaInterruptConfigPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_INTERRUPT_CONFIGURATION_PAGE page len 0x%x \n",agMode.modePageLen));
      break;
  case AGSA_IO_GENERAL_CONFIG_PAGE:
      agMode.modePageLen = sizeof(agsaIoGeneralPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_IO_GENERAL_CONFIG_PAGE page len 0x%x \n",agMode.modePageLen));
      break;
  case AGSA_ENCRYPTION_GENERAL_CONFIG_PAGE:
      agMode.modePageLen = sizeof(agsaEncryptGeneralPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_ENCRYPTION_GENERAL_CONFIG_PAGE page len 0x%x \n",agMode.modePageLen));
#ifdef HIALEAH_ENCRYPTION
      saRoot->EncGenPage.numberOfKeksPageCode = configPage[0];
      saRoot->EncGenPage.KeyCardIdKekIndex    = configPage[1];
      saRoot->EncGenPage.KeyCardId3_0         = configPage[2];
      saRoot->EncGenPage.KeyCardId7_4         = configPage[3];
      saRoot->EncGenPage.KeyCardId11_8        = configPage[4];

      SA_DBG1(("mpiGetControllerConfigRsp: numberOfKeksPageCode 0x%x\n",saRoot->EncGenPage.numberOfKeksPageCode));
      SA_DBG1(("mpiGetControllerConfigRsp: KeyCardIdKekIndex    0x%x\n",saRoot->EncGenPage.KeyCardIdKekIndex));
      SA_DBG1(("mpiGetControllerConfigRsp: KeyCardId3_0         0x%x\n",saRoot->EncGenPage.KeyCardId3_0));
      SA_DBG1(("mpiGetControllerConfigRsp: KeyCardId7_4         0x%x\n",saRoot->EncGenPage.KeyCardId7_4));
      SA_DBG1(("mpiGetControllerConfigRsp: KeyCardId11_8        0x%x\n",saRoot->EncGenPage.KeyCardId11_8));
#endif /* HIALEAH_ENCRYPTION */

      break;
  case AGSA_ENCRYPTION_DEK_CONFIG_PAGE:
      agMode.modePageLen = sizeof(agsaEncryptDekConfigPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_ENCRYPTION_DEK_CONFIG_PAGE page len 0x%x \n",agMode.modePageLen));
      break;
  case AGSA_ENCRYPTION_CONTROL_PARM_PAGE:
      agMode.modePageLen = sizeof(agsaEncryptControlParamPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_ENCRYPTION_CONTROL_PARM_PAGE page len 0x%x \n",agMode.modePageLen));
      break;
  case AGSA_ENCRYPTION_HMAC_CONFIG_PAGE:
      agMode.modePageLen = sizeof(agsaEncryptHMACConfigPage_t);
      SA_DBG1(("mpiGetControllerConfigRsp: AGSA_ENCRYPTION_HMAC_CONFIG_PAGE page len 0x%x \n",agMode.modePageLen));
      break;
  default:
      agMode.modePageLen = 0;
      SA_DBG1(("mpiGetControllerConfigRsp: Unknown !!! page len 0x%x \n",agMode.modePageLen));
      break;
  }

  agMode.modePage = (void *) &pIomb->configPage[0];
  agMode.context = saRoot->IOMap[tag].agContext;

  /* Report the event before freeing the IOMB */
  ossaHwCB(agRoot, NULL, OSSA_HW_EVENT_MODE, errorQualifier, (void *) &agMode, 0);

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetControllerRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3b");
  return AGSA_RC_SUCCESS;
}

/******************************************************************************/
/*! \brief KEK Management Response
 *
 *  This routine handles the response of the KEK management message
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiKekManagementRsp(
  agsaRoot_t               *agRoot,
  agsaKekManagementRsp_t *pIomb
  )
{
  agsaLLRoot_t          *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t   *pRequest;
  agsaContext_t         *agContext;
  agsaHWEventEncrypt_t  agEvent;
  bit32                 status, errorQualifier, tag, flags;
  smTraceFuncEnter(hpDBG_VERY_LOUD,"2A");

  SA_DBG1(("mpiKekManagementRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaKekManagementRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaKekManagementRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &flags, pIomb, OSSA_OFFSET_OF(agsaKekManagementRsp_t, flags));
  OSSA_READ_LE_32(AGROOT, &errorQualifier, pIomb, OSSA_OFFSET_OF(agsaKekManagementRsp_t, errorQualifier));


  SA_DBG1(("mpiKekManagementRsp:status 0x%x flags 0x%x errorQualifier 0x%x\n", status, flags, errorQualifier));

  si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
  if ((flags & 0xFF) == KEK_MGMT_SUBOP_UPDATE)
  {
    SA_DBG1(("mpiKekManagementRsp:KEK_MGMT_SUBOP_UPDATE 0x%x \n", status));
    if (flags & 0xFF00) /* update and store*/
    {
      agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE;
    }
    else /* update */
    {
      agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_UPDATE;
    }
    agEvent.status = status;
    if (status == OSSA_MPI_ENC_ERR_ILLEGAL_KEK_PARAM)
    {
        agEvent.eq = errorQualifier;
    }
    agEvent.info = 0;
    /* Store the new KEK index in agEvent.handle */
    agEvent.handle = (void *) ((bitptr) (flags >> 24));
    /* Store the current KEK index in agEvent.param */
    agEvent.param = (void *) ((bitptr) (flags >> 16) & 0xFF);

  }

  else if ((flags & 0xFF) == KEK_MGMT_SUBOP_INVALIDATE)
  {
      agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_INVALIDTE;
      agEvent.status = status;
      if (status == OSSA_MPI_ENC_ERR_ILLEGAL_KEK_PARAM)
      {
          agEvent.eq = errorQualifier;
      }
      agEvent.info = 0;
      /* Store the new KEK index in agEvent.handle */
      agEvent.handle = (void *) ((bitptr) (flags >> 24));
      /* Store the current KEK index in agEvent.param */
      agEvent.param = (void *) ((bitptr) (flags >> 16) & 0xFF);
  }

  else if ((flags & 0xFF) == KEK_MGMT_SUBOP_KEYCARDINVALIDATE)
  {
     agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_UPDATE_AND_STORE;
      agEvent.status = status;
      if (status == OSSA_MPI_ENC_ERR_ILLEGAL_KEK_PARAM)
      {
          agEvent.eq = errorQualifier;
      }
      agEvent.info = 0;
      /* Store the new KEK index in agEvent.handle */
      agEvent.handle = (void *) ((bitptr) (flags >> 24));
      /* Store the current KEK index in agEvent.param */
      agEvent.param = (void *) ((bitptr) (flags >> 16) & 0xFF);

  }

  else if ((flags & 0xFF) == KEK_MGMT_SUBOP_KEYCARDUPDATE)
  {
     agEvent.encryptOperation = OSSA_HW_ENCRYPT_KEK_UPDATE;
      agEvent.status = status;
      if (status == OSSA_MPI_ENC_ERR_ILLEGAL_KEK_PARAM)
      {
          agEvent.eq = errorQualifier;
      }
      agEvent.info = 0;
      /* Store the new KEK index in agEvent.handle */
      agEvent.handle = (void *) ((bitptr) (flags >> 24));
      /* Store the current KEK index in agEvent.param */
      agEvent.param = (void *) ((bitptr) (flags >> 16) & 0xFF);

  }
  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiKekManagementRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2A");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaHwCB(agRoot, NULL, OSSA_HW_EVENT_ENCRYPTION, 0, (void *) &agEvent, agContext);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiKekManagementRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2A");

  return AGSA_RC_SUCCESS;
}

/******************************************************************************/
/*! \brief DEK Management Response
 *
 *  This routine handles the response of the DEK management message
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiDekManagementRsp(
  agsaRoot_t               *agRoot,
  agsaDekManagementRsp_t   *pIomb
  )
{
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  agsaHWEventEncrypt_t agEvent;
  bit32               flags, status, errorQualifier, tag, dekIndex;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"2B");

  SA_DBG1(("mpiDekManagementRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaDekManagementRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaDekManagementRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &flags, pIomb, OSSA_OFFSET_OF(agsaDekManagementRsp_t, flags));
  OSSA_READ_LE_32(AGROOT, &errorQualifier, pIomb, OSSA_OFFSET_OF(agsaDekManagementRsp_t, errorQualifier));
  OSSA_READ_LE_32(AGROOT, &dekIndex, pIomb, OSSA_OFFSET_OF(agsaDekManagementRsp_t, dekIndex));

  SA_DBG2(("mpiDekManagementRsp:tag =0x%x\n",tag ));
  SA_DBG2(("mpiDekManagementRsp:status =0x%x\n", status));
  SA_DBG2(("mpiDekManagementRsp:flags =0x%x\n",flags ));
  SA_DBG2(("mpiDekManagementRsp:errorQualifier =0x%x\n", errorQualifier));
  SA_DBG2(("mpiDekManagementRsp:dekIndex =0x%x\n",dekIndex ));

  si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
  if ((flags & 0xFF) == DEK_MGMT_SUBOP_UPDATE)
  {
     agEvent.encryptOperation = OSSA_HW_ENCRYPT_DEK_UPDATE;
  }
  else
  {
     agEvent.encryptOperation = OSSA_HW_ENCRYPT_DEK_INVALIDTE;
  }
  agEvent.status = status;
  if (status == OSSA_MPI_ENC_ERR_ILLEGAL_DEK_PARAM || status == OSSA_MPI_ERR_DEK_MANAGEMENT_DEK_UNWRAP_FAIL)
  {
    agEvent.eq = errorQualifier;
  }
  /* Store the DEK in agEvent.info */
  agEvent.info = (flags >> 8) & 0xF;
  /* Store the KEK index in agEvent.handle */
  agEvent.handle = (void *) ((bitptr) (flags >> 24));
  /* Store the DEK index in agEvent.param */
  agEvent.param = (void *) (bitptr) dekIndex;

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiDekManagementRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2B");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaHwCB(agRoot, NULL, OSSA_HW_EVENT_ENCRYPTION, 0, (void *) &agEvent,agContext );

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiDekManagementRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2B");

  return AGSA_RC_SUCCESS;
}

/******************************************************************************/
/*! \brief Operator Management Response
 *
 *  This routine handles the response of the Operator management message
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiOperatorManagementRsp(
  agsaRoot_t                *agRoot,
  agsaOperatorMangmenRsp_t  *pIomb
  )
{
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  agsaHWEventEncrypt_t agEvent;
  bit32               OPRIDX_AUTIDX_R_OMO,status, errorQualifier, tag;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"36");

  SA_DBG1(("mpiOperatorManagementRsp: HTag=0x%x\n", pIomb->tag));

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaOperatorMangmenRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaOperatorMangmenRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &OPRIDX_AUTIDX_R_OMO, pIomb, OSSA_OFFSET_OF(agsaOperatorMangmenRsp_t, OPRIDX_AUTIDX_R_OMO));
  OSSA_READ_LE_32(AGROOT, &errorQualifier, pIomb, OSSA_OFFSET_OF(agsaOperatorMangmenRsp_t, errorQualifier));

  SA_DBG2(("mpiOperatorManagementRsp:tag =0x%x\n",tag ));
  SA_DBG2(("mpiOperatorManagementRsp:status =0x%x\n", status));
  SA_DBG2(("mpiOperatorManagementRsp:OPRIDX_AUTIDX_R_OMO =0x%x\n",OPRIDX_AUTIDX_R_OMO ));
  SA_DBG2(("mpiOperatorManagementRsp:errorQualifier =0x%x\n", errorQualifier));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiOperatorManagementRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "36");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
  agEvent.status = status;
  agEvent.info = OPRIDX_AUTIDX_R_OMO;
  agEvent.encryptOperation = OSSA_HW_ENCRYPT_OPERATOR_MANAGEMENT;
  if (status == OPR_MGMT_MPI_ENC_ERR_OPR_PARAM_ILLEGAL)
  {
    agEvent.eq = errorQualifier;
  }

  ossaOperatorManagementCB(agRoot, agContext, status, errorQualifier);

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiOperatorManagementRsp: 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);

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

  return AGSA_RC_SUCCESS;
}

GLOBAL bit32 mpiBistRsp(
  agsaRoot_t               *agRoot,
  agsaEncryptBistRsp_t     *pIomb
  )
{
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  agsaHWEventEncrypt_t agEvent;
  bit32               status;
  bit32               results[11];
  bit32               length;
  bit32               subop;
  bit32               tag;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"37");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &subop, pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, subop));
  OSSA_READ_LE_32(AGROOT, &results[0], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[0]));
  OSSA_READ_LE_32(AGROOT, &results[1], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[1]));
  OSSA_READ_LE_32(AGROOT, &results[2], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[2]));
  OSSA_READ_LE_32(AGROOT, &results[3], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[3]));
  OSSA_READ_LE_32(AGROOT, &results[4], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[4]));
  OSSA_READ_LE_32(AGROOT, &results[5], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[5]));
  OSSA_READ_LE_32(AGROOT, &results[6], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[6]));
  OSSA_READ_LE_32(AGROOT, &results[7], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[7]));
  OSSA_READ_LE_32(AGROOT, &results[8], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[8]));
  OSSA_READ_LE_32(AGROOT, &results[9], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[9]));
  OSSA_READ_LE_32(AGROOT, &results[10], pIomb, OSSA_OFFSET_OF(agsaEncryptBistRsp_t, testResults[10]));

  subop &= 0xFF;
  SA_DBG1(("mpiBistRsp: HTag=0x%x subops =0x%x status =0x%x\n",pIomb->tag, subop, status));

  switch(subop)
  {
    case AGSA_BIST_TEST:
      length =  sizeof(agsaEncryptSelfTestStatusBitMap_t);
      break;
    case AGSA_SHA_TEST:
      length = sizeof(agsaEncryptSHATestResult_t);
      break;
    case AGSA_HMAC_TEST:
      length = sizeof(agsaEncryptHMACTestResult_t);
      break;
    default:
      length = 0;
      break;
  }

  si_memset(&agEvent, 0, sizeof(agsaHWEventEncrypt_t));
  agEvent.status = status;
  agEvent.encryptOperation = OSSA_HW_ENCRYPT_TEST_EXECUTE;
  agEvent.info = length;
  agEvent.eq   = subop;
  agEvent.handle = agNULL;
  agEvent.param = &results;

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiBistRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "37");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  ossaHwCB(agRoot, NULL, OSSA_HW_EVENT_ENCRYPTION, 0, (void*)&agEvent, agContext);

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiBistRsp: 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);

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

  return AGSA_RC_SUCCESS;
}

/******************************************************************************/
/*! \brief Set Operator Response
 *
 *  This routine handles the response of the Operator management message
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiSetOperatorRsp(
  agsaRoot_t               *agRoot,
  agsaSetOperatorRsp_t     *pIomb
  )
{
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest = agNULL;
  agsaContext_t       *agContext = agNULL;
  bit32               ERR_QLFR_OPRIDX_PIN_ACS, OPRIDX_PIN_ACS, status, errorQualifier, tag = 0;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"38");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaSetOperatorRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaSetOperatorRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &ERR_QLFR_OPRIDX_PIN_ACS, pIomb, OSSA_OFFSET_OF(agsaSetOperatorRsp_t, ERR_QLFR_OPRIDX_PIN_ACS));

  errorQualifier = ERR_QLFR_OPRIDX_PIN_ACS >> 16;
  OPRIDX_PIN_ACS = ERR_QLFR_OPRIDX_PIN_ACS & 0xFFFF;

  SA_DBG1(("mpiSetOperatorRsp: HTag=0x%x ERR_QLFR=0x%x OPRIDX_PIN_ACS=0x%x \n",tag, errorQualifier, OPRIDX_PIN_ACS));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiSetOperatorRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "38");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;


  ossaSetOperatorCB(agRoot,agContext,status,errorQualifier );

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiSetOperatorRsp: 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);

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

  return AGSA_RC_SUCCESS;
}

/******************************************************************************/
/*! \brief Get Operator Response
 *
 *  This routine handles the response of the Operator management message
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiGetOperatorRsp(
  agsaRoot_t               *agRoot,
  agsaGetOperatorRsp_t     *pIomb
  )
{
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32                Num_Option, NumOperators ,status, tag;
  bit8                 option, Role = 0;
  bit32                IDstr[8];
  bit8                *tmpIDstr = agNULL;
  agsaID_t            *IDString = agNULL;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3f");

  si_memset(&IDstr, 0, sizeof(IDstr));
  OSSA_READ_LE_32(AGROOT, &tag,         pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, tag));
  OSSA_READ_LE_32(AGROOT, &status,      pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, status));
  OSSA_READ_LE_32(AGROOT, &Num_Option,  pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, Num_Option));
  OSSA_READ_LE_32(AGROOT, &IDstr[0],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[0]));
  OSSA_READ_LE_32(AGROOT, &IDstr[1],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[1]));
  OSSA_READ_LE_32(AGROOT, &IDstr[2],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[2]));
  OSSA_READ_LE_32(AGROOT, &IDstr[3],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[3]));
  OSSA_READ_LE_32(AGROOT, &IDstr[4],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[4]));
  OSSA_READ_LE_32(AGROOT, &IDstr[5],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[5]));
  OSSA_READ_LE_32(AGROOT, &IDstr[6],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[6]));
  OSSA_READ_LE_32(AGROOT, &IDstr[7],    pIomb, OSSA_OFFSET_OF(agsaGetOperatorRsp_t, IDString[7]));

  SA_DBG1(("mpiGetOperatorRsp:tag=0x%x status=0x%x Num_Option=0x%x IDString_Role=0x%x\n",
           tag, status, Num_Option, IDstr[0]));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetOperatorRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3f");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;
  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;
  option = Num_Option & 0xFF;
  NumOperators = (Num_Option >> SHIFT8) & 0xFF;
  /* current operator's Role/ID, valid only if option == 1 */
  if ( option == 1)
  {
    /* extra the role value as parameter */
    Role = IDstr[0] & 0xFF;
    tmpIDstr = (bit8*)&IDstr[0];
    tmpIDstr++; /* skip role byte */
    IDString = (agsaID_t *)tmpIDstr;
    SA_DBG1(("mpiGetOperatorRsp: OSSA_IO_SUCCESS\n"));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[0], IDString->ID[1], IDString->ID[2], IDString->ID[3]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[4], IDString->ID[5], IDString->ID[6], IDString->ID[7]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[8], IDString->ID[9], IDString->ID[10],IDString->ID[11]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[12],IDString->ID[13],IDString->ID[14],IDString->ID[15]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[16],IDString->ID[17],IDString->ID[18],IDString->ID[19]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[20],IDString->ID[21],IDString->ID[22],IDString->ID[23]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x 0x%02x\n",IDString->ID[24],IDString->ID[25],IDString->ID[26],IDString->ID[27]));
    SA_DBG2(("mpiGetOperatorRsp: 0x%02x 0x%02x 0x%02x\n",       IDString->ID[28],IDString->ID[29],IDString->ID[30]));
  }

  SA_DBG1(("mpiGetOperatorRsp:status 0x%x option 0x%x Role 0x%x\n",status,option,Role ));

  ossaGetOperatorCB(agRoot,agContext,status,option,NumOperators ,Role,IDString );

  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  SA_ASSERT((pRequest->valid), "pRequest->valid");
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
  {
    SA_DBG1(("mpiGetOperatorRsp: 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);

  smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3f");

  return AGSA_RC_SUCCESS;
}


GLOBAL bit32 mpiGetVHistRsp(
   agsaRoot_t         *agRoot,
   agsaGetVHistCapRsp_t *pIomb
  )
{

  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = agNULL;
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;

  bit32    tag = 0;           /* 1 */
  bit32    status = 0;        /* 2 */
  bit32    channel;          /* 3 */
  bit32    BistLo;           /* 4 */
  bit32    BistHi;           /* 5 */
  bit32    BytesXfered = 0;  /* 6 */
  bit32    PciLo;            /* 7 */
  bit32    PciHi;            /* 8 */
  bit32    PciBytecount = 0;  /* 9 */

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3K");

  /* sanity check */
  SA_ASSERT((agNULL != agRoot), "");
  saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
  SA_ASSERT((agNULL != saRoot), "");

  if(smIS_SPC12V(agRoot))
  {
    OSSA_READ_LE_32(AGROOT, &tag,          pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,tag));
    OSSA_READ_LE_32(AGROOT, &status,       pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,status));
    OSSA_READ_LE_32(AGROOT, &channel,      pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,channel));
    OSSA_READ_LE_32(AGROOT, &BistLo,       pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,BistLo));
    OSSA_READ_LE_32(AGROOT, &BistHi,       pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,BistHi));
    OSSA_READ_LE_32(AGROOT, &BytesXfered,  pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,BytesXfered));
    OSSA_READ_LE_32(AGROOT, &PciLo,        pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,PciLo));
    OSSA_READ_LE_32(AGROOT, &PciHi,        pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,PciHi));
    OSSA_READ_LE_32(AGROOT, &PciBytecount, pIomb, OSSA_OFFSET_OF(agsaGetVHistCapRsp_t,PciBytecount));
  }
  else
  {
    /* SPC does not support this command */
    SA_DBG1(("mpiGetVHistRsp: smIS_SPC12V only\n"));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3K");
    return AGSA_RC_FAILURE;
  }

  SA_DBG3(("mpiGetVHistRsp: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiGetVHistRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3K");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* check status success or failure */
  if (status)
  {
    SA_DBG1(("mpiGetVHistRsp: status is FAILED, status = %x\n", status ));

    if (pRequest->completionCB == agNULL)
    {
      ossaVhistCaptureCB(agRoot, agContext, status, BytesXfered);
    }
    else
    {
      (*(ossaVhistCaptureCB_t)(pRequest->completionCB))(agRoot, agContext, status, BytesXfered);
    }

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

    smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "3K");
    return AGSA_RC_FAILURE;
  }

  /* status is SUCCESS */
  SA_DBG1(("mpiGetVHistRsp: status is SUCCESS\n" ));

  if (pRequest->completionCB == agNULL)
  {
    ossaVhistCaptureCB(agRoot, agContext, status, BytesXfered);
  }
  else
  {
    (*(ossaVhistCaptureCB_t)(pRequest->completionCB))(agRoot, agContext, status, BytesXfered);
  }
  
  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "3K");

  return ret;
}



/******************************************************************************/
/*! \brief DifEncOffload Response
 *
 *  This routine handles the response of the DifEncOffload Response
 *
 *  \param agRoot       Handles for this instance of SAS/SATA LLL
 *  \param pIomb        Pointer of IOMB Mesage
 *
 *  \return sucess or fail
 *
 */
/*******************************************************************************/
GLOBAL bit32 mpiDifEncOffloadRsp(
  agsaRoot_t               *agRoot,
  agsaDifEncOffloadRspV_t  *pIomb
  )
{

  bit32               ret = AGSA_RC_SUCCESS;
  agsaLLRoot_t        *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
  agsaIORequestDesc_t *pRequest;
  agsaContext_t       *agContext;
  bit32               tag, status;
  agsaOffloadDifDetails_t details;

  smTraceFuncEnter(hpDBG_VERY_LOUD,"3F");

  OSSA_READ_LE_32(AGROOT, &tag, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, tag));
  OSSA_READ_LE_32(AGROOT, &status, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, status));
  /* get TAG */
  SA_DBG3(("mpiDifEncOffloadRsp: HTag=0x%x\n", tag));

  /* get request from IOMap */
  pRequest = (agsaIORequestDesc_t*)saRoot->IOMap[tag].IORequest;
  if (agNULL == pRequest)
  {
    SA_DBG1(("mpiDifEncOffloadRsp: Bad Response IOMB!!! pRequest is NULL. TAG=0x%x STATUS=0x%x\n", tag, status));
    smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3F");
    return AGSA_RC_FAILURE;
  }

  agContext = saRoot->IOMap[tag].agContext;

  /* remove the request from IOMap */
  saRoot->IOMap[tag].Tag = MARK_OFF;
  saRoot->IOMap[tag].IORequest = agNULL;
  saRoot->IOMap[tag].agContext = agNULL;

  SA_ASSERT((pRequest->valid), "pRequest->valid");

  /* check status success or failure */
  if (status)
  {
    SA_DBG1(("mpiDifEncOffloadRsp: status is FAILED, status = %x\n", status ));

    if (status == OSSA_IO_XFR_ERROR_DIF_MISMATCH || status == OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH ||
        status == OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH || status == OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH)
    {
      si_memset(&details, 0, sizeof(agsaOffloadDifDetails_t));
      OSSA_READ_LE_32(AGROOT, &details.ExpectedCRCUDT01, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, ExpectedCRCUDT01));
      OSSA_READ_LE_32(AGROOT, &details.ExpectedUDT2345, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, ExpectedUDT2345));
      OSSA_READ_LE_32(AGROOT, &details.ActualCRCUDT01, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, ActualCRCUDT01));
      OSSA_READ_LE_32(AGROOT, &details.ActualUDT2345, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, ActualUDT2345));
      OSSA_READ_LE_32(AGROOT, &details.DIFErr, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, DIFErr));
      OSSA_READ_LE_32(AGROOT, &details.ErrBoffset, pIomb, OSSA_OFFSET_OF(agsaDifEncOffloadRspV_t, ErrBoffset));

      if (pRequest->completionCB == agNULL)
      {
        ossaDIFEncryptionOffloadStartCB(agRoot, agContext, status, &details);
      }
      else
      {
        (*(ossaDIFEncryptionOffloadStartCB_t)(pRequest->completionCB))(agRoot, agContext, status, &details);
      }
    }
    else
    {
      if (pRequest->completionCB == agNULL)
      {
        ossaDIFEncryptionOffloadStartCB(agRoot, agContext, status, agNULL);
      }
      else
      {
        (*(ossaDIFEncryptionOffloadStartCB_t)(pRequest->completionCB))(agRoot, agContext, status, agNULL);
      }
    }

    smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3F");

    ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
    pRequest->valid = agFALSE;
    /* return the request to free pool */
    saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
    ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

    return AGSA_RC_FAILURE;
  }

  /* status is SUCCESS */
  SA_DBG1(("mpiDifEncOffloadRsp: status is SUCCESS\n" ));

  if (pRequest->completionCB == agNULL)
  {
    ossaDIFEncryptionOffloadStartCB(agRoot, agContext, status, agNULL);
  }
  else
  {
    (*(ossaDIFEncryptionOffloadStartCB_t)(pRequest->completionCB))(agRoot, agContext, status, agNULL);
  }
  
  ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
  pRequest->valid = agFALSE;
  /* return the request to free pool */
  saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
  ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);

  /* return value */
  smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "3F");

  return ret;
}