freebsd-skq/sys/dev/pms/RefTisa/sallsdk/spc/sampicmd.c

2939 lines
113 KiB
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 sampicmd.c
* \brief The file implements the functions of MPI Inbound IOMB/Command to SPC
*
*/
/******************************************************************************/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#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 'I'
#endif
/******************************************************************************/
/*! \brief SAS/SATA LL API ECHO Command
*
* This command used to test that MPI between host and SPC IOP is operational.
*
* \param agRoot Handles for this instance of SAS/SATA hardware
* \param agContext Context of SPC FW Flash Update Command
* \param queueNum Inbound/outbound queue number
* \param echoPayload Pointer of Echo payload of IOMB
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 saEchoCommand(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
void *echoPayload
)
{
bit32 ret = AGSA_RC_SUCCESS;
smTraceFuncEnter(hpDBG_VERY_LOUD, "xa");
/* setup IOMB payload */
ret = mpiEchoCmd(agRoot, queueNum, agContext, echoPayload);
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xa");
return ret;
}
/******************************************************************************/
/*! \brief Build a IOMB command and send to SPC
*
* Build an IOMB if there is a free message buffer and Send it to SPC
*
* \param agRoot Handles for this instance of SAS/SATA hardware
* \param payload Pointer of payload in the IOMB
* \param category Category of IOMB
* \param opcode Opcode of IOMB
* \param size Size of IOMB
* \param queueNum Inbound/outbound queue number
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*/
/*******************************************************************************/
GLOBAL bit32 mpiBuildCmd(
agsaRoot_t *agRoot,
bit32 *payload,
mpiMsgCategory_t category,
bit16 opcode,
bit16 size,
bit32 queueNum
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
mpiICQueue_t *circularQ;
void *pMessage;
bit32 ret = AGSA_RC_SUCCESS;
bit32 retVal;
bit8 inq, outq;
smTraceFuncEnter(hpDBG_VERY_LOUD, "xb");
inq = (bit8)(queueNum & MPI_IB_NUM_MASK);
outq = (bit8)((queueNum & MPI_OB_NUM_MASK) >> MPI_OB_SHIFT);
SA_ASSERT((AGSA_MAX_INBOUND_Q > inq), "The IBQ Number is out of range.");
SA_ASSERT((AGSA_MAX_OUTBOUND_Q > outq), "The OBQ Number is out of range.");
#ifdef SA_USE_MAX_Q
outq = saRoot->QueueConfig.numOutboundQueues -1;
SA_DBG1(("mpiBuildCmd, set OBQ to %d\n",outq));
#endif /* SA_USE_MAX_Q */
/* get a free inbound queue entry */
#ifdef SA_LL_IBQ_PROTECT
ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
#endif /* SA_LL_IBQ_PROTECT */
circularQ = &saRoot->inboundQueue[inq];
retVal = mpiMsgFreeGet(circularQ, size, &pMessage);
/* return FAILURE if error happened */
if (AGSA_RC_FAILURE == retVal)
{
#ifdef SA_LL_IBQ_PROTECT
ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
#endif /* SA_LL_IBQ_PROTECT */
/* the message size exceeds the inbound queue message size */
SA_DBG1(("mpiBuildCmd, failure\n"));
ret = AGSA_RC_FAILURE;
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xb");
return ret;
}
/* return BUSY if no more inbound queue entry available */
if (AGSA_RC_BUSY == retVal)
{
SA_DBG1(("mpiBuildCmd, no more IOMB\n"));
ret = AGSA_RC_BUSY;
}
else
{
/* copy payload if it is necessary */
if (agNULL != payload)
{
si_memcpy(pMessage, payload, (size - sizeof(mpiMsgHeader_t)));
}
/* post the message to SPC */
if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pMessage, category, opcode, outq, (bit8)circularQ->priority))
{
ret = AGSA_RC_FAILURE;
}
}
#ifdef SA_LL_IBQ_PROTECT
ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq);
#endif /* SA_LL_IBQ_PROTECT */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xb");
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI ECHO Command
*
* This command used to test that MPI between host and SPC IOP is operational.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param queueNum Inbound/outbound queue number
* \param tag Tag of this IOMB
* \param echoPayload Pointer to the ECHO payload of inbound IOMB
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiEchoCmd(
agsaRoot_t *agRoot,
bit32 queueNum,
agsaContext_t *agContext,
void *echoPayload
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaEchoCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD, "xc");
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Get request from free IORequests */
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiEchoCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xc");
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* build IOMB command and send to SPC */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaEchoCmd_t, tag), pRequest->HTag);
/* copy Echo payload */
si_memcpy(&payload.payload[0], echoPayload, (sizeof(agsaEchoCmd_t) - 4));
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_ECHO, IOMB_SIZE64, queueNum);
SA_DBG3(("mpiEchoCmd, return value = %d\n", ret));
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiEchoCmd, sending IOMB failed\n" ));
}
#ifdef SALL_API_TEST
else
{
saRoot->LLCounters.IOCounter.numEchoSent++;
}
#endif
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xc");
return ret;
}
/******************************************************************************/
/*! \brief Get Phy Profile Command SPCv
*
* This command is get # of phys and support speeds from SPCV.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agDevHandle Handle of device
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiGetPhyProfileCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 Operation,
bit32 PhyId,
void *agCB
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
bit32 ret = AGSA_RC_SUCCESS;
agsaGetPhyProfileCmd_V_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD, "xd");
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Get request from free IORequests */
pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
SA_DBG1(("mpiGetPhyProfileCmd, Operation 0x%x PhyId %d \n",Operation ,PhyId ));
/* If no LL Control request entry avalibale */
if ( agNULL == pRequest )
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiGetPhyProfileCmd, No request from free list\n" ));
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
/* Remove the request from free list */
saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->completionCB = agCB;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaGetPhyProfileCmd_V_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetPhyProfileCmd_V_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetPhyProfileCmd_V_t, Reserved_Ppc_SOP_PHYID), (((Operation & 0xF) << SHIFT8 ) | (PhyId & 0xFF) ) );
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_PHY_PROFILE, IOMB_SIZE128, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiGetPhyProfileCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiGetPhyProfileCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xd");
/* return value */
return ret;
}
GLOBAL bit32 mpiVHistCapCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 Channel,
bit32 NumBitLo,
bit32 NumBitHi,
bit32 PcieAddrLo,
bit32 PcieAddrHi,
bit32 ByteCount )
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest= agNULL;
bit32 ret = AGSA_RC_SUCCESS;
agsaGetVHistCap_V_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"3C");
SA_DBG1(("mpiVHistCapCmd\n"));
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Get request from free IORequests */
pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry avalibale */
if ( agNULL == pRequest )
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1((", No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3C");
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
/* Remove the request from free list */
saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->completionCB = (void *)ossaGetPhyProfileCB;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaGetVHistCap_V_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, Channel), Channel );
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, NumBitLo), NumBitLo);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, NumBitHi), NumBitHi);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, PcieAddrLo),PcieAddrLo);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, PcieAddrHi),PcieAddrHi);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetVHistCap_V_t, ByteCount), ByteCount );
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_VHIST_CAP, IOMB_SIZE128,queueNum );
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiVHistCapCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiVHistCapCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3C");
/* return value */
return(ret);
}
GLOBAL bit32 mpiSetPhyProfileCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 Operation,
bit32 PhyId,
bit32 length,
void * buffer
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
bit32 ret = AGSA_RC_SUCCESS;
bit32 i;
agsaSetPhyProfileCmd_V_t payload;
bit32 * PageData =(bit32 * )buffer;
smTraceFuncEnter(hpDBG_VERY_LOUD,"2P");
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Get request from free IORequests */
pRequest = (agsaIORequestDesc_t *)saLlistGetHead(&(saRoot->freeIORequests));
SA_DBG1(("mpiSetPhyProfileCmd, Operation 0x%x PhyId %d \n",Operation ,PhyId ));
/* If no LL Control request entry avalibale */
if ( agNULL == pRequest )
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetPhyProfileCmd, No request from free list\n" ));
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
/* Remove the request from free list */
saLlistRemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->SOP = (bit16) Operation;
pRequest->completionCB = (void *)ossaGetPhyProfileCB;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaSetPhyProfileCmd_V_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetPhyProfileCmd_V_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetPhyProfileCmd_V_t, Reserved_Ppc_SOP_PHYID), (((Operation & 0xF) << SHIFT8 ) | (PhyId & 0xFF) ) );
for(i=0; i < (length / sizeof(bit32)); i++)
{
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetPhyProfileCmd_V_t, PageSpecificArea[i]),* (PageData+i) );
}
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_PHY_PROFILE, IOMB_SIZE128, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetPhyProfileCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiGetPhyProfileCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2P");
/* return value */
return ret;
}
/******************************************************************************/
/*! \brief Get Device Information Command
*
* This command is get # of phys and support speeds from SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agDevHandle Handle of device
* \param deviceid Device Id
* \param opton oprion
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiGetDeviceInfoCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 deviceid,
bit32 option,
bit32 queueNum
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
bit32 ret = AGSA_RC_SUCCESS;
agsaGetDevInfoCmd_t payload;
SA_ASSERT((agNULL !=saRoot ), "");
if(saRoot == agNULL)
{
SA_DBG1(("mpiGetDeviceInfoCmd: saRoot == agNULL\n"));
return(AGSA_RC_FAILURE);
}
smTraceFuncEnter(hpDBG_VERY_LOUD,"2K");
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Get request from free IORequests */
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiGetDeviceInfoCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2K");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->DeviceInfoCmdOption = (bit8)option;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaGetDevInfoCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevInfoCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevInfoCmd_t, DeviceId), deviceid);
/* build IOMB command and send to SPC */
if( smIS_SPC(agRoot))
{
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SPC_GET_DEV_INFO, IOMB_SIZE64, queueNum);
}
else
{
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DEV_INFO, IOMB_SIZE64, queueNum);
}
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiGetDeviceInfoCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiGetDeviceInfoCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2K");
/* return value */
return ret;
}
/******************************************************************************/
/*! \brief Set Device Information Command
*
* This command is Set Device Information to SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agDevHandle Handle of device
* \param deviceid Device Id
* \param opton oprion
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiSetDeviceInfoCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 deviceid,
bit32 option,
bit32 queueNum,
bit32 param,
ossaSetDeviceInfoCB_t agCB
)
{
agsaLLRoot_t *saRoot = agNULL;
agsaIORequestDesc_t *pRequest = agNULL;
bit32 ret = AGSA_RC_SUCCESS;
agsaSetDevInfoCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xe");
/* sanity check */
SA_ASSERT((agNULL != agRoot), "");
saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
SA_ASSERT((agNULL != saRoot), "");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
SA_DBG2(("mpiSetDeviceInfoCmd, param 0x%08X option 0x%08X\n",param,option ));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiSetDeviceInfoCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xe");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
/* Remove the request from free list */
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->completionCB = (ossaSSPCompletedCB_t)agCB;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaSetDevInfoCmd_t));
/* set tag field */
if(smIS_SPC(agRoot))
{
option &= SET_DEV_INFO_SPC_DW3_MASK;
param &= SET_DEV_INFO_SPC_DW4_MASK;
}
else
{
option &= SET_DEV_INFO_V_DW3_MASK;
param &= SET_DEV_INFO_V_DW4_MASK;
}
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, deviceId), deviceid);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, SA_SR_SI), option);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDevInfoCmd_t, DEVA_MCN_R_ITNT), param );
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_DEV_INFO, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetDeviceInfoCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiSetDeviceInfoCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xe");
/* return value */
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI Phy Start Command
*
* This command sends to SPC for the I/O.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param tag tage for IOMB
* \param phyId the phy id of the link will be started
* \param agPhyConfig the phy properity
* \param agSASIdentify the SAS identify frame will be sent by the phy
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiPhyStartCmd(
agsaRoot_t *agRoot,
bit32 tag,
bit32 phyId,
agsaPhyConfig_t *agPhyConfig,
agsaSASIdentify_t *agSASIdentify,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaPhyStartCmd_t payload;
bit32 *pValue;
bit32 *ptemp;
bit32 index;
bit32 dw2 = 0;
#if defined(SALLSDK_DEBUG)
bit32 Sscd;
#endif /* SALLSDK_DEBUG */
smTraceFuncEnter(hpDBG_VERY_LOUD,"xg");
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaPhyStartCmd_t));
pValue = (bit32 *)agSASIdentify;
ptemp = (bit32 *)&payload.sasIdentify;
index = (agPhyConfig->phyProperties & 0x0ff00) >> SHIFT8;
#if defined(SALLSDK_DEBUG)
Sscd = (agPhyConfig->phyProperties & 0xf0000) >> SHIFT16;
#endif /* SALLSDK_DEBUG */
SA_DBG1(("mpiPhyStartCmd,phyId = %d dw 2 0x%08X\n",phyId ,((phyId & SM_PHYID_MASK) | ((agPhyConfig->phyProperties & 0xfff) << SHIFT8) | (agPhyConfig->phyProperties & 0xf0000) )));
SA_DBG2(("mpiPhyStartCmd,phyId 0x%x phyProperties 0x%x index 0x%x Sscd 0x%x\n",phyId, agPhyConfig->phyProperties,index,Sscd));
dw2 = ((phyId & SM_PHYID_MASK) | /* PHY id */
((agPhyConfig->phyProperties & 0x000000FF) << SHIFT8)| /* SLR Mode */
(agPhyConfig->phyProperties & 0x000f0000) | /* SSCD */
(agPhyConfig->phyProperties & 0x00700000) | /* setting bit20, bit21 and bit22 for optical mode */
(agPhyConfig->phyProperties & 0x00800000) ); /* bit23 active cable mode BCT Disable 12g only*/
/* Haileah Phy analogsetting bit enable*/
if(smIS_SPC(agRoot))
{
if( smIS_spc8081(agRoot))
{
dw2 = dw2 | 0x08000;
}
}
SA_DBG1(("mpiPhyStartCmd,dw2 0x%08x\n",dw2));
SA_ASSERT(((agSASIdentify->sasAddressHi[0] || agSASIdentify->sasAddressHi[1] ||
agSASIdentify->sasAddressHi[2] || agSASIdentify->sasAddressHi[3] ||
agSASIdentify->sasAddressLo[0] || agSASIdentify->sasAddressLo[1] ||
agSASIdentify->sasAddressLo[2] || agSASIdentify->sasAddressLo[3])), "SAS Address Zero");
SA_DBG1(("mpiPhyStartCmd,SAS addr Hi 0x%02X%02X%02X%02X Lo 0x%02X%02X%02X%02X\n",
agSASIdentify->sasAddressHi[0],agSASIdentify->sasAddressHi[1],
agSASIdentify->sasAddressHi[2],agSASIdentify->sasAddressHi[3],
agSASIdentify->sasAddressLo[0],agSASIdentify->sasAddressLo[1],
agSASIdentify->sasAddressLo[2],agSASIdentify->sasAddressLo[3]));
/* setup phy ID field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStartCmd_t, SscdAseSHLmMlrPhyId),dw2);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStartCmd_t, tag), tag);
/* setup analog setting index field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStartCmd_t, analogSetupIdx), index);
/* copy SASIdentify to payload of IOMB */
si_memcpy(ptemp, pValue, sizeof(agsaSASIdentify_t));
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PHYSTART, IOMB_SIZE64, queueNum);
SA_DBG3(("mpiPhyStartCmd, return value = %d\n", ret));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xg");
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI Phy Stop Command
*
* This command sends to SPC for the I/O.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param tag tag of IOMB
* \param phyId To stop the phyId
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiPhyStopCmd(
agsaRoot_t *agRoot,
bit32 tag,
bit32 phyId,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaPhyStopCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xh");
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaPhyStopCmd_t));
/* set tag */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStopCmd_t, tag), tag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaPhyStopCmd_t, phyId), (phyId & SM_PHYID_MASK ));
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_PHYSTOP, IOMB_SIZE64, queueNum);
SA_DBG3(("mpiPhyStopCmd, return value = %d\n", ret));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xh");
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI SMP Request Command
*
* This command sends to SPC for the SMP.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param pIomb pointer of IOMB
* \param opcode opcode of IOMB
* \param payload pointer of payload
* \param inq inbound queue number
* \param outq outbound queue number
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiSMPCmd(
agsaRoot_t *agRoot,
void *pIomb,
bit16 opcode,
agsaSMPCmd_t *payload,
bit8 inq,
bit8 outq
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
mpiICQueue_t *circularQ;
bit32 ret = AGSA_RC_SUCCESS;
#if defined(SALLSDK_DEBUG)
mpiMsgHeader_t *msgHeader;
bit32 bc;
#endif /* SALLSDK_DEBUG */
smTraceFuncEnter(hpDBG_VERY_LOUD,"xi");
SA_DBG6(("mpiSMPCmd: start\n"));
#if defined(SALLSDK_DEBUG)
msgHeader = (mpiMsgHeader_t*)(((bit8*)pIomb) - sizeof(mpiMsgHeader_t));
bc = (((msgHeader->Header) >> SHIFT24) & BC_MASK);
#endif /* SALLSDK_DEBUG */
SA_DBG6(("mpiSMPCmd: before msgHeader bc %d\n", bc));
/* copy payload if it is necessary */
if (agNULL != payload)
{
si_memcpy(pIomb, payload, sizeof(agsaSMPCmd_t));
}
SA_DBG6(("mpiSMPCmd: after msgHeader bc %d\n", bc));
/* post the IOMB to SPC */
circularQ = &saRoot->inboundQueue[inq];
if (AGSA_RC_FAILURE == mpiMsgProduce(circularQ, (void *)pIomb, MPI_CATEGORY_SAS_SATA, opcode, outq, (bit8)circularQ->priority))
ret = AGSA_RC_FAILURE;
SA_DBG3(("mpiSMPCmd, return value = %d\n", ret));
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xi");
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI Deregister Device Handle Command
*
* This command used to deregister(remove) the device handle.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agDevHandle Device Handle
* \param deviceId index of device
* \param portId index of port
* \param queueNum IQ/OQ number
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiDeregDevHandleCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaDeviceDesc_t *pDevice,
bit32 deviceId,
bit32 portId,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaDeregDevHandleCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xp");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiDeregDevHandleCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xp");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
pRequest->pDevice = pDevice;
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
pRequest->valid = agTRUE;
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* clean the payload to zeros */
si_memset(&payload, 0, sizeof(agsaDeregDevHandleCmd_t));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDeregDevHandleCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDeregDevHandleCmd_t, deviceId), deviceId);
/* build IOMB command and send it to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_DEREG_DEV_HANDLE, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetVPDCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiDeregDevHandleCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xp");
/* return value */
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI Get Device Handle Command
*
* This command used to get device handle.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context of Device Handle Command
* \param portId index of port
* \param flags flags
* \param maxDevs Maximum Device Handles
* \param queueNum IQ/OQ number
* \param skipCount skip device entry count
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiGetDeviceHandleCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 portId,
bit32 flags,
bit32 maxDevs,
bit32 queueNum,
bit32 skipCount
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaGetDevHandleCmd_t payload;
bit32 using_reserved = agFALSE;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xj");
/* Get request from free CntrlRequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
if(agNULL != pRequest)
{
using_reserved = agTRUE;
SA_DBG1(("mpiGetDeviceHandleCmd, using saRoot->freeReservedRequests\n"));
}
else
{
SA_DBG1(("mpiGetDeviceHandleCmd, No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xj");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
}
/* Remove the request from free list */
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* clean the payload to zeros */
si_memset(&payload, 0, sizeof(agsaGetDevHandleCmd_t));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevHandleCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevHandleCmd_t, DevADevTMaxDIDportId),
((portId & PORTID_MASK) | (maxDevs << SHIFT8) | (flags << SHIFT24)));
/* set starting Number */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDevHandleCmd_t, skipCount), skipCount);
/* build IOMB command and send it to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DEV_HANDLE, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("mpiGetDeviceHandleCmd: 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(("mpiGetDeviceHandleCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiGetDeviceHandleCmd, return value = %d\n", ret));
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xj");
return ret;
}
/******************************************************************************/
/*! \brief SPC MPI LOCAL PHY CONTROL Command
*
* This command used to do the SPC Phy operation.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param tag tag of IOMB
* \param phyId PHY Id
* \param operation operation of PHY control
* \param queueNum IQ/OQ number
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiLocalPhyControlCmd(
agsaRoot_t *agRoot,
bit32 tag,
bit32 phyId,
bit32 operation,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLocalPhyCntrlCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xl");
SA_DBG3(("mpiLocalPhyControlCmd, phyId 0x%X operation 0x%x dw2 0x%x\n",phyId, operation,(((operation & BYTE_MASK) << SHIFT8) | (phyId & SM_PHYID_MASK))));
/* clean the payload field */
si_memset(&payload, 0, sizeof(agsaLocalPhyCntrlCmd_t));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaLocalPhyCntrlCmd_t, phyOpPhyId),
(((operation & BYTE_MASK) << SHIFT8) | (phyId & SM_PHYID_MASK)));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaLocalPhyCntrlCmd_t, tag), tag);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_LOCAL_PHY_CONTROL, IOMB_SIZE64, queueNum);
SA_DBG3(("mpiLocalPhyControlCmd, return value = %d\n", ret));
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xl");
return ret;
}
/******************************************************************************/
/*! \brief Device Handle Accept Command
*
* This command is Device Handle Accept IOMB to SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the set VPD command
* \param ctag controller tag
* \param deviceId device Id
* \param action action
* \param queueNum queue Number
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiDevHandleAcceptCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 ctag,
bit32 deviceId,
bit32 action,
bit32 flag,
bit32 itlnx,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaDevHandleAcceptCmd_t payload;
bit32 DW4 =0;
bit32 mcn =0;
bit32 awt =0;
bit32 ha =0;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xt");
if(deviceId & 0xFFFF0000)
{
ha = 1;
}
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot,LL_IOREQ_LOCKEQ_LOCK );
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
SA_DBG2(("mpiDevHandleAcceptCmd, deviceId 0x%x action 0x%x flag 0x%x itlnx 0x%x\n",deviceId,action,flag,itlnx ));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
ossaSingleThreadedLeave(agRoot,LL_IOREQ_LOCKEQ_LOCK );
SA_DBG1(("mpiDevHandleAcceptCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xt");
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Do not mark as valid at this IOMB does not complete in OBQ */
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaDevHandleAcceptCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, deviceId), deviceId);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, Ctag), ctag);
mcn = (flag & 0xF0000) >>SHIFT16;
awt = (flag & 2)>>SHIFT1;
DW4 = (action << SHIFT24) | \
mcn << SHIFT20 | \
awt << SHIFT17 | \
ha << SHIFT16 | \
itlnx;
SA_DBG2(("mpiDevHandleAcceptCmd,DW4 0x%x\n",DW4 ));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDevHandleAcceptCmd_t, DevA_MCN_R_R_HA_ITNT),DW4);
}
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_DEV_HANDLE_ACCEPT, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
SA_DBG1(("mpiDevHandleAcceptCmd, sending IOMB failed\n" ));
}
else
{
SA_DBG1(("mpiDevHandleAcceptCmd, sending IOMB succeeded\n" ));
}
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("mpiDevHandleAcceptCmd: 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));
}
/* return value */
ossaSingleThreadedLeave(agRoot,LL_IOREQ_LOCKEQ_LOCK );
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xt");
return ret;
}
/******************************************************************************/
/*! \brief SPC READ REGISTER DUMP Command
*
* This command used to do the SPC Read Register Dump command.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param tag tag of IOMB
* \param cpuId CPU Id
* \param queueNum IQ/OQ number
* \param cpuId AAP1 or IOP
* \param cOffset offset of the register dump data
* \param addrHi Hi address if Register Dump data
* \param addrHi Low address if Register Dump data
* \param len the length of for read
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiNVMReadRegDumpCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 cpuId,
bit32 cOffset,
bit32 addrHi,
bit32 addrLo,
bit32 len
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaGetNVMDataCmd_t payload;
bit32 nvmd = 0;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xk");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiNVMReadRegDumpCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xk");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* clean the payload field */
si_memset(&payload, 0, sizeof(agsaGetNVMDataCmd_t));
/* only indirect mode */
if (cpuId <= 1)
{
if (cpuId == 0)
nvmd = AAP1_RDUMP | IRMode;
else
nvmd = IOP_RDUMP | IRMode;
/* setup IOMB */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD), nvmd);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset), cOffset);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrLo), addrLo);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrHi), addrHi);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respLen), len);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_NVMD_DATA, IOMB_SIZE64, queueNum);
}
else
{
SA_DBG1(("mpiNVMReadRegDumpCmd, Wrong device type\n" ));
ret = AGSA_RC_FAILURE;
}
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiNVMReadRegDumpCmd, sending IOMB failed\n" ));
}
}
SA_DBG3(("mpiNVMReadRegDumpCmd, return value = %d\n", ret));
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xk");
return ret;
}
/******************************************************************************/
/*! \brief Get NVM Data command
*
* This command is get NVM Data from SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the VPD command
* \param VPDInfo Pointer of VPD Information
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiGetNVMDCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaNVMDData_t *NVMDInfo,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_FAILURE;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaGetNVMDataCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xr");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiGetNVMDCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xr");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG3(("mpiGetNVMDCmd, Build IOMB NVMDDevice= 0x%x\n", NVMDInfo->NVMDevice));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaGetNVMDataCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, tag), pRequest->HTag);
if (NVMDInfo->indirectPayload)
{
/* indirect payload IP = 1 */
switch (NVMDInfo->NVMDevice)
{
case AGSA_NVMD_TWI_DEVICES:
/* NVMD = 0 */
/* indirect payload IP = 1 and 0x0 (TWI) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->TWIDeviceAddress << 16) | (NVMDInfo->TWIBusNumber << 12) |
(NVMDInfo->TWIDevicePageSize << 8) | (NVMDInfo->TWIDeviceAddressSize << 4) |
(NVMDInfo->indirectPayload << 31) | NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
case AGSA_NVMD_CONFIG_SEEPROM:
/* NVMD = 1 */
/* Data Offset should be 0 */
if (NVMDInfo->dataOffsetAddress != 0)
{
/* Error for Offset */
SA_DBG1(("mpiGetNVMDCmd, (IP=1)wrong offset = 0x%x\n", NVMDInfo->dataOffsetAddress));
}
/* indirect payload IP = 1, NVMD = 0x1 (SEEPROM0) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | (NVMDInfo->NVMDevice));
break;
case AGSA_NVMD_VPD_FLASH:
/* indirect payload IP = 1 and 0x4 (FLASH) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
case AGSA_NVMD_EXPANSION_ROM:
/* indirect payload IP = 1 and 0x7 (EXPANSION ROM PARTITION) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
case AGSA_NVMD_AAP1_REG_FLASH: /* AGSA_NVMD_REG_FLASH SPCv uses 5 as well */
/* indirect payload IP = 1 and 0x5 (AGSA_NVMD_AAP1_REG_FLASH ) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
case AGSA_NVMD_IOP_REG_FLASH:
/* indirect payload IP = 1 and 0x6 ( AGSA_NVMD_IOP_REG_FLASH ) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
default:
SA_DBG1(("mpiGetNVMDCmd, (IP=1)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
break;
}
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrLo), NVMDInfo->indirectAddrLower32);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respAddrHi), NVMDInfo->indirectAddrUpper32);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, respLen), NVMDInfo->indirectLen);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_NVMD_DATA, IOMB_SIZE64, queueNum);
}
else
{
/* direct payload IP = 0 only for TWI device */
if (AGSA_NVMD_TWI_DEVICES == NVMDInfo->NVMDevice)
{
/* NVMD = 0 */
/* indirect payload IP = 0 and 0x0 (TWI) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->TWIDeviceAddress << SHIFT16) | (NVMDInfo->TWIBusNumber << SHIFT12) |
(NVMDInfo->TWIDevicePageSize << SHIFT8) | (NVMDInfo->TWIDeviceAddressSize << SHIFT4) |
NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress | (NVMDInfo->directLen << SHIFT24));
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_NVMD_DATA, IOMB_SIZE64, queueNum);
}
else
{
SA_DBG1(("mpiGetNVMDCmd, (IP=0)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
ret = AGSA_RC_FAILURE;
/* CB for NVMD with error */
ossaGetNVMDResponseCB(agRoot, agContext, OSSA_NVMD_MODE_ERROR, 0, NVMDInfo->directLen, agNULL);
}
}
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiGetNVMDCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiGetNVMDCmd, return value = %d\n", ret));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xr");
/* return value */
return ret;
}
/******************************************************************************/
/*! \brief Set NVM Data Command
*
* This command is set NVM Data to SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the set VPD command
* \param NVMDInfo pointer of VPD information
* \param queueNum queue Number
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiSetNVMDCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaNVMDData_t *NVMDInfo,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_FAILURE;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaSetNVMDataCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xm");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiSetNVMDCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xm");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG3(("mpiSetNVMDCmd, Build IOMB NVMDDevice= 0x%x\n", NVMDInfo->NVMDevice));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaSetNVMDataCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, tag), pRequest->HTag);
if (NVMDInfo->indirectPayload)
{
/* indirect payload IP = 1 */
switch (NVMDInfo->NVMDevice)
{
case AGSA_NVMD_TWI_DEVICES:
/* NVMD = 0 */
/* indirect payload IP = 1 and 0x0 (TWI) */
/* set up signature */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.signature), NVMDInfo->signature);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->TWIDeviceAddress << SHIFT16) | (NVMDInfo->TWIBusNumber << SHIFT12) |
(NVMDInfo->TWIDevicePageSize << SHIFT8) | (NVMDInfo->TWIDeviceAddressSize << SHIFT4) |
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
/* 0x01:SEEPROM-0 and 0x04:FLASH only in indirect mode */
case AGSA_NVMD_CONFIG_SEEPROM:
/* NVMD=1 */
/* Data Offset should be 0 */
/* set up signature */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.signature), NVMDInfo->signature);
/* indirect payload IP = 1, NVMD = 0x1 (SEEPROM0) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
break;
case AGSA_NVMD_VPD_FLASH:
/* indirect payload IP = 1, NVMD=0x4 (FLASH) */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->indirectPayload << SHIFT31) | NVMDInfo->NVMDevice);
/* set up Offset */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress);
break;
default:
SA_DBG1(("mpiSetNVMDCmd, (IP=1)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
ret = AGSA_RC_FAILURE;
ossaSetNVMDResponseCB(agRoot, agContext, OSSA_NVMD_MODE_ERROR);
break;
}
/* set up SGL field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.ISglAL), (NVMDInfo->indirectAddrLower32));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.ISglAH), (NVMDInfo->indirectAddrUpper32));
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, Data.indirectData.ILen), (NVMDInfo->indirectLen));
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_NVMD_DATA, IOMB_SIZE64, queueNum);
}
else
{
/* direct payload IP = 0 */
if (AGSA_NVMD_TWI_DEVICES == NVMDInfo->NVMDevice)
{
/* NVMD = 0 */
/* indirect payload IP = 0 and 0x0 (TWI) */
/* not allow write to Config SEEPROM for direct mode, so don't set singature */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, LEN_IR_VPDD),
(NVMDInfo->TWIDeviceAddress << SHIFT16) | (NVMDInfo->TWIBusNumber << SHIFT12) |
(NVMDInfo->TWIDevicePageSize << SHIFT8) | (NVMDInfo->TWIDeviceAddressSize << SHIFT4) |
NVMDInfo->NVMDevice);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetNVMDataCmd_t, VPDOffset),
NVMDInfo->dataOffsetAddress | (NVMDInfo->directLen << SHIFT24));
si_memcpy(&payload.Data.NVMData[0], NVMDInfo->directData, NVMDInfo->directLen);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_NVMD_DATA, IOMB_SIZE64, queueNum);
}
else
{
SA_DBG1(("mpiSetNVMDCmd, (IP=0)wrong device type = 0x%x\n", NVMDInfo->NVMDevice));
ret = AGSA_RC_FAILURE;
ossaSetNVMDResponseCB(agRoot, agContext, OSSA_NVMD_MODE_ERROR);
}
}
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetVPDCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiSetNVMDCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xm");
return ret;
}
/******************************************************************************/
/*! \brief Set Device State command
*
* This command is set Device State to SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Set Nexus State command
* \param deviceId DeviceId
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiSetDeviceStateCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 deviceId,
bit32 nds,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaSetDeviceStateCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xn");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiSetDeviceStateCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xn");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG3(("mpiSetDeviceStateCmd, Build IOMB DeviceId= 0x%x\n", deviceId));
/* Remove the request from free list */
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaSetDeviceStateCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDeviceStateCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDeviceStateCmd_t, deviceId), deviceId);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSetDeviceStateCmd_t, NDS), nds);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_DEVICE_STATE, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetNexusStateCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiSetDeviceStateCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xn");
return ret;
}
/******************************************************************************/
/*! \brief Get Device State command
*
* This command is get device State to SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Get Nexus State command
* \param deviceId DeviceId
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiGetDeviceStateCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 deviceId,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaGetDeviceStateCmd_t payload;
bit32 using_reserved = agFALSE;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xf");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeReservedRequests)); /**/
/* If no LL Control request entry available */
if(agNULL != pRequest)
{
using_reserved = agTRUE;
SA_DBG1(("mpiGetDeviceStateCmd, using saRoot->freeReservedRequests\n"));
}
else
{
SA_DBG1(("mpiGetDeviceStateCmd, No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xf");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
}
/* If LL Control request entry avaliable */
SA_DBG3(("mpiGetDeviceStateCmd, Build IOMB DeviceId= 0x%x\n", deviceId));
/* Remove the request from free list */
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaGetDeviceStateCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDeviceStateCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaGetDeviceStateCmd_t, deviceId), deviceId);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_DEVICE_STATE, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("mpiGetDeviceStateCmd: 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(("mpiGetDeviceStateCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiGetDeviceStateCmd, return value = %d\n", ret));
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xf");
return ret;
}
/******************************************************************************/
/*! \brief SAS ReInitialize command
*
* This command is Reinitialize SAS paremeters to SPC.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Get Nexus State command
* \param agSASConfig SAS Configuration Parameters
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiSasReinitializeCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaSASReconfig_t *agSASConfig,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaSasReInitializeCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xo");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiSasReinitializeCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xo");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG3(("mpiSasReinitializeCmd, Build IOMB SAS_RE_INITIALIZE\n"));
/* Remove the request from free list */
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaSasReInitializeCmd_t));
/* set tag field */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, setFlags), agSASConfig->flags);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, MaxPorts), agSASConfig->maxPorts);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, openRejReCmdData),
(agSASConfig->openRejectRetriesCmd << SHIFT16) | agSASConfig->openRejectRetriesData);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSasReInitializeCmd_t, sataHOLTMO), agSASConfig->sataHolTmo);
/* build IOMB command and send to SPC */
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_RE_INITIALIZE, IOMB_SIZE64, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSasReinitializeCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiSasReinitializeCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xo");
return ret;
}
/******************************************************************************/
/*! \brief SAS Set Controller Configuration Command
*
* This command updates the contents of a controller mode page.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Get Nexus State command
* \param agControllerConfig Mode page being sent to the controller
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32
mpiSetControllerConfigCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaSetControllerConfigCmd_t *agControllerConfig,
bit32 queueNum,
bit8 modePageContext
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"x1");
SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x 0x%08x 0x%08x\n",
agControllerConfig->pageCode,agControllerConfig->configPage[0],
agControllerConfig->configPage[1], agControllerConfig->configPage[2]));
SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x 0x%08x 0x%08x\n",
agControllerConfig->configPage[3],agControllerConfig->configPage[4],
agControllerConfig->configPage[5], agControllerConfig->configPage[6]));
SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x 0x%08x 0x%08x\n",
agControllerConfig->configPage[7],agControllerConfig->configPage[8],
agControllerConfig->configPage[9], agControllerConfig->configPage[10]));
SA_DBG2(("mpiSetControllerConfigCmd: agControllerConfig 0x%08x 0x%08x\n",
agControllerConfig->configPage[11],agControllerConfig->configPage[12]));
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* Get request from free IORequests */
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiSetControllerConfigCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "x1");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG2(("mpiSetControllerConfigCmd, Build IOMB pageCode 0x%x configPage[0] 0x%x\n",agControllerConfig->pageCode,agControllerConfig->configPage[0]));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->modePageContext = modePageContext;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set tag field */
agControllerConfig->tag = pRequest->HTag;
ret = mpiBuildCmd(agRoot, (bit32 *)agControllerConfig,
MPI_CATEGORY_SAS_SATA, OPC_INB_SET_CONTROLLER_CONFIG, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetControllerConfigCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiSetControllerConfigCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "x1");
return ret;
}
/******************************************************************************/
/*! \brief SAS Get Controller Configuration Command
*
* This command retrieves the contents of a controller mode page.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Get Nexus State command
* \param agControllerConfig Mode page to retrieve from the controller
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiGetControllerConfigCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaGetControllerConfigCmd_t *agControllerConfig,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xq");
SA_DBG1(("mpiGetControllerConfigCmd: Tag 0x%0X Page Code %0X\n",agControllerConfig->tag,agControllerConfig->pageCode ));
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiGetControllerConfigCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xq");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG3(("mpiGetControllerConfig, Build IOMB mpiGetControllerConfigCmd\n"));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* set tag field */
agControllerConfig->tag = pRequest->HTag;
ret = mpiBuildCmd(agRoot, (bit32 *) agControllerConfig,
MPI_CATEGORY_SAS_SATA, OPC_INB_GET_CONTROLLER_CONFIG, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiGetControllerConfigCmd, sending IOMB failed\n" ));
}
else
{
SA_DBG3(("mpiGetControllerConfigCmd, set OK\n"));
}
SA_DBG3(("mpiGetControllerConfigCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xq");
return ret;
}
/******************************************************************************/
/*! \brief SAS Encryption KEK command
*
* This command updates one or more KEK in a controller that supports encryption.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Get Nexus State command
* \param agKekMgmt Kek information that will be sent to the controller
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiKekManagementCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaKekManagementCmd_t *agKekMgmt,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"x2");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiKekManagementCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "x2");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG3(("mpiKekManagementCmd, Build OPC_INB_KEK_MANAGEMENT\n"));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
agKekMgmt->tag = pRequest->HTag;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiKekManagementCmd, 0x%X 0x%X 0x%X\n", agKekMgmt->tag,agKekMgmt->NEWKIDX_CURKIDX_KBF_Reserved_SKNV_KSOP, agKekMgmt->reserved ));
ret = mpiBuildCmd(agRoot, (bit32 *)agKekMgmt, MPI_CATEGORY_SAS_SATA, OPC_INB_KEK_MANAGEMENT, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiKekManagementCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiKekManagementCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "x2");
return ret;
}
/******************************************************************************/
/*! \brief SAS Encryption DEK management command
*
* This command updates one or more DEK in a controller that supports encryption.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context for the Get Nexus State command
* \param agDekMgmt DEK information that will be sent to the controller
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiDekManagementCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
agsaDekManagementCmd_t *agDekMgmt,
bit32 queueNum
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"xs");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiDekManagementCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "xs");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG1(("mpiDekManagementCmd, Build OPC_INB_DEK_MANAGEMENT pRequest %p\n",pRequest));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
agDekMgmt->tag = pRequest->HTag;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiDekManagementCmd: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",
agDekMgmt->tag,
agDekMgmt->KEKIDX_Reserved_TBLS_DSOP,
agDekMgmt->dekIndex,
agDekMgmt->tableAddrLo,
agDekMgmt->tableAddrHi,
agDekMgmt->tableEntries,
agDekMgmt->Reserved_DBF_TBL_SIZE ));
ret = mpiBuildCmd(agRoot, (bit32 *) agDekMgmt, MPI_CATEGORY_SAS_SATA, OPC_INB_DEK_MANAGEMENT, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiDekManagementCmd, sending IOMB failed\n" ));
}
SA_DBG3(("mpiDekManagementCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "xs");
return ret;
}
/******************************************************************************/
/*! \brief
*
* This command sends operator management command.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiOperatorManagementCmd(
agsaRoot_t *agRoot,
bit32 queueNum,
agsaContext_t *agContext,
agsaOperatorMangmentCmd_t *operatorcode )
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"2q");
SA_DBG1(("mpiOperatorManagementCmd, enter\n" ));
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiOperatorManagementCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2q");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG1(("mpiOperatorManagementCmd, Build OPC_INB_OPR_MGMT\n"));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
operatorcode->tag = pRequest->HTag;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
ret = mpiBuildCmd(agRoot, (bit32 *)operatorcode , MPI_CATEGORY_SAS_SATA, OPC_INB_OPR_MGMT, IOMB_SIZE128, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiOperatorManagementCmd, sending IOMB failed\n" ));
}
SA_DBG1(("mpiOperatorManagementCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2q");
return ret;
}
/******************************************************************************/
/*! \brief
*
* This command sends encrypt self test command.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32 mpiEncryptBistCmd(
agsaRoot_t *agRoot,
bit32 queueNum,
agsaContext_t *agContext,
agsaEncryptBist_t *bist )
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"2z");
SA_DBG1(("mpiEncryptBistCmd, enter\n" ));
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiEncryptBistCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2z");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG1(("mpiEncryptBistCmd, Build OPC_INB_ENC_TEST_EXECUTE\n"));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
bist->tag = pRequest->HTag;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiEncryptBistCmd: 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X 0x%X\n",
bist->tag,
bist->r_subop,
bist->testDiscption[0],
bist->testDiscption[1],
bist->testDiscption[2],
bist->testDiscption[3],
bist->testDiscption[4] ));
ret = mpiBuildCmd(agRoot, (bit32 *)bist , MPI_CATEGORY_SAS_SATA, OPC_INB_ENC_TEST_EXECUTE, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiEncryptBistCmd, sending IOMB failed\n" ));
}
SA_DBG1(("mpiEncryptBistCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2z");
return ret;
}
/******************************************************************************/
/*! \brief
*
* This command sends set operator command.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32
mpiSetOperatorCmd(
agsaRoot_t *agRoot,
bit32 queueNum,
agsaContext_t *agContext,
agsaSetOperatorCmd_t *operatorcode
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"39");
SA_DBG1(("mpiSetOperatorCmd, enter\n" ));
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiSetOperatorCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "39");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG1(("mpiSetOperatorCmd, Build OPC_INB_SET_OPERATOR\n"));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
operatorcode->tag = pRequest->HTag;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
ret = mpiBuildCmd(agRoot, (bit32 *)operatorcode, MPI_CATEGORY_SAS_SATA, OPC_INB_SET_OPERATOR, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiSetOperatorCmd, sending IOMB failed\n" ));
}
SA_DBG1(("mpiSetOperatorCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "39");
return ret;
}
/******************************************************************************/
/*! \brief
*
* This command sends get operator command.
*
* \param agRoot Handles for this instance of SAS/SATA LLL
* \param agContext Context
* \param queueNum Queue Number of inbound/outbound queue
*
* \return If the MPI command is sent to SPC successfully
* - \e AGSA_RC_SUCCESS the MPI command is successfully
* - \e AGSA_RC_BUSY the SPC is no resource, cannot send now
* - \e AGSA_RC_FAILURE the MPI command is failure
*
*/
/*******************************************************************************/
GLOBAL bit32
mpiGetOperatorCmd(
agsaRoot_t *agRoot,
bit32 queueNum,
agsaContext_t *agContext,
agsaGetOperatorCmd_t *operatorcode
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
smTraceFuncEnter(hpDBG_VERY_LOUD,"3e");
SA_DBG1(("mpiGetOperatorCmd, enter\n" ));
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiGetOperatorCmd, No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3e");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG1(("mpiGetOperatorCmd, Build OPC_INB_GET_OPERATOR\n"));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
operatorcode->tag = pRequest->HTag;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
ret = mpiBuildCmd(agRoot, (bit32 *)operatorcode, MPI_CATEGORY_SAS_SATA, OPC_INB_GET_OPERATOR, IOMB_SIZE64, 0);
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiGetOperatorCmd, sending IOMB failed\n" ));
}
SA_DBG1(("mpiGetOperatorCmd, return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3e");
return ret;
}
GLOBAL bit32 mpiDIFEncryptionOffloadCmd(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 op,
agsaDifEncPayload_t *agDifEncOffload,
ossaDIFEncryptionOffloadStartCB_t agCB
)
{
bit32 ret = AGSA_RC_SUCCESS;
bit32 dw8=0;
bit32 dw9=0;
bit32 dw10=0;
bit32 dw14=0;
bit32 dw15=0;
agsaLLRoot_t *saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaDifEncOffloadCmd_t payload;
smTraceFuncEnter(hpDBG_VERY_LOUD,"2b");
/* Get request from free IORequests */
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests));
/* If no LL Control request entry available */
if ( agNULL == pRequest )
{
SA_DBG1(("mpiDIFEncryptionOffloadCmd: No request from free list\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "2b");
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return AGSA_RC_BUSY;
}
/* If LL Control request entry avaliable */
else
{
SA_DBG1(("mpiDIFEncryptionOffloadCmd: Build OPC_INB_DIF_ENC_OFFLOAD_CMD pRequest %p\n",pRequest));
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
pRequest->completionCB = (ossaSSPCompletedCB_t)agCB;
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
si_memset(&payload, 0, sizeof(agsaDifEncOffloadCmd_t));
SA_DBG1(("mpiDIFEncryptionOffloadCmd: op %d\n",op));
if(smIS_SPCV(agRoot))
{
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, option), op);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, Src_Data_Len), agDifEncOffload->SrcDL);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, Dst_Data_Len), agDifEncOffload->DstDL);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, flags), agDifEncOffload->dif.flags);
dw8 = agDifEncOffload->dif.udrtArray[1] << SHIFT24 |
agDifEncOffload->dif.udrtArray[0] << SHIFT16 |
agDifEncOffload->dif.udtArray[1] << SHIFT8 |
agDifEncOffload->dif.udtArray[0];
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, UDTR01UDT01), dw8);
dw9 = agDifEncOffload->dif.udtArray[5] << SHIFT24 |
agDifEncOffload->dif.udtArray[4] << SHIFT16 |
agDifEncOffload->dif.udtArray[3] << SHIFT8 |
agDifEncOffload->dif.udtArray[2];
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, UDT2345), dw9);
dw10 = agDifEncOffload->dif.udrtArray[5] << SHIFT24 |
agDifEncOffload->dif.udrtArray[4] << SHIFT16 |
agDifEncOffload->dif.udrtArray[3] << SHIFT8 |
agDifEncOffload->dif.udrtArray[2];
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, UDTR2345), dw10);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, DPLR0SecCnt_IOSeed),
agDifEncOffload->dif.DIFPerLARegion0SecCount << SHIFT16 |
agDifEncOffload->dif.initialIOSeed);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, DPL_Addr_Lo) , agDifEncOffload->dif.DIFPerLAAddrLo);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, DPL_Addr_Hi) , agDifEncOffload->dif.DIFPerLAAddrHi);
dw14 = agDifEncOffload->encrypt.dekInfo.dekIndex << SHIFT8 |
(agDifEncOffload->encrypt.dekInfo.dekTable & 0x3) << SHIFT2 |
(agDifEncOffload->encrypt.keyTagCheck & 0x1) << SHIFT1;
if (agDifEncOffload->encrypt.cipherMode == agsaEncryptCipherModeXTS)
{
dw14 |= AGSA_ENCRYPT_XTS_Mode << SHIFT4;
}
else
{
dw14 |= (agDifEncOffload->encrypt.cipherMode & 0xF) << SHIFT4;
}
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, KeyIndex_CMode_KTS_ENT_R), dw14);
dw15 = agDifEncOffload->encrypt.EncryptionPerLRegion0SecCount << SHIFT16 |
(agDifEncOffload->encrypt.kekIndex & 0xF) << SHIFT5 |
(agDifEncOffload->encrypt.sectorSizeIndex & 0x1F);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, EPLR0SecCnt_KS_ENSS), dw15);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, keyTag_W0), agDifEncOffload->encrypt.keyTag_W0);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, keyTag_W1), agDifEncOffload->encrypt.keyTag_W1);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W0), agDifEncOffload->encrypt.tweakVal_W0);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W1), agDifEncOffload->encrypt.tweakVal_W1);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W2), agDifEncOffload->encrypt.tweakVal_W2);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, tweakVal_W3), agDifEncOffload->encrypt.tweakVal_W3);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, EPL_Addr_Lo), agDifEncOffload->encrypt.EncryptionPerLAAddrLo);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaDifEncOffloadCmd_t, EPL_Addr_Hi), agDifEncOffload->encrypt.EncryptionPerLAAddrHi);
si_memcpy((bit32 *) &(payload.SrcSgl), (bit32 *) &(agDifEncOffload->SrcSgl), sizeof(agsaSgl_t));
si_memcpy((bit32 *) &(payload.DstSgl), (bit32 *) &(agDifEncOffload->DstSgl), sizeof(agsaSgl_t));
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_DIF_ENC_OFFLOAD_CMD, IOMB_SIZE128, queueNum);
}
else
{
/* SPC does not support this command */
ret = AGSA_RC_FAILURE;
}
if (AGSA_RC_SUCCESS != ret)
{
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
/* return the request to free pool */
saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("mpiDIFEncryptionOffloadCmd: sending IOMB failed\n" ));
}
SA_DBG3(("mpiDIFEncryptionOffloadCmd: return value = %d\n", ret));
}
/* return value */
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "2b");
return ret;
}