/******************************************************************************* *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 * * * This file contains initiator IO related functions in TD layer * */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef FDS_SM #include #include #include #endif #ifdef FDS_DM #include #include #include #endif #include #include #include #ifdef INITIATOR_DRIVER #include #include #include #endif #ifdef TARGET_DRIVER #include #include #include #endif #include #include /***************************************************************************** *! \brief tiINIIOStart * * Purpose: This routine is called to initiate a new SCSI request. * * \param tiRoot: Pointer to initiator driver/port instance. * \param tiIORequest: Pointer to the I/O request context for this I/O. * \param tiDeviceHandle: Pointer to device handle for this I/O. * \param tiScsiRequest: Pointer to the SCSI-3 I/O request and SGL list. * \param tiRequestBody: Pointer to the OS Specific module allocated storage * to be used by the TD layer for executing this I/O. * \param interruptContext: The interrupt context within which this function * is called. * \return: * * tiSuccess: I/O request successfully initiated. * tiBusy: No resources available, try again later. * tiIONoDevice: Invalid device handle. * tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ osGLOBAL bit32 tiINIIOStart( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, void *tiRequestBody, bit32 interruptContext ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni; tdsaDeviceData_t *oneDeviceData; agsaRoot_t *agRoot = agNULL; agsaIORequest_t *agIORequest = agNULL; agsaDevHandle_t *agDevHandle = agNULL; bit32 agRequestType; agsaSASRequestBody_t *agSASRequestBody = agNULL; bit32 tiStatus = tiError; bit32 saStatus = AGSA_RC_FAILURE; tdIORequestBody_t *tdIORequestBody; agsaSSPInitiatorRequest_t *agSSPInitiatorRequest; #ifdef REMOVED /* only for debugging */ bit32 i; #endif #ifdef SATA_ENABLE #ifndef FDS_SM satIOContext_t *satIOContext; #endif #endif #ifdef FDS_SM smRoot_t *smRoot = &(tdsaAllShared->smRoot); smIORequest_t *smIORequest; smDeviceHandle_t *smDeviceHandle; smScsiInitiatorRequest_t *smSCSIRequest; #endif TDSA_INP_ENTER(tiRoot); TI_DBG6(("tiINIIOStart: start\n")); TI_DBG6(("tiINIIOStart:: ******* tdsaRoot %p tdsaAllShared %p \n", tdsaRoot,tdsaAllShared)); oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG6(("tiINIIOStart: onedevicedata %p\n", oneDeviceData)); if(oneDeviceData == agNULL) { TI_DBG1(("tiINIIOStart: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle )); tiStatus = tiIONoDevice; goto ext; } /* for hotplug */ if (oneDeviceData->valid != agTRUE || oneDeviceData->registered != agTRUE || oneDeviceData->tdPortContext == agNULL ) { TI_DBG1(("tiINIIOStart: tiDeviceHandle=%p did %d DeviceData was removed\n", tiDeviceHandle, oneDeviceData->id)); TI_DBG6(("tiINIIOStart: device AddrHi 0x%08x AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); // for debugging tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; tdIORequestBody->IOCompletionFunc = itdssIOForDebugging1Completed; TI_DBG6(("tiINIIOStart: IOCompletionFunc %p\n", tdIORequestBody->IOCompletionFunc)); tiStatus = tiIONoDevice; goto ext; } #if 1 if (tiIORequest->osData == agNULL) { TI_DBG1(("tiINIIOStart: tiIORequest->osData is NULL, wrong\n")); } #endif /* starting IO with SAS device */ if (oneDeviceData->DeviceType == TD_SAS_DEVICE) { TI_DBG6(("tiINIIOStart: calling saSSPStart\n")); agRoot = oneDeviceData->agRoot; agDevHandle = oneDeviceData->agDevHandle; /* OS layer has tdlayer data structure pointer in tdIORequestBody_t tdIOReqBody; in ccb_t in agtiapi.h */ tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* initialize */ osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t)); /* let's initialize tdIOrequestBody */ /* initialize callback */ tdIORequestBody->IOCompletionFunc = itdssIOCompleted; /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = tiIORequest; /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; /* initialize expDataLength */ tdIORequestBody->IOType.InitiatorRegIO.expDataLength = tiScsiRequest->scsiCmnd.expDataLength; tdIORequestBody->IOType.InitiatorRegIO.sglVirtualAddr = tiScsiRequest->sglVirtualAddr; /* initializes "agsaSgl_t agSgl" of "agsaDifSSPInitiatorRequest_t" */ tiStatus = itdssIOPrepareSGL( tiRoot, tdIORequestBody, &tiScsiRequest->agSgl1, tiScsiRequest->sglVirtualAddr ); if (tiStatus != tiSuccess) { TI_DBG1(("tiINIIOStart: can't get SGL\n")); goto ext; } /* initialize agIORequest */ agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; agIORequest->sdkData = agNULL; /* LL takes care of this */ /* initialize tdIORequestBody_t tdIORequestBody -> agSASRequestBody */ agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody); agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq); agSSPInitiatorRequest->flag = 0; /* copy cdb bytes */ osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16); /* copy lun field */ osti_memcpy(agSSPInitiatorRequest->sspCmdIU.lun, tiScsiRequest->scsiCmnd.lun.lun, 8); /* setting the data length */ agSSPInitiatorRequest->dataLength = tiScsiRequest->scsiCmnd.expDataLength; TI_DBG6(("tiINIIOStart: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength)); agSSPInitiatorRequest->firstBurstSize = 0; /* process taskattribute */ if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_SIMPLE) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_SIMPLE; } else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ORDERED) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ORDERED; } else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_HEAD_OF_QUEUE) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_HEAD_OF_QUEUE; } else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ACA) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ACA; } if (tiScsiRequest->dataDirection == tiDirectionIn) { agRequestType = AGSA_SSP_INIT_READ; TI_DBG6(("tiINIIOStart: READ\n")); } else if (tiScsiRequest->dataDirection == tiDirectionOut) { agRequestType = AGSA_SSP_INIT_WRITE; TI_DBG6(("tiINIIOStart: WRITE\n")); } else { agRequestType = AGSA_REQ_TYPE_UNKNOWN; TI_DBG1(("tiINIIOStart: unknown data direction\n")); } tdIORequestBody->agRequestType = agRequestType; TI_DBG6(("tiINIIOStart: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); TI_DBG6(("tiINIIOStart: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); /* for debugging */ if (tdIORequestBody->IOCompletionFunc == agNULL) { TI_DBG1(("tiINIIOStart: Error!!!! IOCompletionFunc is NULL\n")); } saStatus = saSSPStart(agRoot, agIORequest, tdsaRotateQnumber(tiRoot, oneDeviceData), agDevHandle, agRequestType, agSASRequestBody, agNULL, &ossaSSPCompleted); tdIORequestBody->ioStarted = agTRUE; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->reTries = 0; if (saStatus == AGSA_RC_SUCCESS) { Initiator->NumIOsActive++; tiStatus = tiSuccess; } else { tdIORequestBody->ioStarted = agFALSE; tdIORequestBody->ioCompleted = agTRUE; if (saStatus == AGSA_RC_BUSY) { TI_DBG4(("tiINIIOStart: saSSPStart busy\n")); tiStatus = tiBusy; } else { tiStatus = tiError; } goto ext; } } #ifdef FDS_SM else if (oneDeviceData->DeviceType == TD_SATA_DEVICE) { TI_DBG5(("tiINIIOStart: calling satIOStart\n")); TI_DBG5(("tiINIIOStart: onedevicedata did %d\n", oneDeviceData->id)); tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* initialize */ osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t)); /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; tdIORequestBody->superIOFlag = agFALSE; tiIORequest->tdData = tdIORequestBody; tdIORequestBody->tiIORequest = tiIORequest; smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest); smIORequest->tdData = tdIORequestBody; smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle); smDeviceHandle->tdData = oneDeviceData; smSCSIRequest = (smScsiInitiatorRequest_t *)&(tdIORequestBody->SM.smSCSIRequest); osti_memcpy(smSCSIRequest, tiScsiRequest, sizeof(smScsiInitiatorRequest_t)); tiStatus = smIOStart(smRoot, smIORequest, smDeviceHandle, smSCSIRequest, interruptContext); /* osGLOBAL bit32 smIOStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, bit32 interruptContext ) */ } #else else if (oneDeviceData->DeviceType == TD_SATA_DEVICE) { TI_DBG5(("tiINIIOStart: calling satIOStart\n")); TI_DBG5(("tiINIIOStart: onedevicedata did %d\n", oneDeviceData->id)); #ifdef SATA_ENABLE tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* initialize */ osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t)); /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = tiIORequest; tdIORequestBody->IOCompletionFunc = itdssIOForDebugging2Completed; satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); /* * Need to initialize all the fields within satIOContext except * reqType and satCompleteCB which will be set in sat.c depending on cmd. */ tdIORequestBody->transport.SATA.tiSenseData.senseData = agNULL; tdIORequestBody->transport.SATA.tiSenseData.senseLen = 0; satIOContext->pSatDevData = &oneDeviceData->satDevData; satIOContext->pFis = &tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev; satIOContext->pScsiCmnd = &tiScsiRequest->scsiCmnd; satIOContext->pSense = &tdIORequestBody->transport.SATA.sensePayload; satIOContext->pTiSenseData = &tdIORequestBody->transport.SATA.tiSenseData; satIOContext->pTiSenseData->senseData = satIOContext->pSense; /* satIOContext->pSense = (scsiRspSense_t *)satIOContext->pTiSenseData->senseData; */ satIOContext->tiRequestBody = tiRequestBody; satIOContext->interruptContext = interruptContext; satIOContext->ptiDeviceHandle = tiDeviceHandle; satIOContext->tiScsiXchg = tiScsiRequest; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; /* satIOContext->tiIORequest = tiIORequest; */ /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; /* followings are used only for internal IO */ satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; TI_DBG5(("tiINIIOStart: pSatDevData=%p\n", satIOContext->pSatDevData )); tiStatus = satIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); goto ext; #endif } #endif /* else of FDS_SM */ else { tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; tdIORequestBody->IOCompletionFunc = itdssIOForDebugging3Completed; TI_DBG1(("tiINIIOStart: wrong unspported Device %d\n", oneDeviceData->DeviceType)); /* error. unsupported IO */ } ext: TDSA_INP_LEAVE(tiRoot); return tiStatus; } #ifdef FAST_IO_TEST osGLOBAL bit32 tiINIFastIOSend(void *ioh) { bit32 saStatus, tiStatus; saStatus = saFastSSPSend(ioh); if (saStatus == AGSA_RC_SUCCESS) tiStatus = tiSuccess; else tiStatus = tiError; return tiStatus; } osGLOBAL bit32 tiINIFastIOCancel(void *ioh) { bit32 saStatus, tiStatus; saStatus = saFastSSPCancel(ioh); if (saStatus == AGSA_RC_SUCCESS) tiStatus = tiSuccess; else tiStatus = tiError; return tiStatus; } osGLOBAL void* tiINIFastIOPrepare( tiRoot_t *tiRoot, void *ioHandle, agsaFastCommand_t *fc) { tdsaDeviceData_t *oneDeviceData; tiDeviceHandle_t *tiDeviceHandle = fc->devHandle; bit32 taskAttribute = fc->taskAttribute; void *ioh = ioHandle; TDSA_INP_ENTER(tiRoot); TI_DBG6(("tiINIFastIOPrepare: enter\n")); oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if(oneDeviceData == agNULL) { TI_DBG1(("tiINIFastIOPrepare: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle)); ioHandle = 0; TD_ASSERT((0), ""); goto ext; } TI_DBG6(("tiINIFastIOPrepare: onedevicedata %p\n", oneDeviceData)); /* starting IO with SAS device */ if (oneDeviceData->DeviceType != TD_SAS_DEVICE) { TI_DBG1(("tiINISuperIOSend: wrong Device %d\n", oneDeviceData->DeviceType)); /* error: unsupported IO */ ioHandle = 0; TD_ASSERT((0), ""); goto ext; } fc->agRoot = oneDeviceData->agRoot; TD_ASSERT((NULL != fc->agRoot), ""); fc->devHandle = oneDeviceData->agDevHandle; TD_ASSERT((NULL != fc->devHandle), ""); fc->safb->oneDeviceData = oneDeviceData; /* process taskattribute */ switch (taskAttribute) { case TASK_SIMPLE: fc->taskAttribute = TD_TASK_SIMPLE; break; case TASK_ORDERED: fc->taskAttribute = TD_TASK_ORDERED; break; case TASK_HEAD_OF_QUEUE: fc->taskAttribute = TD_TASK_HEAD_OF_QUEUE; break; case TASK_ACA: fc->taskAttribute = TD_TASK_ACA; break; /* compile out for "iniload" */ } TI_DBG3(("tiINIFastIOPrepare: data direction: %x\n", fc->agRequestType)); TI_DBG6(("tiINIFastIOPrepare: device AddrHi/Lo 0x%08x / 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); fc->queueNum = tdsaRotateQnumber(tiRoot, oneDeviceData); ioHandle = saFastSSPPrepare(ioHandle, fc, ossaFastSSPCompleted, fc->safb); if (!ioHandle) { TI_DBG1(("tiINIFastIOPrepare: saSuperSSPSend error\n")); TD_ASSERT((0), ""); //goto ext; } ext: if (ioh && !ioHandle) { saFastSSPCancel(ioh); } TI_DBG6(("tiINIFastIOPrepare: leave\n")); TDSA_INP_LEAVE(tiRoot); return ioHandle; } /* tiINIFastIOPrepare */ #endif /***************************************************************************** * * tiINIIOStartDif * * Purpose: This routine is called to initiate a new SCSI request with * DIF enable. * * Parameters: * tiRoot: Pointer to initiator driver/port instance. * tiIORequest: Pointer to the I/O request context for this I/O. * tiDeviceHandle: Pointer to device handle for this I/O. * tiScsiRequest: Pointer to the SCSI-3 I/O request and SGL list. * tiRequestBody: Pointer to the OS Specific module allocated storage * to be used by the TD layer for executing this I/O. * interruptContext: The interrupt context within which this function * is called. * difOption: DIF option. * * Return: * * tiSuccess: I/O request successfully initiated. * tiBusy: No resources available, try again later. * tiIONoDevice: Invalid device handle. * tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ osGLOBAL bit32 tiINIIOStartDif( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, void *tiRequestBody, bit32 interruptContext, tiDif_t *difOption ) { /* This function was never used by SAS/SATA. Use tiINISuperIOStart() instead. */ return tiBusy; } /***************************************************************************** * * tiINISuperIOStart * * Purpose: This routine is called to initiate a new SCSI request. * * Parameters: * tiRoot: Pointer to initiator driver/port instance. * tiIORequest: Pointer to the I/O request context for this I/O. * tiDeviceHandle: Pointer to device handle for this I/O. * tiScsiRequest: Pointer to the SCSI-3 I/O request and SGL list. * tiRequestBody: Pointer to the OS Specific module allocated storage * to be used by the TD layer for executing this I/O. * interruptContext: The interrupt context within which this function * is called. * Return: * * tiSuccess: I/O request successfully initiated. * tiBusy: No resources available, try again later. * tiIONoDevice: Invalid device handle. * tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ osGLOBAL bit32 tiINISuperIOStart( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiSuperScsiInitiatorRequest_t *tiScsiRequest, void *tiRequestBody, bit32 interruptContext ) { tdsaRoot_t *tdsaRoot = agNULL; tdsaContext_t *tdsaAllShared = agNULL; itdsaIni_t *Initiator = agNULL; tdsaDeviceData_t *oneDeviceData = agNULL; tdIORequestBody_t *tdIORequestBody = agNULL; agsaSSPInitiatorRequest_t *agSSPInitiatorRequest = agNULL; agsaRoot_t *agRoot = agNULL; agsaIORequest_t *agIORequest = agNULL; agsaDevHandle_t *agDevHandle = agNULL; agsaSASRequestBody_t *agSASRequestBody = agNULL; bit32 tiStatus = tiError; bit32 saStatus = AGSA_RC_FAILURE; bit32 adjusted_length = 0; bit32 agRequestType = 0; agBOOLEAN needPlusDataLenAdjustment = agFALSE; agBOOLEAN needMinusDataLenAdjustment = agFALSE; #ifdef SATA_ENABLE #ifndef FDS_SM satIOContext_t *satIOContext; #endif #endif #ifdef FDS_SM smRoot_t *smRoot; smIORequest_t *smIORequest; smDeviceHandle_t *smDeviceHandle; smSuperScsiInitiatorRequest_t *smSuperSCSIRequest; #endif #ifdef CCBUILD_INDIRECT_CDB agsaSSPInitiatorRequestIndirect_t *agSSPInitiatorIndRequest = agNULL; #endif TD_ASSERT(tiRoot , "tiRoot"); TD_ASSERT(tiIORequest, "tiIORequest"); TD_ASSERT(tiDeviceHandle, "tiDeviceHandle"); TD_ASSERT(tiRequestBody, "tiRequestBody"); TD_ASSERT(tiRoot->tdData, "tiRoot->tdData"); TD_ASSERT(tiDeviceHandle, "tiDeviceHandle"); tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; TD_ASSERT(tdsaRoot, "tdsaRoot"); tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; TD_ASSERT(tdsaAllShared, "tdsaAllShared"); Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni; TD_ASSERT(Initiator, "Initiator"); oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TD_ASSERT(oneDeviceData, "oneDeviceData"); #ifdef FDS_SM smRoot = &(tdsaAllShared->smRoot); TD_ASSERT(smRoot , "smRoot"); #endif TI_DBG6(("tiINISuperIOStart: start\n")); TI_DBG6(("tiINISuperIOStart:: ******* tdsaRoot %p tdsaAllShared %p \n", tdsaRoot,tdsaAllShared)); TI_DBG6(("tiINISuperIOStart: onedevicedata %p\n", oneDeviceData)); if (oneDeviceData == agNULL) { TI_DBG1(("tiINISuperIOStart: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle )); return tiIONoDevice; } /* for hotplug */ if (oneDeviceData->valid != agTRUE || oneDeviceData->registered != agTRUE || oneDeviceData->tdPortContext == agNULL ) { TI_DBG1(("tiINISuperIOStart: tiDeviceHandle=%p did %d DeviceData was removed\n", tiDeviceHandle, oneDeviceData->id)); TI_DBG6(("tiINISuperIOStart: device AddrHi 0x%08x AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo)); // for debugging tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; tdIORequestBody->IOCompletionFunc = itdssIOForDebugging1Completed; TI_DBG6(("tiINISuperIOStart: IOCompletionFunc %p\n", tdIORequestBody->IOCompletionFunc)); return tiIONoDevice; } #ifdef DBG if (tiIORequest->osData == agNULL) { TI_DBG1(("tiINISuperIOStart: tiIORequest->osData is NULL, wrong\n")); return tiError; } #endif /* starting IO with SAS device */ if (oneDeviceData->DeviceType == TD_SAS_DEVICE) { TI_DBG3(("tiINISuperIOStart: calling saSSPStart\n")); agRoot = oneDeviceData->agRoot; agDevHandle = oneDeviceData->agDevHandle; /* OS layer has tdlayer data structure pointer in tdIORequestBody_t tdIOReqBody; in ccb_t in agtiapi.h */ tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* initialize */ /*the tdIORequestBody has been initialized in HwBuildIo routine */ /*osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));*/ /* let's initialize tdIOrequestBody */ /* initialize callback */ tdIORequestBody->IOCompletionFunc = itdssIOCompleted; /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = tiIORequest; /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; /* initialize expDataLength */ tdIORequestBody->IOType.InitiatorRegIO.expDataLength = tiScsiRequest->scsiCmnd.expDataLength; tdIORequestBody->IOType.InitiatorRegIO.sglVirtualAddr = tiScsiRequest->sglVirtualAddr; /* initialize agIORequest */ agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; /* initialize tdIORequestBody_t tdIORequestBody -> agSASRequestBody */ agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody); agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq); agSSPInitiatorRequest->flag = 0; if (tiScsiRequest->flags & TI_SCSI_INITIATOR_ENCRYPT) { TI_DBG3(("tiINISuperIOStart: TI_SCSI_INITIATOR_ENCRYPT\n")); /* Copy all of the relevant encrypt information */ agSSPInitiatorRequest->flag |= AGSA_SAS_ENABLE_ENCRYPTION; TD_ASSERT( sizeof(tiEncrypt_t) == sizeof(agsaEncrypt_t) , "sizeof(tiEncrypt_t) == sizeof(agsaEncrypt_t)"); osti_memcpy(&agSSPInitiatorRequest->encrypt, &tiScsiRequest->Encrypt, sizeof(agsaEncrypt_t)); } if ((tiScsiRequest->flags & TI_SCSI_INITIATOR_DIF) && (tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_10 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_10 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_6 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_6 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_12 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_12 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_WRITE_16 || tiScsiRequest->scsiCmnd.cdb[0] == SCSIOPC_READ_16 )) { TI_DBG3(("tiINISuperIOStart: TI_SCSI_INITIATOR_DIF\n")); /* Copy all of the relevant DIF information */ agSSPInitiatorRequest->flag |= AGSA_SAS_ENABLE_DIF; osti_memcpy(&agSSPInitiatorRequest->dif, &tiScsiRequest->Dif, sizeof(agsaDif_t)); /* Check if need to adjust dataLength. */ switch (tiScsiRequest->dataDirection) { case tiDirectionOut: /* Write/Outbound */ break; case tiDirectionIn: /* Read/Inbound */ if ((agSSPInitiatorRequest->dif.flags & DIF_ACTION_FLAG_MASK) == DIF_INSERT) { needPlusDataLenAdjustment = agTRUE; } break; } /* Set SGL data len XXX This code needs to support more sector sizes */ /* Length adjustment for PCIe DMA only not SAS */ if (needPlusDataLenAdjustment == agTRUE) { adjusted_length = tiScsiRequest->scsiCmnd.expDataLength; adjusted_length += (adjusted_length/512) * 8; agSSPInitiatorRequest->dataLength = adjusted_length; } else if (needMinusDataLenAdjustment == agTRUE) { adjusted_length = tiScsiRequest->scsiCmnd.expDataLength; adjusted_length -= (adjusted_length/520) * 8; agSSPInitiatorRequest->dataLength = adjusted_length; } else { /* setting the data length */ agSSPInitiatorRequest->dataLength = tiScsiRequest->scsiCmnd.expDataLength; } /* initializes "agsaSgl_t agSgl" of "agsaDifSSPInitiatorRequest_t" */ tiStatus = itdssIOPrepareSGL( tiRoot, tdIORequestBody, &tiScsiRequest->agSgl1, tiScsiRequest->sglVirtualAddr ); TI_DBG2(("tiINISuperIOStart:TI_SCSI_INITIATOR_DIF needMinusDataLenAdjustment %d needPlusDataLenAdjustment %d difAction %X\n", needMinusDataLenAdjustment, needPlusDataLenAdjustment, agSSPInitiatorRequest->dif.flags & DIF_ACTION_FLAG_MASK)); } else { /* setting the data length */ agSSPInitiatorRequest->dataLength = tiScsiRequest->scsiCmnd.expDataLength; /* initializes "agsaSgl_t agSgl" of "agsaSSPInitiatorRequest_t" */ tiStatus = itdssIOPrepareSGL( tiRoot, tdIORequestBody, &tiScsiRequest->agSgl1, tiScsiRequest->sglVirtualAddr ); } if (tiStatus != tiSuccess) { TI_DBG1(("tiINISuperIOStart: can't get SGL\n")); return tiStatus; } TI_DBG6(("tiINISuperIOStart: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength)); /* process taskattribute */ if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_SIMPLE) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_SIMPLE; } else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ORDERED) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ORDERED; } else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_HEAD_OF_QUEUE) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_HEAD_OF_QUEUE; } else if (tiScsiRequest->scsiCmnd.taskAttribute == TASK_ACA) { agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute = (bit8) agSSPInitiatorRequest->sspCmdIU.efb_tp_taskAttribute | TD_TASK_ACA; } /* copy cdb bytes */ osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16); /* copy lun field */ osti_memcpy(agSSPInitiatorRequest->sspCmdIU.lun, tiScsiRequest->scsiCmnd.lun.lun, 8); #ifdef CCBUILD_INDIRECT_CDB /* check the Indirect CDB flag */ if (tiScsiRequest->flags & TI_SCSI_INITIATOR_INDIRECT_CDB) { /* Indirect CDB */ if (tiScsiRequest->dataDirection == tiDirectionIn) { agRequestType = AGSA_SSP_INIT_READ_INDIRECT; TI_DBG6(("tiINISuperIOStart: Indirect READ\n")); } else if (tiScsiRequest->dataDirection == tiDirectionOut) { agRequestType = AGSA_SSP_INIT_WRITE_INDIRECT; TI_DBG6(("tiINISuperIOStart: Indirect WRITE\n")); } else { agRequestType = AGSA_REQ_TYPE_UNKNOWN; TI_DBG1(("tiINISuperIOStart: unknown data direction\n")); } agSSPInitiatorIndRequest = &(agSASRequestBody->sspInitiatorReqIndirect); /* copy the constructed SSPIU info to indirect SSPIU buffer */ osti_memcpy(tiScsiRequest->IndCDBBuffer, &agSSPInitiatorRequest->sspCmdIU, sizeof(agsaSSPCmdInfoUnit_t)); /* initialize the indirect CDB buffer address and length */ agSSPInitiatorIndRequest->sspInitiatorReqAddrLower32 = tiScsiRequest->IndCDBLowAddr; agSSPInitiatorIndRequest->sspInitiatorReqAddrUpper32 = tiScsiRequest->IndCDBHighAddr; agSSPInitiatorIndRequest->sspInitiatorReqLen = sizeof(agsaSSPCmdInfoUnit_t); } else #endif //CCBUILD_INDIRECT_CDB { /* Direct CDB */ if (tiScsiRequest->dataDirection == tiDirectionIn) { agRequestType = AGSA_SSP_INIT_READ; TI_DBG6(("tiINISuperIOStart: READ\n")); } else if (tiScsiRequest->dataDirection == tiDirectionOut) { agRequestType = AGSA_SSP_INIT_WRITE; TI_DBG6(("tiINISuperIOStart: WRITE\n")); } else { agRequestType = AGSA_REQ_TYPE_UNKNOWN; TI_DBG1(("tiINISuperIOStart: unknown data direction\n")); } } tdIORequestBody->agRequestType = agRequestType; TI_DBG6(("tiINISuperIOStart: device AddrHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); TI_DBG6(("tiINISuperIOStart: device AddrLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); #ifdef DBG /* for debugging */ if (tdIORequestBody->IOCompletionFunc == agNULL) { TI_DBG1(("tiINISuperIOStart: Error!!!! IOCompletionFunc is NULL\n")); return tiError; } #endif saStatus = saSSPStart(agRoot, agIORequest, tdsaRotateQnumber(tiRoot, oneDeviceData), agDevHandle, agRequestType, agSASRequestBody, agNULL, &ossaSSPCompleted); if (saStatus == AGSA_RC_SUCCESS) { Initiator->NumIOsActive++; tdIORequestBody->ioStarted = agTRUE; tdIORequestBody->ioCompleted = agFALSE; tiStatus = tiSuccess; } else { tdIORequestBody->ioStarted = agFALSE; tdIORequestBody->ioCompleted = agTRUE; if (saStatus == AGSA_RC_BUSY) { TI_DBG4(("tiINISuperIOStart: saSSPStart busy\n")); tiStatus = tiBusy; } else { tiStatus = tiError; } return tiStatus; } } #ifdef FDS_SM else if (oneDeviceData->DeviceType == TD_SATA_DEVICE) { TI_DBG5(("tiINISuperIOStart: calling satIOStart\n")); TI_DBG5(("tiINISuperIOStart: onedevicedata did %d\n", oneDeviceData->id)); TI_DBG5(("tiINISuperIOStart: SATA sasAddressHi 0x%08x\n", oneDeviceData->SASAddressID.sasAddressHi)); TI_DBG5(("tiINISuperIOStart: SATA sasAddressLo 0x%08x\n", oneDeviceData->SASAddressID.sasAddressLo)); tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* initialize */ /* the tdIORequestBody has been initialized by Storport in SRB Extension */ /*osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t));*/ /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; tdIORequestBody->superIOFlag = agTRUE; tiIORequest->tdData = tdIORequestBody; tdIORequestBody->tiIORequest = tiIORequest; smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest); smIORequest->tdData = tdIORequestBody; smIORequest->smData = &tdIORequestBody->smIORequestBody; smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle); smDeviceHandle->tdData = oneDeviceData; smSuperSCSIRequest = (smSuperScsiInitiatorRequest_t *)&(tdIORequestBody->SM.smSuperSCSIRequest); osti_memcpy(smSuperSCSIRequest, tiScsiRequest, sizeof(smSuperScsiInitiatorRequest_t)); tiStatus = smSuperIOStart(smRoot, smIORequest, smDeviceHandle, smSuperSCSIRequest, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo, interruptContext); } #else else if (oneDeviceData->DeviceType == TD_SATA_DEVICE) { TI_DBG5(("tiINISuperIOStart: calling satIOStart\n")); TI_DBG5(("tiINISuperIOStart: onedevicedata did %d\n", oneDeviceData->id)); #ifdef SATA_ENABLE tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* initialize */ osti_memset(tdIORequestBody, 0, sizeof(tdIORequestBody_t)); /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = tiIORequest; tdIORequestBody->IOCompletionFunc = itdssIOForDebugging2Completed; satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); /* * Need to initialize all the fields within satIOContext except * reqType and satCompleteCB which will be set in sat.c depending on cmd. */ tdIORequestBody->transport.SATA.tiSenseData.senseData = agNULL; tdIORequestBody->transport.SATA.tiSenseData.senseLen = 0; satIOContext->pSatDevData = &oneDeviceData->satDevData; satIOContext->pFis = &tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev; satIOContext->pScsiCmnd = &tiScsiRequest->scsiCmnd; satIOContext->pSense = &tdIORequestBody->transport.SATA.sensePayload; satIOContext->pTiSenseData = &tdIORequestBody->transport.SATA.tiSenseData; satIOContext->pTiSenseData->senseData = satIOContext->pSense; /* satIOContext->pSense = (scsiRspSense_t *)satIOContext->pTiSenseData->senseData; */ satIOContext->tiRequestBody = tiRequestBody; satIOContext->interruptContext = interruptContext; satIOContext->ptiDeviceHandle = tiDeviceHandle; /* This code uses a kludge for the tiScsiXchg. Many subroutines in the SATA code require a tiScsiInitiatorRequest. Since it would be a lot of work to replicate those functions for a tiSuperScsiInitiatorRequest, we will use a short cut. The standard pointer will be passed, but the superIOFlag marks the real type of the structure. */ satIOContext->tiScsiXchg = tiScsiRequest; satIOContext->superIOFlag = agTRUE; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; /* satIOContext->tiIORequest = tiIORequest; */ /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; /* followings are used only for internal IO */ satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; TI_DBG5(("tiINISuperIOStart: pSatDevData=%p\n", satIOContext->pSatDevData )); tiStatus = satIOStart( tiRoot, tiIORequest, tiDeviceHandle, satIOContext->tiScsiXchg, satIOContext); return tiStatus; #endif } #endif /* else of FDS_SM */ else { tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; tdIORequestBody->IOCompletionFunc = itdssIOForDebugging3Completed; TI_DBG1(("tiINISuperIOStart: wrong unspported Device %d\n", oneDeviceData->DeviceType)); /* error. unsupported IO */ } return tiStatus; } osGLOBAL bit32 tiINISMPStart( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiSMPFrame_t *tiSMPFrame, void *tiSMPBody, bit32 interruptContext ) { tdsaDeviceData_t *oneDeviceData; agsaIORequest_t *agIORequest = agNULL; tdIORequestBody_t *tdSMPRequestBody = agNULL; agsaRoot_t *agRoot = agNULL; agsaDevHandle_t *agDevHandle = agNULL; agsaSASRequestBody_t *agRequestBody = agNULL; agsaSMPFrame_t *agSMPFrame = agNULL; bit32 agRequestType; bit32 tiStatus = tiError; bit32 saStatus = AGSA_RC_FAILURE; bit32 queueNum; TDSA_INP_ENTER(tiRoot); TI_DBG6(("tiINISMPStart: start\n")); oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG6(("tiINISMPStart: onedevicedata %p\n", oneDeviceData)); TI_DBG6(("tiINISMPStart: tiDeviceHandle %p\n", tiDeviceHandle)); if (oneDeviceData == agNULL) { TI_DBG1(("tiINISMPStart: tiDeviceHandle=%p Expander DeviceData is NULL\n", tiDeviceHandle )); return tiError; } if (tiIORequest->osData == agNULL) { TI_DBG1(("tiINISMPStart: tiIORequest->osData is NULL, wrong\n")); return tiError; } agRoot = oneDeviceData->agRoot; agDevHandle = oneDeviceData->agDevHandle; tdSMPRequestBody = (tdIORequestBody_t *)tiSMPBody; tdSMPRequestBody->tiIORequest = tiIORequest; tiIORequest->tdData = tdSMPRequestBody; agIORequest = &(tdSMPRequestBody->agIORequest); agIORequest->osData = (void *) tdSMPRequestBody; agRequestBody = &(tdSMPRequestBody->transport.SAS.agSASRequestBody); agSMPFrame = &(agRequestBody->smpFrame); if (!DEVICE_IS_SMP_TARGET(oneDeviceData)) { TI_DBG1(("tiINISMPStart: Target Device is not SMP device\n")); return tiError; } if (tiSMPFrame->flag == 0) // define DIRECT SMP at td layer? { TI_DBG6(("tiINISMPStart: Direct SMP\n")); agSMPFrame->outFrameBuf = tiSMPFrame->outFrameBuf; agSMPFrame->outFrameLen = tiSMPFrame->outFrameLen; tdhexdump("tiINISMPStart agSMPFrame", (bit8 *)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen); agSMPFrame->expectedRespLen = tiSMPFrame->expectedRespLen; agSMPFrame->inFrameLen = 0; agSMPFrame->flag = tiSMPFrame->flag; agRequestType = AGSA_SMP_INIT_REQ; queueNum = 0; saStatus = saSMPStart(agRoot, agIORequest, queueNum, agDevHandle, agRequestType, agRequestBody, &ossaSMPCAMCompleted ); if (saStatus == AGSA_RC_SUCCESS) { tiStatus = tiSuccess; } else { if (saStatus == AGSA_RC_BUSY) { TI_DBG1(("tiINISMPStart: saSSPStart busy\n")); tiStatus = tiBusy; } else { TI_DBG1(("tiINISMPStart: saSSPStart error\n")); tiStatus = tiError; } return tiStatus; } } else { TI_DBG1(("tiINISMPStart: Indirect SMP! Not supported yet\n")); tiStatus = tiError; } return tiStatus; } #ifdef TD_INT_COALESCE osGLOBAL bit32 tiINIIOStartIntCoalesce( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, void *tiRequestBody, bit32 interruptContext, tiIntCoalesceContext_t *tiIntCoalesceCxt ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni; tdsaDeviceData_t *oneDeviceData; agsaRoot_t *agRoot = agNULL; agsaIORequest_t *agIORequest = agNULL; agsaDevHandle_t *agDevHandle = agNULL; bit32 agRequestType; agsaSASRequestBody_t *agSASRequestBody = agNULL; bit32 tiStatus = tiError; bit32 saStatus = AGSA_RC_FAILURE; tdIORequestBody_t *tdIORequestBody; agsaSSPInitiatorRequest_t *agSSPInitiatorRequest; tdsaIntCoalesceContext_t *tdsaIntCoalCxt; agsaIntCoalesceContext_t *agIntCoalCxt; TI_DBG1(("tiINIIOStartIntCoalesce: start\n")); oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG6(("tiINIIOStartIntCoalesce: onedevicedata %p\n", oneDeviceData)); if(oneDeviceData == agNULL) { TI_DBG1(("tiINIIOStartIntCoalesce: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle )); return tiIONoDevice; } /* starting IO with SAS device */ if (oneDeviceData->DeviceType == TD_SAS_DEVICE) { TI_DBG6(("tiINIIOStartIntCoalesce: calling saSSPStart\n")); agRoot = oneDeviceData->agRoot; agDevHandle = oneDeviceData->agDevHandle; /* OS layer has tdlayer data structure pointer in tdIORequestBody_t tdIOReqBody; in ccb_t in agtiapi.h */ tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* let's initialize tdIOrequestBody */ /* initialize callback */ tdIORequestBody->IOCompletionFunc = itdssIOCompleted; /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = tiIORequest; /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; /* initialize expDataLength */ tdIORequestBody->IOType.InitiatorRegIO.expDataLength = tiScsiRequest->scsiCmnd.expDataLength; /* initializes "agsaSgl_t agSgl" of "agsaDifSSPInitiatorRequest_t" */ tiStatus = itdssIOPrepareSGL( tiRoot, tdIORequestBody, &tiScsiRequest->agSgl1, tiScsiRequest->sglVirtualAddr ); if (tiStatus != tiSuccess) { TI_DBG1(("tiINIIOStartIntCoalesce: can't get SGL\n")); return tiStatus; } /* initialize agIORequest */ agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; agIORequest->sdkData = agNULL; /* LL takes care of this */ /* initialize tdIORequestBody_t tdIORequestBody -> agSASRequestBody */ agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody); agSSPInitiatorRequest = &(agSASRequestBody->sspInitiatorReq); /* copy cdb bytes */ osti_memcpy(agSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16); /* copy lun field */ osti_memcpy(agSSPInitiatorRequest->sspCmdIU.lun, tiScsiRequest->scsiCmnd.lun.lun, 8); /* setting the data length */ agSSPInitiatorRequest->dataLength = tiScsiRequest->scsiCmnd.expDataLength; TI_DBG6(("tiINIIOStartIntCoalesce: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength)); agSSPInitiatorRequest->firstBurstSize = 0; if (tiScsiRequest->dataDirection == tiDirectionIn) { agRequestType = AGSA_SSP_INIT_READ; TI_DBG6(("tiINIIOStartIntCoalesce: READ\n")); } else if (tiScsiRequest->dataDirection == tiDirectionOut) { agRequestType = AGSA_SSP_INIT_WRITE; TI_DBG6(("tiINIIOStartIntCoalesce: WRITE\n")); } else { agRequestType = AGSA_REQ_TYPE_UNKNOWN; TI_DBG1(("tiINIIOStartIntCoalesce: unknown data direction\n")); } tdIORequestBody->agRequestType = agRequestType; tdsaIntCoalCxt = (tdsaIntCoalesceContext_t *)tiIntCoalesceCxt->tdData; agIntCoalCxt = &(tdsaIntCoalCxt->agIntCoalCxt); #ifdef LL_INT_COALESCE saStatus = saSSPStartIntCoalesce(agRoot, agIORequest, agIntCoalCxt, agDevHandle, agRequestType, agSASRequestBody, &ossaSSPCompleted); #endif tdIORequestBody->ioStarted = agTRUE; tdIORequestBody->ioCompleted = agFALSE; if (saStatus == AGSA_RC_SUCCESS) { Initiator->NumIOsActive++; tiStatus = tiSuccess; } else { TI_DBG1(("tiINIIOStartIntCoalesce: saSSPStart failed\n")); tdIORequestBody->ioStarted = agFALSE; tdIORequestBody->ioCompleted = agTRUE; if (saStatus == AGSA_RC_BUSY) { tiStatus = tiBusy; } else { tiStatus = tiError; } return tiStatus; } } else if (oneDeviceData->DeviceType == TD_SATA_DEVICE) { /* satIOStart() -> saSATAStartIntCoalesce() */ TI_DBG1(("tiINIIOStartIntCoalesce: SATA not supported yet\n")); return tiStatus; } else { TI_DBG1(("tiINIIOStartIntCoalesce: wrong unspported Device %d\n", oneDeviceData->DeviceType)); /* error. unsupported IO */ } return tiStatus; } osGLOBAL bit32 tiINIIOStartIntCoalesceDif( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, void *tiRequestBody, bit32 interruptContext, tiIntCoalesceContext_t *tiIntCoalesceCxt, tiDif_t *difOption ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni; tdsaDeviceData_t *oneDeviceData; agsaRoot_t *agRoot = agNULL; agsaIORequest_t *agIORequest = agNULL; agsaDevHandle_t *agDevHandle = agNULL; bit32 agRequestType; agsaDifSSPRequestBody_t *agEdcSSPRequestBody = agNULL; bit32 tiStatus = tiError; bit32 saStatus = AGSA_RC_FAILURE; tdIORequestBody_t *tdIORequestBody; agsaDifSSPInitiatorRequest_t *agEdcSSPInitiatorRequest; agsaDif_t *agEdc; bit32 agUpdateMask = 0; bit32 agVerifyMask = 0; tdsaIntCoalesceContext_t *tdsaIntCoalCxt; agsaIntCoalesceContext_t *agIntCoalCxt; TI_DBG1(("tiINIIOStartIntCoalesceDif: start\n")); oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG6(("tiINIIOStartIntCoalesceDif: onedevicedata %p\n", oneDeviceData)); if(oneDeviceData == agNULL) { TI_DBG1(("tiINIIOStartIntCoalesceDif: tiDeviceHandle=%p DeviceData is NULL\n", tiDeviceHandle )); return tiIONoDevice; } /* starting IO with SAS device */ if (oneDeviceData->DeviceType == TD_SAS_DEVICE) { TI_DBG6(("tiINIIOStartIntCoalesceDif: calling saSSPStart\n")); agRoot = oneDeviceData->agRoot; agDevHandle = oneDeviceData->agDevHandle; /* OS layer has tdlayer data structure pointer in tdIORequestBody_t tdIOReqBody; in ccb_t in agtiapi.h */ tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; /* let's initialize tdIOrequestBody */ /* initialize callback */ tdIORequestBody->IOCompletionFunc = itdssIOCompleted; /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = tiIORequest; /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; /* initialize expDataLength */ tdIORequestBody->IOType.InitiatorRegIO.expDataLength = tiScsiRequest->scsiCmnd.expDataLength; /* initializes "agsaSgl_t agSgl" of "agsaDifSSPInitiatorRequest_t" */ tiStatus = itdssIOPrepareSGL( tiRoot, tdIORequestBody, &tiScsiRequest->agSgl1, tiScsiRequest->sglVirtualAddr ); if (tiStatus != tiSuccess) { TI_DBG1(("tiINIIOStartIntCoalesceDif: can't get SGL\n")); return tiStatus; } /* initialize agIORequest */ agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; agIORequest->sdkData = agNULL; /* LL takes care of this */ /* initialize tdIORequestBody_t tdIORequestBody -> agSASRequestBody */ agEdcSSPRequestBody = &(tdIORequestBody->transport.SAS.agEdcSSPRequestBody); agEdcSSPInitiatorRequest = &(agEdcSSPRequestBody->edcSSPInitiatorReq); /* copy cdb bytes */ osti_memcpy(agEdcSSPInitiatorRequest->sspCmdIU.cdb, tiScsiRequest->scsiCmnd.cdb, 16); /* copy lun field */ osti_memcpy(agEdcSSPInitiatorRequest->sspCmdIU.lun, tiScsiRequest->scsiCmnd.lun.lun, 8); /* setting the data length */ agEdcSSPInitiatorRequest->dataLength = tiScsiRequest->scsiCmnd.expDataLength; TI_DBG6(("tiINIIOStartIntCoalesceDif: tiScsiRequest->scsiCmnd.expDataLength %d\n", tiScsiRequest->scsiCmnd.expDataLength)); agEdcSSPInitiatorRequest->firstBurstSize = 0; if (tiScsiRequest->dataDirection == tiDirectionIn) { agRequestType = AGSA_SSP_INIT_READ; TI_DBG1(("tiINIIOStartIntCoalesceDif: READ difAction %X\n",difOption->difAction)); } else if (tiScsiRequest->dataDirection == tiDirectionOut) { agRequestType = AGSA_SSP_INIT_WRITE; TI_DBG1(("tiINIIOStartIntCoalesceDif: WRITE difAction %X\n",difOption->difAction)); } else { agRequestType = AGSA_REQ_TYPE_UNKNOWN; TI_DBG1(("tiINIIOStartIntCoalesceDif: unknown data direction\n")); } tdIORequestBody->agRequestType = agRequestType; /* process interrupt coalesce context */ tdsaIntCoalCxt = (tdsaIntCoalesceContext_t *)tiIntCoalesceCxt->tdData; agIntCoalCxt = &(tdsaIntCoalCxt->agIntCoalCxt); /* process DIF */ agEdc = &(agEdcSSPInitiatorRequest->edc); osti_memset(agEdc, 0, sizeof(agsaDif_t)); /* setting edcFlag */ if (difOption->enableBlockCount) { /* enables block count; bit5 */ agEdc->edcFlag = agEdc->edcFlag | 0x20; /* 0010 0000 */ } if (difOption->enableCrc) { /* enables CRC verification; bit6 */ agEdc->edcFlag = agEdc->edcFlag | 0x40; /* 0100 0000 */ } if (difOption->enableIOSeed) { } if (difOption->difAction == DIF_INSERT) { /* bit 0 - 2; 000 */ agEdc->edcFlag = agEdc->edcFlag & 0xFFFFFFF8; } else if (difOption->difAction == DIF_VERIFY_FORWARD) { /* bit 0 - 2; 001 */ agEdc->edcFlag = agEdc->edcFlag | 0x01; } else if (difOption->difAction == DIF_VERIFY_DELETE) { /* bit 0 - 2; 010 */ agEdc->edcFlag = agEdc->edcFlag | 0x02; } else { /* DIF_VERIFY_REPLACE */ /* bit 0 - 2; 011 */ agEdc->edcFlag = agEdc->edcFlag | 0x04; } /* set Update Mask; bit 16-21 */ agUpdateMask = (difOption->tagUpdateMask) & 0x3F; /* 0011 1111 */ agUpdateMask = agUpdateMask << 16; agEdc->edcFlag = agEdc->edcFlag | agUpdateMask; /* set Verify Mask bit 24-29 */ agVerifyMask = (difOption->tagVerifyMask) & 0x3F; /* 0011 1111 */ agVerifyMask = agVerifyMask << 24; agEdc->edcFlag = agEdc->edcFlag | agVerifyMask; agEdc->appTag = difOption->udtArray[0]; agEdc->appTag = (agEdc->appTag << 8) | difOption->udtArray[1]; agEdc->lbaReferenceTag = difOption->udtArray[2]; agEdc->lbaReferenceTag = (agEdc->lbaReferenceTag << 8) | difOption->udtArray[3]; agEdc->lbaReferenceTag = (agEdc->lbaReferenceTag << 8) | difOption->udtArray[4]; agEdc->lbaReferenceTag = (agEdc->lbaReferenceTag << 8) | difOption->udtArray[5]; /* currently TISA supports only 512 logical block size */ agEdc->lbSize = 512; #ifdef LL_INT_COALESCE saStatus = saSSPStartIntCoalesceEdc(agRoot, agIORequest, agIntCoalCxt, agDevHandle, agRequestType, agEdcSSPRequestBody, &ossaSSPCompleted); #endif tdIORequestBody->ioStarted = agTRUE; tdIORequestBody->ioCompleted = agFALSE; if (saStatus == AGSA_RC_SUCCESS) { Initiator->NumIOsActive++; tiStatus = tiSuccess; } else { TI_DBG1(("tiINIIOStartIntCoalesceDif: saSSPStart failed\n")); tdIORequestBody->ioStarted = agFALSE; tdIORequestBody->ioCompleted = agTRUE; if (saStatus == AGSA_RC_BUSY) { tiStatus = tiBusy; } else { tiStatus = tiError; } return tiStatus; } } else if (oneDeviceData->DeviceType == TD_SATA_DEVICE) { /* satIOStart() -> saSATAStartIntCoalesceEdc() */ TI_DBG1(("tiINIIOStartIntCoalesceDif: SATA not supported yet\n")); return tiStatus; } else { TI_DBG1(("tiINIIOStartIntCoalesceDif: wrong unspported Device %d\n", oneDeviceData->DeviceType)); /* error. unsupported IO */ } return tiStatus; } osGLOBAL bit32 tiINIIntCoalesceInit( tiRoot_t *tiRoot, tiIntCoalesceContext_t *tiIntCoalesceCxt, bit32 count ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = agNULL; tdsaIntCoalesceContext_t *tdsaIntCoalCxtHead = (tdsaIntCoalesceContext_t *)tdsaAllShared->IntCoalesce; tdsaIntCoalesceContext_t *tdsaIntCoalCxt; agsaIntCoalesceContext_t *agIntCoalCxt; tdList_t *tdsaIntCoalCxtList = agNULL; bit32 tiStatus = tiError; TI_DBG1(("tiINIIntCoalesceInit: start\n")); tdsaSingleThreadedEnter(tiRoot, TD_INTCOAL_LOCK); if (TDLIST_NOT_EMPTY(&(tdsaIntCoalCxtHead->FreeLink))) { TDLIST_DEQUEUE_FROM_HEAD(&tdsaIntCoalCxtList, &(tdsaIntCoalCxtHead->FreeLink)); tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK); tdsaIntCoalCxt = TDLIST_OBJECT_BASE(tdsaIntCoalesceContext_t, FreeLink, tdsaIntCoalCxtList); TI_DBG1(("tiINIIntCoalesceInit: id %d\n", tdsaIntCoalCxt->id)); agRoot = &(tdsaAllShared->agRootNonInt); agIntCoalCxt = &(tdsaIntCoalCxt->agIntCoalCxt); tdsaIntCoalCxt->tiIntCoalesceCxt = tiIntCoalesceCxt; tiIntCoalesceCxt->tdData = tdsaIntCoalCxt; agIntCoalCxt->osData = tdsaIntCoalCxt; tdsaSingleThreadedEnter(tiRoot, TD_INTCOAL_LOCK); TDLIST_ENQUEUE_AT_TAIL(&(tdsaIntCoalCxt->MainLink), &(tdsaIntCoalCxtHead->MainLink)); tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK); /* note: currently asynchronously call is assumed. In other words, "ossaIntCoalesceInitCB()" -> "ostiInitiatorCoalesceInitCB()" are used */ #ifdef LL_INT_COALESCE tiStatus = saIntCoalesceInit(agRoot, agIntCoalCxt, count); #endif TI_DBG6(("tiINIIntCoalesceInit: status %d\n", tiStatus)); return tiStatus; } else { tdsaSingleThreadedLeave(tiRoot, TD_INTCOAL_LOCK); TI_DBG1(("tiINIIntCoalesceInit: no more interrupt coalesce context; return fail\n")); return tiStatus; } } #endif /* TD_INT_COALESCE */ /***************************************************************************** *! \brief itdssIOPrepareSGL * * Purpose: This function is called to translate TISA SGL information to the * LL layer SGL. * * \param tiRoot: Pointer to initiator driver/port instance. * \param IORequestBody: TD layer request body for the I/O. * \param tiSgl1: First TISA SGL info. * \param sglVirtualAddr: The virtual address of the first element in * tiSgl1 when tiSgl1 is used with the type tiSglList. * * \return: * * tiSuccess: SGL initialized successfully. * tiError: Failed to initialize SGL. * * *****************************************************************************/ osGLOBAL FORCEINLINE bit32 itdssIOPrepareSGL( tiRoot_t *tiRoot, tdIORequestBody_t *tdIORequestBody, tiSgl_t *tiSgl1, void *sglVirtualAddr ) { agsaSgl_t *agSgl; TI_DBG6(("itdssIOPrepareSGL: start\n")); agSgl = &(tdIORequestBody->transport.SAS.agSASRequestBody.sspInitiatorReq.agSgl); agSgl->len = 0; if (tiSgl1 == agNULL) { TI_DBG1(("itdssIOPrepareSGL: Error tiSgl1 is NULL\n")); return tiError; } if (tdIORequestBody->IOType.InitiatorRegIO.expDataLength == 0) { TI_DBG6(("itdssIOPrepareSGL: expDataLength is 0\n")); agSgl->sgUpper = 0; agSgl->sgLower = 0; agSgl->len = 0; CLEAR_ESGL_EXTEND(agSgl->extReserved); return tiSuccess; } agSgl->sgUpper = tiSgl1->upper; agSgl->sgLower = tiSgl1->lower; agSgl->len = tiSgl1->len; agSgl->extReserved = tiSgl1->type; return tiSuccess; } osGLOBAL bit32 tiNumOfLunIOCTLreq( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, void *tiRequestBody, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); void *respBuffer = agNULL; void *osMemHandle = agNULL; bit32 ostiMemoryStatus = 0; tdsaDeviceData_t *oneDeviceData = agNULL; agsaSSPInitiatorRequest_t *agSSPFrame = agNULL; bit32 status = IOCTL_CALL_SUCCESS; bit32 agRequestType = 0; agsaDevHandle_t *agDevHandle = agNULL; agsaIORequest_t *agIORequest = agNULL; tdIORequestBody_t *tdIORequestBody = agNULL; agsaSASRequestBody_t *agSASRequestBody = agNULL; do { if((tiIORequest == agNULL) || (tiRequestBody == agNULL)) { status = IOCTL_CALL_FAIL; break; } tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; tdIORequestBody->tiIORequest = tiIORequest; /* save context if we need to abort later */ tiIORequest->tdData = tdIORequestBody; agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; agSASRequestBody = &(tdIORequestBody->transport.SAS.agSASRequestBody); agSSPFrame = &(agSASRequestBody->sspInitiatorReq); ostiMemoryStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&respBuffer, &(agSSPFrame->agSgl.sgUpper), &(agSSPFrame->agSgl.sgLower), 8, REPORT_LUN_LEN, agFALSE); if((ostiMemoryStatus != tiSuccess) && (respBuffer == agNULL )) { status = IOCTL_CALL_FAIL; break; } osti_memset((void *)respBuffer, 0, REPORT_LUN_LEN); // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.virtAddr = respBuffer; tdsaAllShared->tdFWControlEx.len = REPORT_LUN_LEN; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; agRequestType = AGSA_SSP_INIT_READ; status = IOCTL_CALL_PENDING; oneDeviceData = (tdsaDeviceData_t *)(tiDeviceHandle->tdData); agDevHandle = oneDeviceData->agDevHandle; agSSPFrame->sspCmdIU.cdb[0] = REPORT_LUN_OPCODE; agSSPFrame->sspCmdIU.cdb[1] = 0x0; agSSPFrame->sspCmdIU.cdb[2] = 0x0; agSSPFrame->sspCmdIU.cdb[3] = 0x0; agSSPFrame->sspCmdIU.cdb[4] = 0x0; agSSPFrame->sspCmdIU.cdb[5] = 0x0; agSSPFrame->sspCmdIU.cdb[6] = 0x0; agSSPFrame->sspCmdIU.cdb[7] = 0x0; agSSPFrame->sspCmdIU.cdb[8] = 0x0; agSSPFrame->sspCmdIU.cdb[9] = REPORT_LUN_LEN; agSSPFrame->sspCmdIU.cdb[10] = 0x0; agSSPFrame->sspCmdIU.cdb[11] = 0x0; agSSPFrame->dataLength = REPORT_LUN_LEN; agSSPFrame->agSgl.len = sizeof(agsaSSPCmdInfoUnit_t); agSSPFrame->agSgl.extReserved = 0; CLEAR_ESGL_EXTEND(agSSPFrame->agSgl.extReserved); status = saSSPStart(agRoot, agIORequest, 0, agDevHandle, agRequestType,agSASRequestBody,agNULL, &ossaSSPIoctlCompleted); if(status != AGSA_RC_SUCCESS) { ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.virtAddr, tdsaAllShared->tdFWControlEx.len); tdsaAllShared->tdFWControlEx.payload = NULL; tdsaAllShared->tdFWControlEx.inProgress = 0; status = IOCTL_CALL_FAIL; } }while(0); return status; }