/******************************************************************************* *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 ********************************************************************************/ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include /* for TIDEBUG_MSG */ #include #ifdef FDS_SM #include #include #include #ifdef FDS_DM #include #endif #ifdef INITIATOR_DRIVER #include #endif #include #include #include #if defined(SM_DEBUG) extern bit32 gSMDebugLevel; #endif osGLOBAL void smReportRemovalDirect( tiRoot_t *tiRoot, agsaRoot_t *agRoot, tdsaDeviceData_t *oneDeviceData ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; bit8 PhyID; TI_DBG2(("smReportRemovalDirect: start\n")); PhyID = oneDeviceData->phyID; tdsaAbortAll(tiRoot, agRoot, oneDeviceData); oneDeviceData->valid = agFALSE; oneDeviceData->valid2 = agFALSE; /* put onedevicedata back to free list */ osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink)); TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[PhyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[PhyID].tiPortalContext ); #endif return; } osGLOBAL void smReportRemoval( tiRoot_t *tiRoot, agsaRoot_t *agRoot, tdsaDeviceData_t *oneDeviceData, tdsaPortContext_t *onePortContext ) { TI_DBG2(("smReportRemoval: start\n")); if (oneDeviceData->registered == agTRUE) { /* 1. remove this device 2. device removal event */ tdsaAbortAll(tiRoot, agRoot, oneDeviceData); oneDeviceData->valid = agFALSE; oneDeviceData->valid2 = agFALSE; oneDeviceData->registered = agFALSE; ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceRemoval, agNULL ); } return; } osGLOBAL void smHandleDirect( tiRoot_t *tiRoot, agsaRoot_t *agRoot, tdsaDeviceData_t *oneDeviceData, void *IDdata ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaSATAIdentifyData_t *pSATAIdData; tdList_t *DeviceListList; tdsaDeviceData_t *tmpOneDeviceData = agNULL; int new_device = agTRUE; bit8 PhyID; TI_DBG2(("smHandleDirect: start\n")); PhyID = oneDeviceData->phyID; pSATAIdData = (agsaSATAIdentifyData_t *)IDdata; //tdhexdump("satAddSATAIDDevCB after", (bit8 *)pSATAIdData, sizeof(agsaSATAIdentifyData_t)); /* compare idenitfy device data to the exiting list */ DeviceListList = tdsaAllShared->MainDeviceList.flink; while (DeviceListList != &(tdsaAllShared->MainDeviceList)) { tmpOneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList); if (tmpOneDeviceData == agNULL) { TI_DBG1(("smHandleDirect: tmpOneDeviceData is NULL!!!\n")); return; } TI_DBG1(("smHandleDirect: LOOP tmpOneDeviceData %p did %d\n", tmpOneDeviceData, tmpOneDeviceData->id)); //tdhexdump("smHandleDirect LOOP", (bit8 *)&tmpOneDeviceData->satDevData.satIdentifyData, sizeof(agsaSATAIdentifyData_t)); /* what is unique ID for sata device -> response of identify devicedata; not really Let's compare serial number, firmware version, model number */ if ( tmpOneDeviceData->DeviceType == TD_SATA_DEVICE && (osti_memcmp (tmpOneDeviceData->satDevData.satIdentifyData.serialNumber, pSATAIdData->serialNumber, 20) == 0) && (osti_memcmp (tmpOneDeviceData->satDevData.satIdentifyData.firmwareVersion, pSATAIdData->firmwareVersion, 8) == 0) && (osti_memcmp (tmpOneDeviceData->satDevData.satIdentifyData.modelNumber, pSATAIdData->modelNumber, 40) == 0) ) { TI_DBG2(("smHandleDirect: did %d\n", tmpOneDeviceData->id)); new_device = agFALSE; break; } DeviceListList = DeviceListList->flink; } if (new_device == agFALSE) { TI_DBG2(("smHandleDirect: old device data\n")); tmpOneDeviceData->valid = agTRUE; tmpOneDeviceData->valid2 = agTRUE; /* save data field from new device data */ tmpOneDeviceData->agRoot = agRoot; tmpOneDeviceData->agDevHandle = oneDeviceData->agDevHandle; tmpOneDeviceData->agDevHandle->osData = tmpOneDeviceData; /* TD layer */ tmpOneDeviceData->tdPortContext = oneDeviceData->tdPortContext; tmpOneDeviceData->phyID = oneDeviceData->phyID; /* one SATA directly attached device per phy; Therefore, deregister then register */ saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData)); if (tmpOneDeviceData->registered == agFALSE) { TI_DBG2(("smHandleDirect: re-registering old device data\n")); /* already has old information; just register it again */ saRegisterNewDevice( /* smHandleDirect */ agRoot, &tmpOneDeviceData->agContext, 0,/*tdsaRotateQnumber(tiRoot, tmpOneDeviceData),*/ &tmpOneDeviceData->agDeviceInfo, tmpOneDeviceData->tdPortContext->agPortContext, 0 ); } // tdsaAbortAll(tiRoot, agRoot, oneDeviceData); /* put tmpOneDeviceData back to free list */ osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink)); TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); TI_DBG2(("smHandleDirect: pid %d\n", tdsaAllShared->Ports[PhyID].portContext->id)); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[PhyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[PhyID].tiPortalContext ); #endif return; } TI_DBG2(("smHandleDirect: new device data\n")); oneDeviceData->satDevData.satIdentifyData = *pSATAIdData; /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[PhyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[PhyID].tiPortalContext ); #endif return; } /* combine satAddSATAIDDevCB(expander) and satAddSATAIDDevCB(directly attached) */ osGLOBAL void tdsmIDCompletedCB( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, bit32 status, void *IDdata ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; agsaRoot_t *agRoot; tdIORequestBody_t *tdIORequestBody; tdsaDeviceData_t *oneDeviceData; tdsaPortContext_t *onePortContext; tiPortalContext_t *tiPortalContext; bit32 pid = 0xff; bit32 IDstatus; agsaSATAIdentifyData_t *pSATAIdData; TI_DBG2(("tdsmIDCompletedCB: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; tdsaAllShared = &(tdsaRoot->tdsaAllShared); tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; tdIORequestBody = (tdIORequestBody_t *)smIORequest->tdData; if (smDeviceHandle == agNULL) { TI_DBG1(("tdsmIDCompletedCB: smDeviceHandle is NULL !!!!\n")); ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); return; } oneDeviceData = (tdsaDeviceData_t *)smDeviceHandle->tdData; onePortContext = oneDeviceData->tdPortContext; agRoot = oneDeviceData->agRoot; pid = tdIORequestBody->pid; // oneDeviceData->satDevData.IDDeviceValid = agFALSE; oneDeviceData->satDevData.IDPending = agFALSE; TI_DBG2(("tdsmIDCompletedCB: tdIORequestBody %p tdIORequestBody->osMemHandle %p\n", tdIORequestBody, tdIORequestBody->osMemHandle)); tdsaSingleThreadedEnter(tiRoot, TD_TIMER_LOCK); if (oneDeviceData->tdIDTimer.timerRunning == agTRUE) { tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK); tdsaKillTimer( tiRoot, &oneDeviceData->tdIDTimer ); } else { tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK); } if (onePortContext == agNULL) { TI_DBG1(("tdsmIDCompletedCB: onePortContext is NULL!!!\n")); ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); return; } /* check port id */ if (pid != onePortContext->id) { TI_DBG1(("tdsmIDCompletedCB: not matching pid; pid %d onePortContext->id %d!!!\n", pid, onePortContext->id)); if (oneDeviceData->directlyAttached == agTRUE) { smReportRemovalDirect(tiRoot, agRoot, oneDeviceData); } else { smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); } ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); return; } tiPortalContext= onePortContext->tiPortalContext; if (tiPortalContext == agNULL) { TI_DBG1(("tdsmIDCompletedCB: tiPortalContext is NULL!!!\n")); if (oneDeviceData->directlyAttached == agTRUE) { smReportRemovalDirect(tiRoot, agRoot, oneDeviceData); } else { smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); } ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); return; } if (agRoot == agNULL) { TI_DBG1(("tdsmIDCompletedCB: agRoot is NULL!!!\n")); ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); return; } if (status == smIOSuccess) { TI_DBG2(("tdsmIDCompletedCB: smIOSuccess\n")); oneDeviceData->satDevData.IDDeviceValid = agTRUE; if (oneDeviceData->directlyAttached == agTRUE) { TI_DBG2(("tdsmIDCompletedCB: directlyAttached\n")); pSATAIdData = (agsaSATAIdentifyData_t *)IDdata; smHandleDirect(tiRoot, agRoot, oneDeviceData, IDdata); /* filling in */ osti_memcpy(onePortContext->remoteName, pSATAIdData->serialNumber, 20); osti_memcpy(&(onePortContext->remoteName[20]), pSATAIdData->firmwareVersion, 8); osti_memcpy(&(onePortContext->remoteName[28]), pSATAIdData->modelNumber, 40); } else /* expander attached */ { TI_DBG2(("tdsmIDCompletedCB: expander attached\n")); if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED) { TI_DBG1(("tdsmIDCompletedCB: ID completed after discovery is done; tiDeviceArrival\n")); /* ID data completed after discovery is completed */ ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceArrival, agNULL ); } } TI_DBG2(("tdsmIDCompletedCB: tdIORequestBody %p tdIORequestBody->osMemHandle %p\n", tdIORequestBody, tdIORequestBody->osMemHandle)); ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); } else if ( status == smIORetry) { TI_DBG1(("tdsmIDCompletedCB: smIORetry!!!\n")); if ( !(oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE && oneDeviceData->tdPortContext != agNULL) ) { TI_DBG1(("tdsmIDCompletedCB: smIORetry but device is not valid!!!\n")); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); oneDeviceData->satDevData.IDDeviceValid = agFALSE; return; } if (tdIORequestBody->reTries <= SM_RETRIES) { tdIORequestBody->tiIORequest = agNULL; /* not in use */ tdIORequestBody->pid = onePortContext->id; smIORequest->tdData = tdIORequestBody; smIORequest->smData = &tdIORequestBody->smIORequestBody; smDeviceHandle->tdData = oneDeviceData; oneDeviceData->satDevData.IDDeviceValid = agFALSE; IDstatus = smIDStart(smRoot, smIORequest, smDeviceHandle ); if (IDstatus != SM_RC_SUCCESS) { /* identify device data is not valid */ TI_DBG1(("tdsmIDCompletedCB: smIDStart fail or busy %d!!!\n", IDstatus)); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); return; } tdIORequestBody->reTries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; oneDeviceData->satDevData.IDPending = agTRUE; /* start a timer */ tdIDStartTimer(tiRoot, smIORequest, oneDeviceData); TI_DBG1(("tdsmIDCompletedCB: being retried!!!\n")); } else { /* give up */ TI_DBG1(("tdsmIDCompletedCB: retries are over!!!\n")); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); oneDeviceData->satDevData.IDDeviceValid = agFALSE; /* SATA device is not usable; remove it */ smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); } } else if ( status == smIOSTPResourceBusy) { /* decides to send smp hard reset or not */ TI_DBG1(("tdsmIDCompletedCB: smIOSTPResourceBusy\n")); ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); oneDeviceData->satDevData.IDDeviceValid = agFALSE; if (tdsaAllShared->FCA) { if (oneDeviceData->SMNumOfFCA <= 0) /* does SMP HARD RESET only upto one time */ { TI_DBG1(("tdsmIDCompletedCB: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; sending HARD_RESET\n")); oneDeviceData->SMNumOfFCA++; tdsaPhyControlSend(tiRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData) ); } else { /* given up after one time of SMP HARD RESET; */ TI_DBG1(("tdsmIDCompletedCB: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; but giving up sending HARD_RESET!!!\n")); smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); } } else { /* do nothing */ } } else { TI_DBG1(("tdsmIDCompletedCB: smIDStart fail, status 0x%x!!!\n", status)); TI_DBG1(("tdsmIDCompletedCB: did %d!!!\n", oneDeviceData->id)); if ( !(oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE && oneDeviceData->tdPortContext != agNULL) ) { TI_DBG1(("tdsmIDCompletedCB: fail but device is not valid!!!\n")); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); oneDeviceData->satDevData.IDDeviceValid = agFALSE; return; } tdsaAllShared->IDRetry = agTRUE; if (tdsaAllShared->IDRetry) { if (tdIORequestBody->reTries <= SM_RETRIES) { tdIORequestBody->tiIORequest = agNULL; /* not in use */ tdIORequestBody->pid = onePortContext->id; smIORequest->tdData = tdIORequestBody; smIORequest->smData = &tdIORequestBody->smIORequestBody; smDeviceHandle->tdData = oneDeviceData; IDstatus = smIDStart(smRoot, smIORequest, smDeviceHandle ); if (IDstatus != SM_RC_SUCCESS) { /* identify device data is not valid */ TI_DBG1(("tdsmIDCompletedCB: smIDStart fail or busy %d!!!\n", IDstatus)); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); oneDeviceData->satDevData.IDDeviceValid = agFALSE; if (oneDeviceData->directlyAttached == agTRUE) { smReportRemovalDirect(tiRoot, agRoot, oneDeviceData); } else { smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); } return; } tdIORequestBody->reTries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; oneDeviceData->satDevData.IDPending = agTRUE; /* start a timer */ tdIDStartTimer(tiRoot, smIORequest, oneDeviceData); TI_DBG1(("tdsmIDCompletedCB: being retried!!!\n")); } else { /* give up */ TI_DBG1(("tdsmIDCompletedCB: retries are over; sending hard reset!!!\n")); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiFreeMemory( tiRoot, tdIORequestBody->osMemHandle, sizeof(tdIORequestBody_t) ); oneDeviceData->satDevData.IDDeviceValid = agFALSE; if (oneDeviceData->SMNumOfID <= 0) /* does SMP HARD RESET only upto one time */ { TI_DBG1(("tdsmIDCompletedCB: fail; sending HARD_RESET\n")); oneDeviceData->SMNumOfID++; if (oneDeviceData->directlyAttached == agTRUE) { saLocalPhyControl(agRoot, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData), oneDeviceData->phyID, AGSA_PHY_HARD_RESET, agNULL); } else { tdsaPhyControlSend(tiRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData) ); } } else { /* given up after one time of SMP HARD RESET; */ TI_DBG1(("tdsmIDCompletedCB: fail; but giving up sending HARD_RESET!!!\n")); if (oneDeviceData->directlyAttached == agTRUE) { smReportRemovalDirect(tiRoot, agRoot, oneDeviceData); } else { smReportRemoval(tiRoot, agRoot, oneDeviceData, onePortContext); } } } } else { /* do nothing */ } } return; } FORCEINLINE void tdsmIOCompletedCB( smRoot_t *smRoot, smIORequest_t *smIORequest, bit32 status, bit32 statusDetail, smSenseData_t *senseData, bit32 interruptContext ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *)smRoot->tdData; tdsaContext_t *tdsaAllShared = &(tdsaRoot->tdsaAllShared); tiRoot_t *tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; tdIORequestBody_t *tdIORequestBody = (tdIORequestBody_t *)smIORequest->tdData; tiIORequest_t *tiIORequest = tdIORequestBody->tiIORequest; tdsaDeviceData_t *oneDeviceData; tiDeviceHandle_t *tiDeviceHandle; smDeviceHandle_t *smDeviceHandle; smScsiInitiatorRequest_t *smSCSIRequest; smSuperScsiInitiatorRequest_t *smSuperSCSIRequest; bit32 SMStatus = SM_RC_FAILURE; TI_DBG5(("tdsmIOCompletedCB: start\n")); if (status == smIOSuccess) { ostiInitiatorIOCompleted( tiRoot, tiIORequest, status, statusDetail, (tiSenseData_t *)senseData, interruptContext); } else if (status == smIORetry) { TI_DBG1(("tdsmIOCompletedCB: smIORetry!!!\n")); smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest); tiDeviceHandle = tdIORequestBody->tiDevHandle; oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (! (oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE && oneDeviceData->tdPortContext != agNULL) ) { TI_DBG1(("tdsmIOCompletedCB: smIORetry but device is not valid!!!\n")); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiInitiatorIOCompleted( tiRoot, tiIORequest, status, statusDetail, (tiSenseData_t *)senseData, interruptContext); return; } if (tdIORequestBody->reTries <= SM_RETRIES) { smDeviceHandle = (smDeviceHandle_t *)&(oneDeviceData->smDeviceHandle); if (tdIORequestBody->superIOFlag == agTRUE) { smSuperSCSIRequest = (smSuperScsiInitiatorRequest_t *)&(tdIORequestBody->SM.smSuperSCSIRequest); SMStatus = smSuperIOStart(smRoot, smIORequest, smDeviceHandle, smSuperSCSIRequest, oneDeviceData->SASAddressID.sasAddressHi, oneDeviceData->SASAddressID.sasAddressLo, interruptContext); } else { smSCSIRequest = (smScsiInitiatorRequest_t *)&(tdIORequestBody->SM.smSCSIRequest); SMStatus = smIOStart(smRoot, smIORequest, smDeviceHandle, smSCSIRequest, interruptContext); } if (SMStatus != SM_RC_SUCCESS) { TI_DBG1(("tdsmIOCompletedCB: smIDStart fail or busy %d!!!\n", SMStatus)); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiInitiatorIOCompleted( tiRoot, tiIORequest, status, statusDetail, (tiSenseData_t *)senseData, interruptContext); return; } else { TI_DBG1(("tdsmIOCompletedCB: being retried!!!\n")); tdIORequestBody->reTries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; } } else { /* give up; complete IO */ TI_DBG1(("tdsmIOCompletedCB: retries are over!!!\n")); tdIORequestBody->reTries = 0; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; ostiInitiatorIOCompleted( tiRoot, tiIORequest, status, statusDetail, (tiSenseData_t *)senseData, interruptContext); return; } } else if ( status == smIOSTPResourceBusy) { /* decides to send smp hard reset or not */ TI_DBG1(("tdsmIOCompletedCB: smIOSTPResourceBusy\n")); if (tdsaAllShared->FCA) { smIORequest = (smIORequest_t *)&(tdIORequestBody->smIORequest); tiDeviceHandle = tdIORequestBody->tiDevHandle; oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData->SMNumOfFCA <= 0) /* does SMP HARD RESET only upto one time */ { TI_DBG1(("tdsmIOCompletedCB: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; sending HARD_RESET\n")); oneDeviceData->SMNumOfFCA++; tdsaPhyControlSend(tiRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData) ); } else { /* given up after one time of SMP HARD RESET; */ TI_DBG1(("tdsmIOCompletedCB: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; but giving up sending HARD_RESET!!!\n")); } } ostiInitiatorIOCompleted( tiRoot, tiIORequest, status, statusDetail, (tiSenseData_t *)senseData, interruptContext); return; } else { if (statusDetail == smDetailAborted) { tiDeviceHandle = tdIORequestBody->tiDevHandle; oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG1(("tdsmIOCompletedCB: agIOStatus = OSSA_IO_ABORTED did %d\n", oneDeviceData->id)); } ostiInitiatorIOCompleted( tiRoot, tiIORequest, status, statusDetail, (tiSenseData_t *)senseData, interruptContext); } return; } /* completion of taskmanagement osGLOBAL void ostiInitiatorEvent ( tiRoot_t *tiRoot, tiPortalContext_t *portalContext, tiDeviceHandle_t *tiDeviceHandle, tiIntrEventType_t eventType, bit32 eventStatus, void *parm ); */ //qqq1 osGLOBAL void tdsmEventCB( smRoot_t *smRoot, smDeviceHandle_t *smDeviceHandle, smIntrEventType_t eventType, bit32 eventStatus, void *parm ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; tdIORequestBody_t *tdIORequestBody; smIORequest_t *SMcurrentTaskTag; tiIORequest_t *currentTaskTag; tdsaDeviceData_t *oneDeviceData; void *osMemHandle; tdsaPortContext_t *onePortContext; tiPortalContext_t *tiportalContext; tiDeviceHandle_t *tiDeviceHandle; /* be sure to free using tdIORequestBody->->IOType.InitiatorTMIO.osMemHandle but how??? parm = pSatDevData->satTmTaskTag (currentTaskTag in tiINITaskManagement) In this case, parm is smIORequest_t */ TI_DBG2(("tdsmEventCB: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; tdsaAllShared = &(tdsaRoot->tdsaAllShared); tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; if (eventType == smIntrEventTypeLocalAbort) { oneDeviceData = (tdsaDeviceData_t *)smDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("tdsmEventCB: oneDeviceData is NULL\n")); return; } else { tiDeviceHandle = &(oneDeviceData->tiDeviceHandle); if (oneDeviceData->OSAbortAll == agTRUE) { oneDeviceData->OSAbortAll = agFALSE; ostiInitiatorEvent( tiRoot, agNULL, tiDeviceHandle, tiIntrEventTypeLocalAbort, tiAbortOK, agNULL); } } } else { SMcurrentTaskTag = (smIORequest_t *)parm; if (SMcurrentTaskTag == agNULL) { TI_DBG1(("tdsmEventCB: SMcurrentTaskTag is NULL!!!\n")); return; } tdIORequestBody = (tdIORequestBody_t *)SMcurrentTaskTag->tdData; if (tdIORequestBody == agNULL) { TI_DBG1(("tdsmEventCB: tdIORequestBody is NULL!!!\n")); return; } osMemHandle = tdIORequestBody->IOType.InitiatorTMIO.osMemHandle; currentTaskTag = tdIORequestBody->IOType.InitiatorTMIO.CurrentTaskTag; oneDeviceData = (tdsaDeviceData_t *)smDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("tdsmEventCB: oneDeviceData is NULL!!!\n")); return; } tiDeviceHandle = &(oneDeviceData->tiDeviceHandle); onePortContext = oneDeviceData->tdPortContext; if (onePortContext == agNULL) { TI_DBG1(("tdsmEventCB: onePortContext is NULL!!!\n")); return; } tiportalContext = onePortContext->tiPortalContext; /* free tdIORequestBody */ ostiFreeMemory( tiRoot, osMemHandle, sizeof(tdIORequestBody_t) ); TI_DBG2(("tdsmEventCB: calling ostiInitiatorEvent\n")); ostiInitiatorEvent( tiRoot, tiportalContext, tiDeviceHandle, eventType, eventStatus, (void *)currentTaskTag ); /* completion of taskmanagement osGLOBAL void ostiInitiatorEvent ( tiRoot_t *tiRoot, tiPortalContext_t *portalContext, tiDeviceHandle_t *tiDeviceHandle, tiIntrEventType_t eventType, bit32 eventStatus, void *parm ); ostiFreeAlloc() */ } return; } FORCEINLINE void tdsmSingleThreadedEnter( smRoot_t *smRoot, bit32 syncLockId ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; bit32 offset = 0; TI_DBG7(("tdsmSingleThreadedEnter: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; if (tdsaRoot == agNULL) { TI_DBG1(("tdsmSingleThreadedEnter: tdsaRoot is NULL\n")); return; } tdsaAllShared = &(tdsaRoot->tdsaAllShared); if (tdsaAllShared == agNULL) { TI_DBG1(("tdsmSingleThreadedEnter: tdsaAllShared is NULL\n")); return; } tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; if (tiRoot == agNULL) { TI_DBG1(("tdsmSingleThreadedEnter: tiRoot is NULL\n")); return; } offset = tdsaAllShared->MaxNumLLLocks + tdsaAllShared->MaxNumOSLocks + TD_MAX_LOCKS + tdsaAllShared->MaxNumDMLocks; ostiSingleThreadedEnter(tiRoot, syncLockId + offset); return; } FORCEINLINE void tdsmSingleThreadedLeave( smRoot_t *smRoot, bit32 syncLockId ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; bit32 offset = 0; TI_DBG7(("tdsmSingleThreadedLeave: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; if (tdsaRoot == agNULL) { TI_DBG1(("tdsmSingleThreadedLeave: tdsaRoot is NULL\n")); return; } tdsaAllShared = &(tdsaRoot->tdsaAllShared); if (tdsaAllShared == agNULL) { TI_DBG1(("tdsmSingleThreadedLeave: tdsaAllShared is NULL\n")); return; } tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; if (tiRoot == agNULL) { TI_DBG1(("tdsmSingleThreadedLeave: tiRoot is NULL\n")); return; } offset = tdsaAllShared->MaxNumLLLocks + tdsaAllShared->MaxNumOSLocks + TD_MAX_LOCKS + tdsaAllShared->MaxNumDMLocks; ostiSingleThreadedLeave(tiRoot, syncLockId + offset); return; } osGLOBAL FORCEINLINE bit8 tdsmBitScanForward( smRoot_t *smRoot, bit32 *Index, bit32 Mask ) { return ostiBitScanForward(agNULL, Index, Mask); } #ifdef LINUX_VERSION_CODE osGLOBAL FORCEINLINE sbit32 tdsmInterlockedIncrement( smRoot_t *smRoot, sbit32 volatile *Addend ) { return ostiAtomicIncrement(agNULL, Addend); } osGLOBAL FORCEINLINE sbit32 tdsmInterlockedDecrement( smRoot_t *smRoot, sbit32 volatile *Addend ) { return ostiAtomicDecrement(agNULL, Addend); } osGLOBAL FORCEINLINE sbit32 tdsmAtomicBitClear( smRoot_t *smRoot, sbit32 volatile *Destination, sbit32 Value ) { return ostiAtomicBitClear(agNULL, Destination, Value); } osGLOBAL FORCEINLINE sbit32 tdsmAtomicBitSet( smRoot_t *smRoot, sbit32 volatile *Destination, sbit32 Value ) { return ostiAtomicBitSet(agNULL, Destination, Value); } osGLOBAL FORCEINLINE sbit32 tdsmAtomicExchange( smRoot_t *smRoot, sbit32 volatile *Target, sbit32 Value ) { return ostiAtomicExchange(agNULL, Target, Value); } #else osGLOBAL FORCEINLINE sbit32 tdsmInterlockedIncrement( smRoot_t *smRoot, sbit32 volatile *Addend ) { return ostiInterlockedIncrement(agNULL, Addend); } osGLOBAL FORCEINLINE sbit32 tdsmInterlockedDecrement( smRoot_t *smRoot, sbit32 volatile *Addend ) { return ostiInterlockedDecrement(agNULL, Addend); } osGLOBAL FORCEINLINE sbit32 tdsmInterlockedAnd( smRoot_t *smRoot, sbit32 volatile *Destination, sbit32 Value ) { return ostiInterlockedAnd(agNULL, Destination, Value); } osGLOBAL FORCEINLINE sbit32 tdsmInterlockedOr( smRoot_t *smRoot, sbit32 volatile *Destination, sbit32 Value ) { return ostiInterlockedOr(agNULL, Destination, Value); } osGLOBAL FORCEINLINE sbit32 tdsmInterlockedExchange( smRoot_t *smRoot, sbit32 volatile *Target, sbit32 Value ) { return ostiInterlockedExchange(agNULL, Target, Value); } #endif /*LINUX_VERSION_CODE*/ osGLOBAL bit32 tdsmAllocMemory( smRoot_t *smRoot, void **osMemHandle, void ** virtPtr, bit32 * physAddrUpper, bit32 * physAddrLower, bit32 alignment, bit32 allocLength, smBOOLEAN isCacheable ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; bit32 status; TI_DBG5(("tdsmAllocMemory: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; if (tdsaRoot == agNULL) { TI_DBG1(("tdsmAllocMemory: tdsaRoot is NULL\n")); return SM_RC_FAILURE; } tdsaAllShared = &(tdsaRoot->tdsaAllShared); if (tdsaAllShared == agNULL) { TI_DBG1(("tdsmAllocMemory: tdsaAllShared is NULL\n")); return SM_RC_FAILURE; } tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; if (tiRoot == agNULL) { TI_DBG1(("tdsmAllocMemory: tiRoot is NULL\n")); return SM_RC_FAILURE; } status = ostiAllocMemory(tiRoot, osMemHandle, virtPtr, physAddrUpper, physAddrLower, alignment, allocLength, isCacheable); if (status == tiSuccess) { return SM_RC_SUCCESS; } else { return SM_RC_FAILURE; } } osGLOBAL bit32 tdsmFreeMemory( smRoot_t *smRoot, void *osDMAHandle, bit32 allocLength ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; bit32 status; TI_DBG5(("tdsmFreeMemory: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; if (tdsaRoot == agNULL) { TI_DBG1(("tdsmFreeMemory: tdsaRoot is NULL\n")); return SM_RC_FAILURE; } tdsaAllShared = &(tdsaRoot->tdsaAllShared); if (tdsaAllShared == agNULL) { TI_DBG1(("tdsmFreeMemory: tdsaAllShared is NULL\n")); return SM_RC_FAILURE; } tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; if (tiRoot == agNULL) { TI_DBG1(("tdsmFreeMemory: tiRoot is NULL\n")); return SM_RC_FAILURE; } status = ostiFreeMemory(tiRoot, osDMAHandle, allocLength); if (status == tiSuccess) { return SM_RC_SUCCESS; } else { return SM_RC_FAILURE; } } FORCEINLINE bit32 tdsmRotateQnumber(smRoot_t *smRoot, smDeviceHandle_t *smDeviceHandle ) { tdsaRoot_t *tdsaRoot; tdsaContext_t *tdsaAllShared; tiRoot_t *tiRoot; tdsaDeviceData_t *oneDeviceData; bit32 ret = 0; tdsaRoot = (tdsaRoot_t *)smRoot->tdData; tdsaAllShared = &(tdsaRoot->tdsaAllShared); tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; TI_DBG6(("tdsmRotateQnumber: start\n")); if (smDeviceHandle == agNULL) { TI_DBG1(("tdsmRotateQnumber: smDeviceHandle is NULL !!!!\n")); return ret; } oneDeviceData = (tdsaDeviceData_t *)smDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("tdsmRotateQnumber: oneDeviceData is NULL !!!!\n")); return ret; } return tdsaRotateQnumber(tiRoot, oneDeviceData); } osGLOBAL bit32 tdsmSetDeviceQueueDepth(smRoot_t *smRoot, smIORequest_t *smIORequest, bit32 QueueDepth ) { tdsaRoot_t *tdsaRoot = agNULL; tdsaContext_t *tdsaAllShared = agNULL; tiRoot_t *tiRoot = agNULL; tdIORequestBody_t *tdIORequestBody = (tdIORequestBody_t *)smIORequest->tdData; tiIORequest_t *tiIORequest = tdIORequestBody->tiIORequest; TI_DBG5(("tdsmSetDeviceQueueDepth: start\n")); tdsaRoot = (tdsaRoot_t *)smRoot->tdData; if (tdsaRoot == agNULL) { TI_DBG1(("tdsmSetDeviceQueueDepth: tdsaRoot is NULL\n")); return SM_RC_FAILURE; } tdsaAllShared = &(tdsaRoot->tdsaAllShared); if (tdsaAllShared == agNULL) { TI_DBG1(("tdsmSetDeviceQueueDepth: tdsaAllShared is NULL\n")); return SM_RC_FAILURE; } tiRoot = tdsaAllShared->agRootOsDataForInt.tiRoot; if (tiRoot == agNULL) { TI_DBG1(("tdsmFreeMemory: tiRoot is NULL\n")); return SM_RC_FAILURE; } return ostiSetDeviceQueueDepth(tiRoot, tiIORequest, QueueDepth); } osGLOBAL bit32 tdsmGetTransportParam( smRoot_t *smRoot, char *key, char *subkey1, char *subkey2, char *subkey3, char *subkey4, char *subkey5, char *valueName, char *buffer, bit32 bufferLen, bit32 *lenReceived ) { bit32 ret = tiError; TI_DBG7(("tdsmGetTransportParam: start\n")); ret = ostiGetTransportParam(agNULL, key, subkey1, subkey2, subkey3, subkey4, subkey5, valueName, buffer, bufferLen, lenReceived ); return ret; } #endif /* FDS_SM */