/******************************************************************************* *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 * * The file implementing SCSI/ATA Translation (SAT) for LL Layer callback * */ /*****************************************************************************/ #include __FBSDID("$FreeBSD: releng/11.0/sys/dev/pms/RefTisa/tisa/sassata/sata/host/ossasat.c 285242 2015-07-07 13:17:02Z achim $"); #include #include #include #include #ifdef SATA_ENABLE #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 #include #include /***************************************************************************** *! \brief ossaSATACompleted * * This routine is called to complete a SATA request previously issued to the * LL Layer in saSATAStart() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * * \return: none * *****************************************************************************/ GLOBAL void ossaSATACompleted( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, void *agFirstDword, bit32 agIOInfoLen, void *agParam ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); tdIORequestBody_t *tdIORequestBody; satIOContext_t *satIOContext; satDeviceData_t *pSatDevData; tdsaDeviceData_t *tdsaDeviceData = agNULL; tdsaPortContext_t *onePortContext; tiDeviceHandle_t *tiDeviceHandle = agNULL; agsaDevHandle_t *agDevHandle = agNULL; bit32 status; tdsaDeviceData_t *oneDeviceData = agNULL; TDSA_OUT_ENTER(tiRoot); TI_DBG6(("ossaSATACompleted: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); if (agIORequest == agNULL) { TI_DBG1(("ossaSATACompleted: agIORequest is NULL!!!!\n")); return; } tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; if (tdIORequestBody == agNULL) { TI_DBG1(("ossaSATACompleted: tdIORequestBody is NULL!!!!\n")); return; } /* for debugging */ if (tdIORequestBody->ioCompleted == agTRUE) { tiDeviceHandle = tdIORequestBody->tiDevHandle; if (tiDeviceHandle == agNULL) { TI_DBG1(("ossaSATACompleted: tiDeviceHandle is NULL!!!!\n")); return; } tdsaDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG1(("ossaSATACompleted: Error!!!!!! double completion\n")); if (tdsaDeviceData == agNULL) { TI_DBG1(("ossaSATACompleted: tdsaDeviceData is NULL!!!!\n")); return; } TI_DBG1(("ossaSATACompleted: did %d \n", tdsaDeviceData->id)); return; } tdIORequestBody->ioCompleted = agTRUE; satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); if (satIOContext == agNULL) { TI_DBG1(("ossaSATACompleted: satIOContext is NULL!!!!\n")); return; } pSatDevData = satIOContext->pSatDevData; if (tdIORequestBody->tiDevHandle != agNULL) { oneDeviceData = (tdsaDeviceData_t *)tdIORequestBody->tiDevHandle->tdData; } if (pSatDevData == agNULL && oneDeviceData != agNULL) { TI_DBG1(("ossaSATACompleted: pSatDevData is NULL, loc 1, wrong\n")); pSatDevData = &(oneDeviceData->satDevData); } if (pSatDevData == agNULL) { TI_DBG1(("ossaSATACompleted: pSatDevData is NULL loc 2, wrong\n")); if (satIOContext->satOrgIOContext == agNULL) { TI_DBG1(("ossaSATACompleted: external command\n")); } else { TI_DBG1(("ossaSATACompleted: internal command\n")); } goto ext; } tdsaDeviceData = (tdsaDeviceData_t *)pSatDevData->satSaDeviceData; if (oneDeviceData != tdsaDeviceData) { if (satIOContext->satOrgIOContext == agNULL) { TI_DBG1(("ossaSATACompleted: diff device handle; external command\n")); } else { TI_DBG1(("ossaSATACompleted: diff device handle; internal command\n")); } } if (tdsaDeviceData == agNULL) { TI_DBG1(("ossaSATACompleted: tdsaDeviceData is NULL!!!!\n")); return; } onePortContext = tdsaDeviceData->tdPortContext; /* retries in OSSA_IO_XFER_OPEN_RETRY_TIMEOUT */ if (agIOStatus == OSSA_IO_XFER_OPEN_RETRY_TIMEOUT) { if (tdsaDeviceData->valid == agTRUE && tdsaDeviceData->registered == agTRUE && tdsaDeviceData->tdPortContext != agNULL ) { if (tdIORequestBody->reTries <= OPEN_RETRY_RETRIES) /* 10 */ { agDevHandle = tdsaDeviceData->agDevHandle; status = saSATAStart( agRoot, agIORequest, tdsaRotateQnumber(tiRoot, tdsaDeviceData), agDevHandle, satIOContext->reqType, &(tdIORequestBody->transport.SATA.agSATARequestBody), satIOContext->sataTag, ossaSATACompleted); if (status == AGSA_RC_SUCCESS) { TI_DBG1(("ossaSATACompleted: retried\n")); tdIORequestBody->ioStarted = agTRUE; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->reTries++; goto ext; } else { TI_DBG1(("ossaSATACompleted: retry failed\n")); tdIORequestBody->ioStarted = agFALSE; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->reTries = 0; } } else { /* retries is over, do nothing */ TI_DBG1(("ossaSATACompleted: retry is over and fail\n")); tdIORequestBody->reTries = 0; } } else { TI_DBG1(("ossaSATACompleted: incorrect device state or no portcontext\n")); tdIORequestBody->reTries = 0; } } /* if OSSA_IO_XFER_OPEN_RETRY_TIMEOUT*/ /* release tag value for SATA */ if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) || (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) ) { satTagRelease(tiRoot, pSatDevData, satIOContext->sataTag); } /* send SMP_PHY_CONTROL_HARD_RESET */ if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY && tdsaAllShared->FCA) { if (pSatDevData->NumOfFCA <= 0) /* does SMP HARD RESET only upto one time */ { TI_DBG1(("ossaSATACompleted: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; sending HARD_RESET\n")); pSatDevData->NumOfFCA++; tdsaPhyControlSend(tiRoot, tdsaDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, tdsaDeviceData) ); } else { /* given up after one time of SMP HARD RESET; */ TI_DBG1(("ossaSATACompleted: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; NO!!! sending HARD_RESET\n")); if (tdsaDeviceData->registered == agTRUE && tdsaAllShared->ResetInDiscovery == 0) { /* 1. remove this device 2. device removal event */ tdsaAbortAll(tiRoot, agRoot, tdsaDeviceData); tdsaDeviceData->valid = agFALSE; tdsaDeviceData->valid2 = agFALSE; tdsaDeviceData->registered = agFALSE; // pSatDevData->NumOfFCA = 0; ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceRemoval, agNULL ); } } } if (agIOStatus == OSSA_IO_ABORTED) { /* free abort IO request itself - agParam; done in ossaSATAEvent() */ } /* just for debugging */ if (agIOStatus == OSSA_IO_DS_NON_OPERATIONAL) { TI_DBG1(("ossaSATACompleted: agIOStatus is OSSA_IO_DS_NON_OPERATIONAL\n")); } if (agIOStatus == OSSA_IO_DS_IN_RECOVERY) { TI_DBG1(("ossaSATACompleted: agIOStatus is OSSA_IO_DS_IN_RECOVERY\n")); } satIOContext->satCompleteCB( agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, satIOContext); ext: TDSA_OUT_LEAVE(tiRoot); } /***************************************************************************** *! \brief satPacketCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal Packet command I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satPacketCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; tiIniScsiCmnd_t *scsiCmnd; bit32 interruptContext = osData->IntContext; bit8 bSenseKey = 0; bit16 bSenseCodeInfo = 0; bit32 status = 0; TI_DBG4(("satPacketCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satPacketCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satPacketCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satPacketCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satPacketCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } /* Parse CDB */ switch(scsiCmnd->cdb[0]) { case SCSIOPC_TEST_UNIT_READY: //satTestUnitReadyCB(agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, ioContext); //break; case SCSIOPC_GET_EVENT_STATUS_NOTIFICATION: //break; case SCSIOPC_READ_CAPACITY_10: case SCSIOPC_READ_CAPACITY_16: //satPacketReadCapacityCB(agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, ioContext); //break; default: break; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* interal structure free */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); if( agIOStatus == OSSA_IO_SUCCESS && agFirstDword == agNULL) { TI_DBG1(("satPacketCB: agIOStatus == OSSA_IO_SUCCESS, agFirstDword == agNULL \n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, interruptContext); } else if (agIOStatus == OSSA_IO_SUCCESS && agFirstDword != agNULL) { TI_DBG1(("satPacketCB: wrong. agIOStatus == OSSA_IO_SUCCESS && agFirstDword != agNULL \n")); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 32, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ /* just translate the ATAPI error register to sense information */ satTranslateATAPIErrorsToSCSIErrors( scsiCmnd->cdb[0], agFirstDword->D2H.status, agFirstDword->D2H.error, &bSenseKey, &bSenseCodeInfo ); satSetSensePayload(pSense, bSenseKey, 0, bSenseCodeInfo, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, interruptContext); TI_DBG1(("satPacketCB: momory allocation fails\n")); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO(satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sends request sense to ATAPI device for acquiring sense information */ status = satRequestSenseForATAPI(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext ); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* just translate the ATAPI error register to sense information */ satTranslateATAPIErrorsToSCSIErrors( scsiCmnd->cdb[0], agFirstDword->D2H.status, agFirstDword->D2H.error, &bSenseKey, &bSenseCodeInfo ); satSetSensePayload(pSense, bSenseKey, 0, bSenseCodeInfo, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, interruptContext); TI_DBG1(("satPacketCB: failed to call satRequestSenseForATAPI()\n")); } } else if (agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satPacketCB: wrong. agIOStatus != OSSA_IO_SUCCESS, status %d\n", agIOStatus)); itdsatProcessAbnormalCompletion( agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, satIOContext); } else { TI_DBG1(("satPacketCB: Unknown error \n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); } } /***************************************************************************** *! \brief satRequestSenseForATAPICB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal non-chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satRequestSenseForATAPICB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; tiIORequest_t *tiOrgIORequest; bit32 interruptContext = osData->IntContext; TI_DBG4(("satPacketCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satPacketCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG4(("satPacketCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satPacketCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satPacketCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* copy the request sense buffer to original IO buffer*/ if (satIntIo != agNULL) { osti_memcpy(satOrgIOContext->pTiSenseData->senseData, satIntIo->satIntDmaMem.virtPtr, SENSE_DATA_LENGTH); satOrgIOContext->pTiSenseData->senseLen = SENSE_DATA_LENGTH; /* interal structure free */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); } /* notify the OS to complete this SRB */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, interruptContext); } /***************************************************************************** *! \brief satSetFeaturesPIOCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal non-chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satSetFeaturesPIOCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; tiIORequest_t *tiOrgIORequest; tiIniScsiCmnd_t *scsiCmnd; bit32 status; TI_DBG3(("satSetFeaturesPIOCB start\n")); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satSetFeaturesPIOCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satSetFeaturesPIOCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satSetFeaturesPIOCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satSetFeaturesPIOCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; scsiCmnd = satOrgIOContext->pScsiCmnd; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* interal structure free */ satFreeIntIoResource(tiRoot, satDevData, satIntIo); /*if the ATAPI device support DMA, then enble this feature*/ if (satDevData->satDMASupport && satDevData->satDMAEnabled) { satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { TI_DBG1(("satSetFeaturesPIOCB: momory allocation fails\n")); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO(satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sends either ATA SET FEATURES based on DMA bit */ status = satSetFeatures(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext, agTRUE ); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); TI_DBG1(("satSetFeaturesPIOCB: failed to call satSetFeatures()\n")); } } } /***************************************************************************** *! \brief satSetFeaturesCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal non-chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satSetFeaturesCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody = agNULL; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; tdsaPortContext_t *onePortContext = agNULL; tiPortalContext_t *tiPortalContext = agNULL; tdsaDeviceData_t *oneDeviceData = agNULL; bit8 PhyID =0; TI_DBG3(("satSetFeaturesCB start\n")); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; oneDeviceData = (tdsaDeviceData_t *)tdIORequestBody->tiDevHandle->tdData; onePortContext = oneDeviceData->tdPortContext; if (onePortContext == agNULL) { TI_DBG4(("satSetFeaturesCB: onePortContext is NULL, wrong\n")); return; } tiPortalContext = onePortContext->tiPortalContext; PhyID = oneDeviceData->phyID; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satSetFeaturesCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; } else { TI_DBG4(("satSetFeaturesCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satSetFeaturesCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satSetFeaturesCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* interal structure free */ satFreeIntIoResource(tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ if (tdOrgIORequestBody!= agNULL) { ostiFreeMemory(tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } if (onePortContext != agNULL) { /* this condition is for tdsaDiscoveryStartIDDevCB routine*/ if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED) { TI_DBG1(("satSetFeaturesCB: ID completed after discovery is done; tiDeviceArrival\n")); /* in case registration is finished after discovery is finished */ ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceArrival, agNULL ); return; } TI_DBG2(("satSetFeaturesCB: pid %d\n", tdsaAllShared->Ports[PhyID].portContext->id)); /* the below codes is for satAddSATAIDDevCB routine*/ /* 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 } else { TI_DBG1(("satSetFeaturesCB: onePortContext is NULL, wrong\n")); } } /***************************************************************************** *! \brief satDeviceResetCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal non-chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satDeviceResetCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* callback for satResetDevice */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody = agNULL; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; // satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; // satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; tiIORequest_t *tiOrgIORequest; #ifdef TD_DEBUG_ENABLE bit32 ataStatus = 0; bit32 ataError; agsaFisPioSetupHeader_t *satPIOSetupHeader = agNULL; #endif // bit32 status; bit32 report = agFALSE; bit32 AbortTM = agFALSE; TI_DBG1(("satDeviceResetCB: start\n")); TI_DBG6(("satDeviceResetCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; if (satIntIo == agNULL) { TI_DBG6(("satDeviceResetCB: External, OS generated\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG6(("satDeviceResetCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG6(("satDeviceResetCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG6(("satDeviceResetCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satDeviceResetCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); if (satOrgIOContext->NotifyOS == agTRUE) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, tiOrgIORequest ); } satDevData->satTmTaskTag = agNULL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_BREAK || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_UNKNOWN_ERROR || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY ) { TI_DBG1(("satDeviceResetCB: OSSA_IO_OPEN_CNX_ERROR\n")); if (satOrgIOContext->NotifyOS == agTRUE) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, tiOrgIORequest ); } satDevData->satTmTaskTag = agNULL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisPioSetup_t is expected */ #ifdef TD_DEBUG_ENABLE satPIOSetupHeader = (agsaFisPioSetupHeader_t *)&(agFirstDword->PioSetup); ataStatus = satPIOSetupHeader->status; /* ATA Status register */ ataError = satPIOSetupHeader->error; /* ATA Eror register */ #endif TI_DBG1(("satDeviceResetCB: ataStatus 0x%x ataError 0x%x\n", ataStatus, ataError)); if (satOrgIOContext->NotifyOS == agTRUE) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, tiOrgIORequest ); } satDevData->satTmTaskTag = agNULL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* success */ if (satOrgIOContext->TMF == AG_ABORT_TASK) { AbortTM = agTRUE; } if (satOrgIOContext->NotifyOS == agTRUE) { report = agTRUE; } if (AbortTM == agTRUE) { TI_DBG1(("satDeResetDeviceCB: calling satAbort\n")); satAbort(agRoot, satOrgIOContext->satToBeAbortedIOContext); } satDevData->satTmTaskTag = agNULL; satDevData->satDriveState = SAT_DEV_STATE_NORMAL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); TI_DBG1(("satDeviceResetCB: satPendingIO %d satNCQMaxIO %d\n", satDevData->satPendingIO, satDevData->satNCQMaxIO )); TI_DBG1(("satDeviceResetCB: satPendingNCQIO %d satPendingNONNCQIO %d\n", satDevData->satPendingNCQIO, satDevData->satPendingNONNCQIO)); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ if (tdOrgIORequestBody != agNULL) { ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else { TI_DBG1(("satDeviceResetCB: tdOrgIORequestBody is NULL, wrong\n")); } if (report) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMOK, tiOrgIORequest ); } TI_DBG5(("satDeviceResetCB: device %p pending IO %d\n", satDevData, satDevData->satPendingIO)); TI_DBG6(("satDeviceResetCB: end\n")); return; } /***************************************************************************** *! \brief satExecuteDeviceDiagnosticCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal non-chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satExecuteDeviceDiagnosticCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; TI_DBG3(("satExecuteDeviceDiagnosticCB start\n")); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satExecuteDeviceDiagnosticCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; } else { TI_DBG4(("satExecuteDeviceDiagnosticCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satExecuteDeviceDiagnosticCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satExecuteDeviceDiagnosticCB: satOrgIOContext is NOT NULL\n")); } } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* interal structure free */ satFreeIntIoResource(tiRoot, satDevData, satIntIo); } /***************************************************************************** *! \brief satNonChainedDataIOCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal non-chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satNonChainedDataIOCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; bit32 interruptContext = osData->IntContext; satIOContext_t *satIOContext; satInternalIo_t *SatIntIo; satDeviceData_t *SatDevData; TI_DBG6(("satNonChainedDataIOCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; SatIntIo = satIOContext->satIntIoContext; SatDevData = satIOContext->pSatDevData; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* interal structure free */ satFreeIntIoResource( tiRoot, SatDevData, SatIntIo); /* Process completion */ if( (agIOStatus == OSSA_IO_SUCCESS) && (agIOInfoLen == 0)) { TI_DBG5(("satNonChainedDataIOCB: success\n")); TI_DBG5(("satNonChainedDataIOCB: success agIORequest %p\n", agIORequest)); /* * Command was completed OK, this is the normal path. * Now call the OS-App Specific layer about this completion. */ ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, interruptContext); } else { TI_DBG1(("satNonChainedDataIOCB: calling itdsatProcessAbnormalCompletion\n")); /* More checking needed */ itdsatProcessAbnormalCompletion( agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, satIOContext); } return; } /***************************************************************************** *! \brief satChainedDataIOCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with normal chained data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satChainedDataIOCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status = tiError; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; bit32 dataLength; TI_DBG6(("satChainedDataIOCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; if (satIOContext == agNULL) { TI_DBG1(("satChainedDataIOCB: satIOContext is NULL\n")); return; } satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG5(("satChainedDataIOCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; } else { TI_DBG5(("satChainedDataIOCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG5(("satChainedDataIOCB: satOrgIOContext is NULL\n")); } else { TI_DBG5(("satChainedDataIOCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satChainedDataIOCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* checking IO status, FIS type and error status */ if (agIOStatus != OSSA_IO_SUCCESS) { /* agsaFisPioSetup_t or agsaFisRegDeviceToHost_t or agsaFisSetDevBits_t for read agsaFisRegDeviceToHost_t or agsaFisSetDevBits_t for write first, assumed to be Reg Device to Host FIS This is OK to just find fis type */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ /* for debugging */ if( (statDevToHostFisHeader->fisType != PIO_SETUP_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != SET_DEV_BITS_FIS) ) { TI_DBG1(("satChainedDataIOCB: FAILED, Wrong FIS type 0x%x\n", statDevToHostFisHeader->fisType)); } /* for debugging */ if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satChainedDataIOCB: FAILED, error status and command 0x%x\n", hostToDevFis->h.command)); } /* the function below handles abort case */ itdsatDelayedProcessAbnormalCompletion(agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, satIOContext); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end of error */ switch (hostToDevFis->h.command) { case SAT_READ_DMA: /* fall through */ case SAT_READ_SECTORS: /* fall through */ case SAT_READ_DMA_EXT: /* fall through */ case SAT_READ_SECTORS_EXT: /* fall through */ case SAT_READ_FPDMA_QUEUED: /* fall through */ case SAT_WRITE_DMA: /* fall through */ case SAT_WRITE_SECTORS:/* fall through */ case SAT_WRITE_DMA_FUA_EXT: /* fall through */ case SAT_WRITE_DMA_EXT: /* fall through */ case SAT_WRITE_SECTORS_EXT: /* fall through */ case SAT_WRITE_FPDMA_QUEUED: TI_DBG5(("satChainedDataIOCB: READ/WRITE success case\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with internally genereated SAT_SMART_RETURN_STATUS */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* let's loop till TL */ /* lba = lba + tl loopnum--; if (loopnum == 0) done */ (satOrgIOContext->LoopNum)--; if (satOrgIOContext->LoopNum == 0) { /* done with read */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } if (satOrgIOContext->superIOFlag) { dataLength = ((tiSuperScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } else { dataLength = ((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, dataLength, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedDataIOCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sending another ATA command */ switch (scsiCmnd->cdb[0]) { case SCSIOPC_READ_6: /* no loop should occur with READ6 since it fits in one ATA command */ break; case SCSIOPC_READ_10: /* fall through */ case SCSIOPC_READ_12: /* fall through */ case SCSIOPC_READ_16: /* fall through */ status = satRead_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); break; case SCSIOPC_WRITE_6: /* no loop should occur with WRITE6 since it fits in one ATA command */ break; case SCSIOPC_WRITE_10: /* fall through */ case SCSIOPC_WRITE_12: /* fall through */ case SCSIOPC_WRITE_16: /* fall through */ status = satWrite_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); break; default: TI_DBG1(("satChainedDataIOCB: success but default case scsi cmd 0x%x ata cmd 0x%x\n",scsiCmnd->cdb[0], hostToDevFis->h.command)); status = tiError; break; } if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedDataIOCB: calling satRead10_1 fails\n")); return; } break; default: TI_DBG1(("satChainedDataIOCB: success but default case command 0x%x\n",hostToDevFis->h.command)); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } return; } void satNonChainedWriteNVerifyCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; tiScsiInitiatorRequest_t *tiScsiRequest; /* tiScsiXchg */ agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; agsaFisSetDevBitsHeader_t *statSetDevBitFisHeader = agNULL; TI_DBG5(("satNonChainedWriteNVerifyCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; /* SPC: Self-Test Result Log page */ tiScsiRequest = satIOContext->tiScsiXchg; if (satIntIo == agNULL) { TI_DBG4(("satNonChainedWriteNVerifyCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satNonChainedWriteNVerifyCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satNonChainedWriteNVerifyCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satNonChainedWriteNVerifyCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satNonChainedWriteNVerifyCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* FIS type should be either REG_DEV_TO_HOST_FIS or SET_DEV_BITS_FIS */ /* First, assumed to be Reg Device to Host FIS */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if (agIOStatus != OSSA_IO_SUCCESS) { if (statDevToHostFisHeader->fisType == SET_DEV_BITS_FIS) { statSetDevBitFisHeader = (agsaFisSetDevBitsHeader_t *)&(agFirstDword->D2H); /* Get ATA Status register */ ataStatus = (statSetDevBitFisHeader->statusHi_Lo & 0x70); /* bits 4,5,6 */ ataStatus = ataStatus | (statSetDevBitFisHeader->statusHi_Lo & 0x07); /* bits 0,1,2 */ /* ATA Eror register */ } } if( agIOStatus != OSSA_IO_SUCCESS) { /* checking IO status, FIS type and error status FIS type should be either REG_DEV_TO_HOST_FIS or SET_DEV_BITS_FIS Both have fisType in the same location */ if ( ((statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != SET_DEV_BITS_FIS)) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satNonChainedWriteNVerifyCB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satNonChainedWriteNVerifyCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if (statDevToHostFisHeader->fisType != SET_DEV_BITS_FIS) { TI_DBG1(("satNonChainedWriteNVerifyCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satNonChainedWriteNVerifyCB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ switch (hostToDevFis->h.command) { case SAT_WRITE_DMA_FUA_EXT: TI_DBG1(("satNonChainedWriteNVerifyCB: SAT_WRITE_DMA_FUA_EXT\n")); break; case SAT_WRITE_DMA_EXT: TI_DBG1(("satNonChainedWriteNVerifyCB: SAT_WRITE_DMA_EXT\n")); break; case SAT_WRITE_SECTORS_EXT: TI_DBG1(("satNonChainedWriteNVerifyCB: SAT_WRITE_SECTORS_EXT\n")); break; case SAT_WRITE_FPDMA_QUEUED: TI_DBG1(("satNonChainedWriteNVerifyCB: SAT_WRITE_FPDMA_QUEUED\n")); break; case SAT_READ_VERIFY_SECTORS: TI_DBG1(("satNonChainedWriteNVerifyCB: SAT_READ_VERIFY_SECTORS\n")); break; case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG1(("satNonChainedWriteNVerifyCB: SAT_READ_VERIFY_SECTORS_EXT\n")); break; default: TI_DBG1(("satNonChainedWriteNVerifyCB: error default case command 0x%x\n", hostToDevFis->h.command)); break; } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end error checking */ } /* process success from this point on */ switch (hostToDevFis->h.command) { case SAT_WRITE_DMA_FUA_EXT: TI_DBG5(("satNonChainedWriteNVerifyCB: SAT_WRITE_DMA_FUA_EXT success\n")); break; case SAT_WRITE_DMA_EXT: TI_DBG5(("satNonChainedWriteNVerifyCB: SAT_WRITE_DMA_EXT success\n")); break; case SAT_WRITE_SECTORS_EXT: TI_DBG5(("satNonChainedWriteNVerifyCB: SAT_WRITE_SECTORS_EXT succes\n")); break; case SAT_WRITE_FPDMA_QUEUED: TI_DBG5(("satNonChainedWriteNVerifyCB: SAT_WRITE_FPDMA_QUEUED succes\n")); break; case SAT_READ_VERIFY_SECTORS: TI_DBG5(("satNonChainedWriteNVerifyCB: SAT_READ_VERIFY_SECTORS succes\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* free */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* return stat_good */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; break; case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satNonChainedWriteNVerifyCB: SAT_READ_VERIFY_SECTORS_EXT succes\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* free */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* return stat_good */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; break; default: TI_DBG1(("satNonChainedWriteNVerifyCB: error default case command 0x%x success\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; break; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* free */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satNonChainedWriteNVerifyCB: momory allocation fails\n")); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sends ATA verify command(READ_VERIFY_SECTORS or READ_VERIFY_SECTORS_EXT) */ status = satNonChainedWriteNVerify_Verify(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, tiScsiRequest, /* orginal from OS layer */ satNewIOContext ); if (status != tiSuccess) { /* sending ATA command fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satNonChainedWriteNVerifyCB: calling satWriteAndVerify10_1 fails\n")); return; } /* end send fails */ return; } void satChainedWriteNVerifyCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* send write in loop then, send verify in loop */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 dataLength; bit32 status = tiError; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG6(("satChainedWriteNVerifyCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG5(("satChainedWriteNVerifyCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; } else { TI_DBG5(("satChainedWriteNVerifyCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG5(("satChainedWriteNVerifyCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG5(("satChainedWriteNVerifyCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satChainedWriteNVerifyCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* checking IO status, FIS type and error status */ if (agIOStatus != OSSA_IO_SUCCESS) { /* agsaFisPioSetup_t or agsaFisRegDeviceToHost_t or agsaFisSetDevBits_t for read agsaFisRegDeviceToHost_t or agsaFisSetDevBits_t for write first, assumed to be Reg Device to Host FIS This is OK to just find fis type */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ /* for debugging */ if( (statDevToHostFisHeader->fisType != PIO_SETUP_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != SET_DEV_BITS_FIS) ) { TI_DBG1(("satChainedWriteNVerifyCB: FAILED, Wrong FIS type 0x%x\n", statDevToHostFisHeader->fisType)); } /* for debugging */ if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satChainedWriteNVerifyCB: FAILED, error status and command 0x%x\n", hostToDevFis->h.command)); } /* the function below handles abort case */ itdsatDelayedProcessAbnormalCompletion(agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, satIOContext); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end of error */ /* process the success case */ switch (hostToDevFis->h.command) { case SAT_WRITE_DMA: /* fall through */ case SAT_WRITE_SECTORS:/* fall through */ // case SAT_WRITE_DMA_FUA_EXT: /* fall through */ case SAT_WRITE_DMA_EXT: /* fall through */ case SAT_WRITE_SECTORS_EXT: /* fall through */ case SAT_WRITE_FPDMA_QUEUED: TI_DBG5(("satChainedWriteNVerifyCB: WRITE success case\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with internally genereated SAT_SMART_RETURN_STATUS */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* let's loop till TL */ (satOrgIOContext->LoopNum)--; if (satOrgIOContext->superIOFlag) { dataLength = ((tiSuperScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } else { dataLength = ((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, dataLength, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedWriteNVerifyCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); if (satOrgIOContext->LoopNum == 0) { /* done with write start with verify */ satOrgIOContext->LoopNum = satOrgIOContext->LoopNum2; status = satChainedWriteNVerify_Start_Verify(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); } else { status = satChainedWriteNVerify_Write(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); } if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedWriteNVerifyCB: calling satChainedWriteNVerify_Write fails\n")); return; } break; case SAT_READ_VERIFY_SECTORS: /* fall through */ case SAT_READ_VERIFY_SECTORS_EXT: satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with internally genereated SAT_SMART_RETURN_STATUS */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* let's loop till TL */ /* lba = lba + tl loopnum--; if (loopnum == 0) done */ (satOrgIOContext->LoopNum)--; if (satOrgIOContext->LoopNum == 0) { /* done with write and verify */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } if (satOrgIOContext->superIOFlag) { dataLength = ((tiSuperScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } else { dataLength = ((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, dataLength, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedWriteNVerifyCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); status = satChainedWriteNVerify_Verify(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedWriteNVerifyCB: calling satChainedWriteNVerify_Verify fails\n")); return; } break; default: TI_DBG1(("satChainedWriteNVerifyCB: success but default case command 0x%x\n",hostToDevFis->h.command)); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } return; } /***************************************************************************** *! \brief itdsatProcessAbnormalCompletion * * This routine is called to complete error case for SATA request previously * issued to the LL Layer in saSATAStart() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void itdsatProcessAbnormalCompletion( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, satIOContext_t *satIOContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; bit32 interruptContext = osData->IntContext; tdIORequestBody_t *tdIORequestBody; satDeviceData_t *pSatDevData; tiDeviceHandle_t *tiDeviceHandle; tdsaDeviceData_t *oneDeviceData = agNULL; agsaDevHandle_t *agDevHandle = agNULL; TI_DBG5(("itdsatProcessAbnormalCompletion: agIORequest=%p agIOStatus=0x%x agIOInfoLen=%d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; pSatDevData = satIOContext->pSatDevData; tiDeviceHandle = satIOContext->ptiDeviceHandle; /* Get into the detail */ switch(agIOStatus) { case OSSA_IO_SUCCESS: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_SUCCESS agIOInfoLen %d calling osSatIOCompleted\n", agIOInfoLen)); /* * At this point agIOInfoLen should be non-zero and there is valid FIS * to read. Pass this info to the SAT layer in order to do the ATA status * to SCSI status translation. */ osSatIOCompleted( tiRoot, tdIORequestBody->tiIORequest, agFirstDword, agIOInfoLen, agParam, satIOContext, interruptContext); break; case OSSA_IO_ABORTED: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_ABORTED\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailAborted, agNULL, interruptContext); if ( pSatDevData->satTmTaskTag != agNULL ) { TI_DBG1(("itdsatProcessAbnormalCompletion: TM callback\n")); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); } /* TM completed */ ostiInitiatorEvent( tiRoot, agNULL, /* portalContext not used */ tiDeviceHandle, tiIntrEventTypeTaskManagement, tiTMOK, pSatDevData->satTmTaskTag); /* * Reset flag */ pSatDevData->satTmTaskTag = agNULL; } /* * Check if we are in recovery mode and need to update the recovery flag */ if ((pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY ) && (pSatDevData->satPendingIO == 0 )) { pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL; TI_DBG1(("itdsatProcessAbnormalCompletion: STATE NORMAL.\n")); } TI_DBG1(("itdsatProcessAbnormalCompletion: satDriveState %d\n", pSatDevData->satDriveState)); TI_DBG1(("itdsatProcessAbnormalCompletion: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG1(("itdsatProcessAbnormalCompletion: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); break; case OSSA_IO_UNDERFLOW: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_UNDERFLOW\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOUnderRun, agIOInfoLen, agNULL, interruptContext); break; case OSSA_IO_FAILED: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_FAILED\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_ABORT_RESET: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_ABORT_RESET\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailAbortReset, agNULL, interruptContext); /* * Check if we are in recovery mode and need to update the recovery flag */ if ((pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY ) && (pSatDevData->satPendingIO == 0 )) { pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL; TI_DBG1(("itdsatProcessAbnormalCompletion: STATE NORMAL.\n")); } TI_DBG1(("itdsatProcessAbnormalCompletion: satDriveState %d\n", pSatDevData->satDriveState)); TI_DBG1(("itdsatProcessAbnormalCompletion: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG1(("itdsatProcessAbnormalCompletion: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); break; case OSSA_IO_NO_DEVICE: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_NO_DEVICE\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailNoLogin, agNULL, interruptContext); break; case OSSA_IO_PROG_ERROR: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_PROG_ERROR\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_BREAK: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_UNKNOWN_ERROR: /* fall through */ TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_OPEN_CNX_ERROR_* 0x%x\n", agIOStatus)); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, oneDeviceData is NULL\n")); } else { TI_DBG1(("itdsatProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, //tiDetailNoDeviceError, //tiDetailAborted, agNULL, interruptContext); break; case OSSA_IO_XFER_ERROR_BREAK: /* fall throuth */ case OSSA_IO_XFER_ERROR_PHY_NOT_READY: /* fall throuth */ case OSSA_IO_XFER_ERROR_PEER_ABORTED: /* fall throuth */ case OSSA_IO_XFER_ERROR_DMA: /* fall throuth */ case OSSA_IO_XFER_ERROR_SATA_LINK_TIMEOUT: /* fall throuth */ case OSSA_IO_XFER_ERROR_ABORTED_DUE_TO_SRST: /* fall throuth */ case OSSA_IO_XFER_ERROR_REJECTED_NCQ_MODE: /* fall throuth */ TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_XFER_ERROR_* 0x%x\n", agIOStatus)); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_DS_IN_ERROR: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_DS_IN_ERROR\n")); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, oneDeviceData is NULL\n")); } else { TI_DBG1(("itdsatProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_DS_NON_OPERATIONAL: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = OSSA_IO_DS_NON_OPERATIONAL\n")); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: wrong, oneDeviceData is NULL\n")); } else { TI_DBG1(("itdsatProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); agDevHandle = oneDeviceData->agDevHandle; if (oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE && oneDeviceData->tdPortContext != agNULL ) { saSetDeviceState(agRoot, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData), agDevHandle, SA_DS_OPERATIONAL); } } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS: /* fall through */ case OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = ENCRYPTION ERROR 0x%x\n", agIOStatus)); itdsatEncryptionHandler(agRoot, agIORequest, agIOStatus, agIOInfoLen, agParam, 0); break; case OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH: /* fall through */ case OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH: /* fall through */ case OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH: TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = DIF ERROR 0x%x\n", agIOStatus)); itdsatDifHandler(agRoot, agIORequest, agIOStatus, agIOInfoLen, agParam, 0); break; default: oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; TI_DBG1(("itdsatProcessAbnormalCompletion: agIOStatus = unknown 0x%x\n", agIOStatus)); if (oneDeviceData != agNULL) { TI_DBG1(("itdsatProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); } else { TI_DBG1(("itdsatProcessAbnormalCompletion: oneDeviceData is NULL\n")); } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; } /* switch */ } /***************************************************************************** *! \brief itdsatDelayedProcessAbnormalCompletion * * This routine is called to complete error case for SATA request previously * issued to the LL Layer in saSATAStart(). * This is used when command is chained. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void itdsatDelayedProcessAbnormalCompletion( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, satIOContext_t *satIOContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; bit32 interruptContext = osData->IntContext; tdIORequestBody_t *tdIORequestBody; satDeviceData_t *pSatDevData; tiDeviceHandle_t *tiDeviceHandle; tdsaDeviceData_t *oneDeviceData = agNULL; agsaDevHandle_t *agDevHandle = agNULL; TI_DBG5(("itdsatDelayedProcessAbnormalCompletion: agIORequest=%p agIOStatus=0x%x agIOInfoLen=%d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; pSatDevData = satIOContext->pSatDevData; tiDeviceHandle = satIOContext->ptiDeviceHandle; /* Get into the detail */ switch(agIOStatus) { case OSSA_IO_SUCCESS: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_SUCCESS calling osSatIOCompleted\n")); /* do nothing */ break; case OSSA_IO_ABORTED: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_ABORTED\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailAborted, agNULL, interruptContext); if ( pSatDevData->satTmTaskTag != agNULL ) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: TM callback\n")); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); } /* TM completed */ ostiInitiatorEvent( tiRoot, agNULL, /* portalContext not used */ tiDeviceHandle, tiIntrEventTypeTaskManagement, tiTMOK, pSatDevData->satTmTaskTag); /* * Reset flag */ pSatDevData->satTmTaskTag = agNULL; } /* * Check if we are in recovery mode and need to update the recovery flag */ if ((pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY ) && (pSatDevData->satPendingIO == 0 )) { pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL; TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: STATE NORMAL.\n")); } TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: satDriveState %d\n", pSatDevData->satDriveState)); TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); break; case OSSA_IO_UNDERFLOW: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_UNDERFLOW\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOUnderRun, agIOInfoLen, agNULL, interruptContext); break; case OSSA_IO_FAILED: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_FAILED\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_ABORT_RESET: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_ABORT_RESET\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailAbortReset, agNULL, interruptContext); /* * Check if we are in recovery mode and need to update the recovery flag */ if ((pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY ) && (pSatDevData->satPendingIO == 0 )) { pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL; TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: STATE NORMAL.\n")); } TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: satDriveState %d\n", pSatDevData->satDriveState)); TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); break; case OSSA_IO_NO_DEVICE: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_NO_DEVICE\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailNoLogin, agNULL, interruptContext); break; case OSSA_IO_PROG_ERROR: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_PROG_ERROR\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_BREAK: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION: /* fall through */ case OSSA_IO_OPEN_CNX_ERROR_UNKNOWN_ERROR: /* fall through */ TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_OPEN_CNX_ERROR_* 0x%x\n", agIOStatus)); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, oneDeviceData is NULL\n")); } else { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, //tiDetailNoDeviceError, //tiDetailAborted, agNULL, interruptContext); break; case OSSA_IO_XFER_ERROR_BREAK: /* fall throuth */ case OSSA_IO_XFER_ERROR_PHY_NOT_READY: /* fall throuth */ case OSSA_IO_XFER_ERROR_PEER_ABORTED: /* fall throuth */ case OSSA_IO_XFER_ERROR_DMA: /* fall throuth */ case OSSA_IO_XFER_ERROR_SATA_LINK_TIMEOUT: /* fall throuth */ case OSSA_IO_XFER_ERROR_ABORTED_DUE_TO_SRST: /* fall throuth */ case OSSA_IO_XFER_ERROR_REJECTED_NCQ_MODE: /* fall throuth */ TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_XFER_ERROR_* 0x%x\n", agIOStatus)); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_DS_IN_ERROR: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_DS_IN_ERROR\n")); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, oneDeviceData is NULL\n")); } else { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_DS_NON_OPERATIONAL: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = OSSA_IO_DS_NON_OPERATIONAL\n")); if (tiDeviceHandle == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, tiDeviceHandle is NULL\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: wrong, oneDeviceData is NULL\n")); } else { TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: did %d\n", oneDeviceData->id)); agDevHandle = oneDeviceData->agDevHandle; if (oneDeviceData->valid == agTRUE && oneDeviceData->registered == agTRUE && oneDeviceData->tdPortContext != agNULL ) { saSetDeviceState(agRoot, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData), agDevHandle, SA_DS_OPERATIONAL); } } ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; case OSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS: /* fall through */ case OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = ENCRYPTION ERROR 0x%x\n", agIOStatus)); itdsatEncryptionHandler(agRoot, agIORequest, agIOStatus, agIOInfoLen, agParam, 0); break; case OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH: /* fall through */ case OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH: /* fall through */ case OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = DIF ERROR 0x%x\n", agIOStatus)); itdsatDifHandler(agRoot, agIORequest, agIOStatus, agIOInfoLen, agParam, 0); break; default: TI_DBG1(("itdsatDelayedProcessAbnormalCompletion: agIOStatus = unknown\n")); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); break; } /* switch */ } /***************************************************************************** *! \brief itdsatEncryptionHandler * * Purpose: This function processes I/Os completed and returned by SATA lower * layer with any encryption specific agIOStatus. * * \param agRoot: pointer to port instance * \param agIORequest: pointer to I/O request * \param agIOStatus: I/O status given by LL layer * \param agIOInfoLen: lenth of complete SAS RESP frame * \param agParam A Handle used to refer to the response frame or handle * of abort request * \return: None * * *****************************************************************************/ osGLOBAL void itdsatEncryptionHandler( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, bit32 agIOInfoLen, void *agParam, bit32 agOtherInfo ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; bit32 intContext = osData->IntContext; bit32 errorDetail = tiDetailOtherError; tdIORequestBody_t *tdIORequestBody; TI_DBG1(("itdsatEncryptionHandler: start\n")); TI_DBG1(("itdsatEncryptionHandler: agIOStatus 0x%x\n", agIOStatus)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; switch (agIOStatus) { case OSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS: TI_DBG1(("itdsatEncryptionHandler: OSSA_IO_XFR_ERROR_DEK_KEY_CACHE_MISS\n")); errorDetail = tiDetailDekKeyCacheMiss; break; case OSSA_IO_XFR_ERROR_CIPHER_MODE_INVALID: TI_DBG1(("itdsatEncryptionHandler: OSSA_IO_XFR_ERROR_CIPHER_MODE_INVALID\n")); errorDetail = tiDetailCipherModeInvalid; break; case OSSA_IO_XFR_ERROR_DEK_IV_MISMATCH: TI_DBG1(("itdsatEncryptionHandler: OSSA_IO_XFR_ERROR_DEK_IV_MISMATCH\n")); errorDetail = tiDetailDekIVMismatch; break; case OSSA_IO_XFR_ERROR_DEK_RAM_INTERFACE_ERROR: TI_DBG1(("itdsatEncryptionHandler: OSSA_IO_XFR_ERROR_DEK_RAM_INTERFACE_ERROR\n")); errorDetail = tiDetailDekRamInterfaceError; break; default: TI_DBG1(("itdsatEncryptionHandler: other error!!! 0x%x\n", agIOStatus)); errorDetail = tiDetailOtherError; break; } ostiInitiatorIOCompleted ( tiRoot, tdIORequestBody->tiIORequest, tiIOEncryptError, errorDetail, agNULL, intContext ); return; } /***************************************************************************** *! \brief itdsatDifHandler * * Purpose: This function processes I/Os completed and returned by SATA lower * layer with any DIF specific agIOStatus. * * \param agRoot: pointer to port instance * \param agIORequest: pointer to I/O request * \param agIOStatus: I/O status given by LL layer * \param agIOInfoLen: lenth of complete SAS RESP frame * \param agParam A Handle used to refer to the response frame or handle * of abort request * \return: None * * *****************************************************************************/ osGLOBAL void itdsatDifHandler( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, bit32 agIOInfoLen, void *agParam, bit32 agOtherInfo ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; bit32 intContext = osData->IntContext; bit32 errorDetail = tiDetailOtherError; tdIORequestBody_t *tdIORequestBody; #ifdef TD_DEBUG_ENABLE agsaDifDetails_t *DifDetail; #endif TI_DBG2(("itdsatDifHandler: start\n")); TI_DBG2(("itdsatDifHandler: agIOStatus 0x%x\n", agIOStatus)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; #ifdef TD_DEBUG_ENABLE DifDetail = (agsaDifDetails_t *)agParam; #endif switch (agIOStatus) { case OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH: TI_DBG1(("itdsatDifHandler: OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH\n")); errorDetail = tiDetailDifAppTagMismatch; break; case OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH: TI_DBG1(("itdsatDifHandler: OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH\n")); errorDetail = tiDetailDifRefTagMismatch; break; case OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH: TI_DBG1(("itdsatDifHandler: OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH\n")); errorDetail = tiDetailDifCrcMismatch; break; default: TI_DBG1(("itdsatDifHandler: other error!!! 0x%x\n", agIOStatus)); errorDetail = tiDetailOtherError; break; } TI_DBG1(("smsatDifHandler: DIF detail UpperLBA 0x%08x LowerLBA 0x%08x\n", DifDetail->UpperLBA, DifDetail->LowerLBA)); ostiInitiatorIOCompleted ( tiRoot, tdIORequestBody->tiIORequest, tiIODifError, errorDetail, agNULL, intContext ); return; } /*****************************************************************************/ /*! \brief satProcessAbort * * This function processes abort. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiIORequest: Pointer to TISA I/O request context for this I/O. * \param satIOContext_t: Pointer to the SAT IO Context * * \return * None */ /*****************************************************************************/ void satProcessAbort( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, satIOContext_t *satIOContext ) { satDeviceData_t *pSatDevData; //tiDeviceHandle_t *tiDeviceHandle; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; TI_DBG5(("satProcessAbort: start\n")); pSatDevData = satIOContext->pSatDevData; //tiDeviceHandle = satIOContext->ptiDeviceHandle; hostToDevFis = satIOContext->pFis; if ( (hostToDevFis->h.command == SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE) && (hostToDevFis->d.lbaLow != 0x01 && hostToDevFis->d.lbaLow != 0x02) ) { /* no completion for send diagnotic in background. It is done in satSendDiagnostic() */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOFailed, tiDetailAborted, agNULL, satIOContext->interruptContext); } if ( pSatDevData->satTmTaskTag != agNULL ) { TI_DBG1(("satProcessAbort: TM callback\n")); /* * Reset flag */ pSatDevData->satTmTaskTag = agNULL; } /* * Check if we are in recovery mode and need to update the recovery flag */ if ((pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY ) && (pSatDevData->satPendingIO == 0 )) { pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL; TI_DBG1(("satProcessAbort: STATE NORMAL.\n")); } TI_DBG1(("satProcessAbort: satDriveState %d\n", pSatDevData->satDriveState)); TI_DBG1(("satProcessAbort: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG1(("satProcessAbort: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); return; } /***************************************************************************** *! \brief satNonDataIOCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with non-data I/O SATA request. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satNonDataIOCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; bit32 interruptContext = osData->IntContext; satIOContext_t *satIOContext; TI_DBG5(("satNonDataIOCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* Process completion */ if( (agIOStatus == OSSA_IO_SUCCESS) && (agIOInfoLen==0)) { /* * !!! We expect that agIOInfoLen should be non-zero !!!!. * Now call the OS-App Specific layer about this unexpected completion. */ TI_DBG1(("satNonDataIOCB: *** ERROR*** agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); ostiInitiatorIOCompleted( tiRoot, tdIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); } else { /* More checking needed, for non-data IO this should be the normal case */ itdsatProcessAbnormalCompletion( agRoot, agIORequest, agIOStatus, agFirstDword, agIOInfoLen, agParam, satIOContext); } } /***************************************************************************** *! \brief tdssSATADeviceTypeDecode * * This routine decodes ATA signature * * \param pSignature: ATA signature * * * \return: * TRUE if ATA signature * FALSE otherwise * *****************************************************************************/ /* ATA p65 PM p65 SATAII p79, p80 */ GLOBAL bit32 tdssSATADeviceTypeDecode( bit8 *pSignature ) { bit32 deviceType = UNKNOWN_DEVICE; if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x00 && (pSignature)[3] == 0x00 && (pSignature)[4] == 0xA0 ) /* this is the signature of a Hitachi SATA HDD*/ { deviceType = SATA_ATA_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x00 && (pSignature)[3] == 0x00 && (pSignature)[4] == 0x00 ) { deviceType = SATA_ATA_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x14 && (pSignature)[3] == 0xEB && ( (pSignature)[4] == 0x00 || (pSignature)[4] == 0x10) ) { deviceType = SATA_ATAPI_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x69 && (pSignature)[3] == 0x96 && (pSignature)[4] == 0x00 ) { deviceType = SATA_PM_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x3C && (pSignature)[3] == 0xC3 && (pSignature)[4] == 0x00 ) { deviceType = SATA_SEMB_DEVICE; } else if ( (pSignature)[0] == 0xFF && (pSignature)[1] == 0xFF && (pSignature)[2] == 0xFF && (pSignature)[3] == 0xFF && (pSignature)[4] == 0xFF ) { deviceType = SATA_SEMB_WO_SEP_DEVICE; } return deviceType; } /***************************************************************************** *! \brief ossaDiscoverSataCB * * Purpose: This function is called by lower layer to inform TD layer of * STP/SATA discovery results * * * \param agRoot Pointer to chip/driver Instance. * \param agPortContext Pointer to the port context of TD and Lower layer * \param event event type * \param pParm1 Pointer to data associated with event * \param pParm2 Pointer to data associated with event * * \return: none * * \note - For details, refer to SAS/SATA Low-Level API Specification * *****************************************************************************/ osGLOBAL void ossaDiscoverSataCB( agsaRoot_t *agRoot, agsaPortContext_t *agPortContext, bit32 event, void *pParm1, void *pParm2 ) { tdsaRootOsData_t *osData; tiRoot_t *tiRoot; tdsaPortContext_t *onePortContext; tdsaDeviceData_t *oneDeviceData; agsaDevHandle_t *agDevHandle; agsaSATADeviceInfo_t *agSATADeviceInfo; tiPortalContext_t *tiPortalContext; bit32 devicetype = UNKNOWN_DEVICE; osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot = (tiRoot_t *)osData->tiRoot; TI_DBG5(("ossaDiscoverSataCB: start\n")); if (agPortContext == agNULL) { TI_DBG1(("ossaDiscoverSataCB: NULL agsaPortContext; wrong\n")); return; } onePortContext = (tdsaPortContext_t *)agPortContext->osData; tiPortalContext = (tiPortalContext_t *)onePortContext->tiPortalContext; switch ( event ) { case OSSA_DISCOVER_STARTED: { TI_DBG5(("ossaDiscoverSataCB: STARTED\n")); /* Do nothing */ break; } case OSSA_DISCOVER_FOUND_DEVICE: { TI_DBG5(("ossaDiscoverSataCB: ***** FOUND DEVICE\n")); agDevHandle = (agsaDevHandle_t *) pParm1; agSATADeviceInfo = (agsaSATADeviceInfo_t *) pParm2; /* parse the device type */ devicetype = tdssSATADeviceTypeDecode(agSATADeviceInfo->signature); /* for now, TD handles only ATA Device or ATAPI Device */ if (devicetype == SATA_ATA_DEVICE || devicetype == SATA_ATAPI_DEVICE) { TI_DBG5(("ossaDiscoverSataCB: ***** adding ....\n")); /* Add SATA device */ tdssAddSATAToSharedcontext( onePortContext, agRoot, agDevHandle, agSATADeviceInfo, agTRUE, agSATADeviceInfo->stpPhyIdentifier ); #ifdef INITIATOR_DRIVER ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceArrival, agNULL ); #endif } /* end of ATA_ATA_DEVICE or ATA_ATAPI_DEVICE */ else { TI_DBG5(("ossaDiscoverSataCB: ***** not adding ..... devicetype 0x%x\n", devicetype)); } break; } case OSSA_DISCOVER_REMOVED_DEVICE: { TI_DBG1(("ossaDiscoverSataCB: REMOVED_DEVICE\n")); agDevHandle = (agsaDevHandle_t *) pParm1; agSATADeviceInfo = (agsaSATADeviceInfo_t *) pParm2; oneDeviceData = (tdsaDeviceData_t *) agDevHandle->osData; TI_DBG1(("ossaDiscoverSataCB: signature: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", agSATADeviceInfo->signature[0], agSATADeviceInfo->signature[1], agSATADeviceInfo->signature[2], agSATADeviceInfo->signature[3], agSATADeviceInfo->signature[4], agSATADeviceInfo->signature[5], agSATADeviceInfo->signature[6], agSATADeviceInfo->signature[7] )); if (oneDeviceData == agNULL) { TI_DBG1(("ossaDiscoverSataCB: Wrong. DevHandle->osData is NULL but is being removed\n")); } tdssRemoveSATAFromSharedcontext( onePortContext, oneDeviceData, agRoot ); agDevHandle->osData = agNULL; #ifdef INITIATOR_DRIVER ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceRemoval, agNULL ); #endif break; } case OSSA_DISCOVER_COMPLETE: { TI_DBG1(("ossaDiscoverSataCB: COMPLETE\n")); onePortContext->DiscoveryState = ITD_DSTATE_COMPLETED; TI_DBG6(("ossaDiscoverSataCB: COMPLETE pid %d\n", onePortContext->id)); /* Let OS-Apps specific layer know discovery has been successfully complete */ ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDiscovery, tiDiscOK, agNULL ); break; } case OSSA_DISCOVER_ABORT: { TI_DBG1(("ossaDiscoverSataCB: OSSA_DISCOVER_ABORT\n")); /* Let OS-Apps specific layer know discovery has failed */ ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDiscovery, tiDiscFailed, agNULL ); break; } default: { TI_DBG1(("ossaDiscoverSataCB: error default event 0x%x\n", event)); /* Let OS-Apps specific layer know discovery has failed */ ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDiscovery, tiDiscFailed, agNULL ); break; } } /* end of switch */ return; } /***************************************************************************** *! \brief tdssAddSataToSharedcontext * * Purpose: This function adds a discovered SATA device to a device list of * a port context * * \param tsddPortContext_Instance Pointer to the target port context * \param agRoot Pointer to the root data structure of * TD and Lower layer * \param agDevHandle Pointer to a device handle * \param agSATADeviceInfo Pointer to SATA device info structure * \param registered indication flag for registration to LL * * \Return: none * *****************************************************************************/ /* split into devicedata allocation/registration and sending identify device data */ osGLOBAL void tdssAddSATAToSharedcontext( tdsaPortContext_t *tdsaPortContext_Instance, agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, agsaSATADeviceInfo_t *agSATADeviceInfo, bit32 registered, bit8 phyID ) { tdsaPortContext_t *onePortContext = agNULL; tdList_t *PortContextList; tdsaDeviceData_t *oneDeviceData = agNULL; tdList_t *DeviceListList = agNULL; tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; satDeviceData_t *pSatDevData; bit32 Indenom = tdsaAllShared->QueueConfig.numInboundQueues; bit32 Outdenom = tdsaAllShared->QueueConfig.numOutboundQueues; bit8 dev_s_rate = 0; bit8 sasorsata = 1; bit8 connectionRate; bit8 flag = 0; bit8 TLR = 0; bit32 found = agFALSE; TI_DBG5(("tdssAddSataToSharedcontext: start\n")); /* * Find a right portcontext, then get devicedata from FreeLink in DeviceList. * Then, add the devicedata to the portcontext. */ /* Find a right portcontext */ PortContextList = tdsaAllShared->MainPortContextList.flink; while (PortContextList != &(tdsaAllShared->MainPortContextList)) { onePortContext = TDLIST_OBJECT_BASE(tdsaPortContext_t, MainLink, PortContextList); if (onePortContext == tdsaPortContext_Instance) { TI_DBG5(("tdssAddSataToSharedcontext: found; oneportContext ID %d\n", onePortContext->id)); found = agTRUE; break; } PortContextList = PortContextList->flink; } if (found == agFALSE) { TI_DBG1(("tdssAddSataToSharedcontext: No corressponding tdsaPortContext\n")); return; } /* 1. add the devicedata 2. Send Identify Device Data 3. In CB of Identify Device Data (satAddSATAIDDevCB), finds out the devicedata is new or old */ tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK); if (!TDLIST_NOT_EMPTY(&(tdsaAllShared->FreeDeviceList))) { tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK); TI_DBG1(("tdssAddSataToSharedcontext: ERROR empty DeviceData FreeLink\n")); /* 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; } TDLIST_DEQUEUE_FROM_HEAD(&DeviceListList, &(tdsaAllShared->FreeDeviceList)); tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK); oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, FreeLink, DeviceListList); TDLIST_DEQUEUE_THIS(&(oneDeviceData->FreeLink)); TI_DBG1(("tdssAddSataToSharedcontext: oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); oneDeviceData->InQID = oneDeviceData->id % Indenom; oneDeviceData->OutQID = oneDeviceData->id % Outdenom; pSatDevData = (satDeviceData_t *)&(oneDeviceData->satDevData); pSatDevData->satDriveState = SAT_DEV_STATE_NORMAL; pSatDevData->satPendingIO = 0; pSatDevData->satNCQMaxIO = 0; pSatDevData->satPendingNCQIO = 0; pSatDevData->satPendingNONNCQIO = 0; pSatDevData->IDDeviceValid = agFALSE; pSatDevData->satDeviceType = tdssSATADeviceTypeDecode(onePortContext->remoteSignature); osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); onePortContext->Count++; oneDeviceData->DeviceType = TD_SATA_DEVICE; // either TD_SAS_DEVICE or TD_SATA_DEVICE oneDeviceData->agRoot = agRoot; // oneDeviceData->agDevHandle = agDevHandle; // agDevHandle->osData = oneDeviceData; /* TD layer */ oneDeviceData->tdPortContext = onePortContext; oneDeviceData->valid = agTRUE; oneDeviceData->directlyAttached = agTRUE; oneDeviceData->initiator_ssp_stp_smp = 0; oneDeviceData->target_ssp_stp_smp = 0x1; /* setting SATA device bit */ oneDeviceData->phyID = phyID; /* parse sasIDframe to fill in agDeviceInfo */ flag = (bit8)((phyID << 4) | TLR); DEVINFO_PUT_SMPTO(&oneDeviceData->agDeviceInfo, DEFAULT_SMP_TIMEOUT); DEVINFO_PUT_ITNEXUSTO(&oneDeviceData->agDeviceInfo, (bit16)tdsaAllShared->itNexusTimeout); DEVINFO_PUT_FBS(&oneDeviceData->agDeviceInfo, 0); //temp //DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, 0); DEVINFO_PUT_FLAG(&oneDeviceData->agDeviceInfo, flag); sasorsata = SATA_DEVICE_TYPE; /* SATA disk */ connectionRate = onePortContext->LinkRate; dev_s_rate = (bit8)(dev_s_rate | (sasorsata << 4)); dev_s_rate = (bit8)(dev_s_rate | connectionRate); DEVINFO_PUT_DEV_S_RATE(&oneDeviceData->agDeviceInfo, dev_s_rate); DEVINFO_PUT_SAS_ADDRESSLO( &oneDeviceData->agDeviceInfo, 0 ); DEVINFO_PUT_SAS_ADDRESSHI( &oneDeviceData->agDeviceInfo, 0 ); if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE ) { oneDeviceData->agDeviceInfo.flag |= ATAPI_DEVICE_FLAG; /* ATAPI device flag*/ } oneDeviceData->agContext.osData = oneDeviceData; oneDeviceData->agContext.sdkData = agNULL; if (oneDeviceData->registered == agFALSE) { saRegisterNewDevice( /* tdssAddSATAToSharedcontext */ agRoot, &oneDeviceData->agContext, 0,/*tdsaRotateQnumber(tiRoot, oneDeviceData),*/ &oneDeviceData->agDeviceInfo, onePortContext->agPortContext, 0 ); } return; } /***************************************************************************** *! \brief tdssRetrySATAID * * Purpose: This function retries identify device data to directly attached SATA * device after device registration * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param oneDeviceData Pointer to a device data * \Return: none * *****************************************************************************/ osGLOBAL void tdssRetrySATAID( tiRoot_t *tiRoot, tdsaDeviceData_t *oneDeviceData ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; void *osMemHandle; tdIORequestBody_t *tdIORequestBody; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; agsaIORequest_t *agIORequest = agNULL; /* identify device data itself */ satIOContext_t *satIOContext = agNULL; bit32 status; TI_DBG5(("tdssRetrySATAID: start\n")); /* allocate identify device data and sends it */ /* allocation tdIORequestBody and pass it to satTM() */ memAllocStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&tdIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(tdIORequestBody_t), agTRUE ); if (memAllocStatus != tiSuccess) { TI_DBG1(("tdssRetrySATAID: ostiAllocMemory failed... loc 2\n")); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #endif return; } if (tdIORequestBody == agNULL) { TI_DBG1(("tdssRetrySATAID: ostiAllocMemory returned NULL tdIORequestBody loc 2\n")); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #endif return; } /* setup identify device data IO structure */ tdIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; tdIORequestBody->IOType.InitiatorTMIO.CurrentTaskTag = agNULL; tdIORequestBody->IOType.InitiatorTMIO.TaskTag = agNULL; /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = &(oneDeviceData->tiDeviceHandle); tdIORequestBody->tiDevHandle->tdData = oneDeviceData; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = agNULL; /* initialize agIORequest */ agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; agIORequest->sdkData = agNULL; /* SA takes care of this */ /* set up satIOContext */ satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satIOContext->pSatDevData = &(oneDeviceData->satDevData); satIOContext->pFis = &(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext->tiRequestBody = tdIORequestBody; satIOContext->ptiDeviceHandle = &(oneDeviceData->tiDeviceHandle); satIOContext->tiScsiXchg = agNULL; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; /* followings are used only for internal IO */ satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; satIOContext->satToBeAbortedIOContext = agNULL; satIOContext->NotifyOS = agFALSE; satIOContext->pid = tdsaAllShared->Ports[oneDeviceData->phyID].portContext->id; status = satAddSATAStartIDDev(tiRoot, agNULL, &(oneDeviceData->tiDeviceHandle), agNULL, satIOContext ); /* assumption; always new device data */ if (status == tiSuccess) { TI_DBG6(("tdssRetrySATAID: successfully sent identify device data\n")); TI_DBG6(("tdssRetrySATAID: one case did %d \n", oneDeviceData->id)); } else { TI_DBG1(("tdssRetrySATAID: failed in sending identify device data\n")); /* put onedevicedata back to free list */ tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK); TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #endif } return; } /***************************************************************************** *! \brief tdssSubAddSATAToSharedcontext * * Purpose: This function sends identify device data to directly attached SATA * device after device registration * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param oneDeviceData Pointer to a device data * \Return: none * *****************************************************************************/ osGLOBAL void tdssSubAddSATAToSharedcontext( tiRoot_t *tiRoot, tdsaDeviceData_t *oneDeviceData ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; void *osMemHandle; tdIORequestBody_t *tdIORequestBody; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; agsaIORequest_t *agIORequest = agNULL; /* identify device data itself */ satIOContext_t *satIOContext = agNULL; bit32 status; TI_DBG1(("tdssSubAddSATAToSharedcontext: start\n")); /* allocate identify device data and sends it */ /* allocation tdIORequestBody and pass it to satTM() */ memAllocStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&tdIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(tdIORequestBody_t), agTRUE ); if (memAllocStatus != tiSuccess) { TI_DBG1(("tdssSubAddSATAToSharedcontext: ostiAllocMemory failed... loc 2\n")); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #endif return; } if (tdIORequestBody == agNULL) { TI_DBG1(("tdssSubAddSATAToSharedcontext: ostiAllocMemory returned NULL tdIORequestBody loc 2\n")); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #endif return; } /* setup identify device data IO structure */ tdIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; tdIORequestBody->IOType.InitiatorTMIO.CurrentTaskTag = agNULL; tdIORequestBody->IOType.InitiatorTMIO.TaskTag = agNULL; /* initialize tiDevhandle */ tdIORequestBody->tiDevHandle = &(oneDeviceData->tiDeviceHandle); tdIORequestBody->tiDevHandle->tdData = oneDeviceData; /* initialize tiIORequest */ tdIORequestBody->tiIORequest = agNULL; /* initialize agIORequest */ agIORequest = &(tdIORequestBody->agIORequest); agIORequest->osData = (void *) tdIORequestBody; agIORequest->sdkData = agNULL; /* SA takes care of this */ /* set up satIOContext */ satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satIOContext->pSatDevData = &(oneDeviceData->satDevData); satIOContext->pFis = &(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext->tiRequestBody = tdIORequestBody; satIOContext->ptiDeviceHandle = &(oneDeviceData->tiDeviceHandle); satIOContext->tiScsiXchg = agNULL; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; /* followings are used only for internal IO */ satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; satIOContext->satToBeAbortedIOContext = agNULL; satIOContext->NotifyOS = agFALSE; satIOContext->pid = tdsaAllShared->Ports[oneDeviceData->phyID].portContext->id; status = satAddSATAStartIDDev(tiRoot, agNULL, &(oneDeviceData->tiDeviceHandle), agNULL, satIOContext ); /* assumption; always new device data */ if (status == tiSuccess) { TI_DBG6(("tdssSubAddSATAToSharedcontext: successfully sent identify device data\n")); /* Add the devicedata to the mainlink */ tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK); TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->MainLink), &(tdsaAllShared->MainDeviceList)); tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK); TI_DBG6(("tdssSubAddSATAToSharedcontext: one case did %d \n", oneDeviceData->id)); } else { TI_DBG1(("tdssSubAddSATAToSharedcontext: failed in sending identify device data\n")); /* put onedevicedata back to free list */ tdsaSingleThreadedEnter(tiRoot, TD_DEVICE_LOCK); TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); tdsaSingleThreadedLeave(tiRoot, TD_DEVICE_LOCK); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[oneDeviceData->phyID].tiPortalContext ); #endif } return; } /***************************************************************************** *! \brief tdssRemoveSATAFromSharedcontext * * Purpose: This function removes a discovered device from a device list of * a port context * * \param tsddPortContext_Ins Pointer to the target port context * \param tdsaDeviceData_Ins Pointer to the target device * \param agRoot Pointer to the root data structure of * TD and Lower layer * * \Return: none * *****************************************************************************/ osGLOBAL void tdssRemoveSATAFromSharedcontext( tdsaPortContext_t *tdsaPortContext_Ins, tdsaDeviceData_t *tdsaDeviceData_ins, agsaRoot_t *agRoot ) { TI_DBG1(("tdssRemoveSATAFromSharedcontex: start\n")); return; } /***************************************************************************** *! \brief satSetDevInfo * * Purpose: Based on ATA identify device data, this functions sets fields of * device data maintained in TD layer * * \param satDevData Pointer to a device data * \param SATAIdData Pointer to ATA identify device data * * * \Return: none * *****************************************************************************/ void satSetDevInfo( satDeviceData_t *satDevData, agsaSATAIdentifyData_t *SATAIdData ) { TI_DBG3(("satSetDevInfo: start\n")); satDevData->satDriveState = SAT_DEV_STATE_NORMAL; satDevData->satFormatState = agFALSE; satDevData->satDeviceFaultState = agFALSE; satDevData->satTmTaskTag = agNULL; satDevData->satAbortAfterReset = agFALSE; satDevData->satAbortCalled = agFALSE; satDevData->satSectorDone = 0; /* Qeueu depth, Word 75 */ satDevData->satNCQMaxIO = SATAIdData->queueDepth + 1; TI_DBG3(("satSetDevInfo: max queue depth %d\n",satDevData->satNCQMaxIO)); /* Support NCQ, if Word 76 bit 8 is set */ if (SATAIdData->sataCapabilities & 0x100) { TI_DBG3(("satSetDevInfo: device supports NCQ\n")); satDevData->satNCQ = agTRUE; } else { TI_DBG3(("satSetDevInfo: no NCQ\n")); satDevData->satNCQ = agFALSE; } /* Support 48 bit addressing, if Word 83 bit 10 and Word 86 bit 10 are set */ if ((SATAIdData->commandSetSupported1 & 0x400) && (SATAIdData->commandSetFeatureEnabled1 & 0x400) ) { TI_DBG3(("satSetDevInfo: support 48 bit addressing\n")); satDevData->sat48BitSupport = agTRUE; } else { TI_DBG3(("satSetDevInfo: NO 48 bit addressing\n")); satDevData->sat48BitSupport = agFALSE; } /* Support SMART Self Test, word84 bit 1 */ if (SATAIdData->commandSetFeatureSupportedExt & 0x02) { TI_DBG3(("satSetDevInfo: SMART self-test supported \n")); satDevData->satSMARTSelfTest = agTRUE; } else { TI_DBG3(("satSetDevInfo: no SMART self-test suppored\n")); satDevData->satSMARTSelfTest = agFALSE; } /* Support SMART feature set, word82 bit 0 */ if (SATAIdData->commandSetSupported & 0x01) { TI_DBG3(("satSetDevInfo: SMART feature set supported \n")); satDevData->satSMARTFeatureSet = agTRUE; } else { TI_DBG3(("satSetDevInfo: no SMART feature set suppored\n")); satDevData->satSMARTFeatureSet = agFALSE; } /* Support SMART enabled, word85 bit 0 */ if (SATAIdData->commandSetFeatureEnabled & 0x01) { TI_DBG3(("satSetDevInfo: SMART enabled \n")); satDevData->satSMARTEnabled = agTRUE; } else { TI_DBG3(("satSetDevInfo: no SMART enabled\n")); satDevData->satSMARTEnabled = agFALSE; } satDevData->satVerifyState = 0; /* Removable Media feature set support, word82 bit 2 */ if (SATAIdData->commandSetSupported & 0x4) { TI_DBG3(("satSetDevInfo: Removable Media supported \n")); satDevData->satRemovableMedia = agTRUE; } else { TI_DBG3(("satSetDevInfo: no Removable Media suppored\n")); satDevData->satRemovableMedia = agFALSE; } /* Removable Media feature set enabled, word 85, bit 2 */ if (SATAIdData->commandSetFeatureEnabled & 0x4) { TI_DBG3(("satSetDevInfo: Removable Media enabled\n")); satDevData->satRemovableMediaEnabled = agTRUE; } else { TI_DBG3(("satSetDevInfo: no Removable Media enabled\n")); satDevData->satRemovableMediaEnabled = agFALSE; } /* DMA Support, word49 bit8 */ if (SATAIdData->dma_lba_iod_ios_stimer & 0x100) { TI_DBG3(("satSetDevInfo: DMA supported \n")); satDevData->satDMASupport = agTRUE; } else { TI_DBG3(("satSetDevInfo: no DMA suppored\n")); satDevData->satDMASupport = agFALSE; } /* DMA Enabled, word88 bit0-6, bit8-14*/ /* 0x7F7F = 0111 1111 0111 1111*/ if (SATAIdData->ultraDMAModes & 0x7F7F) { TI_DBG3(("satSetDevInfo: DMA enabled \n")); satDevData->satDMAEnabled = agTRUE; } else { TI_DBG3(("satSetDevInfo: no DMA enabled\n")); satDevData->satDMAEnabled = agFALSE; } /* setting MaxUserAddrSectors: max user addressable setctors word60 - 61, should be 0x 0F FF FF FF */ satDevData->satMaxUserAddrSectors = (SATAIdData->numOfUserAddressableSectorsHi << (8*2) ) + SATAIdData->numOfUserAddressableSectorsLo; TI_DBG3(("satSetDevInfo: MaxUserAddrSectors 0x%x decimal %d\n", satDevData->satMaxUserAddrSectors, satDevData->satMaxUserAddrSectors)); /* Support DMADIR, if Word 62 bit 8 is set */ if (SATAIdData->word62_74[0] & 0x8000) { TI_DBG3(("satSetDevInfo: DMADIR enabled\n")); satDevData->satDMADIRSupport = agTRUE; } else { TI_DBG3(("satSetDevInfo: DMADIR disabled\n")); satDevData->satDMADIRSupport = agFALSE; } /* write cache enabled for caching mode page SAT Table 67 p69, word85 bit5 */ if (SATAIdData->commandSetFeatureEnabled & 0x20) { TI_DBG3(("satSetDevInfo: write cache enabled\n")); satDevData->satWriteCacheEnabled = agTRUE; } else { TI_DBG3(("satSetDevInfo: no write cache enabled\n")); satDevData->satWriteCacheEnabled = agFALSE; } /* look ahead enabled for caching mode page SAT Table 67 p69, word85 bit6 */ if (SATAIdData->commandSetFeatureEnabled & 0x40) { TI_DBG3(("satSetDevInfo: look ahead enabled\n")); satDevData->satLookAheadEnabled = agTRUE; } else { TI_DBG3(("satSetDevInfo: no look ahead enabled\n")); satDevData->satLookAheadEnabled = agFALSE; } /* Support WWN, if Word 87 bit 8 is set */ if (SATAIdData->commandSetFeatureDefault & 0x100) { TI_DBG3(("satSetDevInfo: device supports WWN\n")); satDevData->satWWNSupport = agTRUE; } else { TI_DBG3(("satSetDevInfo: no WWN\n")); satDevData->satWWNSupport = agFALSE; } return; } /***************************************************************************** *! \brief satInquiryCB * * This routine is a callback function for satInquiry() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satInquiryCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* In the process of Inquiry Process SAT_IDENTIFY_DEVICE */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; #ifdef TD_DEBUG_ENABLE tdsaDeviceData_t *tdsaDeviceData; bit32 ataStatus = 0; bit32 ataError; agsaFisPioSetupHeader_t *satPIOSetupHeader = agNULL; #endif scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; tiScsiInitiatorRequest_t *tiScsiRequest; /* TD's tiScsiXchg */ tiScsiInitiatorRequest_t *tiOrgScsiRequest; /* OS's tiScsiXchg */ agsaSATAIdentifyData_t *pSATAIdData; bit8 *pInquiry; bit8 page = 0xFF; bit16 *tmpptr,tmpptr_tmp; bit32 x; bit32 lenReceived; bit32 lenNeeded = 0; TI_DBG6(("satInquiryCB: start\n")); TI_DBG6(("satInquiryCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; #ifdef TD_DEBUG_ENABLE tdsaDeviceData = (tdsaDeviceData_t *)satDevData->satSaDeviceData; #endif tiScsiRequest = satIOContext->tiScsiXchg; if (satIntIo == agNULL) { TI_DBG6(("satInquiryCB: External, OS generated\n")); pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG6(("satInquiryCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG1(("satInquiryCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG6(("satInquiryCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tiOrgScsiRequest = satOrgIOContext->tiScsiXchg; pInquiry = (bit8 *) tiOrgScsiRequest->sglVirtualAddr; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; TI_DBG3(("satInquiryCB: did %d\n", tdsaDeviceData->id)); if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satInquiryCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY) { TI_DBG1(("satInquiryCB: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n")); /* should NOT be retried */ ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailNoLogin, agNULL, satOrgIOContext->interruptContext ); } else { TI_DBG1(("satInquiryCB: NOT OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY\n")); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailNoLogin, agNULL, satOrgIOContext->interruptContext ); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus == OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_BREAK || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_BAD_DESTINATION || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_UNKNOWN_ERROR || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY ) { TI_DBG1(("satInquiryCB: OSSA_IO_OPEN_CNX_ERROR\n")); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailNoLogin, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if ( agIOStatus != OSSA_IO_SUCCESS || (agIOStatus == OSSA_IO_SUCCESS && agFirstDword != agNULL && agIOInfoLen != 0) ) { #ifdef TD_DEBUG_ENABLE // only agsaFisPioSetup_t is expected satPIOSetupHeader = (agsaFisPioSetupHeader_t *)&(agFirstDword->PioSetup); ataStatus = satPIOSetupHeader->status; // ATA Status register ataError = satPIOSetupHeader->error; // ATA Eror register #endif TI_DBG1(("satInquiryCB: ataStatus 0x%x ataError 0x%x\n", ataStatus, ataError)); /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* success */ /* Convert to host endian */ tmpptr = (bit16*)(tiScsiRequest->sglVirtualAddr); for (x=0; x < sizeof(agsaSATAIdentifyData_t)/sizeof(bit16); x++) { OSSA_READ_LE_16(AGROOT, &tmpptr_tmp, tmpptr, 0); *tmpptr = tmpptr_tmp; tmpptr++; /*Print tmpptr_tmp here for debugging purpose*/ } pSATAIdData = (agsaSATAIdentifyData_t *)(tiScsiRequest->sglVirtualAddr); TI_DBG5(("satInquiryCB: OS satOrgIOContext %p \n", satOrgIOContext)); TI_DBG5(("satInquiryCB: TD satIOContext %p \n", satIOContext)); TI_DBG5(("satInquiryCB: OS tiScsiXchg %p \n", satOrgIOContext->tiScsiXchg)); TI_DBG5(("satInquiryCB: TD tiScsiXchg %p \n", satIOContext->tiScsiXchg)); /* copy ID Dev data to satDevData */ satDevData->satIdentifyData = *pSATAIdData; satDevData->IDDeviceValid = agTRUE; #ifdef TD_INTERNAL_DEBUG tdhexdump("satInquiryCB ID Dev data",(bit8 *)pSATAIdData, sizeof(agsaSATAIdentifyData_t)); tdhexdump("satInquiryCB Device ID Dev data",(bit8 *)&satDevData->satIdentifyData, sizeof(agsaSATAIdentifyData_t)); #endif // tdhexdump("satInquiryCB Device ID Dev data",(bit8 *)&satDevData->satIdentifyData, sizeof(agsaSATAIdentifyData_t)); /* set satDevData fields from IndentifyData */ satSetDevInfo(satDevData,pSATAIdData); lenReceived = ((scsiCmnd->cdb[3]) << 8) + scsiCmnd->cdb[4]; /* SPC-4, spec 6.4 p 141 */ /* EVPD bit == 0 */ if (!(scsiCmnd->cdb[1] & SCSI_EVPD_MASK)) { /* Returns the standard INQUIRY data */ lenNeeded = STANDARD_INQUIRY_SIZE; satInquiryStandard(pInquiry, pSATAIdData, scsiCmnd); //tdhexdump("satInquiryCB ***standard***", (bit8 *)pInquiry, 36); } else { /* EVPD bit != 0 && PAGE CODE != 0 */ /* returns the pages of vital product data information */ /* we must support page 00h, 83h and 89h */ page = scsiCmnd->cdb[2]; if ((page != INQUIRY_SUPPORTED_VPD_PAGE) && (page != INQUIRY_DEVICE_IDENTIFICATION_VPD_PAGE) && (page != INQUIRY_ATA_INFORMATION_VPD_PAGE)) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); TI_DBG1(("satInquiryCB: invalid PAGE CODE 0x%x\n", page)); return; } /* checking length */ switch (page) { case INQUIRY_SUPPORTED_VPD_PAGE: lenNeeded = SATA_PAGE0_INQUIRY_SIZE; /* 36 */ break; case INQUIRY_DEVICE_IDENTIFICATION_VPD_PAGE: if (satDevData->satWWNSupport) { lenNeeded = SATA_PAGE83_INQUIRY_WWN_SIZE; /* 16 */ } else { lenNeeded = SATA_PAGE83_INQUIRY_NO_WWN_SIZE; /* 76 */ } break; case INQUIRY_ATA_INFORMATION_VPD_PAGE: lenNeeded = SATA_PAGE89_INQUIRY_SIZE; /* 572 */ break; default: TI_DBG1(("satInquiryCB: wrong!!! invalid PAGE CODE 0x%x\n", page)); break; } /* * Fill in the Inquiry data depending on what Inquiry data we are returning. */ switch (page) { case INQUIRY_SUPPORTED_VPD_PAGE: satInquiryPage0(pInquiry, pSATAIdData); break; case INQUIRY_DEVICE_IDENTIFICATION_VPD_PAGE: satInquiryPage83(pInquiry, pSATAIdData, satDevData); break; case INQUIRY_ATA_INFORMATION_VPD_PAGE: satInquiryPage89(pInquiry, pSATAIdData, satDevData); break; default: TI_DBG1(("satInquiryCB: wrong!!! invalidinvalid PAGE CODE 0x%x\n", page)); break; } } /* else */ TI_DBG6(("satInquiryCB: calling ostiInitiatorIOCompleted\n")); if (lenReceived > lenNeeded) { TI_DBG6(("satInquiryCB reporting underrun lenNeeded=0x%x lenReceived=0x%x tiIORequest=%p\n", lenNeeded, lenReceived, tiOrgIORequest)); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOUnderRun, lenReceived - lenNeeded, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); TI_DBG5(("satInquiryCB: device %p pending IO %d\n", satDevData, satDevData->satPendingIO)); TI_DBG6(("satInquiryCB: end\n")); return; } /*****************************************************************************/ /*! \brief satInquiryIntCB. * * This function is part of INQUIRY SAT implementation. This is called when * ATA identify device data is available. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiIORequest: Pointer to TISA I/O request context for this I/O. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param tiScsiRequest: Pointer to TISA SCSI I/O request and SGL list. * \param satIOContext_t: Pointer to the SAT IO Context * * \return If command is started successfully * - \e tiSuccess: I/O request successfully initiated. * - \e tiBusy: No resources available, try again later. * - \e tiIONoDevice: Invalid device handle. * - \e tiError: Other errors. */ /*****************************************************************************/ void satInquiryIntCB( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; satDeviceData_t *satDevData; agsaSATAIdentifyData_t *pSATAIdData; bit8 *pInquiry; bit8 page = 0xFF; bit32 lenReceived; bit32 lenNeeded = 0; TI_DBG6(("satInquiryIntCB: start\n")); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pInquiry = (bit8 *) tiScsiRequest->sglVirtualAddr; satDevData = satIOContext->pSatDevData; pSATAIdData = &satDevData->satIdentifyData; lenReceived = ((scsiCmnd->cdb[3]) << 8) + scsiCmnd->cdb[4]; /* SPC-4, spec 6.4 p 141 */ /* EVPD bit == 0 */ if (!(scsiCmnd->cdb[1] & SCSI_EVPD_MASK)) { /* Returns the standard INQUIRY data */ lenNeeded = STANDARD_INQUIRY_SIZE; satInquiryStandard(pInquiry, pSATAIdData, scsiCmnd); //tdhexdump("satInquiryIntCB ***standard***", (bit8 *)pInquiry, 36); } else { /* EVPD bit != 0 && PAGE CODE != 0 */ /* returns the pages of vital product data information */ /* we must support page 00h, 83h and 89h */ page = scsiCmnd->cdb[2]; if ((page != INQUIRY_SUPPORTED_VPD_PAGE) && (page != INQUIRY_DEVICE_IDENTIFICATION_VPD_PAGE) && (page != INQUIRY_ATA_INFORMATION_VPD_PAGE) && (page != INQUIRY_UNIT_SERIAL_NUMBER_VPD_PAGE)) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satInquiryIntCB: invalid PAGE CODE 0x%x\n", page)); return; } /* checking length */ switch (page) { case INQUIRY_SUPPORTED_VPD_PAGE: lenNeeded = SATA_PAGE0_INQUIRY_SIZE; /* 36 */ break; case INQUIRY_DEVICE_IDENTIFICATION_VPD_PAGE: if (satDevData->satWWNSupport) { lenNeeded = SATA_PAGE83_INQUIRY_WWN_SIZE; /* 16 */ } else { lenNeeded = SATA_PAGE83_INQUIRY_NO_WWN_SIZE; /* 76 */ } break; case INQUIRY_ATA_INFORMATION_VPD_PAGE: lenNeeded = SATA_PAGE89_INQUIRY_SIZE; /* 572 */ break; case INQUIRY_UNIT_SERIAL_NUMBER_VPD_PAGE: lenNeeded = SATA_PAGE80_INQUIRY_SIZE; /* 24 */ break; default: TI_DBG1(("satInquiryIntCB: wrong!!! invalidinvalid PAGE CODE 0x%x\n", page)); break; } /* * Fill in the Inquiry data depending on what Inquiry data we are returning. */ switch (page) { case INQUIRY_SUPPORTED_VPD_PAGE: satInquiryPage0(pInquiry, pSATAIdData); break; case INQUIRY_DEVICE_IDENTIFICATION_VPD_PAGE: satInquiryPage83(pInquiry, pSATAIdData, satDevData); break; case INQUIRY_ATA_INFORMATION_VPD_PAGE: satInquiryPage89(pInquiry, pSATAIdData, satDevData); break; case INQUIRY_UNIT_SERIAL_NUMBER_VPD_PAGE: satInquiryPage80(pInquiry, pSATAIdData); break; default: TI_DBG1(("satInquiryIntCB: wrong!!! invalidinvalid PAGE CODE 0x%x\n", page)); break; } } /* else */ TI_DBG6(("satInquiryIntCB: calling ostiInitiatorIOCompleted\n")); if (lenReceived > lenNeeded) { TI_DBG6(("satInquiryIntCB reporting underrun lenNeeded=0x%x lenReceived=0x%x tiIORequest=%p\n", lenNeeded, lenReceived, tiIORequest)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, lenReceived - lenNeeded, agNULL, satIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } TI_DBG5(("satInquiryIntCB: device %p pending IO %d\n", satDevData, satDevData->satPendingIO)); TI_DBG6(("satInquiryIntCB: end\n")); return; } /***************************************************************************** *! \brief satVerify10CB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Verify(10) completion. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satVerify10CB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satVerify10CB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satVerify10CB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; } else { TI_DBG4(("satVerify10CB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satVerify10CB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satVerify10CB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satVerify10CB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if( agIOStatus != OSSA_IO_SUCCESS) { if ( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satVerify10CB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satVerify10CB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satVerify10CB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG1(("satVerify10CB: SAT_READ_VERIFY_SECTORS_EXT\n")); break; default: TI_DBG1(("satVerify10CB: error default case command 0x%x\n", hostToDevFis->h.command)); break; } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end error checking */ } /* process success from this point on */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satVerify10CB: SAT_WRITE_DMA_EXT success \n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); break; default: TI_DBG1(("satVerify10CB: success but error default case command 0x%x\n", hostToDevFis->h.command)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); break; } return; } /* similar to satVerify10CB */ void satNonChainedVerifyCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satNonChainedVerifyCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satNonChainedVerifyCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; } else { TI_DBG4(("satNonChainedVerifyCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satNonChainedVerifyCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satNonChainedVerifyCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satNonChainedVerifyCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if( agIOStatus != OSSA_IO_SUCCESS) { if ( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satNonChainedVerifyCB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satNonChainedVerifyCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satNonChainedVerifyCB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS: TI_DBG1(("satNonChainedVerifyCB: SAT_READ_VERIFY_SECTORS\n")); break; case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG1(("satNonChainedVerifyCB: SAT_READ_VERIFY_SECTORS_EXT\n")); break; default: TI_DBG1(("satNonChainedVerifyCB: error default case command 0x%x\n", hostToDevFis->h.command)); break; } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end error checking */ } /* process success from this point on */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS: /* fall through */ case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satNonChainedVerifyCB: SAT_WRITE_DMA_EXT success \n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); break; default: TI_DBG1(("satNonChainedVerifyCB: success but error default case command 0x%x\n", hostToDevFis->h.command)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); break; } return; } void satChainedVerifyCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; bit32 status = tiError; bit32 dataLength; TI_DBG5(("satChainedVerifyCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satChainedVerifyCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; } else { TI_DBG4(("satChainedVerifyCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satChainedVerifyCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satChainedVerifyCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satChainedVerifyCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if( agIOStatus != OSSA_IO_SUCCESS) { if ( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satChainedVerifyCB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satChainedVerifyCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satChainedVerifyCB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS: TI_DBG1(("satChainedVerifyCB: SAT_READ_VERIFY_SECTORS\n")); break; case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG1(("satChainedVerifyCB: SAT_READ_VERIFY_SECTORS_EXT\n")); break; default: TI_DBG1(("satChainedVerifyCB: error default case command 0x%x\n", hostToDevFis->h.command)); break; } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end error checking */ } /* process success from this point on */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS: /* fall through */ case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satChainedVerifyCB: SAT_WRITE_DMA_EXT success \n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* let's loop till TL */ /* lba = lba + tl loopnum--; if (loopnum == 0) done */ (satOrgIOContext->LoopNum)--; if (satOrgIOContext->LoopNum == 0) { /* done with write and verify */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } if (satOrgIOContext->superIOFlag) { dataLength = ((tiSuperScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } else { dataLength = ((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, dataLength, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedVerifyCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); status = satChainedVerify(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); TI_DBG1(("satChainedVerifyCB: calling satChainedVerify fails\n")); return; } break; default: TI_DBG1(("satChainedVerifyCB: success but error default case command 0x%x\n", hostToDevFis->h.command)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); break; } return; } /***************************************************************************** *! \brief satTestUnitReadyCB * * This routine is a callback function for satTestUnitReady() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satTestUnitReadyCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* In the process of TestUnitReady Process SAT_GET_MEDIA_STATUS Process SAT_CHECK_POWER_MODE */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 ataError; bit32 status; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG6(("satTestUnitReadyCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG5(("satTestUnitReadyCB: no internal satInternalIo_t satIntIoContext\n")); pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG5(("satTestUnitReadyCB: yes internal satInternalIo_t satIntIoContext\n")); /* orginal tiIOContext */ tiOrgIORequest = (tiIORequest_t *)satIOContext->satIntIoContext->satOrgTiIORequest; tdOrgIORequestBody = (tdIORequestBody_t *)tiOrgIORequest->tdData; satOrgIOContext = &(tdOrgIORequestBody->transport.SATA.satIOContext); pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satTestUnitReadyCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* HW checks an error for us and the results is agIOStatus */ if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ ataError = statDevToHostFisHeader->error; /* ATA Eror register */ if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satTestUnitReadyCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satTestUnitReadyCB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } switch (hostToDevFis->h.command) { case SAT_GET_MEDIA_STATUS: TI_DBG1(("satTestUnitReadyCB: SAT_GET_MEDIA_STATUS failed \n")); /* checking NM bit */ if (ataError & SCSI_NM_MASK) { satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_MEDIUM_NOT_PRESENT, satOrgIOContext); } else { satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE, satOrgIOContext); } ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; case SAT_CHECK_POWER_MODE: TI_DBG1(("satTestUnitReadyCB: SAT_CHECK_POWER_MODE failed \n")); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_DOES_NOT_RESPOND_TO_SELECTION, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; default: TI_DBG1(("satTestUnitReadyCB: default failed command %d\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } return; }/* end error */ /* ATA command completes sucessfully */ switch (hostToDevFis->h.command) { case SAT_GET_MEDIA_STATUS: TI_DBG5(("satTestUnitReadyCB: SAT_GET_MEDIA_STATUS success\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satTestUnitReadyCB: momory allocation fails\n")); return; } /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sends SAT_CHECK_POWER_MODE */ status = satTestUnitReady_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); if (status != tiSuccess) { /* sending SAT_CHECK_POWER_MODE fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satTestUnitReadyCB: calling satTestUnitReady_1 fails\n")); return; } break; case SAT_CHECK_POWER_MODE: TI_DBG5(("satTestUnitReadyCB: SAT_CHECK_POWER_MODE success\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* returns good status */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); break; default: TI_DBG1(("satTestUnitReadyCB: default success command %d\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_CAUSE_NOT_REPORTABLE, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } return; } /***************************************************************************** *! \brief satWriteSame10CB * * This routine is a callback function for satWriteSame10() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satWriteSame10CB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; tdIORequestBody_t *tdNewIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; bit32 sectorcount = 0; bit32 lba = 0, tl = 0; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; agsaFisSetDevBitsHeader_t *statSetDevBitFisHeader = agNULL; TI_DBG5(("satWriteSame10CB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satWriteSame10CB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; } else { TI_DBG4(("satWriteSame10CB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satWriteSame10CB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satWriteSame10CB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satWriteSame10CB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* FP, DMA and PIO write */ /* First, assumed to be Reg Device to Host FIS */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if (agIOStatus != OSSA_IO_SUCCESS) { if (statDevToHostFisHeader->fisType == SET_DEV_BITS_FIS) { statSetDevBitFisHeader = (agsaFisSetDevBitsHeader_t *)&(agFirstDword->D2H); /* Get ATA Status register */ ataStatus = (statSetDevBitFisHeader->statusHi_Lo & 0x70); /* bits 4,5,6 */ ataStatus = ataStatus | (statSetDevBitFisHeader->statusHi_Lo & 0x07); /* bits 0,1,2 */ /* ATA Eror register */ } } if( agIOStatus != OSSA_IO_SUCCESS) { /* checking IO status, FIS type and error status FIS type should be either REG_DEV_TO_HOST_FIS or SET_DEV_BITS_FIS */ if ( ((statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != SET_DEV_BITS_FIS)) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satWriteSame10CB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satWriteSame10CB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if (statDevToHostFisHeader->fisType != SET_DEV_BITS_FIS) { TI_DBG1(("satWriteSame10CB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satWriteSame10CB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ switch (hostToDevFis->h.command) { case SAT_WRITE_DMA_EXT: TI_DBG1(("satWriteSame10CB: SAT_WRITE_DMA_EXT\n")); break; case SAT_WRITE_SECTORS_EXT: TI_DBG1(("satWriteSame10CB: SAT_WRITE_SECTORS_EXT\n")); break; case SAT_WRITE_FPDMA_QUEUED: TI_DBG1(("satWriteSame10CB: SAT_WRITE_FPDMA_QUEUED\n")); break; default: TI_DBG1(("satWriteSame10CB: error default case command 0x%x\n", hostToDevFis->h.command)); break; } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* end error */ } /* process success from this point on */ /* note: inefficient implementation until a single block can be manipulated */ if (hostToDevFis->h.command == SAT_WRITE_DMA_EXT) { TI_DBG5(("satWriteSame10CB: SAT_WRITE_DMA_EXT success\n")); } else if (hostToDevFis->h.command == SAT_WRITE_SECTORS_EXT) { TI_DBG5(("satWriteSame10CB: SAT_WRITE_SECTORS_EXT success\n")); } else if (hostToDevFis->h.command == SAT_WRITE_FPDMA_QUEUED) { TI_DBG5(("satWriteSame10CB: SAT_WRITE_FPDMA_QUEUED success\n")); } else { TI_DBG1(("satWriteSame10CB: error case command 0x%x success\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* free */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* increment LBA by one, keeping the same sector count(1) sends another ATA command with the changed parameters */ tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); satDevData->satSectorDone++; tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); TI_DBG1(("satWriteSame10CB: sectordone %d\n", satDevData->satSectorDone)); lba = (scsiCmnd->cdb[2] << (8*3)) + (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; tl = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; TI_DBG5(("satWriteSame10CB: lba 0x%x tl 0x%x\n", lba, tl)); if (tl == 0) { /* (satDevData->satMaxUserAddrSectors - 1) - lba*/ sectorcount = (0x0FFFFFFF - 1) - lba; } else { sectorcount = tl; } if (sectorcount <= 0) { satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satWriteSame10CB: incorrect sectorcount 0x%x\n", sectorcount)); return; } if (sectorcount == satDevData->satSectorDone) { /* done with writesame */ TI_DBG1(("satWriteSame10CB: return writesame done\n")); satDevData->satSectorDone = 0; ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } else { /* sends another ATA command */ if (hostToDevFis->h.command == SAT_WRITE_DMA_EXT) { TI_DBG1(("satWriteSame10CB: sends another SAT_WRITE_DMA_EXT\n")); } else if (hostToDevFis->h.command == SAT_WRITE_SECTORS_EXT) { TI_DBG1(("satWriteSame10CB: sends another SAT_WRITE_SECTORS_EXT\n")); } else if (hostToDevFis->h.command == SAT_WRITE_FPDMA_QUEUED) { TI_DBG1(("satWriteSame10CB: sends another SAT_WRITE_FPDMA_QUEUED\n")); } satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satWriteSame10CB: momory allocation fails\n")); return; } /* end memory allocation */ /* the one to be used */ tdNewIORequestBody = satNewIntIo->satIntRequestBody; satNewIOContext = &tdNewIORequestBody->transport.SATA.satIOContext; satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &tdNewIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev; satNewIOContext->pScsiCmnd = &satNewIntIo->satIntTiScsiXchg.scsiCmnd; /* saves scsi command for LBA and number of blocks */ osti_memcpy(satNewIOContext->pScsiCmnd, scsiCmnd, sizeof(tiIniScsiCmnd_t)); satNewIOContext->pSense = &tdNewIORequestBody->transport.SATA.sensePayload; satNewIOContext->pTiSenseData = &tdNewIORequestBody->transport.SATA.tiSenseData; satNewIOContext->pTiSenseData->senseData = satNewIOContext->pSense; satNewIOContext->tiRequestBody = satNewIntIo->satIntRequestBody; satNewIOContext->interruptContext = satNewIOContext->interruptContext; satNewIOContext->satIntIoContext = satNewIntIo; satNewIOContext->ptiDeviceHandle = satIOContext->ptiDeviceHandle; /* saves tiScsiXchg; only for writesame10() */ satNewIOContext->tiScsiXchg = satOrgIOContext->tiScsiXchg; if (hostToDevFis->h.command == SAT_WRITE_DMA_EXT) { status = satWriteSame10_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext, lba + satDevData->satSectorDone ); } else if (hostToDevFis->h.command == SAT_WRITE_SECTORS_EXT) { status = satWriteSame10_2( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext, lba + satDevData->satSectorDone ); } else if (hostToDevFis->h.command == SAT_WRITE_FPDMA_QUEUED) { status = satWriteSame10_3( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext, lba + satDevData->satSectorDone ); } else { status = tiError; TI_DBG1(("satWriteSame10CB: sucess but error in command 0x%x\n", hostToDevFis->h.command)); } if (status != tiSuccess) { /* sending ATA command fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satWriteSame10CB:calling satWriteSame10_1 fails\n")); return; } /* end send fails */ } /* end sends another ATA command */ return; } /***************************************************************************** *! \brief satStartStopUnitCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Send Diagnostic completion. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satStartStopUnitCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* In the process of StartStopUnit Process FLUSH CACHE (EXT) Process STANDBY Process READ VERIFY SECTOR(S) EXT Process MEDIA EJECT */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satStartStopUnitCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satStartStopUnitCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; } else { TI_DBG4(("satStartStopUnitCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satStartStopUnitCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satStartStopUnitCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satStartStopUnitCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { TI_DBG1(("satStartStopUnitCB: immed bit 0\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } /* IMMED == 1 */ if ( scsiCmnd->cdb[1] & SCSI_IMMED_MASK) { TI_DBG1(("satStartStopUnitCB: immed bit 1\n")); satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } /* checking IO status, FIS type and error status */ if( agIOStatus != OSSA_IO_SUCCESS) { if( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satStartStopUnitCB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satStartStopUnitCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satStartStopUnitCB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } switch (hostToDevFis->h.command) { case SAT_FLUSH_CACHE: /* fall through */ case SAT_FLUSH_CACHE_EXT: TI_DBG1(("satStartStopUnitCB: SAT_FLUSH_CACHE(_EXT)\n")); /* check immed bit in scsi command */ /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } /* IMMED == 1 */ if ( scsiCmnd->cdb[1] & SCSI_IMMED_MASK) { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } break; case SAT_STANDBY: TI_DBG5(("satStartStopUnitCB: SAT_STANDBY\n")); /* check immed bit in scsi command */ /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } /* IMMED == 1 */ if ( scsiCmnd->cdb[1] & SCSI_IMMED_MASK) { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } break; case SAT_READ_VERIFY_SECTORS: /* fall through */ case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satStartStopUnitCB: SAT_READ_VERIFY_SECTORS(_EXT)\n")); /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } /* IMMED == 1 */ if ( scsiCmnd->cdb[1] & SCSI_IMMED_MASK) { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } break; case SAT_MEDIA_EJECT: TI_DBG5(("satStartStopUnitCB: SAT_MEDIA_EJECT\n")); /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_MEDIA_LOAD_OR_EJECT_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } /* IMMED == 1 */ if ( scsiCmnd->cdb[1] & SCSI_IMMED_MASK) { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_MEDIA_LOAD_OR_EJECT_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); } break; default: /* unspecified case, return no sense and no addition info */ TI_DBG5(("satStartStopUnitCB: default command %d\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } /* switch */ return; } /* error check */ } /* ATA command completes sucessfully */ switch (hostToDevFis->h.command) { case SAT_FLUSH_CACHE: /* fall through */ case SAT_FLUSH_CACHE_EXT: TI_DBG5(("satStartStopUnitCB: SAT_READ_VERIFY_SECTORS(_EXT) success case\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with SAT_FLUSH_CACHE(_EXT) */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* at this point, successful SAT_READ_VERIFY_SECTORS(_EXT) send SAT_SATNDBY */ satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); } else /* IMMED == 1 */ { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); } ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satStartStopUnitCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sending SAT_STANDBY */ status = satStartStopUnit_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); if (status != tiSuccess) { /* sending SAT_CHECK_POWER_MODE fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); } else /* IMMED == 1 */ { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_COMMAND_SEQUENCE_ERROR, satOrgIOContext); } ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satStartStopUnitCB: calling satStartStopUnit_1 fails\n")); return; } break; case SAT_STANDBY: TI_DBG5(("satStartStopUnitCB: SAT_STANDBY success case\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with SAT_STANDBY */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* if immed == 0, return good status */ /* IMMED == 0 */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } satDevData->satStopState = agTRUE; break; case SAT_READ_VERIFY_SECTORS: /* fall through */ case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satStartStopUnitCB: SAT_READ_VERIFY_SECTORS(_EXT) success case\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with SAT_READ_VERIFY_SECTORS(_EXT) */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* if immed == 0, return good status */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } /* if immed == 0, return good status */ /* don't forget to check and set driver state; Active power state */ satDevData->satStopState = agFALSE; break; case SAT_MEDIA_EJECT: TI_DBG5(("satStartStopUnitCB: SAT_MEDIA_EJECT success case\n")); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with SAT_READ_VERIFY_SECTORS(_EXT) */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* if immed == 0, return good status */ if (!( scsiCmnd->cdb[1] & SCSI_IMMED_MASK)) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } break; default: TI_DBG1(("satStartStopUnitCB:success but error default case command 0x%x\n", hostToDevFis->h.command)); /* unspecified case, return no sense and no addition info */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } return; } /***************************************************************************** *! \brief satSendDiagnosticCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Send Diagnostic completion. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satSendDiagnosticCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* In the process of SendDiagnotic Process READ VERIFY SECTOR(S) EXT two time Process SMART ECECUTE OFF-LINE IMMEDIATE */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satSendDiagnosticCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satSendDiagnosticCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satSendDiagnosticCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satSendDiagnosticCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satSendDiagnosticCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satSendDiagnosticCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); satDevData->satVerifyState = 0; satDevData->satBGPendingDiag = agFALSE; if (hostToDevFis->d.lbaLow != 0x01 && hostToDevFis->d.lbaLow != 0x02) { /* no completion for background send diagnotic. It is done in satSendDiagnostic() */ ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } TI_DBG5(("satSendDiagnosticCB: fis command 0x%x\n", hostToDevFis->h.command)); if( agIOStatus != OSSA_IO_SUCCESS) { /* checking IO status, FIS type and error status */ satDevData->satVerifyState = 0; satDevData->satBGPendingDiag = agFALSE; if( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { if ( (hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) || (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS_EXT) ) { TI_DBG1(("satSendDiagnosticCB: FAILED, NOT IO_SUCCESS and SAT_READ_VERIFY_SECTORS(_EXT)\n")); } else { TI_DBG1(("satSendDiagnosticCB: FAILED, NOT IO_SUCCESS and SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE\n")); } } /* for debugging */ if( statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { if ( (hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) || (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS_EXT) ) { TI_DBG1(("satSendDiagnosticCB: FAILED, Wrong FIS type 0x%x and SAT_READ_VERIFY_SECTORS(_EXT)\n", statDevToHostFisHeader->fisType)); } else { TI_DBG1(("satSendDiagnosticCB: FAILED, Wrong FIS type 0x%x and SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE\n",statDevToHostFisHeader->fisType)); } } /* for debugging */ if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { if ( (hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) || (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS_EXT) ) { TI_DBG1(("satSendDiagnosticCB: FAILED, error status and SAT_READ_VERIFY_SECTORS(_EXT)\n")); } else { TI_DBG1(("satSendDiagnosticCB: FAILED, error status and SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE\n")); } } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if ( (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS) || (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS_EXT) ) { /* report using the original tiIOrequst */ /* failed during sending SAT_READ_VERIFY_SECTORS(_EXT) */ satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_LOGICAL_UNIT_FAILED_SELF_TEST, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else { /* report using the original tiIOrequst */ /* failed during sending SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE */ satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_LOGICAL_UNIT_FAILED_SELF_TEST, satOrgIOContext); if (hostToDevFis->d.lbaLow != 0x01 && hostToDevFis->d.lbaLow != 0x02) { /* no completion for background send diagnotic. It is done in satSendDiagnostic() */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } } } /* processing success case */ switch (hostToDevFis->h.command) { case SAT_READ_VERIFY_SECTORS: /* fall through */ case SAT_READ_VERIFY_SECTORS_EXT: TI_DBG5(("satSendDiagnosticCB: SAT_READ_VERIFY_SECTORS(_EXT) case\n")); tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); satDevData->satVerifyState++; tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); TI_DBG5(("satSendDiagnosticCB: satVerifyState %d\n",satDevData->satVerifyState)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with internally genereated AT_READ_VERIFY_SECTORS(_EXT) */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satDevData->satVerifyState == 3) { /* reset satVerifyState */ satDevData->satVerifyState = 0; /* return GOOD status */ TI_DBG5(("satSendDiagnosticCB: return GOOD status\n")); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } else { /* prepare SAT_READ_VERIFY_SECTORS(_EXT) */ satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* reset satVerifyState */ satDevData->satVerifyState = 0; /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* failed as a part of sending SAT_READ_VERIFY_SECTORS(_EXT) */ satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_LOGICAL_UNIT_FAILED_SELF_TEST, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satSendDiagnosticCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); if (satDevData->satVerifyState == 1) { /* sending SAT_CHECK_POWER_MODE */ status = satSendDiagnostic_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); } else { /* satDevData->satVerifyState == 2 */ status = satSendDiagnostic_2( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); } if (status != tiSuccess) { /* sending SAT_READ_VERIFY_SECTORS(_EXT) fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* failed during sending SAT_READ_VERIFY_SECTORS(_EXT) */ satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_LOGICAL_UNIT_FAILED_SELF_TEST, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); /* reset satVerifyState */ satDevData->satVerifyState = 0; TI_DBG1(("satSendDiagnosticCB: calling satSendDiagnostic_1 or _2 fails\n")); return; } } /* satDevData->satVerifyState == 1 or 2 */ break; case SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE: TI_DBG5(("satSendDiagnosticCB: SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE case\n")); satDevData->satBGPendingDiag = agFALSE; if (hostToDevFis->d.lbaLow == 0x01 || hostToDevFis->d.lbaLow == 0x02) { /* for background send diagnostic, no completion here. It is done already. */ satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with AT_SMART_EXEUTE_OFF_LINE_IMMEDIATE */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); TI_DBG5(("satSendDiagnosticCB: returning but no IOCompleted\n")); } else { TI_DBG5(("satSendDiagnosticCB: returning good status for senddiagnostic\n")); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with AT_SMART_EXEUTE_OFF_LINE_IMMEDIATE */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); } break; default: TI_DBG1(("satSendDiagnosticCB: success but error default case command 0x%x\n", hostToDevFis->h.command)); /* unspecified case, return no sense and no addition info */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } return; } /***************************************************************************** *! \brief satRequestSenseCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Request Sense completion. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ /* CB for internnaly generated SMART_RETURN_STATUS and SAT_CHECK_POWER_MODE in the process of RequestSense */ void satRequestSenseCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* ATA Vol 1, p299 SAT_SMART_RETURN_STATUS */ /* if threshold exceeds, return SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE else call satRequestSense_1 to send CHECK_POWER_MODE */ tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; agsaFisRegD2HData_t statDevToHostFisData; bit32 lenReceived = 0; bit32 dataLength; TI_DBG4(("satRequestSenseCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satRequestSenseCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; if (satOrgIOContext->superIOFlag) { pSense = (scsiRspSense_t *)(((tiSuperScsiInitiatorRequest_t *)satOrgIOContext->tiScsiXchg)->sglVirtualAddr);//satOrgIOContext->pSense; } else { pSense = (scsiRspSense_t *)(((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->sglVirtualAddr);//satOrgIOContext->pSense; } scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satRequestSenseCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satRequestSenseCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satRequestSenseCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; if (satOrgIOContext->superIOFlag) { pSense = (scsiRspSense_t *)(((tiSuperScsiInitiatorRequest_t *)satOrgIOContext->tiScsiXchg)->sglVirtualAddr);//satOrgIOContext->pSense; } else { pSense = (scsiRspSense_t *)(((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->sglVirtualAddr);//satOrgIOContext->pSense; } scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; TI_DBG4(("satRequestSenseCB: fis command 0x%x\n", hostToDevFis->h.command)); lenReceived = scsiCmnd->cdb[4]; TI_DBG1(("satRequestSenseCB: lenReceived in CDB %d 0x%x\n", lenReceived,lenReceived)); if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satRequestSenseCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* checking IO status, FIS type and error status */ if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ /* for debugging */ if( statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { if (hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) { TI_DBG1(("satRequestSenseCB: FAILED, Wrong FIS type 0x%x and SAT_SMART_RETURN_STATU\n", statDevToHostFisHeader->fisType)); } else { TI_DBG1(("satRequestSenseCB: FAILED, Wrong FIS type 0x%x and SAT_CHECK_POWER_MODE\n",statDevToHostFisHeader->fisType)); } } /* for debugging */ if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { if (hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) { TI_DBG1(("satRequestSenseCB: FAILED, error status and SAT_SMART_RETURN_STATU\n")); } else { TI_DBG1(("satRequestSenseCB: FAILED, error status and SAT_CHECK_POWER_MODE\n")); } } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) { /* report using the original tiIOrequst */ /* failed during sending SMART RETURN STATUS */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } } else { /* report using the original tiIOrequst */ /* failed during sending SAT_CHECK_POWER_MODE */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_LOW_POWER_CONDITION_ON, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } saFrameReadBlock(agRoot, agParam, 0, &statDevToHostFisData, sizeof(agsaFisRegD2HData_t)); switch (hostToDevFis->h.command) { case SAT_SMART_RETURN_STATUS: TI_DBG4(("satRequestSenseCB: SAT_SMART_RETURN_STATUS case\n")); if (statDevToHostFisData.lbaMid == 0xF4 || statDevToHostFisData.lbaHigh == 0x2C) { /* threshold exceeds */ TI_DBG1(("satRequestSenseCB: threshold exceeds\n")); /* report using the original tiIOrequst */ /* failed during sending SMART RETURN STATUS */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with internally genereated SAT_SMART_RETURN_STATUS */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* at this point, successful SMART_RETURN_STATUS xmit SAT_CHECK_POWER_MODE */ if (satOrgIOContext->superIOFlag) { dataLength = ((tiSuperScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } else { dataLength = ((tiScsiInitiatorRequest_t *) satOrgIOContext->tiScsiXchg)->scsiCmnd.expDataLength; } satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, dataLength, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* failed as a part of sending SMART RETURN STATUS */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } TI_DBG1(("satRequestSenseCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sending SAT_CHECK_POWER_MODE */ status = satRequestSense_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); if (status != tiSuccess) { /* sending SAT_CHECK_POWER_MODE fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); /* failed during sending SAT_CHECK_POWER_MODE */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_LOW_POWER_CONDITION_ON, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } TI_DBG1(("satRequestSenseCB: calling satRequestSense_1 fails\n")); return; } break; case SAT_CHECK_POWER_MODE: TI_DBG4(("satRequestSenseCB: SAT_CHECK_POWER_MODE case\n")); /* check ATA STANDBY state */ if (statDevToHostFisData.sectorCount == 0x00) { /* in STANDBY */ TI_DBG1(("satRequestSenseCB: in standby\n")); /* report using the original tiIOrequst */ /* failed during sending SAT_CHECK_POWER_MODE */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_LOW_POWER_CONDITION_ON, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* done with internnaly generated SAT_CHECK_POWER_MODE */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satDevData->satFormatState == agTRUE) { TI_DBG1(("satRequestSenseCB: in format\n")); /* report using the original tiIOrequst */ satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_FORMAT_IN_PROGRESS, satOrgIOContext); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } return; } /* normal: returns good status for requestsense */ /* report using the original tiIOrequst */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); TI_DBG4(("satRequestSenseCB: returning good status for requestsense\n")); if (SENSE_DATA_LENGTH < lenReceived) { /* underrun */ TI_DBG6(("satRequestSenseCB reporting underrun lenNeeded=0x%x lenReceived=0x%x tiIORequest=%p\n", SENSE_DATA_LENGTH, lenReceived, tiOrgIORequest)); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SENSE_DATA_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); } break; default: TI_DBG1(("satRequestSenseCB: success but error default case command 0x%x\n", hostToDevFis->h.command)); /* pSense here is a part of satOrgIOContext */ pSense = satOrgIOContext->pTiSenseData->senseData; satOrgIOContext->pTiSenseData->senseLen = SENSE_DATA_LENGTH; /* unspecified case, return no sense and no addition info */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); break; } /* switch */ return; } /***************************************************************************** *! \brief satSynchronizeCache10n16CB * * This routine is a callback function for satSynchronizeCache10 and * satSynchronizeCache1016() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satSynchronizeCache10n16CB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satSynchronizeCache10n16CB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; /* SPC: Self-Test Result Log page */ if (satIntIo == agNULL) { TI_DBG4(("satSynchronizeCache10n16CB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satIOContext->pSense; scsiCmnd = satIOContext->pScsiCmnd; } else { TI_DBG4(("satSynchronizeCache10n16CB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satSynchronizeCache10n16CB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satSynchronizeCache10n16CB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satSynchronizeCache10n16CB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if( agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if( agIOStatus != OSSA_IO_SUCCESS) { if ( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satSynchronizeCache10n16CB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satSynchronizeCache10n16CB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satSynchronizeCache10n16CB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } switch (hostToDevFis->h.command) { case SAT_FLUSH_CACHE: TI_DBG1(("satSynchronizeCache10n16CB: SAT_FLUSH_CACHE failed\n")); /* checking IMMED bit */ if (scsiCmnd->cdb[1] & SCSI_FLUSH_CACHE_IMMED_MASK) { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); } else { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); } ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; break; case SAT_FLUSH_CACHE_EXT: TI_DBG1(("satSynchronizeCache10n16CB: SAT_FLUSH_CACHE_EXT failed\n")); /* checking IMMED bit */ if (scsiCmnd->cdb[1] & SCSI_FLUSH_CACHE_IMMED_MASK) { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); } else { satSetDeferredSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); } ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; break; default: TI_DBG1(("satSynchronizeCache10n16CB: error unknown command 0x%x\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; break; } return; } /* end of error checking */ } /* prcessing the success case */ satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); switch (hostToDevFis->h.command) { case SAT_FLUSH_CACHE: TI_DBG5(("satSynchronizeCache10n16CB: SAT_FLUSH_CACHE success\n")); /* checking IMMED bit */ if ( !(scsiCmnd->cdb[1] & SCSI_FLUSH_CACHE_IMMED_MASK)) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } break; case SAT_FLUSH_CACHE_EXT: TI_DBG5(("satSynchronizeCache10n16CB: SAT_FLUSH_CACHE_EXT success\n")); /* checking IMMED bit */ if ( !(scsiCmnd->cdb[1] & SCSI_FLUSH_CACHE_IMMED_MASK)) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } break; default: TI_DBG5(("satSynchronizeCache10n16CB: error unknown command 0x%x\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); return; break; } return; } /***************************************************************************** *! \brief satModeSelect6n10CB * * This routine is a callback function for satModeSelect6() and * satModeSelect10() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satModeSelect6n10CB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; tiScsiInitiatorRequest_t *tiScsiRequest; /* tiScsiXchg */ agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satModeSelect6n10CB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satModeSelect6n10CB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; tiScsiRequest = satOrgIOContext->tiScsiXchg; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satModeSelect6n10CB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satModeSelect6n10CB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satModeSelect6n10CB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; tiScsiRequest = satOrgIOContext->tiScsiXchg; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satModeSelect6n10CB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if (agIOStatus != OSSA_IO_SUCCESS) { if ( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satModeSelect6n10CB FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satModeSelect6n10CB FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satModeSelect6n10CB FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ if (hostToDevFis->h.command == SAT_SET_FEATURES) { if ((hostToDevFis->h.features == 0x82) || (hostToDevFis->h.features == 0x02)) { TI_DBG1(("satModeSelect6n10CB 1 SAT_SET_FEATURES failed, feature 0x%x\n", hostToDevFis->h.features)); } else if ((hostToDevFis->h.features == 0xAA) || (hostToDevFis->h.features == 0x55)) { TI_DBG1(("ssatModeSelect6n10CB 2 SAT_SET_FEATURES failed, feature 0x%x\n", hostToDevFis->h.features)); } else { TI_DBG1(("satModeSelect6n10CB error unknown command 0x%x feature 0x%x\n", hostToDevFis->h.command, hostToDevFis->h.features)); } } else if (hostToDevFis->h.command == SAT_SMART) { if ((hostToDevFis->h.features == SAT_SMART_ENABLE_OPERATIONS) || (hostToDevFis->h.features == SAT_SMART_DISABLE_OPERATIONS)) { TI_DBG1(("satModeSelect6n10CB SAT_SMART_ENABLE/DISABLE_OPERATIONS failed, feature 0x%x\n", hostToDevFis->h.features)); } else { TI_DBG1(("satModeSelect6n10CB error unknown command 0x%x feature 0x%x\n", hostToDevFis->h.command, hostToDevFis->h.features)); } } else { TI_DBG1(("satModeSelect6n10CB error default case command 0x%x\n", hostToDevFis->h.command)); } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* error checking */ } /* prcessing the success case */ if (hostToDevFis->h.command == SAT_SET_FEATURES) { if ((hostToDevFis->h.features == 0x82) || (hostToDevFis->h.features == 0x02)) { TI_DBG5(("satModeSelect6n10CB 1 SAT_SET_FEATURES success, feature 0x%x\n", hostToDevFis->h.features)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satModeSelect6n10CB: momory allocation fails\n")); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* sends either ATA SET FEATURES based on DRA bit */ status = satModeSelect6n10_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, tiScsiRequest, /* orginal from OS layer */ satNewIOContext ); if (status != tiSuccess) { /* sending ATA command fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satModeSelect6n10CB calling satModeSelect6_1 fails\n")); return; } /* end send fails */ return; } else if ((hostToDevFis->h.features == 0xAA) || (hostToDevFis->h.features == 0x55)) { TI_DBG5(("satModeSelect6n10CB 2 SAT_SET_FEATURES success, feature 0x%x\n", hostToDevFis->h.features)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* return stat_good */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } else { TI_DBG1(("satModeSelect6n10CB error unknown command success 0x%x feature 0x%x\n", hostToDevFis->h.command, hostToDevFis->h.features)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); return; } } else if (hostToDevFis->h.command == SAT_SMART_ENABLE_OPERATIONS || hostToDevFis->h.command == SAT_SMART_DISABLE_OPERATIONS ) { if ((hostToDevFis->h.features == 0xD8) || (hostToDevFis->h.features == 0xD9)) { TI_DBG5(("satModeSelect6n10CB SAT_SMART_ENABLE/DISABLE_OPERATIONS success, feature 0x%x\n", hostToDevFis->h.features)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* return stat_good */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } else { TI_DBG1(("satModeSelect6n10CB error unknown command failed 0x%x feature 0x%x\n", hostToDevFis->h.command, hostToDevFis->h.features)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); return; } } else { TI_DBG1(("satModeSelect6n10CB error default case command success 0x%x\n", hostToDevFis->h.command)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); return; } return; } /***************************************************************************** *! \brief satSMARTEnableCB * * This routine is a callback function for satSMARTEnable() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satSMARTEnableCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; tiIORequest_t *tiOrgIORequest; tiIniScsiCmnd_t *scsiCmnd; bit32 status; TI_DBG4(("satSMARTEnableCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; /*ttttttthe one */ if (satIntIo == agNULL) { TI_DBG4(("satSMARTEnableCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satSMARTEnableCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satSMARTEnableCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satSMARTEnableCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satSMARTEnableCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* checking IO status, FIS type and error status */ if (agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satSMARTEnableCB: not success status, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* process success case */ satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 512, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); return; } satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); status = satLogSense_1(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext); if (status != tiSuccess) { /* sending SAT_CHECK_POWER_MODE fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); return; } return; } /***************************************************************************** *! \brief satLogSenseCB * * This routine is a callback function for satLogSense() * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satLogSenseCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; tiScsiInitiatorRequest_t *tiScsiRequest; /* tiScsiXchg */ tiScsiInitiatorRequest_t *tiOrgScsiRequest; /* tiScsiXchg */ satReadLogExtSelfTest_t *virtAddr1; satSmartReadLogSelfTest_t *virtAddr2; bit8 *pLogPage; bit8 SelfTestExecutionStatus = 0; bit32 i = 0; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; agsaFisRegD2HData_t statDevToHostFisData; tiIniScsiCmnd_t *scsiCmnd; bit32 lenReceived = 0; TI_DBG5(("satLogSenseCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; if (satIOContext == agNULL) { TI_DBG1(("satLogSenseCB: satIOContext is NULL\n")); return; } satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satLogSenseCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; tiOrgScsiRequest = satOrgIOContext->tiScsiXchg; /* SCSI command response payload to OS layer */ pLogPage = (bit8 *) tiOrgScsiRequest->sglVirtualAddr; /* ATA command response payload */ tiScsiRequest = satOrgIOContext->tiScsiXchg; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satLogSenseCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satLogSenseCB: satOrgIOContext is NULL\n")); } else { TI_DBG4(("satLogSenseCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; tiOrgScsiRequest = satOrgIOContext->tiScsiXchg; /* SCSI command response payload to OS layer */ pLogPage = (bit8 *) tiOrgScsiRequest->sglVirtualAddr; /* ATA command response payload */ tiScsiRequest = (tiScsiInitiatorRequest_t *)&(satIntIo->satIntTiScsiXchg); scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satLogSenseCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* non-data and pio read -> device to host and pio setup fis are expected */ /* first, assumed to be Reg Device to Host FIS This is OK to just find fis type */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if( agIOStatus != OSSA_IO_SUCCESS) { if ( ((statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) && (statDevToHostFisHeader->fisType != PIO_SETUP_DEV_TO_HOST_FIS)) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satLogSenseCB: FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satLogSenseCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if (statDevToHostFisHeader->fisType != PIO_SETUP_DEV_TO_HOST_FIS) { TI_DBG1(("satLogSenseCB: FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satLogSenseCB: FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ if (hostToDevFis->h.command == SAT_READ_LOG_EXT) { TI_DBG1(("satLogSenseCB: SAT_READ_LOG_EXT failed\n")); } else if (hostToDevFis->h.command == SAT_SMART) { if (hostToDevFis->h.features == SAT_SMART_READ_LOG) { TI_DBG1(("satLogSenseCB: SAT_SMART_READ_LOG failed\n")); } else if (hostToDevFis->h.features == SAT_SMART_RETURN_STATUS) { TI_DBG1(("satLogSenseCB: SAT_SMART_RETURN_STATUS failed\n")); } else { TI_DBG1(("satLogSenseCB: error unknown command 0x%x feature 0x%x\n", hostToDevFis->h.command, hostToDevFis->h.features)); } } else { TI_DBG1(("satLogSenseCB: error default case command 0x%x\n", hostToDevFis->h.command)); } satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* error checking */ } /* prcessing the success case */ saFrameReadBlock(agRoot, agParam, 0, &statDevToHostFisData, sizeof(agsaFisRegD2HData_t)); lenReceived = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; TI_DBG5(("satLogSenseCB: lenReceived in CDB %d 0x%x\n", lenReceived,lenReceived)); if (hostToDevFis->h.command == SAT_READ_LOG_EXT) { TI_DBG5(("satLogSenseCB: SAT_READ_LOG_EXT success\n")); /* process log data and sends it to upper */ /* ATA: Extended Self-Test Log */ virtAddr1 = (satReadLogExtSelfTest_t *)(tiScsiRequest->sglVirtualAddr); /* ATA/ATAPI VOLII, p197, 287 self-test execution status (4 bits); ((virtAddr1->byte[5] & 0xF0) >> 4) */ SelfTestExecutionStatus = (bit8)(((virtAddr1->byte[5] & 0xF0) >> 4)); /* fills in the log page from ATA log page */ /* SPC-4, 7.2.10, Table 216, 217, p 259 - 260 */ pLogPage[0] = 0x10; /* page code */ pLogPage[1] = 0; pLogPage[2] = 0x01; /* 0x190, page length */ pLogPage[3] = 0x90; /* SPC-4, Table 217 */ pLogPage[4] = 0; /* Parameter Code */ pLogPage[5] = 0x01; /* Parameter Code, unspecfied but ... */ pLogPage[6] = 3; /* unspecified but ... */ pLogPage[7] = 0x10; /* Parameter Length */ pLogPage[8] = (bit8)(0 | ((virtAddr1->byte[5] & 0xF0) >> 4)); /* Self Test Code and Self-Test Result */ pLogPage[9] = 0; /* self test number */ pLogPage[10] = virtAddr1->byte[7]; /* time stamp, MSB */ pLogPage[11] = virtAddr1->byte[6]; /* time stamp, LSB */ pLogPage[12] = 0; /* address of first failure MSB*/ pLogPage[13] = 0; /* address of first failure */ pLogPage[14] = virtAddr1->byte[14]; /* address of first failure */ pLogPage[15] = virtAddr1->byte[13]; /* address of first failure */ pLogPage[16] = virtAddr1->byte[12]; /* address of first failure */ pLogPage[17] = virtAddr1->byte[11]; /* address of first failure */ pLogPage[18] = virtAddr1->byte[10]; /* address of first failure */ pLogPage[19] = virtAddr1->byte[9]; /* address of first failure LSB */ /* SAT rev8 Table75, p 76 */ switch (SelfTestExecutionStatus) { case 0: pLogPage[20] = 0 | SCSI_SNSKEY_NO_SENSE; pLogPage[21] = (SCSI_SNSCODE_NO_ADDITIONAL_INFO >> 8) & 0xFF; pLogPage[22] = SCSI_SNSCODE_NO_ADDITIONAL_INFO & 0xFF; break; case 1: pLogPage[20] = 0 | SCSI_SNSKEY_ABORTED_COMMAND; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x81; break; case 2: pLogPage[20] = 0 | SCSI_SNSKEY_ABORTED_COMMAND; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x82; break; case 3: pLogPage[20] = 0 | SCSI_SNSKEY_ABORTED_COMMAND; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x83; break; case 4: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x84; break; case 5: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x85; break; case 6: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x86; break; case 7: pLogPage[20] = 0 | SCSI_SNSKEY_MEDIUM_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x87; break; case 8: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x88; break; case 9: /* fall through */ case 10:/* fall through */ case 11:/* fall through */ case 12:/* fall through */ case 13:/* fall through */ case 14: pLogPage[20] = 0 | SCSI_SNSKEY_NO_SENSE; pLogPage[21] = (SCSI_SNSCODE_NO_ADDITIONAL_INFO >> 8) & 0xFF; pLogPage[22] = SCSI_SNSCODE_NO_ADDITIONAL_INFO & 0xFF; break; case 15: pLogPage[20] = 0 | SCSI_SNSKEY_NO_SENSE; pLogPage[21] = (SCSI_SNSCODE_NO_ADDITIONAL_INFO >> 8) & 0xFF; pLogPage[22] = SCSI_SNSCODE_NO_ADDITIONAL_INFO & 0xFF; break; default: TI_DBG1(("satLogSenseCB: Error, incorrect SelfTestExecutionStatus 0x%x\n", SelfTestExecutionStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } pLogPage[23] = 0; /* vendor specific */ /* the rest of Self-test results log */ /* 403 is from SPC-4, 7.2.10, Table 216, p 259*/ for (i=24;i<=403;i++) { pLogPage[i] = 0; /* vendor specific */ } if (SELFTEST_RESULTS_LOG_PAGE_LENGTH < lenReceived) { TI_DBG6(("satLogSenseCB: 1st underrun lenReceived %d len %d \n", lenReceived, SELFTEST_RESULTS_LOG_PAGE_LENGTH)); /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SELFTEST_RESULTS_LOG_PAGE_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else if (hostToDevFis->h.command == SAT_SMART_READ_LOG || hostToDevFis->h.command == SAT_SMART_RETURN_STATUS) { if (hostToDevFis->h.features == 0xd5) { TI_DBG5(("satLogSenseCB: SAT_SMART_READ_LOG success\n")); /* process log data and sends it to upper */ /* ATA: Extended Self-Test Log */ virtAddr2 = (satSmartReadLogSelfTest_t *)(tiScsiRequest->sglVirtualAddr); /* SPC-4, p197, 287 self-test execution status (4 bits); ((virtAddr2->byte[3] & 0xF0) >> 4) */ SelfTestExecutionStatus = (bit8)(((virtAddr2->byte[3] & 0xF0) >> 4)); /* fills in the log page from ATA log page */ /* SPC-4, 7.2.10, Table 216, 217, p 259 - 260 */ pLogPage[0] = 0x10; /* page code */ pLogPage[1] = 0; pLogPage[2] = 0x01; /* 0x190, page length */ pLogPage[3] = 0x90; /* 0x190, page length */ /* SPC-4, Table 217 */ pLogPage[4] = 0; /* Parameter Code */ pLogPage[5] = 0x01; /* Parameter Code unspecfied but ... */ pLogPage[6] = 3; /* unspecified but ... */ pLogPage[7] = 0x10; /* Parameter Length */ pLogPage[8] = (bit8)(0 | ((virtAddr2->byte[3] & 0xF0) >> 4)); /* Self Test Code and Self-Test Result */ pLogPage[9] = 0; /* self test number */ pLogPage[10] = virtAddr2->byte[5]; /* time stamp, MSB */ pLogPage[11] = virtAddr2->byte[4]; /* time stamp, LSB */ pLogPage[12] = 0; /* address of first failure MSB*/ pLogPage[13] = 0; /* address of first failure */ pLogPage[14] = 0; /* address of first failure */ pLogPage[15] = 0; /* address of first failure */ pLogPage[16] = virtAddr2->byte[10]; /* address of first failure */ pLogPage[17] = virtAddr2->byte[9]; /* address of first failure */ pLogPage[18] = virtAddr2->byte[8]; /* address of first failure */ pLogPage[19] = virtAddr2->byte[7]; /* address of first failure LSB */ /* SAT rev8 Table75, p 76 */ switch (SelfTestExecutionStatus) { case 0: pLogPage[20] = 0 | SCSI_SNSKEY_NO_SENSE; pLogPage[21] = (SCSI_SNSCODE_NO_ADDITIONAL_INFO >> 8) & 0xFF; pLogPage[22] = SCSI_SNSCODE_NO_ADDITIONAL_INFO & 0xFF; break; case 1: pLogPage[20] = 0 | SCSI_SNSKEY_ABORTED_COMMAND; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x81; break; case 2: pLogPage[20] = 0 | SCSI_SNSKEY_ABORTED_COMMAND; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x82; break; case 3: pLogPage[20] = 0 | SCSI_SNSKEY_ABORTED_COMMAND; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x83; break; case 4: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x84; break; case 5: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x85; break; case 6: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x86; break; case 7: pLogPage[20] = 0 | SCSI_SNSKEY_MEDIUM_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x87; break; case 8: pLogPage[20] = 0 | SCSI_SNSKEY_HARDWARE_ERROR; pLogPage[21] = (SCSI_SNSCODE_DIAGNOSTIC_FAILURE_ON_COMPONENT_NN >> 8) & 0xFF; pLogPage[22] = 0x88; break; case 9: /* fall through */ case 10:/* fall through */ case 11:/* fall through */ case 12:/* fall through */ case 13:/* fall through */ case 14: /* unspecified */ pLogPage[20] = 0 | SCSI_SNSKEY_NO_SENSE; pLogPage[21] = (SCSI_SNSCODE_NO_ADDITIONAL_INFO >> 8) & 0xFF; pLogPage[22] = SCSI_SNSCODE_NO_ADDITIONAL_INFO & 0xFF; break; case 15: pLogPage[20] = 0 | SCSI_SNSKEY_NO_SENSE; pLogPage[21] = (SCSI_SNSCODE_NO_ADDITIONAL_INFO >> 8) & 0xFF; pLogPage[22] = SCSI_SNSCODE_NO_ADDITIONAL_INFO & 0xFF; break; default: TI_DBG1(("satLogSenseCB: Error, incorrect SelfTestExecutionStatus 0x%x\n", SelfTestExecutionStatus)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } pLogPage[23] = 0; /* vendor specific */ /* the rest of Self-test results log */ /* 403 is from SPC-4, 7.2.10, Table 216, p 259*/ for (i=24;i<=403;i++) { pLogPage[i] = 0; /* vendor specific */ } if (SELFTEST_RESULTS_LOG_PAGE_LENGTH < lenReceived) { TI_DBG6(("satLogSenseCB: 2nd underrun lenReceived %d len %d \n", lenReceived, SELFTEST_RESULTS_LOG_PAGE_LENGTH)); /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - SELFTEST_RESULTS_LOG_PAGE_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else if (hostToDevFis->h.features == 0xda) { TI_DBG5(("satLogSenseCB: SAT_SMART_RETURN_STATUS success\n")); /* fills in the log page from ATA output */ /* SPC-4, 7.2.5, Table 209, 211, p 255 */ pLogPage[0] = 0x2F; /* page code unspecified */ pLogPage[1] = 0; /* reserved */ pLogPage[2] = 0; /* page length */ pLogPage[3] = 0x07; /* page length */ /* SPC-4, 7.2.5, Table 211, p 255 no vendor specific field */ pLogPage[4] = 0; /* Parameter Code */ pLogPage[5] = 0; /* Parameter Code unspecfied but to do: */ pLogPage[6] = 0; /* unspecified */ pLogPage[7] = 0x03; /* Parameter length, unspecified */ /* SAT rev8, 10.2.3.1 Table 72, p 73 */ if (statDevToHostFisData.lbaMid == 0x4F || statDevToHostFisData.lbaHigh == 0xC2) { pLogPage[8] = 0; /* Sense code */ pLogPage[9] = 0; /* Sense code qualifier */ } else if (statDevToHostFisData.lbaMid == 0xF4 || statDevToHostFisData.lbaHigh == 0x2C) { pLogPage[8] = 0x5D; /* Sense code */ pLogPage[9] = 0x10; /* Sense code qualifier */ } /* Assumption: No support for SCT */ pLogPage[10] = 0xFF; /* Most Recent Temperature Reading */ if (INFORMATION_EXCEPTIONS_LOG_PAGE_LENGTH < lenReceived) { TI_DBG6(("satLogSenseCB: 3rd underrun lenReceived %d len %d \n", lenReceived, INFORMATION_EXCEPTIONS_LOG_PAGE_LENGTH)); /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - INFORMATION_EXCEPTIONS_LOG_PAGE_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else { TI_DBG1(("satLogSenseCB: error unknown command success 0x%x feature 0x%x\n", hostToDevFis->h.command, hostToDevFis->h.features)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } } else { TI_DBG1(("satLogSenseCB: error unknown command success 0x%x\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } return; } /***************************************************************************** *! \brief satReadMediaSerialNumberCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Read Media Serial Number completion. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agSATAParm1: Additional info based on status. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satReadMediaSerialNumberCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; tiScsiInitiatorRequest_t *tiOrgScsiRequest; /* tiScsiXchg */ bit8 *pMediaSerialNumber; tiIniScsiCmnd_t *scsiCmnd; bit32 lenReceived = 0; TI_DBG4(("satReadMediaSerialNumberCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satReadMediaSerialNumberCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; tiOrgScsiRequest = satOrgIOContext->tiScsiXchg; /* SCSI command response payload to OS layer */ pMediaSerialNumber = (bit8 *) tiOrgScsiRequest->sglVirtualAddr; /* ATA command response payload */ scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satReadMediaSerialNumberCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satReadMediaSerialNumberCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satReadMediaSerialNumberCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; tiOrgScsiRequest = satOrgIOContext->tiScsiXchg; /* SCSI command response payload to OS layer */ pMediaSerialNumber = (bit8 *) tiOrgScsiRequest->sglVirtualAddr; /* ATA command response payload */ scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satReadMediaSerialNumberCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if( agIOStatus != OSSA_IO_SUCCESS) { /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_MEDIUM_NOT_PRESENT, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* process success case */ lenReceived = (scsiCmnd->cdb[6] << (8*3)) + (scsiCmnd->cdb[7] << (8*2)) + (scsiCmnd->cdb[8] << 8) + scsiCmnd->cdb[9]; TI_DBG5(("satReadMediaSerialNumberCB: lenReceived in CDB %d 0x%x\n", lenReceived,lenReceived)); if (hostToDevFis->h.command == SAT_READ_SECTORS || hostToDevFis->h.command == SAT_READ_SECTORS_EXT ) { pMediaSerialNumber[0] = 0; pMediaSerialNumber[1] = 0; pMediaSerialNumber[2] = 0; pMediaSerialNumber[3] = 4; pMediaSerialNumber[4] = 0; pMediaSerialNumber[5] = 0; pMediaSerialNumber[6] = 0; pMediaSerialNumber[7] = 0; if (ZERO_MEDIA_SERIAL_NUMBER_LENGTH < lenReceived) { TI_DBG1(("satReadMediaSerialNumberCB: 1st underrun lenReceived %d len %d \n", lenReceived, ZERO_MEDIA_SERIAL_NUMBER_LENGTH)); /* underrun */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == satIntIo->satOrgTiIORequest */ tiIOUnderRun, lenReceived - ZERO_MEDIA_SERIAL_NUMBER_LENGTH, agNULL, satOrgIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); } satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else { TI_DBG1(("satReadMediaSerialNumberCB: error unknown command success 0x%x\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } return; } /***************************************************************************** *! \brief satReadBufferCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Read Buffer. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agSATAParm1: Additional info based on status. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satReadBufferCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; TI_DBG4(("satReadBufferCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satReadBufferCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; /* SCSI command response payload to OS layer */ /* ATA command response payload */ } else { TI_DBG4(("satReadBufferCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satReadBufferCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satReadBufferCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; /* SCSI command response payload to OS layer */ /* ATA command response payload */ } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satReadBufferCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if( agIOStatus != OSSA_IO_SUCCESS) { /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_MEDIUM_NOT_PRESENT, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* process success case */ if (hostToDevFis->h.command == SAT_READ_BUFFER ) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else { TI_DBG1(("satReadBufferCB: error unknown command success 0x%x\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } return; } /***************************************************************************** *! \brief satWriteBufferCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Write Buffer. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agSATAParm1: Additional info based on status. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satWriteBufferCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; TI_DBG4(("satWriteBufferCB:agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satWriteBufferCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; /* SCSI command response payload to OS layer */ /* ATA command response payload */ } else { TI_DBG4(("satWriteBufferCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satWriteBufferCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG4(("satWriteBufferCB: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; pSense = satOrgIOContext->pSense; /* SCSI command response payload to OS layer */ /* ATA command response payload */ } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satWriteBufferCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if( agIOStatus != OSSA_IO_SUCCESS) { /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_MEDIUM_NOT_PRESENT, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* process success case */ if (hostToDevFis->h.command == SAT_WRITE_BUFFER ) { ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } else { TI_DBG1(("satWriteBufferCB: error unknown command success 0x%x\n", hostToDevFis->h.command)); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } return; } /***************************************************************************** *! \brief satReassignBlocksCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with Reassign Blocks. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agSATAParm1: Additional info based on status. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ void satReassignBlocksCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiIORequest_t *tiOrgIORequest; agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 status; tiScsiInitiatorRequest_t *tiScsiRequest; /* tiScsiXchg */ agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; TI_DBG5(("satReassignBlocksCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); /* internally generate tiIOContext */ tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; hostToDevFis = satIOContext->pFis; if (satIntIo == agNULL) { TI_DBG4(("satReassignBlocksCB: External satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; tiScsiRequest = satOrgIOContext->tiScsiXchg; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } else { TI_DBG4(("satReassignBlocksCB: Internal satInternalIo_t satIntIoContext\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG4(("satReassignBlocksCB: satOrgIOContext is NULL, Wrong\n")); return; } else { TI_DBG4(("satReassignBlocksCB: satOrgIOContext is NOT NULL, Wrong\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tiOrgIORequest = (tiIORequest_t *)tdOrgIORequestBody->tiIORequest; tiScsiRequest = satOrgIOContext->tiScsiXchg; pSense = satOrgIOContext->pSense; scsiCmnd = satOrgIOContext->pScsiCmnd; } tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satReassignBlocksCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); ostiInitiatorIOCompleted ( tiRoot, tiOrgIORequest, tiIOFailed, tiDetailOtherError, agNULL, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } if (agIOStatus != OSSA_IO_SUCCESS) { /* only agsaFisRegDeviceToHost_t is expected */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ } if (agIOStatus != OSSA_IO_SUCCESS) { if ( (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) || ((ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK)) ) { /* for debugging */ if( agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satReassignBlocksCB FAILED, NOT IO_SUCCESS\n")); } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("satReassignBlocksCB FAILED, Wrong FIS type 0x%x\n",statDevToHostFisHeader->fisType)); } else if ( (ataStatus & ERR_ATA_STATUS_MASK) || (ataStatus & DF_ATA_STATUS_MASK) ) { TI_DBG1(("satReassignBlocksCB FAILED, FAILED, error status\n")); } /* Process abort case */ if (agIOStatus == OSSA_IO_ABORTED) { satProcessAbort(tiRoot, tiOrgIORequest, satOrgIOContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* for debugging */ if (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS || hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS_EXT ) { TI_DBG1(("satReassignBlocksCB SAT_READ_VERIFY_SECTORS(_EXT) failed\n")); /* Verify failed; send Write with same LBA */ satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 512, /* writing 1 sector */ satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satReassignBlocksCB: momory allocation fails\n")); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* send Write with same LBA */ status = satReassignBlocks_2( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, satNewIOContext, satOrgIOContext->LBA ); if (status != tiSuccess) { /* sending ATA command fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satReassignBlocksCB calling fail 1\n")); return; } /* end send fails */ return; } else if (hostToDevFis->h.command == SAT_WRITE_DMA || hostToDevFis->h.command == SAT_WRITE_SECTORS || hostToDevFis->h.command == SAT_WRITE_DMA_EXT || hostToDevFis->h.command == SAT_WRITE_SECTORS_EXT || hostToDevFis->h.command == SAT_WRITE_FPDMA_QUEUED ) { TI_DBG1(("satReassignBlocksCB SAT_WRITE failed\n")); /* fall through */ } else { TI_DBG1(("satReassignBlocksCB error default case unexpected command 0x%x\n", hostToDevFis->h.command)); } satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return; } /* error checking */ } /* prcessing the success case */ if (hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS || hostToDevFis->h.command == SAT_READ_VERIFY_SECTORS_EXT || hostToDevFis->h.command == SAT_WRITE_DMA || hostToDevFis->h.command == SAT_WRITE_SECTORS || hostToDevFis->h.command == SAT_WRITE_DMA_EXT || hostToDevFis->h.command == SAT_WRITE_SECTORS_EXT || hostToDevFis->h.command == SAT_WRITE_FPDMA_QUEUED ) { /* next LBA; verify */ satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satOrgIOContext->ParmIndex >= satOrgIOContext->ParmLen) { TI_DBG5(("satReassignBlocksCB: GOOD status\n")); /* return stat_good */ ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satOrgIOContext->interruptContext ); return; } else { TI_DBG5(("satReassignBlocksCB: processing next LBA\n")); satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satReassignBlocksCB: momory allocation fails\n")); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, scsiCmnd, satOrgIOContext ); /* send Verify with the next LBA */ status = satReassignBlocks_1( tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, tiScsiRequest, /* orginal from OS layer */ satNewIOContext, satOrgIOContext ); if (status != tiSuccess) { /* sending ATA command fails */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); TI_DBG1(("satReassignBlocksCB calling satModeSelect6_1 fails\n")); return; } /* end send fails */ } /* else */ return; } else if (hostToDevFis->h.command == SAT_WRITE_DMA || hostToDevFis->h.command == SAT_WRITE_SECTORS || hostToDevFis->h.command == SAT_WRITE_DMA_EXT || hostToDevFis->h.command == SAT_WRITE_SECTORS_EXT || hostToDevFis->h.command == SAT_WRITE_FPDMA_QUEUED ) { /* next LBA; verify */ } else { TI_DBG1(("satReassignBlocksCB error unknown command success 0x%x \n", hostToDevFis->h.command)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satOrgIOContext); ostiInitiatorIOCompleted( tiRoot, tiOrgIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satOrgIOContext->pTiSenseData, satOrgIOContext->interruptContext ); return; } return; } /***************************************************************************** *! \brief satReadLogExtCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals READ LOG EXT completion. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agIOStatus: Status of completed I/O. * \param agFirstDword:Pointer to the four bytes of FIS. * \param agIOInfoLen: Length in bytes of overrun/underrun residual or FIS * length. * \param agParam: Additional info based on status. * \param ioContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ /* SATAII spec p42 */ void satReadLogExtCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdIORequestBody; satIOContext_t *satReadLogExtIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; tdsaDeviceData_t *tdsaDeviceData; agsaIORequest_t *agAbortIORequest; tdIORequestBody_t *tdAbortIORequestBody; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; TI_DBG1(("satReadLogExtCB: agIORequest=%p agIOStatus=0x%x agIOInfoLen %d\n", agIORequest, agIOStatus, agIOInfoLen)); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satReadLogExtIOContext = (satIOContext_t *) ioContext; satIntIo = satReadLogExtIOContext->satIntIoContext; satDevData = satReadLogExtIOContext->pSatDevData; tdsaDeviceData = (tdsaDeviceData_t *)satDevData->satSaDeviceData; TI_DBG1(("satReadLogExtCB: did %d\n", tdsaDeviceData->id)); satDecrementPendingIO(tiRoot, tdsaAllShared, satReadLogExtIOContext); tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; /* * If READ LOG EXT failed, we issue device reset. */ if ( agIOStatus != OSSA_IO_SUCCESS || (agIOStatus == OSSA_IO_SUCCESS && agFirstDword != agNULL && agIOInfoLen != 0) ) { TI_DBG1(("satReadLogExtCB: FAILED.\n")); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* Abort I/O after completion of device reset */ satDevData->satAbortAfterReset = agTRUE; #ifdef NOT_YET /* needs to investigate this case */ /* no report to OS layer */ satSubTM(tiRoot, satReadLogExtIOContext->ptiDeviceHandle, TD_INTERNAL_TM_RESET, agNULL, agNULL, agNULL, agFALSE); #endif return; } /*************************************************************************** * The following steps take place when READ LOG EXT successfully completed. ***************************************************************************/ /************************************************************************ * * 1. Issue abort to LL layer to all other pending I/Os for the same SATA * drive. * * 2. Free resource allocated for the internally generated READ LOG EXT. * * 3. At the completion of abort, in the context of ossaSATACompleted(), * return the I/O with error status to the OS-App Specific layer. * When all I/O aborts are completed, clear SATA device flag to * indicate ready to process new request. * ***********************************************************************/ /* * Issue abort to LL layer to all other pending I/Os for the same SATA drive */ /* replace the single IO abort with device abort */ TI_DBG1(("satReadLogExtCB: issuing saSATAAbort. Device Abort\n")); /* do not deregister this device */ tdsaDeviceData->OSAbortAll = agTRUE; /* allocating agIORequest for abort itself */ memAllocStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&tdAbortIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(tdIORequestBody_t), agTRUE ); if (memAllocStatus != tiSuccess) { /* let os process IO */ TI_DBG1(("satReadLogExtCB: ostiAllocMemory failed...\n")); return; } if (tdAbortIORequestBody == agNULL) { /* let os process IO */ TI_DBG1(("satReadLogExtCB: ostiAllocMemory returned NULL tdAbortIORequestBody\n")); return; } /* setup task management structure */ tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; tdAbortIORequestBody->tiDevHandle = (tiDeviceHandle_t *)&(tdsaDeviceData->tiDeviceHandle); /* initialize agIORequest */ agAbortIORequest = &(tdAbortIORequestBody->agIORequest); agAbortIORequest->osData = (void *) tdAbortIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ /* * Issue abort */ saSATAAbort( agRoot, agAbortIORequest, 0, tdsaDeviceData->agDevHandle, 1, agNULL, agNULL); /* * Free resource allocated for the internally generated READ LOG EXT. */ satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* * Sequence of recovery continue at some other context: * At the completion of abort, in the context of ossaSATACompleted(), * return the I/O with error status to the OS-App Specific layer. * When all I/O aborts are completed, clear SATA device flag to * indicate ready to process new request. */ satDevData->satDriveState = SAT_DEV_STATE_NORMAL; TI_DBG1(("satReadLogExtCB: end return\n")); return; } #ifndef FDS_SM /***************************************************************************** *! \brief ossaSATAEvent * * This routine is called to notify the OS Layer of an event associated with * SATA port or SATA device * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agPortContext Pointer to the port context of TD and Lower layer * \param agDevHandle: Pointer to a device handle * \param event: event type * * \return: none * *****************************************************************************/ osGLOBAL void ossaSATAEvent( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, agsaPortContext_t *agPortContext, agsaDevHandle_t *agDevHandle, bit32 event, bit32 agIOInfoLen, void *agParam ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; bit32 interruptContext = osData->IntContext; tdsaDeviceData_t *pDeviceData; satDeviceData_t *pSatDevData; satInternalIo_t *satIntIo = agNULL; bit32 status; satIOContext_t *satIOContext2; tdIORequestBody_t *tdIORequestBody; tiDeviceHandle_t *tiDeviceHandle; tiIORequest_t tiIORequestTMP; agsaDifDetails_t agDifDetails; bit8 framePayload[256]; bit16 frameOffset = 0; bit16 frameLen = 0; /* new */ tdsaDeviceData_t *tdsaDeviceData = agNULL; satIOContext_t *satIOContext; tdsaPortContext_t *onePortContext; if (event == OSSA_IO_XFER_ERROR_ABORTED_NCQ_MODE) { /************************************************************************** * * !!!! See Section 13.5.2.4 of SATA 2.5 specs. !!!! * !!!! If the NCQ error ends up here, it means that the device sent !!!! * !!!! Register Device To Host FIS (which does not have SActive !!!! * !!!! register) instead of Set Device Bit FIS (which has SActive !!!! * !!!! register). The routine osSatIOCompleted() deals with the case !!!! * !!!! where Set Device Bit FIS was sent by the device. !!!! * * For NCQ we need to issue READ LOG EXT command with log page 10h * to get the error and to allow other I/Os to continue. * * Here is the basic flow or sequence of error recovery, this sequence is * similar to the one described in SATA 2.5: * * 1. Set SATA device flag to indicate error condition and returning busy * for all new request. * * 2. Prepare READ LOG EXT page 10h command. Set flag to indicate that * the failed I/O has NOT been returned to the OS Layer. Send command. * * 3. When the device receives READ LOG EXT page 10h request all other * pending I/O are implicitly aborted. No completion (aborted) status * will be sent to the host for these aborted commands. * * 4. SATL receives the completion for READ LOG EXT command in * satReadLogExtCB(). Steps 5,6,7,8 below are the step 1,2,3,4 in * satReadLogExtCB(). * * 5. Check flag that indicates whether the failed I/O has been returned * to the OS Layer. If not, search the I/O context in device data * looking for a matched tag. Then return the completion of the failed * NCQ command with the appopriate/trasnlated SCSI status. * * 6. Issue abort to LL layer to all other pending I/Os for the same SATA * drive. * * 7. Free resource allocated for the internally generated READ LOG EXT. * * 8. At the completion of abort, in the context of ossaSATACompleted(), * return the I/O with error status to the OS-App Specific layer. * When all I/O aborts are completed, clear SATA device flag to * indicate ready to process new request. * *************************************************************************/ pDeviceData = (tdsaDeviceData_t *) agDevHandle->osData; pSatDevData = &pDeviceData->satDevData; tiDeviceHandle = &((tdsaDeviceData_t *)(pSatDevData->satSaDeviceData))->tiDeviceHandle; TI_DBG1(("ossaSATAEvent: did %d\n", pDeviceData->id)); if (pSatDevData->satDriveState == SAT_DEV_STATE_NORMAL) { TI_DBG1(("ossaSATAEvent: NCQ ERROR agDevHandle=%p.\n", agDevHandle )); /* Set flag to indicate we are in recovery */ pSatDevData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; /* * Allocate resource for READ LOG EXIT page 10h */ satIntIo = satAllocIntIoResource( tiRoot, &(tiIORequestTMP), /* anything but NULL */ pSatDevData, sizeof (satReadLogExtPage10h_t), satIntIo); /* * If we cannot allocate resource to do the normal NCQ recovery, we * will do SATA device reset. */ if (satIntIo == agNULL) { /* Abort I/O after completion of device reset */ pSatDevData->satAbortAfterReset = agTRUE; TI_DBG1(("ossaSATAEvent: can't send RLE due to resource lack\n")); #ifdef NOT_YET /* needs to investigate this case */ /* no report to OS layer */ satSubTM(tiRoot, tiDeviceHandle, TD_INTERNAL_TM_RESET, agNULL, agNULL, agNULL, agFALSE); #endif return; } /* * Clear flag to indicate that the failed I/O has NOT been returned to the * OS-App specific Layer. */ satIntIo->satIntFlag = 0; /* compare to satPrepareNewIO() */ /* Send READ LOG EXIT page 10h command */ /* * Need to initialize all the fields within satIOContext except * reqType and satCompleteCB which will be set depending on cmd. */ tdIORequestBody = (tdIORequestBody_t *)satIntIo->satIntRequestBody; satIOContext2 = &(tdIORequestBody->transport.SATA.satIOContext); satIOContext2->pSatDevData = pSatDevData; satIOContext2->pFis = &(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext2->pScsiCmnd = &(satIntIo->satIntTiScsiXchg.scsiCmnd); satIOContext2->pSense = &(tdIORequestBody->transport.SATA.sensePayload); satIOContext2->pTiSenseData = &(tdIORequestBody->transport.SATA.tiSenseData); satIOContext2->pTiSenseData->senseData = satIOContext2->pSense; satIOContext2->tiRequestBody = satIntIo->satIntRequestBody; satIOContext2->interruptContext = interruptContext; satIOContext2->satIntIoContext = satIntIo; satIOContext2->ptiDeviceHandle = tiDeviceHandle; satIOContext2->satOrgIOContext = agNULL; satIOContext2->tiScsiXchg = agNULL; status = satSendReadLogExt( tiRoot, &satIntIo->satIntTiIORequest, tiDeviceHandle, &satIntIo->satIntTiScsiXchg, satIOContext2); if (status !=tiSuccess) { TI_DBG1(("ossaSATAEvent: can't send RLE due to LL api failure\n")); satFreeIntIoResource( tiRoot, pSatDevData, satIntIo); /* Abort I/O after completion of device reset */ pSatDevData->satAbortAfterReset = agTRUE; #ifdef NOT_YET /* needs to investigate this case */ /* no report to OS layer */ satSubTM(tiRoot, tiDeviceHandle, TD_INTERNAL_TM_RESET, agNULL, agNULL, agNULL, agFALSE); #endif return; } } else { TI_DBG1(("ossaSATAEvent: NCQ ERROR but recovery in progress\n")); } } else if (event == OSSA_IO_XFER_CMD_FRAME_ISSUED) { TI_DBG1(("ossaSATAEvent: OSSA_IO_XFER_CMD_FRAME_ISSUED\n")); } else if (event == OSSA_IO_XFER_PIO_SETUP_ERROR) { TI_DBG1(("ossaSATAEvent: OSSA_IO_XFER_PIO_SETUP_ERROR\n")); } else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED) { TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_RETRY_BACKOFF_THRESHOLD_REACHED\n")); } else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO) { TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_TMO\n")); } else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST) { TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_NO_DEST\n")); } else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE) { TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_OPEN_COLLIDE\n")); } else if (event == OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED) { TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS_PATHWAY_BLOCKED\n")); } else if (event == OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH) { TI_DBG1(("ossaSATAEvent: OSSA_IO_XFR_ERROR_DEK_KEY_TAG_MISMATCH\n")); } else if (event == OSSA_IO_XFR_ERROR_DIF_MISMATCH || event == OSSA_IO_XFR_ERROR_DIF_APPLICATION_TAG_MISMATCH || event == OSSA_IO_XFR_ERROR_DIF_REFERENCE_TAG_MISMATCH || event == OSSA_IO_XFR_ERROR_DIF_CRC_MISMATCH) { TI_DBG1(("ossaSSPEvent: DIF related, event 0x%x\n", event)); /* process DIF detail information */ TI_DBG2(("ossaSSPEvent: agIOInfoLen %d\n", agIOInfoLen)); if (agParam == agNULL) { TI_DBG2(("ossaSSPEvent: agParam is NULL!!!\n")); return; } if (agIOInfoLen < sizeof(agsaDifDetails_t)) { TI_DBG2(("ossaSSPEvent: wrong agIOInfoLen!!! agIOInfoLen %d sizeof(agsaDifDetails_t) %d\n", agIOInfoLen, sizeof(agsaDifDetails_t))); return; } /* reads agsaDifDetails_t */ saFrameReadBlock(agRoot, agParam, 0, &agDifDetails, sizeof(agsaDifDetails_t)); frameOffset = (agDifDetails.ErrBoffsetEDataLen & 0xFFFF); frameLen = (agDifDetails.ErrBoffsetEDataLen & 0xFFFF0000) >> 16; TI_DBG2(("ossaSSPEvent: UpperLBA 0x%08x LowerLBA 0x%08x\n", agDifDetails.UpperLBA, agDifDetails.LowerLBA)); TI_DBG2(("ossaSSPEvent: SASAddrHI 0x%08x SASAddrLO 0x%08x\n", TD_GET_SAS_ADDRESSHI(agDifDetails.sasAddressHi), TD_GET_SAS_ADDRESSLO(agDifDetails.sasAddressLo))); TI_DBG2(("ossaSSPEvent: DIF error mask 0x%x Device ID 0x%x\n", (agDifDetails.DIFErrDevID) & 0xFF, (agDifDetails.DIFErrDevID & 0xFFFF0000) >> 16)); if (frameLen != 0 && frameLen <= 256) { saFrameReadBlock(agRoot, agParam, sizeof(agsaDifDetails_t), framePayload, frameLen); tdhexdump("ossaSSPEvent frame", framePayload, frameLen); } } else { TI_DBG1(("ossaSATAEvent: ERROR event %d agDevHandle=%p.\n", event, agDevHandle )); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); pSatDevData = satIOContext->pSatDevData; tdsaDeviceData = (tdsaDeviceData_t *)pSatDevData->satSaDeviceData; onePortContext = tdsaDeviceData->tdPortContext; TI_DBG1(("ossaSATAEvent: did %d\n", tdsaDeviceData->id)); /* send SMP_PHY_CONTROL_HARD_RESET */ if (event == OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY && tdsaAllShared->FCA) { if (pSatDevData->NumOfFCA <= 0) /* does SMP HARD RESET only upto one time */ { TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; sending HARD_RESET\n")); pSatDevData->NumOfFCA++; tdsaPhyControlSend(tiRoot, tdsaDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL); } else { /* given up after one time of SMP HARD RESET; */ TI_DBG1(("ossaSATAEvent: OSSA_IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY; NO!!! sending HARD_RESET\n")); if (tdsaDeviceData->registered == agTRUE && tdsaAllShared->ResetInDiscovery == 0) { /* 1. remove this device 2. device removal event */ tdsaAbortAll(tiRoot, agRoot, tdsaDeviceData); tdsaDeviceData->valid = agFALSE; tdsaDeviceData->valid2 = agFALSE; tdsaDeviceData->registered = agFALSE; ostiInitiatorEvent( tiRoot, onePortContext->tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceRemoval, agNULL ); } } } } } #endif /* FDS_SM */ /***************************************************************************** *! \brief itdsatErrorSATAEventHandle * * This routine is called to handle SATA error event * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agIORequest: Pointer to the LL I/O request context for this I/O. * \param agPortContext Pointer to the port context of TD and Lower layer * \param agDevHandle: Pointer to a device handle * \param event: event type * \param ioContext: Pointer to satIOContext_t * * \return: none * *****************************************************************************/ osGLOBAL void itdsatErrorSATAEventHandle( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, agsaPortContext_t *agPortContext, agsaDevHandle_t *agDevHandle, bit32 event, satIOContext_t *ioContext ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdIORequestBody_t *tdOrgIORequestBody; satIOContext_t *satIOContext; satIOContext_t *satOrgIOContext; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; bit32 interruptContext = osData->IntContext; TI_DBG1(("itdsatErrorSATAEventHandle: start\n")); satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; TI_DBG1(("itdsatErrorSATAEventHandle: event 0x%x\n", event)); if (satIntIo == agNULL) { TI_DBG1(("itdsatErrorSATAEventHandle: External, OS generated\n")); satOrgIOContext = satIOContext; tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (event == OSSA_IO_OVERFLOW) { TI_DBG1(("itdsatErrorSATAEventHandle: tiIOOverRun\n")); ostiInitiatorIOCompleted( tiRoot, tdOrgIORequestBody->tiIORequest, tiIOOverRun, 0, agNULL, interruptContext); } else { TI_DBG1(("itdsatErrorSATAEventHandle: else\n")); ostiInitiatorIOCompleted( tiRoot, tdOrgIORequestBody->tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, interruptContext); } } else { TI_DBG1(("itdsatErrorSATAEventHandle: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG1(("itdsatErrorSATAEventHandle: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG6(("itdsatErrorSATAEventHandle: satOrgIOContext is NOT NULL\n")); } tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } return; } osGLOBAL void ossaSATAAbortCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 flag, bit32 status) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdIORequestBody_t *tdAbortIORequestBody = agNULL; tdsaDeviceData_t *oneDeviceData = agNULL; tiDeviceHandle_t *tiDeviceHandle = agNULL; tiIORequest_t *taskTag = agNULL; TI_DBG1(("ossaSATAAbortCB: start\n")); tdAbortIORequestBody = (tdIORequestBody_t *)agIORequest->osData; if (tdAbortIORequestBody == agNULL) { TI_DBG1(("ossaSATAAbortCB: tdAbortIORequestBody is NULL warning!!!!\n")); return; } if (flag == 2) { /* abort per port */ TI_DBG1(("ossaSATAAbortCB: abort per port\n")); } else if (flag == 1) { TI_DBG1(("ossaSATAAbortCB: abort all\n")); tiDeviceHandle = (tiDeviceHandle_t *)tdAbortIORequestBody->tiDevHandle; if (tiDeviceHandle == agNULL) { TI_DBG1(("ossaSATAAbortCB: tiDeviceHandle is NULL warning!!!!\n")); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if (oneDeviceData == agNULL) { TI_DBG1(("ossaSATAAbortCB: oneDeviceData is NULL warning!!!!\n")); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } if (status == OSSA_IO_SUCCESS) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_SUCCESS\n")); /* clean up TD layer's IORequestBody */ if (oneDeviceData->OSAbortAll == agTRUE) { oneDeviceData->OSAbortAll = agFALSE; ostiInitiatorEvent( tiRoot, agNULL, tiDeviceHandle, tiIntrEventTypeLocalAbort, tiAbortOK, agNULL); } else { TI_DBG1(("ossaSATAAbortCB: calling saDeregisterDeviceHandle did %d\n", oneDeviceData->id)); saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData)); } /* callback to OS layer here ??? */ TI_DBG1(("ossaSATAAbortCB: did %d\n", oneDeviceData->id)); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else if (status == OSSA_IO_NOT_VALID) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_NOT_VALID\n")); /* Nothing is reproted to OS layer */ if (oneDeviceData->OSAbortAll == agTRUE) { oneDeviceData->OSAbortAll = agFALSE; ostiInitiatorEvent( tiRoot, agNULL, tiDeviceHandle, tiIntrEventTypeLocalAbort, tiAbortFailed, agNULL ); } else { TI_DBG1(("ossaSATAAbortCB: calling saDeregisterDeviceHandle did %d\n", oneDeviceData->id)); saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData)); } TI_DBG1(("ossaSATAAbortCB: did %d\n", oneDeviceData->id)); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else if (status == OSSA_IO_NO_DEVICE) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_NO_DEVICE\n")); /* Nothing is reproted to OS layer */ if (oneDeviceData->OSAbortAll == agTRUE) { oneDeviceData->OSAbortAll = agFALSE; ostiInitiatorEvent( tiRoot, agNULL, tiDeviceHandle, tiIntrEventTypeLocalAbort, tiAbortInProgress, agNULL ); } else { TI_DBG1(("ossaSATAAbortCB: calling saDeregisterDeviceHandle did %d\n", oneDeviceData->id)); saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData)); } TI_DBG1(("ossaSATAAbortCB: did %d\n", oneDeviceData->id)); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else if (status == OSSA_IO_ABORT_IN_PROGRESS) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n")); /* Nothing is reproted to OS layer */ if (oneDeviceData->OSAbortAll == agTRUE) { oneDeviceData->OSAbortAll = agFALSE; ostiInitiatorEvent( tiRoot, agNULL, tiDeviceHandle, tiIntrEventTypeLocalAbort, tiAbortInProgress, agNULL ); } else { TI_DBG1(("ossaSATAAbortCB: calling saDeregisterDeviceHandle did %d\n", oneDeviceData->id)); saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData)); } TI_DBG1(("ossaSATAAbortCB: did %d\n", oneDeviceData->id)); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else { TI_DBG1(("ossaSATAAbortCB: unspecified status 0x%x\n", status )); /* Nothing is reproted to OS layer */ if (oneDeviceData->OSAbortAll == agTRUE) { oneDeviceData->OSAbortAll = agFALSE; ostiInitiatorEvent( tiRoot, agNULL, tiDeviceHandle, tiIntrEventTypeLocalAbort, tiAbortInProgress, agNULL ); } else { TI_DBG1(("ossaSATAAbortCB: calling saDeregisterDeviceHandle did %d\n", oneDeviceData->id)); saDeregisterDeviceHandle(agRoot, agNULL, oneDeviceData->agDevHandle, tdsaRotateQnumber(tiRoot, oneDeviceData)); } TI_DBG1(("ossaSATAAbortCB: did %d\n", oneDeviceData->id)); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } } else if (flag == 0) { TI_DBG1(("ossaSATAAbortCB: abort one\n")); taskTag = tdAbortIORequestBody->tiIOToBeAbortedRequest; if (status == OSSA_IO_SUCCESS) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_SUCCESS\n")); ostiInitiatorEvent( tiRoot, agNULL, agNULL, tiIntrEventTypeLocalAbort, tiAbortOK, taskTag ); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else if (status == OSSA_IO_NOT_VALID) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_NOT_VALID\n")); ostiInitiatorEvent( tiRoot, agNULL, agNULL, tiIntrEventTypeLocalAbort, tiAbortFailed, taskTag ); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else if (status == OSSA_IO_NO_DEVICE) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_NO_DEVICE\n")); ostiInitiatorEvent( tiRoot, agNULL, agNULL, tiIntrEventTypeLocalAbort, tiAbortInProgress, taskTag ); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else if (status == OSSA_IO_ABORT_IN_PROGRESS) { TI_DBG1(("ossaSATAAbortCB: OSSA_IO_ABORT_IN_PROGRESS\n")); ostiInitiatorEvent( tiRoot, agNULL, agNULL, tiIntrEventTypeLocalAbort, tiAbortInProgress, taskTag ); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } else { TI_DBG1(("ossaSATAAbortCB: unspecified status 0x%x\n", status )); ostiInitiatorEvent( tiRoot, agNULL, agNULL, tiIntrEventTypeLocalAbort, tiAbortFailed, taskTag ); ostiFreeMemory( tiRoot, tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } } else { TI_DBG1(("ossaSATAAbortCB: wrong flag %d\n", flag)); } return; } /***************************************************************************** *! \brief ossaSATADeviceResetCB * * This routine is called to complete a SATA device reset request previously * issued to the LL Layer in saSATADeviceReset(). * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param agDevHandle: Pointer to a device handle * \param resetStatus: Reset status: * OSSA_SUCCESS: The reset operation completed successfully. * OSSA_FAILURE: The reset operation failed. * \param resetparm: Pointer to the Device-To-Host FIS received from the device. * * \return: none * *****************************************************************************/ osGLOBAL void ossaSATADeviceResetCB( agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, bit32 resetStatus, void *resetparm) { bit32 tiResetStatus; tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdsaDeviceData_t *pDeviceData; tiDeviceHandle_t *tiDeviceHandle; TI_DBG1(("ossaSATADeviceResetCB: agDevHandle=%p resetStatus=0x%x\n", agDevHandle, resetStatus )); pDeviceData = (tdsaDeviceData_t *) agDevHandle->osData; tiDeviceHandle = &(pDeviceData->tiDeviceHandle); if (resetStatus == OSSA_SUCCESS ) tiResetStatus = tiSuccess; else tiResetStatus = tiError; osSatResetCB( tiRoot, tiDeviceHandle, tiResetStatus, resetparm); } /*****************************************************************************/ /*! \brief satDecrementPendingIO * * This function decrements the number of pending IO's * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tdsaAllShared: Pointer to TD context. * \param satIOContext_t: Pointer to the SAT IO Context * * \return * None */ /*****************************************************************************/ GLOBAL void satDecrementPendingIO( tiRoot_t *tiRoot, tdsaContext_t *tdsaAllShared, satIOContext_t *satIOContext ) { satDeviceData_t *satDevData; TI_DBG4(("satDecrementPendingIO: start\n")); satDevData = satIOContext->pSatDevData; if ( (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) || (satIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) ) { tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); satDevData->satPendingNCQIO--; satIOContext->pSatDevData->satPendingIO--; TDLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); } else { tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); satDevData->satPendingNONNCQIO--; satIOContext->pSatDevData->satPendingIO--; TDLIST_DEQUEUE_THIS (&satIOContext->satIoContextLink); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); } return; } GLOBAL void satTranslateATAPIErrorsToSCSIErrors( bit8 bCommand, bit8 bATAStatus, bit8 bATAError, bit8 *pSenseKey, bit16 *pSenseCodeInfo ) { if (pSenseKey == agNULL || pSenseCodeInfo == agNULL) { TI_DBG0(("TranslateATAErrorsToSCSIErros: pSenseKey == agNULL || pSenseCodeInfo == agNULL\n")); return; } if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & NM_ATA_ERROR_MASK)) { *pSenseKey = SCSI_SNSKEY_NOT_READY; *pSenseCodeInfo = 0x3a00; } else if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & ABRT_ATA_ERROR_MASK)) { *pSenseKey = SCSI_SNSKEY_ABORTED_COMMAND; *pSenseCodeInfo = 0; } else if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & MCR_ATA_ERROR_MASK)) { *pSenseKey = SCSI_SNSKEY_UNIT_ATTENTION; *pSenseCodeInfo = 0x5a01; } else if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & IDNF_ATA_ERROR_MASK)) { *pSenseKey = SCSI_SNSKEY_MEDIUM_ERROR; *pSenseCodeInfo = 0x1401; } else if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & MC_ATA_ERROR_MASK)) { *pSenseKey = SCSI_SNSKEY_UNIT_ATTENTION; *pSenseCodeInfo = 0x2800; } else if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & UNC_ATA_ERROR_MASK)) { /*READ*/ *pSenseKey = SCSI_SNSKEY_MEDIUM_ERROR; *pSenseCodeInfo = 0x1100; /*add WRITE here */ } else if((bATAStatus & ERR_ATA_STATUS_MASK) && (bATAError & ICRC_ATA_ERROR_MASK)) { *pSenseKey = SCSI_SNSKEY_ABORTED_COMMAND; *pSenseCodeInfo = 0x4703; } else if((bATAStatus & DF_ATA_STATUS_MASK)) { *pSenseKey = SCSI_SNSKEY_HARDWARE_ERROR; *pSenseCodeInfo = 0x4400; } else { TI_DBG0(("unhandled ata error: bATAStatus = 0x%x, bATAError = 0x%x\n", bATAStatus, bATAError)); } } #endif /* #ifdef SATA_ENABLE */