/*******************************************************************************
*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 saphy.c
* \brief The file implements the functions to Start, Stop a phy
*
*
*/
/******************************************************************************/
#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 'K'
#endif
extern bit32 gFPGA_TEST;
/******************************************************************************/
/*! \brief Start a Phy
*
* Start a Phy
*
* \param agRoot handles for this instance of SAS/SATA hardware
* \param agContext
* \param phyId the phy id of the link will be started
* \param agPhyConfig the phy configuration
* \param agSASIdentify the SAS identify frame will be sent by the phy
*
* \return If phy is started successfully
* - \e AGSA_RC_SUCCESS phy is started successfully
* - \e AGSA_RC_BUSY phy is already started or starting
* - \e AGSA_RC_FAILURE phy is not started successfully
*/
/*******************************************************************************/
GLOBAL bit32 saPhyStart(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 phyId,
agsaPhyConfig_t *agPhyConfig,
agsaSASIdentify_t *agSASIdentify
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
bit32 ret = AGSA_RC_SUCCESS;
bit32 using_reserved = agFALSE;
smTraceFuncEnter(hpDBG_VERY_LOUD, "7a");
/* sanity check */
SA_ASSERT((agNULL != agRoot), "");
SA_ASSERT((agNULL != agSASIdentify), "");
SA_DBG3(("saPhyStart: phy%d started with ID %08X:%08X\n",
phyId,
SA_IDFRM_GET_SAS_ADDRESSHI(agSASIdentify),
SA_IDFRM_GET_SAS_ADDRESSLO(agSASIdentify)));
/* If phyId is invalid, return failure */
if ( phyId >= saRoot->phyCount )
{
ret = AGSA_RC_FAILURE;
}
/* If phyId is valid */
else
{
/* 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(("saPhyStart, using saRoot->freeReservedRequests\n"));
}
else
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("saPhyStart, No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7a");
return AGSA_RC_BUSY;
}
}
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
pRequest->valid = agTRUE;
/* If LL Control request entry avaliable */
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
/* Remove the request from free list */
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
/* Build the Phy Start IOMB command and send to SPC */
smTrace(hpDBG_VERY_LOUD,"P2", phyId);
/* TP:P2 phyId */
ret = mpiPhyStartCmd(agRoot, pRequest->HTag, phyId, agPhyConfig, agSASIdentify, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("saPhyStart: 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(("saPhyStart, sending IOMB failed\n" ));
}
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7a");
return ret;
}
/******************************************************************************/
/*! \brief Stop a Phy
*
* Stop a Phy
*
* \param agRoot handles for this instance of SAS/SATA hardware
* \param agContext the context of this API
* \param phyId the phy id of the link will be stopped
*
* \return If phy is stopped successfully
* - \e AGSA_RC_SUCCESS phy is stopped successfully
* - \e AGSA_RC_FAILURE phy is not stopped successfully
*/
/*******************************************************************************/
GLOBAL bit32 saPhyStop(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 phyId
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
bit32 ret = AGSA_RC_SUCCESS;
bit32 using_reserved = agFALSE;
smTraceFuncEnter(hpDBG_VERY_LOUD,"7b");
/* sanity check */
SA_ASSERT((agNULL != agRoot), "");
SA_DBG2(("saPhyStop: phy%d stop\n", phyId));
if(1)
{
mpiOCQueue_t *circularQ;
int i;
SA_DBG4(("saPhyStop:\n"));
for ( i = 0; i < saRoot->QueueConfig.numOutboundQueues; i++ )
{
circularQ = &saRoot->outboundQueue[i];
OSSA_READ_LE_32(circularQ->agRoot, &circularQ->producerIdx, circularQ->piPointer, 0);
if(circularQ->producerIdx != circularQ->consumerIdx)
{
SA_DBG1(("saPhyStop: PI 0x%03x CI 0x%03x\n",circularQ->producerIdx, circularQ->consumerIdx ));
}
}
}
if(smIS_SPC(agRoot))
{
phyId &= 0xF;
}
/* If phyId is invalid, return failure */
if ( (phyId & 0xF) >= saRoot->phyCount )
{
ret = AGSA_RC_FAILURE;
SA_DBG1(("saPhyStop: phy%d - failure with phyId\n", phyId));
}
else
{
/* If phyId is valid */
/* 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(("saPhyStop: using saRoot->freeReservedRequests\n"));
}
else
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("saPhyStop, No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7b");
return AGSA_RC_BUSY;
}
}
/* Remove the request from free list */
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
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;
/* build IOMB command and send to SPC */
ret = mpiPhyStopCmd(agRoot, pRequest->HTag, phyId, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG2(("saPhyStop: 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(("saPhyStop, sending IOMB failed\n" ));
}
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7b");
return ret;
}
/******************************************************************************/
/*! \brief CallBack Routine to stop a Phy
*
* CallBack for Stop a Phy
*
* \param agRoot handles for this instance of SAS/SATA hardware
* \param phyId the phy id of the link will be stopped
* \param status the status of the phy
* \param agContext the context of the saPhyStop
*
* \return If phy is stopped successfully
* - \e AGSA_RC_SUCCESS phy is stopped successfully
* - \e AGSA_RC_FAILURE phy is not stopped successfully
*/
/*******************************************************************************/
GLOBAL bit32 siPhyStopCB(
agsaRoot_t *agRoot,
bit32 phyId,
bit32 status,
agsaContext_t *agContext,
bit32 portId,
bit32 npipps
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
agsaPhy_t *pPhy;
agsaPort_t *pPort;
bit32 ret = AGSA_RC_SUCCESS;
bit32 iomb_status = status;
smTraceFuncEnter(hpDBG_VERY_LOUD,"7c");
/* sanity check */
SA_ASSERT((agNULL != agRoot), "");
/* If phyId is invalid, return failure */
if ( phyId >= saRoot->phyCount )
{
ret = AGSA_RC_FAILURE;
SA_DBG1(("siPhyStopCB: phy%d - failure with phyId\n", phyId));
/* makeup for CB */
status = (status << SHIFT8) | phyId;
status |= ((npipps & PORT_STATE_MASK) << SHIFT16);
ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_STOP_STATUS, status, agContext, agNULL);
}
/* If phyId is valid */
else
{
pPhy = &(saRoot->phys[phyId]);
/* get the port of the phy */
pPort = pPhy->pPort;
/* makeup for CB */
status = (status << SHIFT8) | phyId;
status |= ((npipps & PORT_STATE_MASK) << SHIFT16);
/* Callback to stop phy */
if ( agNULL != pPort )
{
if ( iomb_status == OSSA_SUCCESS && (OSSA_PORT_INVALID == (npipps & PORT_STATE_MASK) ))
{
SA_DBG1(("siPhyStopCB: phy%d invalidating port\n", phyId));
/* invalid port state, remove the port */
pPort->status |= PORT_INVALIDATING;
saRoot->PortMap[portId].PortStatus |= PORT_INVALIDATING;
/* invalid the port */
siPortInvalid(agRoot, pPort);
/* map out the portmap */
saRoot->PortMap[pPort->portId].PortContext = agNULL;
saRoot->PortMap[pPort->portId].PortID = PORT_MARK_OFF;
saRoot->PortMap[pPort->portId].PortStatus |= PORT_INVALIDATING;
}
ossaHwCB(agRoot, &(pPort->portContext), OSSA_HW_EVENT_PHY_STOP_STATUS, status, agContext, agNULL);
}
else
{
SA_DBG1(("siPhyStopCB: phy%d - Port is not established\n", phyId));
ossaHwCB(agRoot, agNULL, OSSA_HW_EVENT_PHY_STOP_STATUS, status, agContext, agNULL);
}
/* set PHY_STOPPED status */
PHY_STATUS_SET(pPhy, PHY_STOPPED);
/* Exclude the phy from a port */
if ( agNULL != pPort )
{
/* Acquire port list lock */
ossaSingleThreadedEnter(agRoot, LL_PORT_LOCK);
/* Delete the phy from the port */
pPort->phyMap[phyId] = agFALSE;
saRoot->phys[phyId].pPort = agNULL;
/* Release port list lock */
ossaSingleThreadedLeave(agRoot, LL_PORT_LOCK);
}
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7c");
/* return */
return ret;
}
/******************************************************************************/
/*! \brief Initiate a Local PHY control command
*
* This function is called to initiate a PHY control command to the local PHY.
* The completion of this function is reported in ossaLocalPhyControlCB()
*
* \param agRoot handles for this instance of SAS/SATA hardware
* \param agContext the context of this API
* \param phyId phy number
* \param phyOperation
* one of AGSA_PHY_LINK_RESET, AGSA_PHY_HARD_RESET, AGSA_PHY_ENABLE_SPINUP
*
* \return
* - none
*/
/*******************************************************************************/
GLOBAL bit32 saLocalPhyControl(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 phyId,
bit32 phyOperation,
ossaLocalPhyControlCB_t agCB
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaPhyErrCounters_t errorParam;
bit32 ret = AGSA_RC_SUCCESS;
bit32 value, value1, value2, copyPhyId;
bit32 count = 100;
bit32 using_reserved = agFALSE;
/* sanity check */
SA_ASSERT((agNULL != saRoot), "");
if(saRoot == agNULL)
{
SA_DBG1(("saLocalPhyControl: saRoot == agNULL\n"));
return(AGSA_RC_FAILURE);
}
smTraceFuncEnter(hpDBG_VERY_LOUD,"7d");
si_memset(&errorParam,0,sizeof(agsaPhyErrCounters_t));
SA_DBG2(("saLocalPhyControl: phy%d operation %08X\n", phyId, phyOperation));
switch(phyOperation)
{
case AGSA_PHY_LINK_RESET:
case AGSA_PHY_HARD_RESET:
case AGSA_PHY_NOTIFY_ENABLE_SPINUP:
case AGSA_PHY_BROADCAST_ASYNCH_EVENT:
case AGSA_PHY_COMINIT_OOB:
{
/* 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(("saLocalPhyControl, using saRoot->freeReservedRequests\n"));
}
else
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("saLocalPhyControl, No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7d");
return AGSA_RC_BUSY;
}
}
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
/* Remove the request from free list */
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
pRequest->completionCB = (void*)agCB;
// pRequest->abortCompletionCB = agCB;
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 the local phy control IOMB command and send to SPC */
ret = mpiLocalPhyControlCmd(agRoot, pRequest->HTag, phyId, phyOperation, queueNum);
if (AGSA_RC_SUCCESS != ret)
{
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("saLocalPhyControl: 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));
}
SA_DBG1(("saLocalPhyControl, sending IOMB failed\n" ));
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
return ret;
}
}
break;
case AGSA_PHY_GET_ERROR_COUNTS:
{
if(smIS_SPCV(agRoot))
{
SA_ASSERT((smIS_SPC(agRoot)), "SPC only");
SA_DBG1(("saLocalPhyControl: V AGSA_PHY_GET_ERROR_COUNTS\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7d");
return AGSA_RC_FAILURE;
}
/* If phyId is invalid, return failure */
if ( phyId >= saRoot->phyCount )
{
ret = AGSA_RC_FAILURE;
si_memset(&errorParam, 0, sizeof(agsaPhyErrCounters_t));
SA_DBG1(("saLocalPhyControl: phy%d - failure with phyId\n", phyId));
/* call back with the status */
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "7d");
return ret;
}
/* save phyId */
copyPhyId = phyId;
/* map 0x030000 or 0x040000 based on phyId to BAR4(0x20), BAT2(win) to access the register */
if (phyId < 4)
{
/* for phyId = 0, 1, 2, 3 */
value = 0x030000;
}
else
{
/* for phyId = 4, 5, 6, 7 */
phyId = phyId - 4;
value = 0x040000;
}
/* Need to make sure DEVICE_LCLK_GENERATION register bit 6 is 0 */
value1 = ossaHwRegReadExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK);
SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK Register value = %08X\n", value1));
/* If LCLK_CLEAR bit set then disable it */
if (value1 & DEVICE_LCLK_CLEAR)
{
ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, (value1 & 0xFFFFFFBF) );
SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK value = %08X\n", (value1 & 0xFFFFFFBF)));
}
if (AGSA_RC_FAILURE == siBar4Shift(agRoot, value))
{
SA_DBG1(("saLocalPhyControl:Shift Bar4 to 0x%x failed\n", value));
phyId = copyPhyId;
/* call back with the status */
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "7d");
return AGSA_RC_FAILURE;
}
/* set LCLK = 1 and LCLK_CLEAR = 0 */
SPC_WRITE_COUNTER_CNTL(phyId, LCLK);
/* LCLK bit should be low to be able to read error registers */
while((value = SPC_READ_COUNTER_CNTL(phyId)) & LCLK)
{
if(--count == 0)
{
SA_DBG1(("saLocalPhyControl: Timeout,SPC_COUNTER_CNTL value = %08X\n", value));
ret = AGSA_RC_FAILURE;
break;
}
} /* while */
value = SPC_READ_COUNTER_CNTL(phyId);
SA_DBG3(("saLocalPhyControl: SPC_COUNTER_CNTL value = %08X\n", value));
/* invalidDword */
errorParam.invalidDword = SPC_READ_INV_DW_COUNT(phyId);
/* runningDisparityError */
errorParam.runningDisparityError = SPC_READ_DISP_ERR_COUNT(phyId);
/* lossOfDwordSynch */
errorParam.lossOfDwordSynch = SPC_READ_LOSS_DW_COUNT(phyId);
/* phyResetProblem */
errorParam.phyResetProblem = SPC_READ_PHY_RESET_COUNT(phyId);
/* codeViolation */
errorParam.codeViolation = SPC_READ_CODE_VIO_COUNT(phyId);
/* never occurred in SPC8x6G */
errorParam.elasticityBufferOverflow = 0;
errorParam.receivedErrorPrimitive = 0;
errorParam.inboundCRCError = 0;
SA_DBG3(("saLocalPhyControl:INV_DW_COUNT 0x%x\n", SPC_READ_INV_DW_COUNT(phyId)));
SA_DBG3(("saLocalPhyControl:DISP_ERR_COUNT 0x%x\n", SPC_READ_DISP_ERR_COUNT(phyId)));
SA_DBG3(("saLocalPhyControl:LOSS_DW_COUNT 0x%x\n", SPC_READ_LOSS_DW_COUNT(phyId)));
SA_DBG3(("saLocalPhyControl:PHY_RESET_COUNT 0x%x\n", SPC_READ_PHY_RESET_COUNT(phyId)));
SA_DBG3(("saLocalPhyControl:CODE_VIOLATION_COUNT 0x%x\n", SPC_READ_CODE_VIO_COUNT(phyId)));
/* Shift back to BAR4 original address */
if (AGSA_RC_FAILURE == siBar4Shift(agRoot, 0x0))
{
SA_DBG1(("saLocalPhyControl:Shift Bar4 to 0x%x failed\n", 0x0));
ret = AGSA_RC_FAILURE;
}
/* restore back the Top Device LCLK generation register value */
ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, value1);
/* restore phyId */
phyId = copyPhyId;
/* call back with the status */
if (AGSA_RC_SUCCESS == ret)
{
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, copyPhyId, phyOperation, OSSA_SUCCESS, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, copyPhyId, phyOperation, OSSA_SUCCESS, (void *)&errorParam);
}
}
else
{
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
}
break;
}
case AGSA_PHY_CLEAR_ERROR_COUNTS:
{
if(smIS_SPCV(agRoot))
{
SA_ASSERT((smIS_SPC(agRoot)), "SPC only");
SA_DBG1(("saLocalPhyControl: V AGSA_PHY_CLEAR_ERROR_COUNTS\n" ));
smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "7d");
return AGSA_RC_FAILURE;
}
/* If phyId is invalid, return failure */
if ( phyId >= saRoot->phyCount )
{
si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
SA_DBG3(("saLocalPhyControl(CLEAR): phy%d - failure with phyId\n", phyId));
/* call back with the status */
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "7d");
return AGSA_RC_FAILURE;
}
/* save phyId */
copyPhyId = phyId;
/* map 0x030000 or 0x040000 based on phyId to BAR4(0x20), BAT2(win) to access the register */
if (phyId < 4)
{
/* for phyId = 0, 1, 2, 3 */
value = 0x030000;
}
else
{
/* for phyId = 4, 5, 6, 7 */
phyId = phyId - 4;
value = 0x040000;
}
/* Need to make sure DEVICE_LCLK_GENERATION register bit 6 is 1 */
value2 = ossaHwRegReadExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK);
SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK Register value = %08X\n", value2));
/* If LCLK_CLEAR bit not set then set it */
if ((value2 & DEVICE_LCLK_CLEAR) == 0)
{
ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, (value2 | DEVICE_LCLK_CLEAR) );
SA_DBG3(("saLocalPhyControl: TOP DEVICE LCLK value = %08X\n", (value2 & 0xFFFFFFBF)));
}
if (AGSA_RC_FAILURE == siBar4Shift(agRoot, value))
{
SA_DBG1(("saLocalPhyControl(CLEAR):Shift Bar4 to 0x%x failed\n", value));
phyId = copyPhyId;
/* call back with the status */
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "7d");
return AGSA_RC_FAILURE;
}
/* read Counter Control register */
value1 = SPC_READ_COUNTER_CNTL(phyId);
SA_DBG3(("saLocalPhyControl(CLEAR): SPC_COUNTER_CNTL value = %08X\n", value1));
/* set LCLK and LCLK_CLEAR */
SPC_WRITE_COUNTER_CNTL(phyId, (LCLK_CLEAR | LCLK));
/* read back the value of register */
/* poll LCLK bit = 0 */
while((value = SPC_READ_COUNTER_CNTL(phyId)) & LCLK)
{
if(--count == 0)
{
SA_DBG1(("saLocalPhyControl: Timeout,SPC_COUNTER_CNTL value = %08X\n", value));
ret = AGSA_RC_FAILURE;
break;
}
} /* while */
value = SPC_READ_COUNTER_CNTL(phyId);
SA_DBG3(("saLocalPhyControl(CLEAR): SPC_COUNTER_CNTL value = %08X\n", value));
/* restore the value */
SPC_WRITE_COUNTER_CNTL(phyId, value1);
/* Shift back to BAR4 original address */
if (AGSA_RC_FAILURE == siBar4Shift(agRoot, 0x0))
{
SA_DBG1(("saLocalPhyControl:Shift Bar4 to 0x%x failed\n", 0x0));
ret = AGSA_RC_FAILURE;
}
/* restore back the Top Device LCLK generation register value */
ossaHwRegWriteExt(agRoot, PCIBAR2, SPC_REG_DEVICE_LCLK, value2);
/* restore phyId */
phyId = copyPhyId;
/* call back with the status */
if (AGSA_RC_SUCCESS == ret)
{
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_SUCCESS, agNULL);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_SUCCESS, agNULL);
}
}
else
{
if( agCB == agNULL )
{
ossaLocalPhyControlCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
else
{
agCB(agRoot, agContext, phyId, phyOperation, OSSA_FAILURE, (void *)&errorParam);
}
}
break;
}
case AGSA_PHY_GET_BW_COUNTS:
{
SA_ASSERT((smIS_SPC(agRoot)), "SPCv only");
SA_DBG1(("saLocalPhyControl: AGSA_PHY_GET_BW_COUNTS\n" ));
break;
}
default:
ret = AGSA_RC_FAILURE;
SA_ASSERT(agFALSE, "(saLocalPhyControl) Unknown operation");
break;
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "7d");
return ret;
}
GLOBAL bit32 saGetPhyProfile(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 ppc,
bit32 phyId
)
{
bit32 ret = AGSA_RC_SUCCESS;
agsaLLRoot_t *saRoot = agNULL;
agsaPhyErrCountersPage_t errorParam;
ossaLocalPhyControlCB_t agCB = ossaGetPhyProfileCB;
/* sanity check */
SA_ASSERT((agNULL != agRoot), "");
saRoot = (agsaLLRoot_t *) (agRoot->sdkData);
SA_ASSERT((agNULL != saRoot), "");
if(saRoot == agNULL)
{
SA_DBG3(("saGetPhyProfile : saRoot is NULL"));
return AGSA_RC_FAILURE;
}
SA_DBG1(("saGetPhyProfile: ppc 0x%x phyID %d\n", ppc,phyId));
switch(ppc)
{
case AGSA_SAS_PHY_ERR_COUNTERS_PAGE:
{
if(smIS_SPCV(agRoot))
{
SA_DBG1(("saGetPhyProfile: V AGSA_SAS_PHY_ERR_COUNTERS_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "7d");
return ret;
}
}
case AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE:
{
/* If phyId is invalid, return failure */
if ( phyId >= saRoot->phyCount )
{
si_memset(&errorParam, 0, sizeof(agsaPhyErrCountersPage_t));
SA_DBG3(("saGetPhyProfile(CLEAR): phy%d - failure with phyId\n", phyId));
/* call back with the status */
ossaGetPhyProfileCB(agRoot, agContext, phyId, ppc, OSSA_FAILURE, (void *)&errorParam);
smTraceFuncExit(hpDBG_VERY_LOUD, 'j', "7d");
return AGSA_RC_FAILURE;
}
if(smIS_SPCV(agRoot))
{
SA_DBG1(("saGetPhyProfile: V AGSA_SAS_PHY_ERR_COUNTERS_CLR_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext, ppc,phyId,agCB);
smTraceFuncExit(hpDBG_VERY_LOUD, 'k', "7d");
return ret;
}
}
case AGSA_SAS_PHY_BW_COUNTERS_PAGE:
{
SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_BW_COUNTERS_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
break;
}
case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
{
SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
break;
}
case AGSA_SAS_PHY_GENERAL_STATUS_PAGE:
{
SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_GENERAL_STATUS_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
break;
}
case AGSA_PHY_SNW3_PAGE:
{
SA_DBG1(("saGetPhyProfile: AGSA_PHY_SNW3_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
break;
}
case AGSA_PHY_RATE_CONTROL_PAGE:
{
SA_DBG1(("saGetPhyProfile: AGSA_PHY_RATE_CONTROL_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
break;
}
case AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE:
{
SA_DBG1(("saGetPhyProfile: AGSA_SAS_PHY_OPEN_REJECT_RETRY_BACKOFF_THRESHOLD_PAGE\n" ));
ret = mpiGetPhyProfileCmd( agRoot,agContext,ppc ,phyId,agCB);
break;
}
default:
SA_DBG1(("saGetPhyProfile: Unknown operation 0x%X\n",ppc ));
SA_ASSERT(agFALSE, "saGetPhyProfile Unknown operation " );
break;
}
return ret;
}
GLOBAL bit32 saSetPhyProfile (
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
bit32 ppc,
bit32 length,
void *buffer,
bit32 phyID
)
{
bit32 ret = AGSA_RC_SUCCESS;
SA_DBG1(("saSetPhyProfile: ppc 0x%x length 0x%x phyID %d\n", ppc,length,phyID));
switch(ppc)
{
case AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE:
{
SA_DBG1(("saSetPhyProfile: AGSA_SAS_PHY_ANALOG_SETTINGS_PAGE\n" ));
ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
break;
}
case AGSA_PHY_SNW3_PAGE:
{
SA_DBG1(("saSetPhyProfile: AGSA_PHY_SNW3_PAGE\n" ));
ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
break;
}
case AGSA_PHY_RATE_CONTROL_PAGE:
{
SA_DBG1(("saSetPhyProfile: AGSA_PHY_RATE_CONTROL_PAGE\n" ));
ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
break;
}
case AGSA_SAS_PHY_MISC_PAGE:
{
SA_DBG1(("saSetPhyProfile: AGSA_SAS_PHY_MISC_PAGE\n"));
ret = mpiSetPhyProfileCmd( agRoot,agContext,ppc ,phyID,length,buffer);
break;
}
default:
SA_DBG1(("saSetPhyProfile: Unknown operation 0x%X\n",ppc ));
SA_ASSERT(agFALSE, "saSetPhyProfile Unknown operation " );
ret = AGSA_RC_FAILURE;
break;
}
return ret;
}
/******************************************************************************/
/*! \brief Initiate a HW Event Ack command
*
* This function is called to initiate a HW Event Ack command to the SPC.
* The completion of this function is reported in ossaHwEventAckCB().
*
* \param agRoot handles for this instance of SAS/SATA hardware
* \param agContext the context of this API
* \param queueNum queue number
* \param eventSource point to the event source structure
* \param param0
* \param param1
*
* \return
* - none
*/
/*******************************************************************************/
GLOBAL bit32 saHwEventAck(
agsaRoot_t *agRoot,
agsaContext_t *agContext,
bit32 queueNum,
agsaEventSource_t *eventSource,
bit32 param0,
bit32 param1
)
{
agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData);
agsaIORequestDesc_t *pRequest;
agsaPortContext_t *agPortContext;
agsaPort_t *pPort = agNULL;
agsaSASHwEventAckCmd_t payload;
bit32 phyportid;
bit32 ret = AGSA_RC_SUCCESS;
bit32 using_reserved = agFALSE;
smTraceFuncEnter(hpDBG_VERY_LOUD,"7e");
/* sanity check */
SA_ASSERT((agNULL != saRoot), "");
if(saRoot == agNULL)
{
SA_DBG1(("saHwEventAck: saRoot == agNULL\n"));
return(AGSA_RC_FAILURE);
}
SA_DBG2(("saHwEventAck: agContext %p eventSource %p\n", agContext, eventSource));
SA_DBG1(("saHwEventAck: event 0x%x param0 0x%x param1 0x%x\n", eventSource->event, param0, param1));
agPortContext = eventSource->agPortContext;
/* 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(agNULL != pRequest)
{
using_reserved = agTRUE;
SA_DBG1(("saHwEventAck, using saRoot->freeReservedRequests\n"));
}
else
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* If no LL Control request entry available */
SA_DBG1(("saHwEventAck, No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "7e");
return AGSA_RC_BUSY;
}
}
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
/* Remove the request from free list */
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
SA_DBG2(("saHwEventAck: queueNum 0x%x HTag 0x%x\n",queueNum ,pRequest->HTag));
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
/* build IOMB command and send to SPC */
/* set payload to zeros */
si_memset(&payload, 0, sizeof(agsaSASHwEventAckCmd_t));
/* find port id */
if (agPortContext)
{
pPort = (agsaPort_t *) (agPortContext->sdkData);
if (pPort)
{
if(eventSource->event == OSSA_HW_EVENT_PHY_DOWN)
{
pPort->tobedeleted = agTRUE;
}
SA_DBG3(("saHwEventAck,pPort->portId %X\n",pPort->portId));
if(smIS_SPC(agRoot))
{
/* fillup PORT_ID field */
phyportid = pPort->portId & 0xF;
}
else
{
/* fillup PORT_ID field */
phyportid = pPort->portId & 0xFF;
}
}
else
{
/* pPort is NULL - set PORT_ID to not intialized */
if(smIS_SPC(agRoot))
{
phyportid = 0xF;
}
else
{
phyportid = 0xFF;
}
}
}
else
{
/* agPortContext is NULL - set PORT_ID to not intialized */
if(smIS_SPC(agRoot))
{
phyportid = 0xF;
}
else
{
phyportid = 0xFF;
}
}
pRequest->pPort = pPort;
SA_DBG3(("saHwEventAck,eventSource->param 0x%X\n",eventSource->param));
SA_DBG3(("saHwEventAck,eventSource->event 0x%X\n",eventSource->event));
if(smIS_SPC(agRoot))
{
/* fillup up PHY_ID */
phyportid |= ((eventSource->param & 0x0000000F) << 4);
/* fillup SEA field */
phyportid |= (eventSource->event & 0x0000FFFF) << 8;
SA_DBG3(("saHwEventAck: portId 0x%x phyId 0x%x SEA 0x%x\n", phyportid & 0xF,
eventSource->param & 0x0000000F, eventSource->event & 0x0000FFFF));
}
else
{
/* fillup up PHY_ID */
phyportid |= ((eventSource->param & 0x000000FF) << SHIFT24);
/* fillup SEA field */
phyportid |= (eventSource->event & 0x00FFFFFF) << SHIFT8;
SA_DBG3(("saHwEventAck: portId 0x%x phyId 0x%x SEA 0x%x\n", phyportid & 0xFF,
eventSource->param & 0x0000000F, eventSource->event & 0x0000FFFF));
}
pRequest->HwAckType = (bit16)phyportid;
SA_DBG1(("saHwEventAck,phyportid 0x%X HwAckType 0x%X\n",phyportid,pRequest->HwAckType));
/* set tag */
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, tag), pRequest->HTag);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, sEaPhyIdPortId), phyportid);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, Param0), param0);
OSSA_WRITE_LE_32(agRoot, &payload, OSSA_OFFSET_OF(agsaSASHwEventAckCmd_t, Param1), param1);
/* build IOMB command and send to SPC */
if(smIS_SPC(agRoot))
{
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SPC_SAS_HW_EVENT_ACK, IOMB_SIZE64, queueNum);
}
else
{
ret = mpiBuildCmd(agRoot, (bit32 *)&payload, MPI_CATEGORY_SAS_SATA, OPC_INB_SAS_HW_EVENT_ACK, IOMB_SIZE64, queueNum);
}
if (AGSA_RC_SUCCESS != ret)
{
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("saHwEventAck: 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(("saHwEventAck, sending IOMB failed\n" ));
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "7e");
return ret;
}
GLOBAL bit32 saVhistCapture(
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;
bit32 ret = AGSA_RC_SUCCESS;
bit32 using_reserved = agFALSE;
smTraceFuncEnter(hpDBG_VERY_LOUD,"3N");
/* sanity check */
SA_ASSERT((agNULL != agRoot), "");
SA_DBG1(("saVhistCapture:Channel 0x%08X 0x%08X%08X 0x%08X%08X count 0x%X\n",Channel, NumBitHi, NumBitLo ,PcieAddrHi,PcieAddrLo,ByteCount));
{
/* 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((", using saRoot->freeReservedRequests\n"));
}
else
{
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
SA_DBG1(("saVhistCapture: No request from free list Not using saRoot->freeReservedRequests\n"));
smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "3N");
return AGSA_RC_BUSY;
}
}
SA_ASSERT((!pRequest->valid), "The pRequest is in use");
pRequest->valid = agTRUE;
/* If LL Control request entry avaliable */
if( using_reserved )
{
saLlistIORemove(&(saRoot->freeReservedRequests), &(pRequest->linkNode));
}
else
{
/* Remove the request from free list */
saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode));
}
ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK);
saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag;
saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest;
saRoot->IOMap[pRequest->HTag].agContext = agContext;
pRequest->valid = agTRUE;
/* Build the VhisCapture IOMB command and send to SPCv */
ret = mpiVHistCapCmd(agRoot,agContext, queueNum, Channel, NumBitLo, NumBitHi ,PcieAddrLo, PcieAddrHi, ByteCount);
if (AGSA_RC_SUCCESS != ret)
{
/* remove the request from IOMap */
saRoot->IOMap[pRequest->HTag].Tag = MARK_OFF;
saRoot->IOMap[pRequest->HTag].IORequest = agNULL;
saRoot->IOMap[pRequest->HTag].agContext = agNULL;
pRequest->valid = agFALSE;
ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK);
/* return the request to free pool */
if(saLlistIOGetCount(&(saRoot->freeReservedRequests)) < SA_RESERVED_REQUEST_COUNT)
{
SA_DBG1(("saPhyStart: 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(("saVhistCapture: sending IOMB failed\n" ));
}
}
smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "3N");
return ret;
}