/******************************************************************************* *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 __FBSDID("$FreeBSD$"); #include #include #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; }