summaryrefslogtreecommitdiffstats
path: root/sys/dev/pms/RefTisa/sallsdk/spc/saphy.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pms/RefTisa/sallsdk/spc/saphy.c')
-rw-r--r--sys/dev/pms/RefTisa/sallsdk/spc/saphy.c1302
1 files changed, 1302 insertions, 0 deletions
diff --git a/sys/dev/pms/RefTisa/sallsdk/spc/saphy.c b/sys/dev/pms/RefTisa/sallsdk/spc/saphy.c
new file mode 100644
index 0000000..3603129
--- /dev/null
+++ b/sys/dev/pms/RefTisa/sallsdk/spc/saphy.c
@@ -0,0 +1,1302 @@
+/*******************************************************************************
+*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;
+}
+
OpenPOWER on IntegriCloud