/******************************************************************************* *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 sasata.c * \brief The file implements the functions to SATA IO * */ /******************************************************************************/ #include __FBSDID("$FreeBSD$"); #include #include #ifdef SA_ENABLE_TRACE_FUNCTIONS #ifdef siTraceFileID #undef siTraceFileID #endif #define siTraceFileID 'M' #endif /******************************************************************************/ /*! \brief Start SATA command * * Start SATA command * * \param agRoot handles for this instance of SAS/SATA hardware * \param queueNum * \param agIORequest * \param agDevHandle * \param agRequestType * \param agSATAReq * \param agTag * \param agCB * * \return If command is started successfully * - \e AGSA_RC_SUCCESS command is started successfully * - \e AGSA_RC_FAILURE command is not started successfully */ /*******************************************************************************/ GLOBAL bit32 saSATAStart( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 queueNum, agsaDevHandle_t *agDevHandle, bit32 agRequestType, agsaSATAInitiatorRequest_t *agSATAReq, bit8 agTag, ossaSATACompletedCB_t agCB ) { agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); mpiICQueue_t *circularQ = agNULL; agsaDeviceDesc_t *pDevice = agNULL; agsaPort_t *pPort = agNULL; agsaIORequestDesc_t *pRequest = agNULL; void *pMessage = agNULL; agsaSgl_t *pSgl = agNULL; bit32 *payload = agNULL; bit32 deviceIndex = 0; bit32 ret = AGSA_RC_SUCCESS, retVal = 0; bit32 AtapDir = 0; bit32 encryptFlags = 0; bit16 size = 0; bit16 opCode = 0; bit8 inq = 0, outq = 0; OSSA_INP_ENTER(agRoot); smTraceFuncEnter(hpDBG_VERY_LOUD, "8a"); SA_DBG3(("saSATAStart: in\n")); /* sanity check */ SA_ASSERT((agNULL != agRoot), "(saSATAStart) agRoot is NULL"); SA_ASSERT((agNULL != agIORequest), "(saSATAStart) agIORequest is NULL"); SA_ASSERT((agNULL != agDevHandle), "(saSATAStart) agDevHandle is NULL"); SA_ASSERT((agNULL != agSATAReq), "(saSATAStart) agSATAReq is NULL"); /* Assign inbound and outbound queue */ 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."); /* Find the outgoing port for the device */ pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData); SA_ASSERT((agNULL != pDevice), "(saSATAStart) pDevice is NULL"); pPort = pDevice->pPort; SA_ASSERT((agNULL != pPort), "(saSATAStart) pPort is NULL"); /* SATA DIF is obsolete */ if (agSATAReq->option & AGSA_SATA_ENABLE_DIF) { return AGSA_RC_FAILURE; } /* find deviceID for IOMB */ deviceIndex = pDevice->DeviceMapIndex; /* Get request from free IORequests */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); if ( agNULL != pRequest ) { /* If free IOMB avaliable */ /* Remove the request from free list */ saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode)); /* Add the request to the pendingSTARequests list of the device */ pRequest->valid = agTRUE; saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); if ((agSATAReq->option & AGSA_SATA_ENABLE_ENCRYPTION) || (agSATAReq->option & AGSA_SATA_ENABLE_DIF)) { opCode = OPC_INB_SATA_DIF_ENC_OPSTART; size = IOMB_SIZE128; } else { opCode = OPC_INB_SATA_HOST_OPSTART; if (agRequestType == AGSA_SATA_PROTOCOL_NON_PKT || agRequestType == AGSA_SATA_PROTOCOL_H2D_PKT || agRequestType == AGSA_SATA_PROTOCOL_D2H_PKT) size = IOMB_SIZE128; else size = IOMB_SIZE64; } /* If LL IO request entry avaliable */ /* set up pRequest */ pRequest->pIORequestContext = agIORequest; pRequest->pDevice = pDevice; pRequest->pPort = pPort; pRequest->requestType = agRequestType; pRequest->startTick = saRoot->timeTick; pRequest->completionCB = (ossaSSPCompletedCB_t)agCB; /* Set request to the sdkData of agIORequest */ agIORequest->sdkData = pRequest; /* save tag and IOrequest pointer to IOMap */ saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag; saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest; #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ /* get a free inbound queue entry */ circularQ = &saRoot->inboundQueue[inq]; retVal = mpiMsgFreeGet(circularQ, size, &pMessage); if (AGSA_RC_FAILURE == retVal) { #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ /* if not sending return to free list rare */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); pRequest->valid = agFALSE; saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG3(("saSATAStart, error when get free IOMB\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "8a"); ret = AGSA_RC_FAILURE; goto ext; } /* return busy if inbound queue is full */ if (AGSA_RC_BUSY == retVal) { #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ /* if not sending return to free list rare */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); pRequest->valid = agFALSE; saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG1(("saSATAStart, no more IOMB\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "8a"); ret = AGSA_RC_BUSY; goto ext; } } else /* If no LL IO request entry available */ { ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG1(("saSATAStart, No request from free list\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "8a"); ret = AGSA_RC_BUSY; goto ext; } payload = (bit32 *)pMessage; SA_DBG4(("saSATAStart: Payload offset 0x%X\n", (unsigned int)(payload - (bit32 *)pMessage))); switch ( agRequestType ) { case AGSA_SATA_PROTOCOL_FPDMA_READ: case AGSA_SATA_PROTOCOL_FPDMA_WRITE: case AGSA_SATA_PROTOCOL_FPDMA_READ_M: case AGSA_SATA_PROTOCOL_FPDMA_WRITE_M: pSgl = &(agSATAReq->agSgl); AtapDir = agRequestType & (AGSA_DIR_MASK | AGSA_SATA_ATAP_MASK); if (agRequestType & AGSA_MSG) { /* set M bit */ AtapDir |= AGSA_MSG_BIT; } break; case AGSA_SATA_PROTOCOL_DMA_READ: case AGSA_SATA_PROTOCOL_DMA_WRITE: case AGSA_SATA_PROTOCOL_DMA_READ_M: case AGSA_SATA_PROTOCOL_DMA_WRITE_M: case AGSA_SATA_PROTOCOL_PIO_READ_M: case AGSA_SATA_PROTOCOL_PIO_WRITE_M: case AGSA_SATA_PROTOCOL_PIO_READ: case AGSA_SATA_PROTOCOL_PIO_WRITE: case AGSA_SATA_PROTOCOL_H2D_PKT: case AGSA_SATA_PROTOCOL_D2H_PKT: agTag = 0; /* agTag not valid for these requests */ pSgl = &(agSATAReq->agSgl); AtapDir = agRequestType & (AGSA_DIR_MASK | AGSA_SATA_ATAP_MASK); if (agRequestType & AGSA_MSG) { /* set M bit */ AtapDir |= AGSA_MSG_BIT; } break; case AGSA_SATA_PROTOCOL_NON_DATA: case AGSA_SATA_PROTOCOL_NON_DATA_M: case AGSA_SATA_PROTOCOL_NON_PKT: agTag = 0; /* agTag not valid for these requests */ AtapDir = agRequestType & (AGSA_DIR_MASK | AGSA_SATA_ATAP_MASK); if (agRequestType & AGSA_MSG) { /* set M bit */ AtapDir |= AGSA_MSG_BIT; } break; case AGSA_SATA_PROTOCOL_SRST_ASSERT: agTag = 0; /* agTag not valid for these requests */ AtapDir = AGSA_SATA_ATAP_SRST_ASSERT; break; case AGSA_SATA_PROTOCOL_SRST_DEASSERT: agTag = 0; /* agTag not valid for these requests */ AtapDir = AGSA_SATA_ATAP_SRST_DEASSERT; break; case AGSA_SATA_PROTOCOL_DEV_RESET: case AGSA_SATA_PROTOCOL_DEV_RESET_M: /* TestBase */ agTag = 0; /* agTag not valid for these requests */ AtapDir = AGSA_SATA_ATAP_PKT_DEVRESET; if (agRequestType & AGSA_MSG) { /* set M bit */ AtapDir |= AGSA_MSG_BIT; /* TestBase */ } break; default: SA_DBG1(("saSATAStart: (Unknown agRequestType) 0x%X \n",agRequestType)); SA_ASSERT((0), "saSATAStart: (Unknown agRequestType)"); break; } if ((AGSA_SATA_PROTOCOL_SRST_ASSERT == agRequestType) || (AGSA_SATA_PROTOCOL_SRST_DEASSERT == agRequestType) || (AGSA_SATA_PROTOCOL_DEV_RESET == agRequestType)) { SA_DBG3(("saSATAStart:AGSA_SATA_PROTOCOL_SRST_DEASSERT AGSA_SATA_PROTOCOL_SRST_ASSERT\n")); si_memset((void *)payload, 0, sizeof(agsaSATAStartCmd_t)); /* build IOMB DW 1 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t, tag), pRequest->HTag); /* DWORD 2 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,deviceId ), deviceIndex); /* DWORD 3 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,dataLen ), 0 ); /* DWORD 4 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,optNCQTagataProt ), (((agSATAReq->option & SATA_FIS_MASK) << SHIFT24) | (agTag << SHIFT16) | AtapDir)); si_memcpy((void *)(payload+4), (void *)&agSATAReq->fis.fisRegHostToDev, sizeof(agsaFisRegHostToDevice_t)); } else { /* build IOMB DW 1 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t, tag), pRequest->HTag); /* DWORD 2 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,deviceId ), deviceIndex); /* DWORD 3 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,dataLen ), agSATAReq->dataLength ); /* Since we are writing the payload in order, check for any special modes now. */ if (agSATAReq->option & AGSA_SATA_ENABLE_ENCRYPTION) { SA_ASSERT((opCode == OPC_INB_SATA_DIF_ENC_OPSTART), "opcode"); SA_DBG4(("saSATAStart: 1 Payload offset 0x%X\n", (unsigned int)(payload - (bit32 *)pMessage))); AtapDir |= AGSA_ENCRYPT_BIT; } if (agSATAReq->option & AGSA_SATA_ENABLE_DIF) { SA_ASSERT((opCode == OPC_INB_SATA_DIF_ENC_OPSTART), "opcode"); AtapDir |= AGSA_DIF_BIT; } #ifdef CCBUILD_TEST_EPL if(agSATAReq->encrypt.enableEncryptionPerLA) AtapDir |= (1 << SHIFT4); // enable EPL #endif /* DWORD 4 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,optNCQTagataProt ), (((agSATAReq->option & SATA_FIS_MASK) << SHIFT24) | (agTag << SHIFT16) | AtapDir)); /* DWORD 5 6 7 8 9 */ si_memcpy((void *)(payload+4), (void *)&agSATAReq->fis.fisRegHostToDev, sizeof(agsaFisRegHostToDevice_t)); /* DWORD 10 reserved */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,reserved1 ), 0 ); /* DWORD 11 reserved */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,reserved2 ), 0 ); SA_DBG4(("saSATAStart: 2 Payload offset 0x%X\n", (unsigned int)(payload - (bit32 *)pMessage))); } if (agSATAReq->option & AGSA_SATA_ENABLE_ENCRYPTION) { /* Write 10 dwords of zeroes as payload, skipping all DIF fields */ SA_DBG4(("saSATAStart: 2a Payload offset 0x%X\n", (unsigned int)(payload - (bit32 *)pMessage))); if (opCode == OPC_INB_SATA_DIF_ENC_OPSTART) { /* DW 11 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,Res_EPL_DESCL ),0 ); /* DW 12 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,resSKIPBYTES ),0 ); /* DW 13 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,Res_DPL_DESCL_NDPLR ),0 ); /* DW 14 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,Res_EDPL_DESCH ),0 ); /* DW 15 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,DIF_flags ),0 ); /* DW 16 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,udt ),0 ); /* DW 17 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,udtReplacementLo ),0 ); /* DW 18 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,udtReplacementHi ),0 ); /* DW 19 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,DIF_seed ),0 ); } if (agSATAReq->option & AGSA_SATA_ENABLE_ENCRYPTION) { SA_ASSERT((opCode == OPC_INB_SATA_DIF_ENC_OPSTART), "opcode"); SA_DBG4(("saSATAStart: 3 Payload offset 0x%X\n", (unsigned int)(payload - (bit32 *)pMessage))); /* Configure DWORD 20 */ encryptFlags = 0; if (agSATAReq->encrypt.keyTagCheck == agTRUE) { encryptFlags |= AGSA_ENCRYPT_KEY_TAG_BIT; } if( agSATAReq->encrypt.cipherMode == agsaEncryptCipherModeXTS ) { encryptFlags |= AGSA_ENCRYPT_XTS_Mode << SHIFT4; } encryptFlags |= agSATAReq->encrypt.dekInfo.dekTable << SHIFT2; encryptFlags |= (agSATAReq->encrypt.dekInfo.dekIndex & 0xFFFFFF) << SHIFT8; OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,encryptFlagsLo ),encryptFlags ); /* Configure DWORD 21*/ /* This information is available in the sectorSizeIndex */ encryptFlags = agSATAReq->encrypt.sectorSizeIndex; /* * Set Region0 sectors count */ if(agSATAReq->encrypt.enableEncryptionPerLA) { encryptFlags |= (agSATAReq->encrypt.EncryptionPerLRegion0SecCount << SHIFT16); } encryptFlags |= (agSATAReq->encrypt.kekIndex) << SHIFT5; OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,encryptFlagsHi ),encryptFlags ); /* Configure DWORD 22*/ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,keyTagLo ), agSATAReq->encrypt.keyTag_W0 ); /* Configure DWORD 23 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,keyTagHi ), agSATAReq->encrypt.keyTag_W1 ); /* Configure DWORD 24 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W0 ), agSATAReq->encrypt.tweakVal_W0 ); /* Configure DWORD 25 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W1 ), agSATAReq->encrypt.tweakVal_W1 ); /* Configure DWORD 26 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W2 ), agSATAReq->encrypt.tweakVal_W2 ); /* Configure DWORD 27 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W3 ), agSATAReq->encrypt.tweakVal_W3 ); } else { /* Write 8 dwords of zeros as payload, skipping all encryption fields */ if (opCode == OPC_INB_SATA_DIF_ENC_OPSTART) { /* Configure DWORD 22*/ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,keyTagLo ), 0 ); /* Configure DWORD 23 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,keyTagHi ), 0 ); /* Configure DWORD 24 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W0 ), 0 ); /* Configure DWORD 25 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W1 ), 0 ); /* Configure DWORD 26 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W2 ), 0 ); /* Configure DWORD 27 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,tweakVal_W3 ), 0 ); } } SA_DBG4(("saSATAStart: 4 Payload offset 0x%X\n", (unsigned int)(payload - (bit32 *)pMessage))); /* DWORD 11 13 14*/ if(agSATAReq->encrypt.enableEncryptionPerLA) { /* DWORD 11 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t, Res_EPL_DESCL), agSATAReq->encrypt.EncryptionPerLAAddrLo); /* DWORD 13 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t, Res_DPL_DESCL_NDPLR), 0); /* DWORD 14 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t, Res_EDPL_DESCH), agSATAReq->encrypt.EncryptionPerLAAddrHi); } else { /* DWORD 11 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t, Res_EPL_DESCL),0); /* DW 13 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t, Res_DPL_DESCL_NDPLR), 0); /* DWORD 14 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,Res_EDPL_DESCH ),0 ); } /* Configure DWORD 28 for encryption*/ if (pSgl) { /* Configure DWORD 28 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,AddrLow0 ), pSgl->sgLower ); /* Configure DWORD 29 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,AddrHi0 ), pSgl->sgUpper ); /* Configure DWORD 30 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,Len0 ), pSgl->len ); /* Configure DWORD 31 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,E0 ), pSgl->extReserved ); } else { /* Configure DWORD 28 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,AddrLow0 ), 0 ); /* Configure DWORD 29 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,AddrHi0 ), 0 ); /* Configure DWORD 30 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,Len0 ), 0 ); /* Configure DWORD 31 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAEncryptStartCmd_t,E0 ), 0 ); } } else { SA_ASSERT((opCode == OPC_INB_SATA_HOST_OPSTART), "opcode"); if (pSgl) { /* Configure DWORD 12 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,AddrLow0 ), pSgl->sgLower ); /* Configure DWORD 13 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,AddrHi0 ), pSgl->sgUpper ); /* Configure DWORD 14 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,Len0 ), pSgl->len ); /* Configure DWORD 15 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,E0 ), pSgl->extReserved ); } else { /* Configure DWORD 12 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,AddrLow0 ), 0 ); /* Configure DWORD 13 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,AddrHi0 ), 0 ); /* Configure DWORD 14 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,Len0 ), 0 ); /* Configure DWORD 15 */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,E0 ), 0 ); } /* support ATAPI packet command */ if ((agRequestType == AGSA_SATA_PROTOCOL_NON_PKT || agRequestType == AGSA_SATA_PROTOCOL_H2D_PKT || agRequestType == AGSA_SATA_PROTOCOL_D2H_PKT)) { /*DWORD 16 - 19 as SCSI CDB for support ATAPI Packet command*/ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,ATAPICDB ), (bit32)(agSATAReq->scsiCDB[0]|(agSATAReq->scsiCDB[1]<<8)|(agSATAReq->scsiCDB[2]<<16)|(agSATAReq->scsiCDB[3]<<24))); OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,ATAPICDB )+ 4, (bit32)(agSATAReq->scsiCDB[4]|(agSATAReq->scsiCDB[5]<<8)|(agSATAReq->scsiCDB[6]<<16)|(agSATAReq->scsiCDB[7]<<24))); OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,ATAPICDB )+ 8, (bit32)(agSATAReq->scsiCDB[8]|(agSATAReq->scsiCDB[9]<<8)|(agSATAReq->scsiCDB[10]<<16)|(agSATAReq->scsiCDB[11]<<24))); OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAStartCmd_t,ATAPICDB )+ 12, (bit32)(agSATAReq->scsiCDB[12]|(agSATAReq->scsiCDB[13]<<8)|(agSATAReq->scsiCDB[14]<<16)|(agSATAReq->scsiCDB[15]<<24))); } } /* send IOMB to SPC */ ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, opCode, outq, (bit8)circularQ->priority); #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ #ifdef SALL_API_TEST if (AGSA_RC_FAILURE != ret) { saRoot->LLCounters.IOCounter.numSataStarted++; } #endif smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "8a"); ext: OSSA_INP_LEAVE(agRoot); return ret; } /******************************************************************************/ /*! \brief Abort SATA command * * Abort SATA command * * \param agRoot handles for this instance of SAS/SATA hardware * \param queueNum inbound/outbound queue number * \param agIORequest the IO Request descriptor * \param agIOtoBeAborted * * \return If command is aborted successfully * - \e AGSA_RC_SUCCESS command is aborted successfully * - \e AGSA_RC_FAILURE command is not aborted successfully */ /*******************************************************************************/ GLOBAL bit32 saSATAAbort( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 queueNum, agsaDevHandle_t *agDevHandle, bit32 flag, void *abortParam, ossaGenericAbortCB_t agCB ) { bit32 ret = AGSA_RC_SUCCESS, retVal; agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); agsaIORequestDesc_t *pRequest; agsaIORequestDesc_t *pRequestABT = agNULL; agsaDeviceDesc_t *pDevice = agNULL; agsaDeviceDesc_t *pDeviceABT = NULL; agsaPort_t *pPort = agNULL; mpiICQueue_t *circularQ; void *pMessage; agsaSATAAbortCmd_t *payload; agsaIORequest_t *agIOToBeAborted; bit8 inq, outq; bit32 flag_copy = flag; smTraceFuncEnter(hpDBG_VERY_LOUD,"8b"); /* sanity check */ SA_ASSERT((agNULL != agRoot), ""); SA_ASSERT((agNULL != agIORequest), ""); SA_DBG3(("saSATAAbort: Aborting request %p ITtoBeAborted %p\n", agIORequest, abortParam)); /* Assign inbound and outbound Ring Buffer */ 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."); if( ABORT_SINGLE == (flag & ABORT_MASK) ) { agIOToBeAborted = (agsaIORequest_t *)abortParam; /* Get LL IORequest entry for saSATAAbort() */ pRequest = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData); if (agNULL == pRequest) { /* no pRequest found - can not Abort */ SA_DBG1(("saSATAAbort: pRequest AGSA_RC_FAILURE\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "8b"); return AGSA_RC_FAILURE; } /* Find the device the request sent to */ pDevice = pRequest->pDevice; /* Get LL IORequest entry */ pRequestABT = (agsaIORequestDesc_t *) (agIOToBeAborted->sdkData); /* Find the device the request sent to */ if (agNULL == pRequestABT) { /* no pRequestABT - can not find pDeviceABT */ SA_DBG1(("saSATAAbort: pRequestABT AGSA_RC_FAILURE\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'b', "8b"); return AGSA_RC_FAILURE; } pDeviceABT = pRequestABT->pDevice; if (agNULL == pDeviceABT) { /* no deviceID - can not build IOMB */ SA_DBG1(("saSATAAbort: pDeviceABT AGSA_RC_FAILURE\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'c', "8b"); return AGSA_RC_FAILURE; } if (agNULL != pDevice) { /* Find the port the request was sent to */ pPort = pDevice->pPort; } /* Get request from free IORequests */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); } else { if (ABORT_ALL == (flag & ABORT_MASK)) { /* abort all */ /* Find the outgoing port for the device */ pDevice = (agsaDeviceDesc_t *) (agDevHandle->sdkData); pPort = pDevice->pPort; ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); pRequest = (agsaIORequestDesc_t *)saLlistIOGetHead(&(saRoot->freeIORequests)); } else { /* only support 00 and 01 for flag */ SA_DBG1(("saSATAAbort: flag AGSA_RC_FAILURE\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'd', "8b"); return AGSA_RC_FAILURE; } } /* If no LL IO request entry avalable */ if ( agNULL == pRequest ) { ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG1(("saSATAAbort, No request from free list\n" )); smTraceFuncExit(hpDBG_VERY_LOUD, 'e', "8b"); return AGSA_RC_BUSY; } /* If free IOMB avaliable */ /* Remove the request from free list */ saLlistIORemove(&(saRoot->freeIORequests), &(pRequest->linkNode)); SA_ASSERT((!pRequest->valid), "The pRequest is in use"); /* Add the request to the pendingIORequests list of the device */ pRequest->valid = agTRUE; saLlistIOAdd(&(pDevice->pendingIORequests), &(pRequest->linkNode)); /* set up pRequest */ ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); pRequest->pIORequestContext = agIORequest; pRequest->requestType = AGSA_SATA_REQTYPE; pRequest->pDevice = pDevice; pRequest->pPort = pPort; pRequest->completionCB = (void*)agCB; /* pRequest->abortCompletionCB = agCB; */ pRequest->startTick = saRoot->timeTick; /* Set request to the sdkData of agIORequest */ agIORequest->sdkData = pRequest; /* save tag and IOrequest pointer to IOMap */ saRoot->IOMap[pRequest->HTag].Tag = pRequest->HTag; saRoot->IOMap[pRequest->HTag].IORequest = (void *)pRequest; #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedEnter(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ /* If LL IO request entry avaliable */ /* Get a free inbound queue entry */ circularQ = &saRoot->inboundQueue[inq]; retVal = mpiMsgFreeGet(circularQ, IOMB_SIZE64, &pMessage); /* if message size is too large return failure */ if (AGSA_RC_FAILURE == retVal) { #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); pRequest->valid = agFALSE; saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG1(("saSATAAbort, error when get free IOMB\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'f', "8b"); return AGSA_RC_FAILURE; } /* return busy if inbound queue is full */ if (AGSA_RC_BUSY == retVal) { #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); pRequest->valid = agFALSE; saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG1(("saSATASAbort, no more IOMB\n")); smTraceFuncExit(hpDBG_VERY_LOUD, 'g', "8b"); return AGSA_RC_BUSY; } /* setup payload */ payload = (agsaSATAAbortCmd_t*)pMessage; OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAAbortCmd_t, tag), pRequest->HTag); if( ABORT_SINGLE == (flag & ABORT_MASK) ) { /* If no device */ if ( agNULL == pDeviceABT ) { #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); pRequest->valid = agFALSE; saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); SA_DBG1(("saSATAAbort,no device\n" )); smTraceFuncExit(hpDBG_VERY_LOUD, 'h', "8b"); return AGSA_RC_FAILURE; } OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAAbortCmd_t, deviceId), pDeviceABT->DeviceMapIndex); OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAAbortCmd_t, HTagAbort), pRequestABT->HTag); } else { /* abort all */ OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAAbortCmd_t, deviceId), pDevice->DeviceMapIndex); OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAAbortCmd_t, HTagAbort), 0); } if(flag & ABORT_TSDK_QUARANTINE) { if(smIS_SPCV(agRoot)) { flag_copy &= ABORT_SCOPE; flag_copy |= ABORT_QUARANTINE_SPCV; } } OSSA_WRITE_LE_32(agRoot, payload, OSSA_OFFSET_OF(agsaSATAAbortCmd_t, abortAll), flag_copy); SA_DBG1(("saSATAAbort, HTag 0x%x HTagABT 0x%x deviceId 0x%x\n", payload->tag, payload->HTagAbort, payload->deviceId)); /* post the IOMB to SPC */ ret = mpiMsgProduce(circularQ, (void *)pMessage, MPI_CATEGORY_SAS_SATA, OPC_INB_SATA_ABORT, outq, (bit8)circularQ->priority); #ifdef SA_LL_IBQ_PROTECT ossaSingleThreadedLeave(agRoot, LL_IOREQ_IBQ0_LOCK + inq); #endif /* SA_LL_IBQ_PROTECT */ #ifdef SALL_API_TEST if (AGSA_RC_FAILURE != ret) { saRoot->LLCounters.IOCounter.numSataAborted++; } #endif siCountActiveIORequestsOnDevice( agRoot, payload->deviceId ); smTraceFuncExit(hpDBG_VERY_LOUD, 'i', "8b"); return ret; } /******************************************************************************/ /*! \brief Routine to handle for received SATA with data payload event * * The handle for received SATA with data payload event * * \param agRoot handles for this instance of SAS/SATA hardware * \param pRequest the IO request descriptor * \param agFirstDword pointer to the first Dword * \param pResp pointer to the rest of SATA response * \param lengthResp total length of SATA Response frame * * \return -void- */ /*******************************************************************************/ GLOBAL void siEventSATAResponseWtDataRcvd( agsaRoot_t *agRoot, agsaIORequestDesc_t *pRequest, bit32 *agFirstDword, bit32 *pResp, bit32 lengthResp ) { agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); agsaDeviceDesc_t *pDevice; #if defined(SALLSDK_DEBUG) agsaFrameHandle_t frameHandle; /* get frame handle */ frameHandle = (agsaFrameHandle_t)(pResp); #endif /* SALLSDK_DEBUG */ smTraceFuncEnter(hpDBG_VERY_LOUD,"8c"); /* If the request is still valid */ if ( agTRUE == pRequest->valid ) { /* get device */ pDevice = pRequest->pDevice; ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); /* Delete the request from the pendingIORequests */ saLlistIORemove(&(pDevice->pendingIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); (*(ossaSATACompletedCB_t)(pRequest->completionCB))(agRoot, pRequest->pIORequestContext, OSSA_IO_SUCCESS, agFirstDword, lengthResp, (void *)pResp); ossaSingleThreadedEnter(agRoot, LL_IOREQ_LOCKEQ_LOCK); pRequest->valid = agFALSE; /* return the request to free pool */ saLlistIOAdd(&(saRoot->freeIORequests), &(pRequest->linkNode)); ossaSingleThreadedLeave(agRoot, LL_IOREQ_LOCKEQ_LOCK); } smTraceFuncExit(hpDBG_VERY_LOUD, 'a', "8c"); return; } /******************************************************************************/ /*! \brief copy a SATA signature to another * * copy a SATA signature to another * * \param pDstSignature pointer to the destination signature * \param pSrcSignature pointer to the source signature * * \return If they match * - \e agTRUE match * - \e agFALSE doesn't match */ /*******************************************************************************/ GLOBAL void siSATASignatureCpy( bit8 *pDstSignature, bit8 *pSrcSignature ) { bit32 i; for ( i = 0; i < 5; i ++ ) { pDstSignature[i] = pSrcSignature[i]; } return; }