/******************************************************************************* *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). * The routines in this file are independent from HW LL API. * */ /*****************************************************************************/ #include #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 satIOStart * * This routine is called to initiate a new SCSI request to SATL. * * \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: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiIONoDevice: Invalid device handle. * \e tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ GLOBAL bit32 satIOStart( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { bit32 retVal = tiSuccess; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; tiLUN_t *pLun; satInternalIo_t *pSatIntIo; #ifdef TD_DEBUG_ENABLE tdsaDeviceData_t *oneDeviceData; #endif pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; pLun = &scsiCmnd->lun; /* * Reject all other LUN other than LUN 0. */ if ( ((pLun->lun[0] | pLun->lun[1] | pLun->lun[2] | pLun->lun[3] | pLun->lun[4] | pLun->lun[5] | pLun->lun[6] | pLun->lun[7] ) != 0) && (scsiCmnd->cdb[0] != SCSIOPC_INQUIRY) ) { TI_DBG1(("satIOStart: *** REJECT *** LUN not zero, cdb[0]=0x%x tiIORequest=%p tiDeviceHandle=%p\n", scsiCmnd->cdb[0], tiIORequest, tiDeviceHandle)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_NOT_SUPPORTED, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); retVal = tiSuccess; goto ext; } TI_DBG6(("satIOStart: satPendingIO %d satNCQMaxIO %d\n",pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); /* this may happen after tiCOMReset until OS sends inquiry */ if (pSatDevData->IDDeviceValid == agFALSE && (scsiCmnd->cdb[0] != SCSIOPC_INQUIRY)) { #ifdef TD_DEBUG_ENABLE oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; #endif TI_DBG1(("satIOStart: invalid identify device data did %d\n", oneDeviceData->id)); retVal = tiIONoDevice; goto ext; } /* * Check if we need to return BUSY, i.e. recovery in progress */ if (pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY) { #ifdef TD_DEBUG_ENABLE oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; #endif TI_DBG1(("satIOStart: IN RECOVERY STATE cdb[0]=0x%x tiIORequest=%p tiDeviceHandle=%p\n", scsiCmnd->cdb[0], tiIORequest, tiDeviceHandle)); TI_DBG1(("satIOStart: IN RECOVERY STATE did %d\n", oneDeviceData->id)); TI_DBG1(("satIOStart: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG1(("satIOStart: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); retVal = tiError; goto ext; // return tiBusy; } if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE) { if (scsiCmnd->cdb[0] == SCSIOPC_REPORT_LUN) { return satReportLun(tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); } else { return satPacket(tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); } } else /* pSatDevData->satDeviceType != SATA_ATAPI_DEVICE */ { /* Parse CDB */ switch(scsiCmnd->cdb[0]) { case SCSIOPC_READ_6: retVal = satRead6( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_10: retVal = satRead10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_12: TI_DBG5(("satIOStart: SCSIOPC_READ_12\n")); retVal = satRead12( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_16: retVal = satRead16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_6: retVal = satWrite6( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_10: retVal = satWrite10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_12: TI_DBG5(("satIOStart: SCSIOPC_WRITE_12 \n")); retVal = satWrite12( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_16: TI_DBG5(("satIOStart: SCSIOPC_WRITE_16\n")); retVal = satWrite16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_VERIFY_10: retVal = satVerify10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_VERIFY_12: TI_DBG5(("satIOStart: SCSIOPC_VERIFY_12\n")); retVal = satVerify12( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_VERIFY_16: TI_DBG5(("satIOStart: SCSIOPC_VERIFY_16\n")); retVal = satVerify16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_TEST_UNIT_READY: retVal = satTestUnitReady( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_INQUIRY: retVal = satInquiry( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_REQUEST_SENSE: retVal = satRequestSense( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_MODE_SENSE_6: retVal = satModeSense6( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_MODE_SENSE_10: retVal = satModeSense10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_CAPACITY_10: retVal = satReadCapacity10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_CAPACITY_16: retVal = satReadCapacity16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_REPORT_LUN: retVal = satReportLun( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_FORMAT_UNIT: TI_DBG5(("satIOStart: SCSIOPC_FORMAT_UNIT\n")); retVal = satFormatUnit( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_SEND_DIAGNOSTIC: /* Table 28, p40 */ TI_DBG5(("satIOStart: SCSIOPC_SEND_DIAGNOSTIC\n")); retVal = satSendDiagnostic( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_START_STOP_UNIT: TI_DBG5(("satIOStart: SCSIOPC_START_STOP_UNIT\n")); retVal = satStartStopUnit( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_SAME_10: /* sector and LBA; SAT p64 case 3 accessing payload and very inefficient now */ TI_DBG5(("satIOStart: SCSIOPC_WRITE_SAME_10\n")); retVal = satWriteSame10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_SAME_16: /* no support due to transfer length(sector count) */ TI_DBG5(("satIOStart: SCSIOPC_WRITE_SAME_16\n")); retVal = satWriteSame16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_LOG_SENSE: /* SCT and log parameter(informational exceptions) */ TI_DBG5(("satIOStart: SCSIOPC_LOG_SENSE\n")); retVal = satLogSense( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_MODE_SELECT_6: /*mode layout and AlloLen check */ TI_DBG5(("satIOStart: SCSIOPC_MODE_SELECT_6\n")); retVal = satModeSelect6( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_MODE_SELECT_10: /* mode layout and AlloLen check and sharing CB with satModeSelect6*/ TI_DBG5(("satIOStart: SCSIOPC_MODE_SELECT_10\n")); retVal = satModeSelect10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_SYNCHRONIZE_CACHE_10: /* on error what to return, sharing CB with satSynchronizeCache16 */ TI_DBG5(("satIOStart: SCSIOPC_SYNCHRONIZE_CACHE_10\n")); retVal = satSynchronizeCache10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_SYNCHRONIZE_CACHE_16:/* on error what to return, sharing CB with satSynchronizeCache16 */ TI_DBG5(("satIOStart: SCSIOPC_SYNCHRONIZE_CACHE_16\n")); retVal = satSynchronizeCache16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_AND_VERIFY_10: /* single write and multiple writes */ TI_DBG5(("satIOStart: SCSIOPC_WRITE_AND_VERIFY_10\n")); retVal = satWriteAndVerify10( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_AND_VERIFY_12: TI_DBG5(("satIOStart: SCSIOPC_WRITE_AND_VERIFY_12\n")); retVal = satWriteAndVerify12( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_AND_VERIFY_16: TI_DBG5(("satIOStart: SCSIOPC_WRITE_AND_VERIFY_16\n")); retVal = satWriteAndVerify16( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_MEDIA_SERIAL_NUMBER: TI_DBG5(("satIOStart: SCSIOPC_READ_MEDIA_SERIAL_NUMBER\n")); retVal = satReadMediaSerialNumber( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_READ_BUFFER: TI_DBG5(("satIOStart: SCSIOPC_READ_BUFFER\n")); retVal = satReadBuffer( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_WRITE_BUFFER: TI_DBG5(("satIOStart: SCSIOPC_WRITE_BUFFER\n")); retVal = satWriteBuffer( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; case SCSIOPC_REASSIGN_BLOCKS: TI_DBG5(("satIOStart: SCSIOPC_REASSIGN_BLOCKS\n")); retVal = satReassignBlocks( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); break; default: /* Not implemented SCSI cmd, set up error response */ TI_DBG1(("satIOStart: unsupported SCSI cdb[0]=0x%x tiIORequest=%p tiDeviceHandle=%p\n", scsiCmnd->cdb[0], tiIORequest, tiDeviceHandle)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); retVal = tiSuccess; break; } /* end switch */ } if (retVal == tiBusy) { #ifdef TD_DEBUG_ENABLE oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; #endif TI_DBG1(("satIOStart: BUSY did %d\n", oneDeviceData->id)); TI_DBG3(("satIOStart: LL is busy or target queue is full\n")); TI_DBG3(("satIOStart: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); TI_DBG3(("satIOStart: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); pSatIntIo = satIOContext->satIntIoContext; /* interal structure free */ satFreeIntIoResource( tiRoot, pSatDevData, pSatIntIo); } ext: return retVal; } /*****************************************************************************/ /*! \brief Setup up the SCSI Sense response. * * This function is used to setup up the Sense Data payload for * CHECK CONDITION status. * * \param pSense: Pointer to the scsiRspSense_t sense data structure. * \param SnsKey: SCSI Sense Key. * \param SnsInfo: SCSI Sense Info. * \param SnsCode: SCSI Sense Code. * * \return: None */ /*****************************************************************************/ void satSetSensePayload( scsiRspSense_t *pSense, bit8 SnsKey, bit32 SnsInfo, bit16 SnsCode, satIOContext_t *satIOContext ) { /* for fixed format sense data, SPC-4, p37 */ bit32 i; bit32 senseLength; TI_DBG5(("satSetSensePayload: start\n")); senseLength = sizeof(scsiRspSense_t); /* zero out the data area */ for (i=0;i< senseLength;i++) { ((bit8*)pSense)[i] = 0; } /* * SCSI Sense Data part of response data */ pSense->snsRespCode = 0x70; /* 0xC0 == vendor specific */ /* 0x70 == standard current error */ pSense->senseKey = SnsKey; /* * Put sense info in scsi order format */ pSense->info[0] = (bit8)((SnsInfo >> 24) & 0xff); pSense->info[1] = (bit8)((SnsInfo >> 16) & 0xff); pSense->info[2] = (bit8)((SnsInfo >> 8) & 0xff); pSense->info[3] = (bit8)((SnsInfo) & 0xff); pSense->addSenseLen = 11; /* fixed size of sense data = 18 */ pSense->addSenseCode = (bit8)((SnsCode >> 8) & 0xFF); pSense->senseQual = (bit8)(SnsCode & 0xFF); /* * Set pointer in scsi status */ switch(SnsKey) { /* * set illegal request sense key specific error in cdb, no bit pointer */ case SCSI_SNSKEY_ILLEGAL_REQUEST: pSense->skeySpecific[0] = 0xC8; break; default: break; } /* setting sense data length */ if (satIOContext != agNULL) { satIOContext->pTiSenseData->senseLen = 18; } else { TI_DBG1(("satSetSensePayload: satIOContext is NULL\n")); } } /*****************************************************************************/ /*! \brief Setup up the SCSI Sense response. * * This function is used to setup up the Sense Data payload for * CHECK CONDITION status. * * \param pSense: Pointer to the scsiRspSense_t sense data structure. * \param SnsKey: SCSI Sense Key. * \param SnsInfo: SCSI Sense Info. * \param SnsCode: SCSI Sense Code. * * \return: None */ /*****************************************************************************/ void satSetDeferredSensePayload( scsiRspSense_t *pSense, bit8 SnsKey, bit32 SnsInfo, bit16 SnsCode, satIOContext_t *satIOContext ) { /* for fixed format sense data, SPC-4, p37 */ bit32 i; bit32 senseLength; senseLength = sizeof(scsiRspSense_t); /* zero out the data area */ for (i=0;i< senseLength;i++) { ((bit8*)pSense)[i] = 0; } /* * SCSI Sense Data part of response data */ pSense->snsRespCode = 0x71; /* 0xC0 == vendor specific */ /* 0x70 == standard current error */ pSense->senseKey = SnsKey; /* * Put sense info in scsi order format */ pSense->info[0] = (bit8)((SnsInfo >> 24) & 0xff); pSense->info[1] = (bit8)((SnsInfo >> 16) & 0xff); pSense->info[2] = (bit8)((SnsInfo >> 8) & 0xff); pSense->info[3] = (bit8)((SnsInfo) & 0xff); pSense->addSenseLen = 11; /* fixed size of sense data = 18 */ pSense->addSenseCode = (bit8)((SnsCode >> 8) & 0xFF); pSense->senseQual = (bit8)(SnsCode & 0xFF); /* * Set pointer in scsi status */ switch(SnsKey) { /* * set illegal request sense key specific error in cdb, no bit pointer */ case SCSI_SNSKEY_ILLEGAL_REQUEST: pSense->skeySpecific[0] = 0xC8; break; default: break; } /* setting sense data length */ if (satIOContext != agNULL) { satIOContext->pTiSenseData->senseLen = 18; } else { TI_DBG1(("satSetDeferredSensePayload: satIOContext is NULL\n")); } } /*****************************************************************************/ /*! \brief SAT implementation for ATAPI Packet Command. * * SAT implementation for ATAPI Packet and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satPacket( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; satDeviceData_t *pSatDevData; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG3(("satPacket: start, SCSI CDB is 0x%X %X %X %X %X %X %X %X %X %X %X %X\n", scsiCmnd->cdb[0],scsiCmnd->cdb[1],scsiCmnd->cdb[2],scsiCmnd->cdb[3], scsiCmnd->cdb[4],scsiCmnd->cdb[5],scsiCmnd->cdb[6],scsiCmnd->cdb[7], scsiCmnd->cdb[8],scsiCmnd->cdb[9],scsiCmnd->cdb[10],scsiCmnd->cdb[11])); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set 1*/ fis->h.command = SAT_PACKET; /* 0xA0 */ if (pSatDevData->satDMADIRSupport) /* DMADIR enabled*/ { fis->h.features = (tiScsiRequest->dataDirection == tiDirectionIn)? 0x04 : 0; /* 1 for D2H, 0 for H2D */ } else { fis->h.features = 0; /* FIS reserve */ } /* Byte count low and byte count high */ if ( scsiCmnd->expDataLength > 0xFFFF ) { fis->d.lbaMid = 0xFF; /* FIS LBA (7 :0 ) */ fis->d.lbaHigh = 0xFF; /* FIS LBA (15:8 ) */ } else { fis->d.lbaMid = (bit8)scsiCmnd->expDataLength; /* FIS LBA (7 :0 ) */ fis->d.lbaHigh = (bit8)(scsiCmnd->expDataLength>>8); /* FIS LBA (15:8 ) */ } fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.device = 0; /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; satIOContext->ATACmd = SAT_PACKET; if (tiScsiRequest->dataDirection == tiDirectionIn) { agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; } else { agRequestType = AGSA_SATA_PROTOCOL_H2D_PKT; } if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /*DMA transfer mode*/ fis->h.features |= 0x01; } else { /*PIO transfer mode*/ fis->h.features |= 0x0; } satIOContext->satCompleteCB = &satPacketCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satPacket: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for satSetFeatures. * * This function creates SetFeatures fis and sends the request to LL layer * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSetFeatures( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, bit8 bIsDMAMode ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; TI_DBG3(("satSetFeatures: start\n")); /* * Send the Set Features command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0x03; /* set transfer mode */ fis->d.lbaLow = 0; fis->d.lbaMid = 0; fis->d.lbaHigh = 0; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ if (bIsDMAMode) { fis->d.sectorCount = 0x45; /*satIOContext->satCompleteCB = &satSetFeaturesDMACB;*/ } else { fis->d.sectorCount = 0x0C; /*satIOContext->satCompleteCB = &satSetFeaturesPIOCB;*/ } satIOContext->satCompleteCB = &satSetFeaturesCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSetFeatures: return\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI REQUEST SENSE to ATAPI device. * * SAT implementation for SCSI REQUEST SENSE. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRequestSenseForATAPI( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; satDeviceData_t *pSatDevData; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; scsiCmnd->cdb[0] = SCSIOPC_REQUEST_SENSE; scsiCmnd->cdb[1] = 0; scsiCmnd->cdb[2] = 0; scsiCmnd->cdb[3] = 0; scsiCmnd->cdb[4] = SENSE_DATA_LENGTH; scsiCmnd->cdb[5] = 0; TI_DBG3(("satRequestSenseForATAPI: start, SCSI CDB is 0x%X %X %X %X %X %X %X %X %X %X %X %X\n", scsiCmnd->cdb[0],scsiCmnd->cdb[1],scsiCmnd->cdb[2],scsiCmnd->cdb[3], scsiCmnd->cdb[4],scsiCmnd->cdb[5],scsiCmnd->cdb[6],scsiCmnd->cdb[7], scsiCmnd->cdb[8],scsiCmnd->cdb[9],scsiCmnd->cdb[10],scsiCmnd->cdb[11])); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set 1*/ fis->h.command = SAT_PACKET; /* 0xA0 */ if (pSatDevData->satDMADIRSupport) /* DMADIR enabled*/ { fis->h.features = (tiScsiRequest->dataDirection == tiDirectionIn)? 0x04 : 0; /* 1 for D2H, 0 for H2D */ } else { fis->h.features = 0; /* FIS reserve */ } fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0x20; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = (bit32)(scsiCmnd->cdb[0]|(scsiCmnd->cdb[1]<<8)|(scsiCmnd->cdb[2]<<16)|(scsiCmnd->cdb[3]<<24)); satIOContext->ATACmd = SAT_PACKET; agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; //if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { fis->h.features |= 0x01; } else { fis->h.features |= 0x0; } } satIOContext->satCompleteCB = &satRequestSenseForATAPICB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satRequestSenseForATAPI: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for satDeviceReset. * * This function creates DEVICE RESET fis and sends the request to LL layer * * \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. */ /*****************************************************************************/ GLOBAL bit32 satDeviceReset( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; TI_DBG3(("satDeviceReset: start\n")); /* * Send the Execute Device Diagnostic command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_DEVICE_RESET; /* 0x90 */ fis->h.features = 0; fis->d.lbaLow = 0; fis->d.lbaMid = 0; fis->d.lbaHigh = 0; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DEV_RESET; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satDeviceResetCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG3(("satDeviceReset: return\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for saExecuteDeviceDiagnostic. * * This function creates Execute Device Diagnostic fis and sends the request to LL layer * * \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. */ /*****************************************************************************/ GLOBAL bit32 satExecuteDeviceDiagnostic( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; TI_DBG3(("satExecuteDeviceDiagnostic: start\n")); /* * Send the Execute Device Diagnostic command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_EXECUTE_DEVICE_DIAGNOSTIC; /* 0x90 */ fis->h.features = 0; fis->d.lbaLow = 0; fis->d.lbaMid = 0; fis->d.lbaHigh = 0; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satExecuteDeviceDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satExecuteDeviceDiagnostic: return\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI READ10. * * SAT implementation for SCSI READ10 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRead10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satRead10: start\n")); TI_DBG5(("satRead10: pSatDevData=%p\n", pSatDevData)); // tdhexdump("satRead10", (bit8 *)scsiCmnd->cdb, 10); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { 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(("satRead10: return FUA_NV\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satRead10: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = scsiCmnd->cdb[7]; /* MSB */ TL[3] = scsiCmnd->cdb[8]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); /* cbd10; computing LBA and transfer length */ 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(("satRead10: lba %d functioned lba %d\n", lba, satComputeCDB10LBA(satIOContext))); TI_DBG5(("satRead10: lba 0x%x functioned lba 0x%x\n", lba, satComputeCDB10LBA(satIOContext))); TI_DBG5(("satRead10: tl %d functioned tl %d\n", tl, satComputeCDB10TL(satIOContext))); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { TI_DBG1(("satRead10: return LBA out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satRead10: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* READ DMA*/ /* in case that we can't fit the transfer length, we need to make it fit by sending multiple ATA cmnds */ TI_DBG5(("satRead10: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA; /* 0xC8 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satIOContext->ATACmd = SAT_READ_DMA; } else { /* case 1 */ /* READ MULTIPLE or READ SECTOR(S) */ /* READ SECTORS for easier implemetation */ /* in case that we can't fit the transfer length, we need to make it fit by sending multiple ATA cmnds */ TI_DBG5(("satRead10: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS; /* 0x20 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->ATACmd = SAT_READ_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* READ DMA EXT */ TI_DBG5(("satRead10: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA_EXT; /* 0x25 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satIOContext->ATACmd = SAT_READ_DMA_EXT; } else { /* case 4 */ /* READ MULTIPLE EXT or READ SECTOR(S) EXT or READ VERIFY SECTOR(S) EXT*/ /* READ SECTORS EXT for easier implemetation */ TI_DBG5(("satRead10: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ10_FUA_MASK) { /* for now, no support for FUA */ 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 ); return tiSuccess; } fis->h.command = SAT_READ_SECTORS_EXT; /* 0x24 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->ATACmd = SAT_READ_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* READ FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satRead10: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satRead10: case 5\n")); /* Support 48-bit FPDMA addressing, use READ FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_FPDMA_QUEUED; /* 0x60 */ fis->h.features = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_READ; satIOContext->ATACmd = SAT_READ_FPDMA_QUEUED; } // tdhexdump("satRead10 final fis", (bit8 *)fis, sizeof(agsaFisRegHostToDevice_t)); /* saves the current LBA and orginal TL */ satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_SECTORS_EXT || fis->h.command == SAT_READ_DMA_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_READ_FPDMA_QUEUED */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; /* Initialize CB for SATA completion. */ if (LoopNum == 1) { TI_DBG5(("satRead10: NON CHAINED data\n")); satIOContext->satCompleteCB = &satNonChainedDataIOCB; } else { TI_DBG1(("satRead10: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_SECTORS_EXT || fis->h.command == SAT_READ_DMA_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_READ_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* chained data */ satIOContext->satCompleteCB = &satChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satRead10: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satRead_1. * * SAT implementation for SCSI satRead_1 * Sub function of satRead10 * * \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. */ /*****************************************************************************/ /* * as a part of loop for read10 */ GLOBAL bit32 satRead_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* Assumption: error check on lba and tl has been done in satRead*() lba = lba + tl; */ bit32 status; satIOContext_t *satOrgIOContext = agNULL; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; bit32 lba = 0; bit32 DenomTL = 0xFF; bit32 Remainder = 0; bit8 LBA[4]; /* 0 MSB, 3 LSB */ TI_DBG2(("satRead_1: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; scsiCmnd = satOrgIOContext->pScsiCmnd; osti_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_READ_DMA: DenomTL = 0xFF; break; case SAT_READ_SECTORS: DenomTL = 0xFF; break; case SAT_READ_DMA_EXT: DenomTL = 0xFFFF; break; case SAT_READ_SECTORS_EXT: DenomTL = 0xFFFF; break; case SAT_READ_FPDMA_QUEUED: DenomTL = 0xFFFF; break; default: TI_DBG1(("satRead_1: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xF000) >> (8 * 3)); LBA[1] = (bit8)((lba & 0xF00) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xF0) >> 8); LBA[3] = (bit8)(lba & 0xF); switch (satOrgIOContext->ATACmd) { case SAT_READ_DMA: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA; /* 0xC8 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; break; case SAT_READ_SECTORS: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS; /* 0x20 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; break; case SAT_READ_DMA_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA_EXT; /* 0x25 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; break; case SAT_READ_SECTORS_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS_EXT; /* 0x24 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; break; case SAT_READ_FPDMA_QUEUED: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_FPDMA_QUEUED; /* 0x60 */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->h.features = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.featuresExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->h.features = 0xFF; /* FIS sector count (7:0) */ fis->d.featuresExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_READ; break; default: TI_DBG1(("satRead_1: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &satChainedDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satRead_1: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI READ12. * * SAT implementation for SCSI READ12 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRead12( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satRead12: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { 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(("satRead12: return FUA_NV\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { 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_DBG2(("satRead12: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = scsiCmnd->cdb[6]; /* MSB */ TL[1] = scsiCmnd->cdb[7]; TL[2] = scsiCmnd->cdb[8]; TL[3] = scsiCmnd->cdb[9]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); lba = satComputeCDB12LBA(satIOContext); tl = satComputeCDB12TL(satIOContext); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { TI_DBG1(("satRead12: return LBA out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satRead12: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* READ DMA*/ /* in case that we can't fit the transfer length, we need to make it fit by sending multiple ATA cmnds */ TI_DBG5(("satRead12: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA; /* 0xC8 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satIOContext->ATACmd = SAT_READ_DMA; } else { /* case 1 */ /* READ MULTIPLE or READ SECTOR(S) */ /* READ SECTORS for easier implemetation */ /* can't fit the transfer length but need to make it fit by sending multiple*/ TI_DBG5(("satRead12: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS; /* 0x20 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->ATACmd = SAT_READ_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* READ DMA EXT */ TI_DBG5(("satRead12: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA_EXT; /* 0x25 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satIOContext->ATACmd = SAT_READ_DMA_EXT; } else { /* case 4 */ /* READ MULTIPLE EXT or READ SECTOR(S) EXT or READ VERIFY SECTOR(S) EXT*/ /* READ SECTORS EXT for easier implemetation */ TI_DBG5(("satRead12: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ12_FUA_MASK) { /* for now, no support for FUA */ 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 ); return tiSuccess; } fis->h.command = SAT_READ_SECTORS_EXT; /* 0x24 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->ATACmd = SAT_READ_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* READ FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satRead12: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satRead12: case 5\n")); /* Support 48-bit FPDMA addressing, use READ FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_FPDMA_QUEUED; /* 0x60 */ fis->h.features = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ12_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_READ; satIOContext->ATACmd = SAT_READ_FPDMA_QUEUED; } /* saves the current LBA and orginal TL */ satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_SECTORS_EXT || fis->h.command == SAT_READ_DMA_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_READ_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satRead12: NON CHAINED data\n")); satIOContext->satCompleteCB = &satNonChainedDataIOCB; } else { TI_DBG1(("satRead12: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_SECTORS_EXT || fis->h.command == SAT_READ_DMA_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_READ_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* chained data */ satIOContext->satCompleteCB = &satChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satRead12: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI READ16. * * SAT implementation for SCSI READ16 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRead16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 rangeChk = agFALSE; /* lba and tl range check */ bit32 limitChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satRead16: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { 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(("satRead16: return FUA_NV\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { 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(("satRead16: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; LBA[4] = scsiCmnd->cdb[6]; LBA[5] = scsiCmnd->cdb[7]; LBA[6] = scsiCmnd->cdb[8]; LBA[7] = scsiCmnd->cdb[9]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[10]; /* MSB */ TL[5] = scsiCmnd->cdb[11]; TL[6] = scsiCmnd->cdb[12]; TL[7] = scsiCmnd->cdb[13]; /* LSB */ rangeChk = satAddNComparebit64(LBA, TL); limitChk = satCompareLBALimitbit(LBA); lba = satComputeCDB16LBA(satIOContext); tl = satComputeCDB16TL(satIOContext); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (limitChk) { TI_DBG1(("satRead16: return LBA out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satRead16: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* READ DMA*/ /* in case that we can't fit the transfer length, we need to make it fit by sending multiple ATA cmnds */ TI_DBG5(("satRead16: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA; /* 0xC8 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satIOContext->ATACmd = SAT_READ_DMA; } else { /* case 1 */ /* READ MULTIPLE or READ SECTOR(S) */ /* READ SECTORS for easier implemetation */ /* can't fit the transfer length but need to make it fit by sending multiple*/ TI_DBG5(("satRead16: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS; /* 0x20 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->ATACmd = SAT_READ_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* READ DMA EXT */ TI_DBG5(("satRead16: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA_EXT; /* 0x25 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satIOContext->ATACmd = SAT_READ_DMA_EXT; } else { /* case 4 */ /* READ MULTIPLE EXT or READ SECTOR(S) EXT or READ VERIFY SECTOR(S) EXT*/ /* READ SECTORS EXT for easier implemetation */ TI_DBG5(("satRead16: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ16_FUA_MASK) { /* for now, no support for FUA */ 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 ); return tiSuccess; } fis->h.command = SAT_READ_SECTORS_EXT; /* 0x24 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->ATACmd = SAT_READ_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* READ FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satRead16: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satRead16: case 5\n")); /* Support 48-bit FPDMA addressing, use READ FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_FPDMA_QUEUED; /* 0x60 */ fis->h.features = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_READ16_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_READ; satIOContext->ATACmd = SAT_READ_FPDMA_QUEUED; } /* saves the current LBA and orginal TL */ satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_SECTORS_EXT || fis->h.command == SAT_READ_DMA_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_READ_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satRead16: NON CHAINED data\n")); satIOContext->satCompleteCB = &satNonChainedDataIOCB; } else { TI_DBG1(("satRead16: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_SECTORS_EXT || fis->h.command == SAT_READ_DMA_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_READ_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* chained data */ satIOContext->satCompleteCB = &satChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satRead16: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI READ6. * * SAT implementation for SCSI READ6 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRead6( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit16 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satRead6: start\n")); /* no FUA checking since read6 */ /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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_DBG2(("satRead6: return control\n")); return tiSuccess; } /* cbd6; computing LBA and transfer length */ lba = (((scsiCmnd->cdb[1]) & 0x1f) << (8*2)) + (scsiCmnd->cdb[2] << 8) + scsiCmnd->cdb[3]; tl = scsiCmnd->cdb[4]; /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satRead6: return LBA out of range\n")); return tiSuccess; } } /* case 1 and 2 */ if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* READ DMA*/ TI_DBG5(("satRead6: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA; /* 0xC8 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (tl == 0) { /* temporary fix */ fis->d.sectorCount = 0xff; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; } else { /* case 1 */ /* READ SECTORS for easier implemetation */ TI_DBG5(("satRead6: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS; /* 0x20 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (tl == 0) { /* temporary fix */ fis->d.sectorCount = 0xff; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* READ DMA EXT only */ TI_DBG5(("satRead6: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_DMA_EXT; /* 0x25 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (tl == 0) { /* sector count is 256, 0x100*/ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0x01; /* FIS sector count (15:8) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; } else { /* case 4 */ /* READ SECTORS EXT for easier implemetation */ TI_DBG5(("satRead6: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS_EXT; /* 0x24 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (tl == 0) { /* sector count is 256, 0x100*/ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0x01; /* FIS sector count (15:8) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* READ FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { /* sanity check */ TI_DBG5(("satRead6: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG5(("satRead6: case 5\n")); /* Support 48-bit FPDMA addressing, use READ FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_FPDMA_QUEUED; /* 0x60 */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ if (tl == 0) { /* sector count is 256, 0x100*/ fis->h.features = 0; /* FIS sector count (7:0) */ fis->d.featuresExp = 0x01; /* FIS sector count (15:8) */ } else { fis->h.features = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ fis->d.featuresExp = 0; /* FIS sector count (15:8) */ } fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_READ; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI WRITE16. * * SAT implementation for SCSI WRITE16 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWrite16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 rangeChk = agFALSE; /* lba and tl range check */ bit32 limitChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWrite16: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { 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(("satWrite16: return FUA_NV\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { 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(("satWrite16: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; LBA[4] = scsiCmnd->cdb[6]; LBA[5] = scsiCmnd->cdb[7]; LBA[6] = scsiCmnd->cdb[8]; LBA[7] = scsiCmnd->cdb[9]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[10]; /* MSB */ TL[5] = scsiCmnd->cdb[11]; TL[6] = scsiCmnd->cdb[12]; TL[7] = scsiCmnd->cdb[13]; /* LSB */ rangeChk = satAddNComparebit64(LBA, TL); limitChk = satCompareLBALimitbit(LBA); lba = satComputeCDB16LBA(satIOContext); tl = satComputeCDB16TL(satIOContext); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (limitChk) { TI_DBG1(("satWrite16: return LBA out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satWrite16: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWrite16: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWrite16: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWrite16: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA_EXT; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWrite16: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWrite16: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satWrite16: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE16_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satWrite16: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedDataIOCB; } else { TI_DBG1(("satWrite16: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI WRITE12. * * SAT implementation for SCSI WRITE12 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWrite12( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWrite12: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { 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(("satWrite12: return FUA_NV\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { 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(("satWrite12: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = scsiCmnd->cdb[6]; /* MSB */ TL[1] = scsiCmnd->cdb[7]; TL[2] = scsiCmnd->cdb[8]; TL[3] = scsiCmnd->cdb[9]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); lba = satComputeCDB12LBA(satIOContext); tl = satComputeCDB12TL(satIOContext); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWrite12: return LBA out of range, not EXT\n")); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satWrite12: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWrite12: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWrite12: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWrite12: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA_EXT; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWrite12: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWrite12: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satWrite12: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE12_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satWrite12: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedDataIOCB; } else { TI_DBG1(("satWrite12: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI WRITE10. * * SAT implementation for SCSI WRITE10 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWrite10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWrite10: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { 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(("satWrite10: return FUA_NV\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satWrite10: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = scsiCmnd->cdb[7]; /* MSB */ TL[3] = scsiCmnd->cdb[8]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); /* cbd10; computing LBA and transfer length */ 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(("satWrite10: lba %d functioned lba %d\n", lba, satComputeCDB10LBA(satIOContext))); TI_DBG5(("satWrite10: tl %d functioned tl %d\n", tl, satComputeCDB10TL(satIOContext))); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWrite10: return LBA out of range, not EXT\n")); TI_DBG1(("satWrite10: cdb 0x%x 0x%x 0x%x 0x%x\n",scsiCmnd->cdb[2], scsiCmnd->cdb[3], scsiCmnd->cdb[4], scsiCmnd->cdb[5])); TI_DBG1(("satWrite10: lba 0x%x SAT_TR_LBA_LIMIT 0x%x\n", lba, SAT_TR_LBA_LIMIT)); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satWrite10: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ TI_DBG5(("satWrite10: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* can't fit the transfer length */ TI_DBG5(("satWrite10: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWrite10: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ satIOContext->ATACmd = SAT_WRITE_DMA_EXT; fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWrite10: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWrite10: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satWrite10: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } // tdhexdump("satWrite10 final fis", (bit8 *)fis, sizeof(agsaFisRegHostToDevice_t)); satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satWrite10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedDataIOCB; } else { TI_DBG1(("satWrite10: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWrite_1. * * SAT implementation for SCSI WRITE10 and send FIS request to LL layer. * This is used when WRITE10 is divided into multiple ATA commands * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWrite_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* Assumption: error check on lba and tl has been done in satWrite*() lba = lba + tl; */ bit32 status; satIOContext_t *satOrgIOContext = agNULL; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; bit32 lba = 0; bit32 DenomTL = 0xFF; bit32 Remainder = 0; bit8 LBA[4]; /* 0 MSB, 3 LSB */ TI_DBG2(("satWrite_1: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; scsiCmnd = satOrgIOContext->pScsiCmnd; osti_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_WRITE_DMA: DenomTL = 0xFF; break; case SAT_WRITE_SECTORS: DenomTL = 0xFF; break; case SAT_WRITE_DMA_EXT: DenomTL = 0xFFFF; break; case SAT_WRITE_DMA_FUA_EXT: DenomTL = 0xFFFF; break; case SAT_WRITE_SECTORS_EXT: DenomTL = 0xFFFF; break; case SAT_WRITE_FPDMA_QUEUED: DenomTL = 0xFFFF; break; default: TI_DBG1(("satWrite_1: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xF000) >> (8 * 3)); /* MSB */ LBA[1] = (bit8)((lba & 0xF00) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xF0) >> 8); LBA[3] = (bit8)(lba & 0xF); /* LSB */ switch (satOrgIOContext->ATACmd) { case SAT_WRITE_DMA: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; break; case SAT_WRITE_SECTORS: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; break; case SAT_WRITE_DMA_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x3D */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; break; case SAT_WRITE_SECTORS_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; break; case SAT_WRITE_FPDMA_QUEUED: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = LBA[0];; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->h.features = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.featuresExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->h.features = 0xFF; /* FIS sector count (7:0) */ fis->d.featuresExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; break; default: TI_DBG1(("satWrite_1: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &satChainedDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satWrite_1: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI WRITE6. * * SAT implementation for SCSI WRITE6 and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWrite6( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit16 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWrite6: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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(("satWrite6: return control\n")); return tiSuccess; } /* cbd6; computing LBA and transfer length */ lba = (((scsiCmnd->cdb[1]) & 0x1f) << (8*2)) + (scsiCmnd->cdb[2] << 8) + scsiCmnd->cdb[3]; tl = scsiCmnd->cdb[4]; /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWrite6: return LBA out of range\n")); return tiSuccess; } } /* case 1 and 2 */ if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ TI_DBG5(("satWrite6: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (tl == 0) { /* temporary fix */ fis->d.sectorCount = 0xff; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; } else { /* case 1 */ /* WRITE SECTORS for easier implemetation */ TI_DBG5(("satWrite6: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (tl == 0) { /* temporary fix */ fis->d.sectorCount = 0xff; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT only */ TI_DBG5(("satWrite6: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (tl == 0) { /* sector count is 256, 0x100*/ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0x01; /* FIS sector count (15:8) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; } else { /* case 4 */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWrite6: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (tl == 0) { /* sector count is 256, 0x100*/ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0x01; /* FIS sector count (15:8) */ } else { fis->d.sectorCount = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { /* sanity check */ TI_DBG5(("satWrite6: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG5(("satWrite6: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->d.lbaLow = scsiCmnd->cdb[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)((scsiCmnd->cdb[1]) & 0x1f); /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ if (tl == 0) { /* sector count is 256, 0x100*/ fis->h.features = 0; /* FIS sector count (7:0) */ fis->d.featuresExp = 0x01; /* FIS sector count (15:8) */ } else { fis->h.features = scsiCmnd->cdb[4]; /* FIS sector count (7:0) */ fis->d.featuresExp = 0; /* FIS sector count (15:8) */ } fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI TEST UNIT READY. * * SAT implementation for SCSI TUR and send FIS request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satTestUnitReady( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG6(("satTestUnitReady: entry tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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(("satTestUnitReady: return control\n")); return tiSuccess; } /* SAT revision 8, 8.11.2, p42*/ if (pSatDevData->satStopState == agTRUE) { satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satTestUnitReady: stop state\n")); return tiSuccess; } /* * Check if format is in progress */ if (pSatDevData->satDriveState == SAT_DEV_STATE_FORMAT_IN_PROGRESS) { TI_DBG1(("satTestUnitReady() FORMAT_IN_PROGRESS tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_FORMAT_IN_PROGRESS, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satTestUnitReady: format in progress\n")); return tiSuccess; } /* check previously issued ATA command */ if (pSatDevData->satPendingIO != 0) { if (pSatDevData->satDeviceFaultState == agTRUE) { satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_LOGICAL_UNIT_FAILURE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satTestUnitReady: previous command ended in error\n")); return tiSuccess; } } /* check removalbe media feature set */ if(pSatDevData->satRemovableMedia && pSatDevData->satRemovableMediaEnabled) { TI_DBG5(("satTestUnitReady: sending get media status cmnd\n")); /* send GET MEDIA STATUS command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_GET_MEDIA_STATUS; /* 0xDA */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satTestUnitReadyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /* number 6) in SAT p42 send ATA CHECK POWER MODE */ TI_DBG5(("satTestUnitReady: sending check power mode cmnd\n")); status = satTestUnitReady_1( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satTestUnitReady_1. * * SAT implementation for SCSI satTestUnitReady_1. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satTestUnitReady_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* sends SAT_CHECK_POWER_MODE as a part of TESTUNITREADY internally generated - no directly corresponding scsi called in satIOCompleted as a part of satTestUnitReady(), SAT, revision8, 8.11.2, p42 */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; TI_DBG5(("satTestUnitReady_1: start\n")); /* * Send the ATA CHECK POWER MODE command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_CHECK_POWER_MODE; /* 0xE5 */ fis->h.features = 0; fis->d.lbaLow = 0; fis->d.lbaMid = 0; fis->d.lbaHigh = 0; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satTestUnitReadyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satTestUnitReady_1: return\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReportLun. * * SAT implementation for SCSI satReportLun. Only LUN0 is reported. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satReportLun( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { scsiRspSense_t *pSense; bit32 allocationLen; bit32 reportLunLen; scsiReportLun_t *pReportLun; tiIniScsiCmnd_t *scsiCmnd; TI_DBG5(("satReportLun entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; pReportLun = (scsiReportLun_t *) tiScsiRequest->sglVirtualAddr; scsiCmnd = &tiScsiRequest->scsiCmnd; // tdhexdump("satReportLun cdb", (bit8 *)scsiCmnd, 16); /* Find the buffer size allocated by Initiator */ allocationLen = (((bit32)scsiCmnd->cdb[6]) << 24) | (((bit32)scsiCmnd->cdb[7]) << 16) | (((bit32)scsiCmnd->cdb[8]) << 8 ) | (((bit32)scsiCmnd->cdb[9]) ); reportLunLen = 16; /* 8 byte header and 8 bytes of LUN0 */ if (allocationLen < reportLunLen) { TI_DBG1(("satReportLun *** ERROR *** insufficient len=0x%x tiDeviceHandle=%p tiIORequest=%p\n", reportLunLen, tiDeviceHandle, tiIORequest)); 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 ); return tiSuccess; } /* Set length to one entry */ pReportLun->len[0] = 0; pReportLun->len[1] = 0; pReportLun->len[2] = 0; pReportLun->len[3] = sizeof (tiLUN_t); pReportLun->reserved = 0; /* Set to LUN 0: * - address method to 0x00: Peripheral device addressing method, * - bus identifier to 0 */ pReportLun->lunList[0].lun[0] = 0; pReportLun->lunList[0].lun[1] = 0; pReportLun->lunList[0].lun[2] = 0; pReportLun->lunList[0].lun[3] = 0; pReportLun->lunList[0].lun[4] = 0; pReportLun->lunList[0].lun[5] = 0; pReportLun->lunList[0].lun[6] = 0; pReportLun->lunList[0].lun[7] = 0; if (allocationLen > reportLunLen) { /* underrun */ TI_DBG1(("satReportLun reporting underrun reportLunLen=0x%x allocationLen=0x%x \n", reportLunLen, allocationLen)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, allocationLen - reportLunLen, agNULL, satIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI REQUEST SENSE. * * SAT implementation for SCSI REQUEST SENSE. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRequestSense( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* SAT Rev 8 p38, Table25 sending SMART RETURN STATUS Checking SMART Treshold Exceeded Condition is done in satRequestSenseCB() Only fixed format sense data is support. In other words, we don't support DESC bit is set in Request Sense */ bit32 status; bit32 agRequestType; scsiRspSense_t *pSense; satDeviceData_t *pSatDevData; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; tdIORequestBody_t *tdIORequestBody; satInternalIo_t *satIntIo = agNULL; satIOContext_t *satIOContext2; TI_DBG4(("satRequestSense entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = (scsiRspSense_t *) tiScsiRequest->sglVirtualAddr; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG4(("satRequestSense: pSatDevData=%p\n", pSatDevData)); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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(("satRequestSense: return control\n")); return tiSuccess; } /* Only fixed format sense data is support. In other words, we don't support DESC bit is set in Request Sense */ if ( scsiCmnd->cdb[1] & ATA_REMOVABLE_MEDIA_DEVICE_MASK ) { 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(("satRequestSense: DESC bit is set, which we don't support\n")); return tiSuccess; } if (pSatDevData->satSMARTEnabled == agTRUE) { /* sends SMART RETURN STATUS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_RETURN_STATUS; /* 0xB0 */ fis->h.features = 0xDA; /* FIS features */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satRequestSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG4(("satRequestSense: if return, status %d\n", status)); return (status); } else { /*allocate iocontext for xmitting xmit SAT_CHECK_POWER_MODE then call satRequestSense2 */ TI_DBG4(("satRequestSense: before satIntIo %p\n", satIntIo)); /* allocate iocontext */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, /* original request */ pSatDevData, tiScsiRequest->scsiCmnd.expDataLength, satIntIo); TI_DBG4(("satRequestSense: after satIntIo %p\n", satIntIo)); if (satIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, pSatDevData, satIntIo); /* failed during sending SMART RETURN STATUS */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); TI_DBG4(("satRequestSense: else fail 1\n")); return tiSuccess; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext except * reqType and satCompleteCB which will be set depending on cmd. */ if (satIntIo == agNULL) { TI_DBG4(("satRequestSense: satIntIo is NULL\n")); } else { TI_DBG4(("satRequestSense: satIntIo is NOT NULL\n")); } /* use this --- tttttthe one the same */ satIntIo->satOrgTiIORequest = tiIORequest; 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 = satIOContext->interruptContext; satIOContext2->satIntIoContext = satIntIo; satIOContext2->ptiDeviceHandle = tiDeviceHandle; satIOContext2->satOrgIOContext = satIOContext; TI_DBG4(("satRequestSense: satIntIo->satIntTiScsiXchg.agSgl1.len %d\n", satIntIo->satIntTiScsiXchg.agSgl1.len)); TI_DBG4(("satRequestSense: satIntIo->satIntTiScsiXchg.agSgl1.upper %d\n", satIntIo->satIntTiScsiXchg.agSgl1.upper)); TI_DBG4(("satRequestSense: satIntIo->satIntTiScsiXchg.agSgl1.lower %d\n", satIntIo->satIntTiScsiXchg.agSgl1.lower)); TI_DBG4(("satRequestSense: satIntIo->satIntTiScsiXchg.agSgl1.type %d\n", satIntIo->satIntTiScsiXchg.agSgl1.type)); status = satRequestSense_1( tiRoot, &(satIntIo->satIntTiIORequest), tiDeviceHandle, &(satIntIo->satIntTiScsiXchg), satIOContext2); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, pSatDevData, satIntIo); /* failed during sending SMART RETURN STATUS */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, agNULL, satIOContext->interruptContext ); TI_DBG1(("satRequestSense: else fail 2\n")); return tiSuccess; } TI_DBG4(("satRequestSense: else return success\n")); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI REQUEST SENSE. * * SAT implementation for SCSI REQUEST SENSE. * Sub function of satRequestSense * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRequestSense_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* sends SAT_CHECK_POWER_MODE */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; TI_DBG4(("satRequestSense_1 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* * Send the ATA CHECK POWER MODE command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_CHECK_POWER_MODE; /* 0xE5 */ fis->h.features = 0; fis->d.lbaLow = 0; fis->d.lbaMid = 0; fis->d.lbaHigh = 0; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satRequestSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ TI_DBG4(("satRequestSense_1: agSgl1.len %d\n", tiScsiRequest->agSgl1.len)); TI_DBG4(("satRequestSense_1: agSgl1.upper %d\n", tiScsiRequest->agSgl1.upper)); TI_DBG4(("satRequestSense_1: agSgl1.lower %d\n", tiScsiRequest->agSgl1.lower)); TI_DBG4(("satRequestSense_1: agSgl1.type %d\n", tiScsiRequest->agSgl1.type)); // tdhexdump("satRequestSense_1", (bit8 *)fis, sizeof(agsaFisRegHostToDevice_t)); status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY. * * SAT implementation for SCSI INQUIRY. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satInquiry( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* CMDDT bit is obsolete in SPC-3 and this is assumed in SAT revision 8 */ scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; satDeviceData_t *pSatDevData; bit32 status; TI_DBG5(("satInquiry: start\n")); TI_DBG5(("satInquiry entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; TI_DBG5(("satInquiry: pSatDevData=%p\n", pSatDevData)); //tdhexdump("satInquiry", (bit8 *)scsiCmnd->cdb, 6); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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_DBG2(("satInquiry: return control\n")); return tiSuccess; } /* checking EVPD and Allocation Length */ /* SPC-4 spec 6.4 p141 */ /* EVPD bit == 0 && PAGE CODE != 0 */ if ( !(scsiCmnd->cdb[1] & SCSI_EVPD_MASK) && (scsiCmnd->cdb[2] != 0) ) { 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(("satInquiry: return EVPD and PAGE CODE\n")); return tiSuccess; } TI_DBG6(("satInquiry: allocation length 0x%x %d\n", ((scsiCmnd->cdb[3]) << 8) + scsiCmnd->cdb[4], ((scsiCmnd->cdb[3]) << 8) + scsiCmnd->cdb[4])); /* convert OS IO to TD internal IO */ if ( pSatDevData->IDDeviceValid == agFALSE) { status = satStartIDDev( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext ); TI_DBG6(("satInquiry: end status %d\n", status)); return status; } else { TI_DBG6(("satInquiry: calling satInquiryIntCB\n")); satInquiryIntCB( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext ); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReadCapacity10. * * SAT implementation for SCSI satReadCapacity10. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satReadCapacity10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; bit8 *pVirtAddr; satDeviceData_t *pSatDevData; agsaSATAIdentifyData_t *pSATAIdData; bit32 lastLba; bit32 word117_118; bit32 word117; bit32 word118; TI_DBG5(("satReadCapacity10: start: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; pVirtAddr = (bit8 *) tiScsiRequest->sglVirtualAddr; scsiCmnd = &tiScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; pSATAIdData = &pSatDevData->satIdentifyData; /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satReadCapacity10: return control\n")); return tiSuccess; } /* * If Logical block address is not set to zero, return error */ if ((scsiCmnd->cdb[2] || scsiCmnd->cdb[3] || scsiCmnd->cdb[4] || scsiCmnd->cdb[5])) { TI_DBG1(("satReadCapacity10 *** ERROR *** logical address non zero, tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); 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 ); return tiSuccess; } /* * If PMI bit is not zero, return error */ if ( ((scsiCmnd->cdb[8]) & SCSI_READ_CAPACITY10_PMI_MASK) != 0 ) { TI_DBG1(("satReadCapacity10 *** ERROR *** PMI is not zero, tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); 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 ); return tiSuccess; } /* filling in Read Capacity parameter data saved identify device has been already flipped See ATA spec p125 and p136 and SBC spec p54 */ /* * If 48-bit addressing is supported, set capacity information from Identify * Device Word 100-103. */ if (pSatDevData->sat48BitSupport == agTRUE) { /* * Setting RETURNED LOGICAL BLOCK ADDRESS in READ CAPACITY(10) response data: * SBC-2 specifies that if the capacity exceeded the 4-byte RETURNED LOGICAL * BLOCK ADDRESS in READ CAPACITY(10) parameter data, the RETURNED LOGICAL * BLOCK ADDRESS should be set to 0xFFFFFFFF so the application client would * then issue a READ CAPACITY(16) command. */ /* ATA Identify Device information word 100 - 103 */ if ( (pSATAIdData->maxLBA32_47 != 0 ) || (pSATAIdData->maxLBA48_63 != 0)) { pVirtAddr[0] = 0xFF; /* MSB number of block */ pVirtAddr[1] = 0xFF; pVirtAddr[2] = 0xFF; pVirtAddr[3] = 0xFF; /* LSB number of block */ TI_DBG1(("satReadCapacity10: returns 0xFFFFFFFF\n")); } else /* Fit the Readcapacity10 4-bytes response length */ { lastLba = (((pSATAIdData->maxLBA16_31) << 16) ) | (pSATAIdData->maxLBA0_15); lastLba = lastLba - 1; /* LBA starts from zero */ /* for testing lastLba = lastLba - (512*10) - 1; */ pVirtAddr[0] = (bit8)((lastLba >> 24) & 0xFF); /* MSB */ pVirtAddr[1] = (bit8)((lastLba >> 16) & 0xFF); pVirtAddr[2] = (bit8)((lastLba >> 8) & 0xFF); pVirtAddr[3] = (bit8)((lastLba ) & 0xFF); /* LSB */ TI_DBG3(("satReadCapacity10: lastLba is 0x%x %d\n", lastLba, lastLba)); TI_DBG3(("satReadCapacity10: LBA 0 is 0x%x %d\n", pVirtAddr[0], pVirtAddr[0])); TI_DBG3(("satReadCapacity10: LBA 1 is 0x%x %d\n", pVirtAddr[1], pVirtAddr[1])); TI_DBG3(("satReadCapacity10: LBA 2 is 0x%x %d\n", pVirtAddr[2], pVirtAddr[2])); TI_DBG3(("satReadCapacity10: LBA 3 is 0x%x %d\n", pVirtAddr[3], pVirtAddr[3])); } } /* * For 28-bit addressing, set capacity information from Identify * Device Word 60-61. */ else { /* ATA Identify Device information word 60 - 61 */ lastLba = (((pSATAIdData->numOfUserAddressableSectorsHi) << 16) ) | (pSATAIdData->numOfUserAddressableSectorsLo); lastLba = lastLba - 1; /* LBA starts from zero */ pVirtAddr[0] = (bit8)((lastLba >> 24) & 0xFF); /* MSB */ pVirtAddr[1] = (bit8)((lastLba >> 16) & 0xFF); pVirtAddr[2] = (bit8)((lastLba >> 8) & 0xFF); pVirtAddr[3] = (bit8)((lastLba ) & 0xFF); /* LSB */ } /* SAT Rev 8d */ if (((pSATAIdData->word104_107[2]) & 0x1000) == 0) { TI_DBG5(("satReadCapacity10: Default Block Length is 512\n")); /* * Set the block size, fixed at 512 bytes. */ pVirtAddr[4] = 0x00; /* MSB block size in bytes */ pVirtAddr[5] = 0x00; pVirtAddr[6] = 0x02; pVirtAddr[7] = 0x00; /* LSB block size in bytes */ } else { word118 = pSATAIdData->word112_126[6]; word117 = pSATAIdData->word112_126[5]; word117_118 = (word118 << 16) + word117; word117_118 = word117_118 * 2; pVirtAddr[4] = (bit8)((word117_118 >> 24) & 0xFF); /* MSB block size in bytes */ pVirtAddr[5] = (bit8)((word117_118 >> 16) & 0xFF); pVirtAddr[6] = (bit8)((word117_118 >> 8) & 0xFF); pVirtAddr[7] = (bit8)(word117_118 & 0xFF); /* LSB block size in bytes */ TI_DBG1(("satReadCapacity10: Nondefault word118 %d 0x%x \n", word118, word118)); TI_DBG1(("satReadCapacity10: Nondefault word117 %d 0x%x \n", word117, word117)); TI_DBG1(("satReadCapacity10: Nondefault Block Length is %d 0x%x \n",word117_118, word117_118)); } /* fill in MAX LBA, which is used in satSendDiagnostic_1() */ pSatDevData->satMaxLBA[0] = 0; /* MSB */ pSatDevData->satMaxLBA[1] = 0; pSatDevData->satMaxLBA[2] = 0; pSatDevData->satMaxLBA[3] = 0; pSatDevData->satMaxLBA[4] = pVirtAddr[0]; pSatDevData->satMaxLBA[5] = pVirtAddr[1]; pSatDevData->satMaxLBA[6] = pVirtAddr[2]; pSatDevData->satMaxLBA[7] = pVirtAddr[3]; /* LSB */ TI_DBG4(("satReadCapacity10 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x , tiDeviceHandle=%p tiIORequest=%p\n", pVirtAddr[0], pVirtAddr[1], pVirtAddr[2], pVirtAddr[3], pVirtAddr[4], pVirtAddr[5], pVirtAddr[6], pVirtAddr[7], tiDeviceHandle, tiIORequest)); /* * Send the completion response now. */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReadCapacity16. * * SAT implementation for SCSI satReadCapacity16. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satReadCapacity16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; bit8 *pVirtAddr; satDeviceData_t *pSatDevData; agsaSATAIdentifyData_t *pSATAIdData; bit32 lastLbaLo; bit32 allocationLen; bit32 readCapacityLen = 32; bit32 i = 0; TI_DBG5(("satReadCapacity16 start: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; pVirtAddr = (bit8 *) tiScsiRequest->sglVirtualAddr; scsiCmnd = &tiScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; pSATAIdData = &pSatDevData->satIdentifyData; /* Find the buffer size allocated by Initiator */ allocationLen = (((bit32)scsiCmnd->cdb[10]) << 24) | (((bit32)scsiCmnd->cdb[11]) << 16) | (((bit32)scsiCmnd->cdb[12]) << 8 ) | (((bit32)scsiCmnd->cdb[13]) ); if (allocationLen < readCapacityLen) { TI_DBG1(("satReadCapacity16 *** ERROR *** insufficient len=0x%x readCapacityLen=0x%x\n", allocationLen, readCapacityLen)); 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 ); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { 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(("satReadCapacity16: return control\n")); return tiSuccess; } /* * If Logical blcok address is not set to zero, return error */ if ((scsiCmnd->cdb[2] || scsiCmnd->cdb[3] || scsiCmnd->cdb[4] || scsiCmnd->cdb[5]) || (scsiCmnd->cdb[6] || scsiCmnd->cdb[7] || scsiCmnd->cdb[8] || scsiCmnd->cdb[9]) ) { TI_DBG1(("satReadCapacity16 *** ERROR *** logical address non zero, tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); 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 ); return tiSuccess; } /* * If PMI bit is not zero, return error */ if ( ((scsiCmnd->cdb[14]) & SCSI_READ_CAPACITY16_PMI_MASK) != 0 ) { TI_DBG1(("satReadCapacity16 *** ERROR *** PMI is not zero, tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); 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 ); return tiSuccess; } /* filling in Read Capacity parameter data */ /* * If 48-bit addressing is supported, set capacity information from Identify * Device Word 100-103. */ if (pSatDevData->sat48BitSupport == agTRUE) { pVirtAddr[0] = (bit8)(((pSATAIdData->maxLBA48_63) >> 8) & 0xff); /* MSB */ pVirtAddr[1] = (bit8)((pSATAIdData->maxLBA48_63) & 0xff); pVirtAddr[2] = (bit8)(((pSATAIdData->maxLBA32_47) >> 8) & 0xff); pVirtAddr[3] = (bit8)((pSATAIdData->maxLBA32_47) & 0xff); lastLbaLo = (((pSATAIdData->maxLBA16_31) << 16) ) | (pSATAIdData->maxLBA0_15); lastLbaLo = lastLbaLo - 1; /* LBA starts from zero */ pVirtAddr[4] = (bit8)((lastLbaLo >> 24) & 0xFF); pVirtAddr[5] = (bit8)((lastLbaLo >> 16) & 0xFF); pVirtAddr[6] = (bit8)((lastLbaLo >> 8) & 0xFF); pVirtAddr[7] = (bit8)((lastLbaLo ) & 0xFF); /* LSB */ } /* * For 28-bit addressing, set capacity information from Identify * Device Word 60-61. */ else { pVirtAddr[0] = 0; /* MSB */ pVirtAddr[1] = 0; pVirtAddr[2] = 0; pVirtAddr[3] = 0; lastLbaLo = (((pSATAIdData->numOfUserAddressableSectorsHi) << 16) ) | (pSATAIdData->numOfUserAddressableSectorsLo); lastLbaLo = lastLbaLo - 1; /* LBA starts from zero */ pVirtAddr[4] = (bit8)((lastLbaLo >> 24) & 0xFF); pVirtAddr[5] = (bit8)((lastLbaLo >> 16) & 0xFF); pVirtAddr[6] = (bit8)((lastLbaLo >> 8) & 0xFF); pVirtAddr[7] = (bit8)((lastLbaLo ) & 0xFF); /* LSB */ } /* * Set the block size, fixed at 512 bytes. */ pVirtAddr[8] = 0x00; /* MSB block size in bytes */ pVirtAddr[9] = 0x00; pVirtAddr[10] = 0x02; pVirtAddr[11] = 0x00; /* LSB block size in bytes */ /* fill in MAX LBA, which is used in satSendDiagnostic_1() */ pSatDevData->satMaxLBA[0] = pVirtAddr[0]; /* MSB */ pSatDevData->satMaxLBA[1] = pVirtAddr[1]; pSatDevData->satMaxLBA[2] = pVirtAddr[2]; pSatDevData->satMaxLBA[3] = pVirtAddr[3]; pSatDevData->satMaxLBA[4] = pVirtAddr[4]; pSatDevData->satMaxLBA[5] = pVirtAddr[5]; pSatDevData->satMaxLBA[6] = pVirtAddr[6]; pSatDevData->satMaxLBA[7] = pVirtAddr[7]; /* LSB */ TI_DBG5(("satReadCapacity16 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x , tiDeviceHandle=%p tiIORequest=%p\n", pVirtAddr[0], pVirtAddr[1], pVirtAddr[2], pVirtAddr[3], pVirtAddr[4], pVirtAddr[5], pVirtAddr[6], pVirtAddr[7], pVirtAddr[8], pVirtAddr[9], pVirtAddr[10], pVirtAddr[11], tiDeviceHandle, tiIORequest)); for(i=12;i<=31;i++) { pVirtAddr[i] = 0x00; } /* * Send the completion response now. */ if (allocationLen > readCapacityLen) { /* underrun */ TI_DBG1(("satReadCapacity16 reporting underrun readCapacityLen=0x%x allocationLen=0x%x \n", readCapacityLen, allocationLen)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, allocationLen - readCapacityLen, agNULL, satIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI MODE SENSE (6). * * SAT implementation for SCSI MODE SENSE (6). * * \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. */ /*****************************************************************************/ GLOBAL bit32 satModeSense6( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { scsiRspSense_t *pSense; bit32 requestLen; tiIniScsiCmnd_t *scsiCmnd; bit32 pageSupported; bit8 page; bit8 *pModeSense; /* Mode Sense data buffer */ satDeviceData_t *pSatDevData; bit8 PC; bit8 AllPages[MODE_SENSE6_RETURN_ALL_PAGES_LEN]; bit8 Control[MODE_SENSE6_CONTROL_PAGE_LEN]; bit8 RWErrorRecovery[MODE_SENSE6_READ_WRITE_ERROR_RECOVERY_PAGE_LEN]; bit8 Caching[MODE_SENSE6_CACHING_LEN]; bit8 InfoExceptionCtrl[MODE_SENSE6_INFORMATION_EXCEPTION_CONTROL_PAGE_LEN]; bit8 lenRead = 0; TI_DBG5(("satModeSense6 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pModeSense = (bit8 *) tiScsiRequest->sglVirtualAddr; pSatDevData = satIOContext->pSatDevData; //tdhexdump("satModeSense6", (bit8 *)scsiCmnd->cdb, 6); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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_DBG2(("satModeSense6: return control\n")); return tiSuccess; } /* checking PC(Page Control) SAT revion 8, 8.5.3 p33 and 10.1.2, p66 */ PC = (bit8)((scsiCmnd->cdb[2]) & SCSI_MODE_SENSE6_PC_MASK); if (PC != 0) { 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(("satModeSense6: return due to PC value pc 0x%x\n", PC >> 6)); return tiSuccess; } /* reading PAGE CODE */ page = (bit8)((scsiCmnd->cdb[2]) & SCSI_MODE_SENSE6_PAGE_CODE_MASK); TI_DBG5(("satModeSense6: page=0x%x, tiDeviceHandle=%p tiIORequest=%p\n", page, tiDeviceHandle, tiIORequest)); requestLen = scsiCmnd->cdb[4]; /* Based on page code value, returns a corresponding mode page note: no support for subpage */ switch(page) { case MODESENSE_RETURN_ALL_PAGES: case MODESENSE_CONTROL_PAGE: /* control */ case MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE: /* Read-Write Error Recovery */ case MODESENSE_CACHING: /* caching */ case MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE: /* informational exceptions control*/ pageSupported = agTRUE; break; case MODESENSE_VENDOR_SPECIFIC_PAGE: /* vendor specific */ default: pageSupported = agFALSE; break; } if (pageSupported == agFALSE) { TI_DBG1(("satModeSense6 *** ERROR *** not supported page 0x%x tiDeviceHandle=%p tiIORequest=%p\n", page, tiDeviceHandle, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } switch(page) { case MODESENSE_RETURN_ALL_PAGES: lenRead = (bit8)MIN(requestLen, MODE_SENSE6_RETURN_ALL_PAGES_LEN); break; case MODESENSE_CONTROL_PAGE: /* control */ lenRead = (bit8)MIN(requestLen, MODE_SENSE6_CONTROL_PAGE_LEN); break; case MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE: /* Read-Write Error Recovery */ lenRead = (bit8)MIN(requestLen, MODE_SENSE6_READ_WRITE_ERROR_RECOVERY_PAGE_LEN); break; case MODESENSE_CACHING: /* caching */ lenRead = (bit8)MIN(requestLen, MODE_SENSE6_CACHING_LEN); break; case MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE: /* informational exceptions control*/ lenRead = (bit8)MIN(requestLen, MODE_SENSE6_INFORMATION_EXCEPTION_CONTROL_PAGE_LEN); break; default: TI_DBG1(("satModeSense6: default error page %d\n", page)); break; } if (page == MODESENSE_RETURN_ALL_PAGES) { TI_DBG5(("satModeSense6: MODESENSE_RETURN_ALL_PAGES\n")); AllPages[0] = (bit8)(lenRead - 1); AllPages[1] = 0x00; /* default medium type (currently mounted medium type) */ AllPages[2] = 0x00; /* no write-protect, no support for DPO-FUA */ AllPages[3] = 0x08; /* block descriptor length */ /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ /* density code */ AllPages[4] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ AllPages[5] = 0x00; /* unspecified */ AllPages[6] = 0x00; /* unspecified */ AllPages[7] = 0x00; /* unspecified */ /* reserved */ AllPages[8] = 0x00; /* reserved */ /* Block size */ AllPages[9] = 0x00; AllPages[10] = 0x02; /* Block size is always 512 bytes */ AllPages[11] = 0x00; /* MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE */ AllPages[12] = 0x01; /* page code */ AllPages[13] = 0x0A; /* page length */ AllPages[14] = 0x40; /* ARRE is set */ AllPages[15] = 0x00; AllPages[16] = 0x00; AllPages[17] = 0x00; AllPages[18] = 0x00; AllPages[19] = 0x00; AllPages[20] = 0x00; AllPages[21] = 0x00; AllPages[22] = 0x00; AllPages[23] = 0x00; /* MODESENSE_CACHING */ AllPages[24] = 0x08; /* page code */ AllPages[25] = 0x12; /* page length */ #ifdef NOT_YET if (pSatDevData->satWriteCacheEnabled == agTRUE) { AllPages[26] = 0x04;/* WCE bit is set */ } else { AllPages[26] = 0x00;/* WCE bit is NOT set */ } #endif AllPages[26] = 0x00;/* WCE bit is NOT set */ AllPages[27] = 0x00; AllPages[28] = 0x00; AllPages[29] = 0x00; AllPages[30] = 0x00; AllPages[31] = 0x00; AllPages[32] = 0x00; AllPages[33] = 0x00; AllPages[34] = 0x00; AllPages[35] = 0x00; if (pSatDevData->satLookAheadEnabled == agTRUE) { AllPages[36] = 0x00;/* DRA bit is NOT set */ } else { AllPages[36] = 0x20;/* DRA bit is set */ } AllPages[37] = 0x00; AllPages[38] = 0x00; AllPages[39] = 0x00; AllPages[40] = 0x00; AllPages[41] = 0x00; AllPages[42] = 0x00; AllPages[43] = 0x00; /* MODESENSE_CONTROL_PAGE */ AllPages[44] = 0x0A; /* page code */ AllPages[45] = 0x0A; /* page length */ AllPages[46] = 0x02; /* only GLTSD bit is set */ if (pSatDevData->satNCQ == agTRUE) { AllPages[47] = 0x12; /* Queue Alogorithm modifier 1b and QErr 01b*/ } else { AllPages[47] = 0x02; /* Queue Alogorithm modifier 0b and QErr 01b */ } AllPages[48] = 0x00; AllPages[49] = 0x00; AllPages[50] = 0x00; /* obsolete */ AllPages[51] = 0x00; /* obsolete */ AllPages[52] = 0xFF; /* Busy Timeout Period */ AllPages[53] = 0xFF; /* Busy Timeout Period */ AllPages[54] = 0x00; /* we don't support non-000b value for the self-test code */ AllPages[55] = 0x00; /* we don't support non-000b value for the self-test code */ /* MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE */ AllPages[56] = 0x1C; /* page code */ AllPages[57] = 0x0A; /* page length */ if (pSatDevData->satSMARTEnabled == agTRUE) { AllPages[58] = 0x00;/* DEXCPT bit is NOT set */ } else { AllPages[58] = 0x08;/* DEXCPT bit is set */ } AllPages[59] = 0x00; /* We don't support MRIE */ AllPages[60] = 0x00; /* Interval timer vendor-specific */ AllPages[61] = 0x00; AllPages[62] = 0x00; AllPages[63] = 0x00; AllPages[64] = 0x00; /* REPORT-COUNT */ AllPages[65] = 0x00; AllPages[66] = 0x00; AllPages[67] = 0x00; osti_memcpy(pModeSense, &AllPages, lenRead); } else if (page == MODESENSE_CONTROL_PAGE) { TI_DBG5(("satModeSense6: MODESENSE_CONTROL_PAGE\n")); Control[0] = MODE_SENSE6_CONTROL_PAGE_LEN - 1; Control[1] = 0x00; /* default medium type (currently mounted medium type) */ Control[2] = 0x00; /* no write-protect, no support for DPO-FUA */ Control[3] = 0x08; /* block descriptor length */ /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ /* density code */ Control[4] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ Control[5] = 0x00; /* unspecified */ Control[6] = 0x00; /* unspecified */ Control[7] = 0x00; /* unspecified */ /* reserved */ Control[8] = 0x00; /* reserved */ /* Block size */ Control[9] = 0x00; Control[10] = 0x02; /* Block size is always 512 bytes */ Control[11] = 0x00; /* * Fill-up control mode page, SAT, Table 65 */ Control[12] = 0x0A; /* page code */ Control[13] = 0x0A; /* page length */ Control[14] = 0x02; /* only GLTSD bit is set */ if (pSatDevData->satNCQ == agTRUE) { Control[15] = 0x12; /* Queue Alogorithm modifier 1b and QErr 01b*/ } else { Control[15] = 0x02; /* Queue Alogorithm modifier 0b and QErr 01b */ } Control[16] = 0x00; Control[17] = 0x00; Control[18] = 0x00; /* obsolete */ Control[19] = 0x00; /* obsolete */ Control[20] = 0xFF; /* Busy Timeout Period */ Control[21] = 0xFF; /* Busy Timeout Period */ Control[22] = 0x00; /* we don't support non-000b value for the self-test code */ Control[23] = 0x00; /* we don't support non-000b value for the self-test code */ osti_memcpy(pModeSense, &Control, lenRead); } else if (page == MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE) { TI_DBG5(("satModeSense6: MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE\n")); RWErrorRecovery[0] = MODE_SENSE6_READ_WRITE_ERROR_RECOVERY_PAGE_LEN - 1; RWErrorRecovery[1] = 0x00; /* default medium type (currently mounted medium type) */ RWErrorRecovery[2] = 0x00; /* no write-protect, no support for DPO-FUA */ RWErrorRecovery[3] = 0x08; /* block descriptor length */ /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ /* density code */ RWErrorRecovery[4] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ RWErrorRecovery[5] = 0x00; /* unspecified */ RWErrorRecovery[6] = 0x00; /* unspecified */ RWErrorRecovery[7] = 0x00; /* unspecified */ /* reserved */ RWErrorRecovery[8] = 0x00; /* reserved */ /* Block size */ RWErrorRecovery[9] = 0x00; RWErrorRecovery[10] = 0x02; /* Block size is always 512 bytes */ RWErrorRecovery[11] = 0x00; /* * Fill-up Read-Write Error Recovery mode page, SAT, Table 66 */ RWErrorRecovery[12] = 0x01; /* page code */ RWErrorRecovery[13] = 0x0A; /* page length */ RWErrorRecovery[14] = 0x40; /* ARRE is set */ RWErrorRecovery[15] = 0x00; RWErrorRecovery[16] = 0x00; RWErrorRecovery[17] = 0x00; RWErrorRecovery[18] = 0x00; RWErrorRecovery[19] = 0x00; RWErrorRecovery[20] = 0x00; RWErrorRecovery[21] = 0x00; RWErrorRecovery[22] = 0x00; RWErrorRecovery[23] = 0x00; osti_memcpy(pModeSense, &RWErrorRecovery, lenRead); } else if (page == MODESENSE_CACHING) { TI_DBG5(("satModeSense6: MODESENSE_CACHING\n")); /* special case */ if (requestLen == 4 && page == MODESENSE_CACHING) { TI_DBG5(("satModeSense6: linux 2.6.8.24 support\n")); pModeSense[0] = 0x20 - 1; /* 32 - 1 */ pModeSense[1] = 0x00; /* default medium type (currently mounted medium type) */ pModeSense[2] = 0x00; /* no write-protect, no support for DPO-FUA */ pModeSense[3] = 0x08; /* block descriptor length */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } Caching[0] = MODE_SENSE6_CACHING_LEN - 1; Caching[1] = 0x00; /* default medium type (currently mounted medium type) */ Caching[2] = 0x00; /* no write-protect, no support for DPO-FUA */ Caching[3] = 0x08; /* block descriptor length */ /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ /* density code */ Caching[4] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ Caching[5] = 0x00; /* unspecified */ Caching[6] = 0x00; /* unspecified */ Caching[7] = 0x00; /* unspecified */ /* reserved */ Caching[8] = 0x00; /* reserved */ /* Block size */ Caching[9] = 0x00; Caching[10] = 0x02; /* Block size is always 512 bytes */ Caching[11] = 0x00; /* * Fill-up Caching mode page, SAT, Table 67 */ /* length 20 */ Caching[12] = 0x08; /* page code */ Caching[13] = 0x12; /* page length */ #ifdef NOT_YET if (pSatDevData->satWriteCacheEnabled == agTRUE) { Caching[14] = 0x04;/* WCE bit is set */ } else { Caching[14] = 0x00;/* WCE bit is NOT set */ } #endif Caching[14] = 0x00;/* WCE bit is NOT set */ Caching[15] = 0x00; Caching[16] = 0x00; Caching[17] = 0x00; Caching[18] = 0x00; Caching[19] = 0x00; Caching[20] = 0x00; Caching[21] = 0x00; Caching[22] = 0x00; Caching[23] = 0x00; if (pSatDevData->satLookAheadEnabled == agTRUE) { Caching[24] = 0x00;/* DRA bit is NOT set */ } else { Caching[24] = 0x20;/* DRA bit is set */ } Caching[25] = 0x00; Caching[26] = 0x00; Caching[27] = 0x00; Caching[28] = 0x00; Caching[29] = 0x00; Caching[30] = 0x00; Caching[31] = 0x00; osti_memcpy(pModeSense, &Caching, lenRead); } else if (page == MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE) { TI_DBG5(("satModeSense6: MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE\n")); InfoExceptionCtrl[0] = MODE_SENSE6_INFORMATION_EXCEPTION_CONTROL_PAGE_LEN - 1; InfoExceptionCtrl[1] = 0x00; /* default medium type (currently mounted medium type) */ InfoExceptionCtrl[2] = 0x00; /* no write-protect, no support for DPO-FUA */ InfoExceptionCtrl[3] = 0x08; /* block descriptor length */ /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ /* density code */ InfoExceptionCtrl[4] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ InfoExceptionCtrl[5] = 0x00; /* unspecified */ InfoExceptionCtrl[6] = 0x00; /* unspecified */ InfoExceptionCtrl[7] = 0x00; /* unspecified */ /* reserved */ InfoExceptionCtrl[8] = 0x00; /* reserved */ /* Block size */ InfoExceptionCtrl[9] = 0x00; InfoExceptionCtrl[10] = 0x02; /* Block size is always 512 bytes */ InfoExceptionCtrl[11] = 0x00; /* * Fill-up informational-exceptions control mode page, SAT, Table 68 */ InfoExceptionCtrl[12] = 0x1C; /* page code */ InfoExceptionCtrl[13] = 0x0A; /* page length */ if (pSatDevData->satSMARTEnabled == agTRUE) { InfoExceptionCtrl[14] = 0x00;/* DEXCPT bit is NOT set */ } else { InfoExceptionCtrl[14] = 0x08;/* DEXCPT bit is set */ } InfoExceptionCtrl[15] = 0x00; /* We don't support MRIE */ InfoExceptionCtrl[16] = 0x00; /* Interval timer vendor-specific */ InfoExceptionCtrl[17] = 0x00; InfoExceptionCtrl[18] = 0x00; InfoExceptionCtrl[19] = 0x00; InfoExceptionCtrl[20] = 0x00; /* REPORT-COUNT */ InfoExceptionCtrl[21] = 0x00; InfoExceptionCtrl[22] = 0x00; InfoExceptionCtrl[23] = 0x00; osti_memcpy(pModeSense, &InfoExceptionCtrl, lenRead); } else { /* Error */ TI_DBG1(("satModeSense6: Error page %d\n", page)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } /* there can be only underrun not overrun in error case */ if (requestLen > lenRead) { TI_DBG6(("satModeSense6 reporting underrun lenRead=0x%x requestLen=0x%x tiIORequest=%p\n", lenRead, requestLen, tiIORequest)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, requestLen - lenRead, agNULL, satIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI MODE SENSE (10). * * SAT implementation for SCSI MODE SENSE (10). * * \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. */ /*****************************************************************************/ GLOBAL bit32 satModeSense10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { scsiRspSense_t *pSense; bit32 requestLen; tiIniScsiCmnd_t *scsiCmnd; bit32 pageSupported; bit8 page; bit8 *pModeSense; /* Mode Sense data buffer */ satDeviceData_t *pSatDevData; bit8 PC; /* page control */ bit8 LLBAA; /* Long LBA Accepted */ bit32 index; bit8 AllPages[MODE_SENSE10_RETURN_ALL_PAGES_LLBAA_LEN]; bit8 Control[MODE_SENSE10_CONTROL_PAGE_LLBAA_LEN]; bit8 RWErrorRecovery[MODE_SENSE10_READ_WRITE_ERROR_RECOVERY_PAGE_LLBAA_LEN]; bit8 Caching[MODE_SENSE10_CACHING_LLBAA_LEN]; bit8 InfoExceptionCtrl[MODE_SENSE10_INFORMATION_EXCEPTION_CONTROL_PAGE_LLBAA_LEN]; bit8 lenRead = 0; TI_DBG5(("satModeSense10 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pModeSense = (bit8 *) tiScsiRequest->sglVirtualAddr; pSatDevData = satIOContext->pSatDevData; /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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_DBG2(("satModeSense10: return control\n")); return tiSuccess; } /* checking PC(Page Control) SAT revion 8, 8.5.3 p33 and 10.1.2, p66 */ PC = (bit8)((scsiCmnd->cdb[2]) & SCSI_MODE_SENSE10_PC_MASK); if (PC != 0) { 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(("satModeSense10: return due to PC value pc 0x%x\n", PC)); return tiSuccess; } /* finding LLBAA bit */ LLBAA = (bit8)((scsiCmnd->cdb[1]) & SCSI_MODE_SENSE10_LLBAA_MASK); /* reading PAGE CODE */ page = (bit8)((scsiCmnd->cdb[2]) & SCSI_MODE_SENSE10_PAGE_CODE_MASK); TI_DBG5(("satModeSense10: page=0x%x, tiDeviceHandle=%p tiIORequest=%p\n", page, tiDeviceHandle, tiIORequest)); requestLen = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; /* Based on page code value, returns a corresponding mode page note: no support for subpage */ switch(page) { case MODESENSE_RETURN_ALL_PAGES: /* return all pages */ case MODESENSE_CONTROL_PAGE: /* control */ case MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE: /* Read-Write Error Recovery */ case MODESENSE_CACHING: /* caching */ case MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE: /* informational exceptions control*/ pageSupported = agTRUE; break; case MODESENSE_VENDOR_SPECIFIC_PAGE: /* vendor specific */ default: pageSupported = agFALSE; break; } if (pageSupported == agFALSE) { TI_DBG1(("satModeSense10 *** ERROR *** not supported page 0x%x tiDeviceHandle=%p tiIORequest=%p\n", page, tiDeviceHandle, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } switch(page) { case MODESENSE_RETURN_ALL_PAGES: if (LLBAA) { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_RETURN_ALL_PAGES_LLBAA_LEN); } else { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_RETURN_ALL_PAGES_LEN); } break; case MODESENSE_CONTROL_PAGE: /* control */ if (LLBAA) { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_CONTROL_PAGE_LLBAA_LEN); } else { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_CONTROL_PAGE_LEN); } break; case MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE: /* Read-Write Error Recovery */ if (LLBAA) { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_READ_WRITE_ERROR_RECOVERY_PAGE_LLBAA_LEN); } else { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_READ_WRITE_ERROR_RECOVERY_PAGE_LEN); } break; case MODESENSE_CACHING: /* caching */ if (LLBAA) { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_CACHING_LLBAA_LEN); } else { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_CACHING_LEN); } break; case MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE: /* informational exceptions control*/ if (LLBAA) { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_INFORMATION_EXCEPTION_CONTROL_PAGE_LLBAA_LEN); } else { lenRead = (bit8)MIN(requestLen, MODE_SENSE10_INFORMATION_EXCEPTION_CONTROL_PAGE_LEN); } break; default: TI_DBG1(("satModeSense10: default error page %d\n", page)); break; } if (page == MODESENSE_RETURN_ALL_PAGES) { TI_DBG5(("satModeSense10: MODESENSE_RETURN_ALL_PAGES\n")); AllPages[0] = 0; AllPages[1] = (bit8)(lenRead - 2); AllPages[2] = 0x00; /* medium type: default medium type (currently mounted medium type) */ AllPages[3] = 0x00; /* device-specific param: no write-protect, no support for DPO-FUA */ if (LLBAA) { AllPages[4] = 0x00; /* reserved and LONGLBA */ AllPages[4] = (bit8)(AllPages[4] | 0x1); /* LONGLBA is set */ } else { AllPages[4] = 0x00; /* reserved and LONGLBA: LONGLBA is not set */ } AllPages[5] = 0x00; /* reserved */ AllPages[6] = 0x00; /* block descriptot length */ if (LLBAA) { AllPages[7] = 0x10; /* block descriptor length: LONGLBA is set. So, length is 16 */ } else { AllPages[7] = 0x08; /* block descriptor length: LONGLBA is NOT set. So, length is 8 */ } /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ if (LLBAA) { /* density code */ AllPages[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ AllPages[9] = 0x00; /* unspecified */ AllPages[10] = 0x00; /* unspecified */ AllPages[11] = 0x00; /* unspecified */ AllPages[12] = 0x00; /* unspecified */ AllPages[13] = 0x00; /* unspecified */ AllPages[14] = 0x00; /* unspecified */ AllPages[15] = 0x00; /* unspecified */ /* reserved */ AllPages[16] = 0x00; /* reserved */ AllPages[17] = 0x00; /* reserved */ AllPages[18] = 0x00; /* reserved */ AllPages[19] = 0x00; /* reserved */ /* Block size */ AllPages[20] = 0x00; AllPages[21] = 0x00; AllPages[22] = 0x02; /* Block size is always 512 bytes */ AllPages[23] = 0x00; } else { /* density code */ AllPages[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ AllPages[9] = 0x00; /* unspecified */ AllPages[10] = 0x00; /* unspecified */ AllPages[11] = 0x00; /* unspecified */ /* reserved */ AllPages[12] = 0x00; /* reserved */ /* Block size */ AllPages[13] = 0x00; AllPages[14] = 0x02; /* Block size is always 512 bytes */ AllPages[15] = 0x00; } if (LLBAA) { index = 24; } else { index = 16; } /* MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE */ AllPages[index+0] = 0x01; /* page code */ AllPages[index+1] = 0x0A; /* page length */ AllPages[index+2] = 0x40; /* ARRE is set */ AllPages[index+3] = 0x00; AllPages[index+4] = 0x00; AllPages[index+5] = 0x00; AllPages[index+6] = 0x00; AllPages[index+7] = 0x00; AllPages[index+8] = 0x00; AllPages[index+9] = 0x00; AllPages[index+10] = 0x00; AllPages[index+11] = 0x00; /* MODESENSE_CACHING */ /* * Fill-up Caching mode page, SAT, Table 67 */ /* length 20 */ AllPages[index+12] = 0x08; /* page code */ AllPages[index+13] = 0x12; /* page length */ #ifdef NOT_YET if (pSatDevData->satWriteCacheEnabled == agTRUE) { AllPages[index+14] = 0x04;/* WCE bit is set */ } else { AllPages[index+14] = 0x00;/* WCE bit is NOT set */ } #endif AllPages[index+14] = 0x00;/* WCE bit is NOT set */ AllPages[index+15] = 0x00; AllPages[index+16] = 0x00; AllPages[index+17] = 0x00; AllPages[index+18] = 0x00; AllPages[index+19] = 0x00; AllPages[index+20] = 0x00; AllPages[index+21] = 0x00; AllPages[index+22] = 0x00; AllPages[index+23] = 0x00; if (pSatDevData->satLookAheadEnabled == agTRUE) { AllPages[index+24] = 0x00;/* DRA bit is NOT set */ } else { AllPages[index+24] = 0x20;/* DRA bit is set */ } AllPages[index+25] = 0x00; AllPages[index+26] = 0x00; AllPages[index+27] = 0x00; AllPages[index+28] = 0x00; AllPages[index+29] = 0x00; AllPages[index+30] = 0x00; AllPages[index+31] = 0x00; /* MODESENSE_CONTROL_PAGE */ /* * Fill-up control mode page, SAT, Table 65 */ AllPages[index+32] = 0x0A; /* page code */ AllPages[index+33] = 0x0A; /* page length */ AllPages[index+34] = 0x02; /* only GLTSD bit is set */ if (pSatDevData->satNCQ == agTRUE) { AllPages[index+35] = 0x12; /* Queue Alogorithm modifier 1b and QErr 01b*/ } else { AllPages[index+35] = 0x02; /* Queue Alogorithm modifier 0b and QErr 01b */ } AllPages[index+36] = 0x00; AllPages[index+37] = 0x00; AllPages[index+38] = 0x00; /* obsolete */ AllPages[index+39] = 0x00; /* obsolete */ AllPages[index+40] = 0xFF; /* Busy Timeout Period */ AllPages[index+41] = 0xFF; /* Busy Timeout Period */ AllPages[index+42] = 0x00; /* we don't support non-000b value for the self-test code */ AllPages[index+43] = 0x00; /* we don't support non-000b value for the self-test code */ /* MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE */ /* * Fill-up informational-exceptions control mode page, SAT, Table 68 */ AllPages[index+44] = 0x1C; /* page code */ AllPages[index+45] = 0x0A; /* page length */ if (pSatDevData->satSMARTEnabled == agTRUE) { AllPages[index+46] = 0x00;/* DEXCPT bit is NOT set */ } else { AllPages[index+46] = 0x08;/* DEXCPT bit is set */ } AllPages[index+47] = 0x00; /* We don't support MRIE */ AllPages[index+48] = 0x00; /* Interval timer vendor-specific */ AllPages[index+49] = 0x00; AllPages[index+50] = 0x00; AllPages[index+51] = 0x00; AllPages[index+52] = 0x00; /* REPORT-COUNT */ AllPages[index+53] = 0x00; AllPages[index+54] = 0x00; AllPages[index+55] = 0x00; osti_memcpy(pModeSense, &AllPages, lenRead); } else if (page == MODESENSE_CONTROL_PAGE) { TI_DBG5(("satModeSense10: MODESENSE_CONTROL_PAGE\n")); Control[0] = 0; Control[1] = (bit8)(lenRead - 2); Control[2] = 0x00; /* medium type: default medium type (currently mounted medium type) */ Control[3] = 0x00; /* device-specific param: no write-protect, no support for DPO-FUA */ if (LLBAA) { Control[4] = 0x00; /* reserved and LONGLBA */ Control[4] = (bit8)(Control[4] | 0x1); /* LONGLBA is set */ } else { Control[4] = 0x00; /* reserved and LONGLBA: LONGLBA is not set */ } Control[5] = 0x00; /* reserved */ Control[6] = 0x00; /* block descriptot length */ if (LLBAA) { Control[7] = 0x10; /* block descriptor length: LONGLBA is set. So, length is 16 */ } else { Control[7] = 0x08; /* block descriptor length: LONGLBA is NOT set. So, length is 8 */ } /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ if (LLBAA) { /* density code */ Control[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ Control[9] = 0x00; /* unspecified */ Control[10] = 0x00; /* unspecified */ Control[11] = 0x00; /* unspecified */ Control[12] = 0x00; /* unspecified */ Control[13] = 0x00; /* unspecified */ Control[14] = 0x00; /* unspecified */ Control[15] = 0x00; /* unspecified */ /* reserved */ Control[16] = 0x00; /* reserved */ Control[17] = 0x00; /* reserved */ Control[18] = 0x00; /* reserved */ Control[19] = 0x00; /* reserved */ /* Block size */ Control[20] = 0x00; Control[21] = 0x00; Control[22] = 0x02; /* Block size is always 512 bytes */ Control[23] = 0x00; } else { /* density code */ Control[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ Control[9] = 0x00; /* unspecified */ Control[10] = 0x00; /* unspecified */ Control[11] = 0x00; /* unspecified */ /* reserved */ Control[12] = 0x00; /* reserved */ /* Block size */ Control[13] = 0x00; Control[14] = 0x02; /* Block size is always 512 bytes */ Control[15] = 0x00; } if (LLBAA) { index = 24; } else { index = 16; } /* * Fill-up control mode page, SAT, Table 65 */ Control[index+0] = 0x0A; /* page code */ Control[index+1] = 0x0A; /* page length */ Control[index+2] = 0x02; /* only GLTSD bit is set */ if (pSatDevData->satNCQ == agTRUE) { Control[index+3] = 0x12; /* Queue Alogorithm modifier 1b and QErr 01b*/ } else { Control[index+3] = 0x02; /* Queue Alogorithm modifier 0b and QErr 01b */ } Control[index+4] = 0x00; Control[index+5] = 0x00; Control[index+6] = 0x00; /* obsolete */ Control[index+7] = 0x00; /* obsolete */ Control[index+8] = 0xFF; /* Busy Timeout Period */ Control[index+9] = 0xFF; /* Busy Timeout Period */ Control[index+10] = 0x00; /* we don't support non-000b value for the self-test code */ Control[index+11] = 0x00; /* we don't support non-000b value for the self-test code */ osti_memcpy(pModeSense, &Control, lenRead); } else if (page == MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE) { TI_DBG5(("satModeSense10: MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE\n")); RWErrorRecovery[0] = 0; RWErrorRecovery[1] = (bit8)(lenRead - 2); RWErrorRecovery[2] = 0x00; /* medium type: default medium type (currently mounted medium type) */ RWErrorRecovery[3] = 0x00; /* device-specific param: no write-protect, no support for DPO-FUA */ if (LLBAA) { RWErrorRecovery[4] = 0x00; /* reserved and LONGLBA */ RWErrorRecovery[4] = (bit8)(RWErrorRecovery[4] | 0x1); /* LONGLBA is set */ } else { RWErrorRecovery[4] = 0x00; /* reserved and LONGLBA: LONGLBA is not set */ } RWErrorRecovery[5] = 0x00; /* reserved */ RWErrorRecovery[6] = 0x00; /* block descriptot length */ if (LLBAA) { RWErrorRecovery[7] = 0x10; /* block descriptor length: LONGLBA is set. So, length is 16 */ } else { RWErrorRecovery[7] = 0x08; /* block descriptor length: LONGLBA is NOT set. So, length is 8 */ } /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ if (LLBAA) { /* density code */ RWErrorRecovery[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ RWErrorRecovery[9] = 0x00; /* unspecified */ RWErrorRecovery[10] = 0x00; /* unspecified */ RWErrorRecovery[11] = 0x00; /* unspecified */ RWErrorRecovery[12] = 0x00; /* unspecified */ RWErrorRecovery[13] = 0x00; /* unspecified */ RWErrorRecovery[14] = 0x00; /* unspecified */ RWErrorRecovery[15] = 0x00; /* unspecified */ /* reserved */ RWErrorRecovery[16] = 0x00; /* reserved */ RWErrorRecovery[17] = 0x00; /* reserved */ RWErrorRecovery[18] = 0x00; /* reserved */ RWErrorRecovery[19] = 0x00; /* reserved */ /* Block size */ RWErrorRecovery[20] = 0x00; RWErrorRecovery[21] = 0x00; RWErrorRecovery[22] = 0x02; /* Block size is always 512 bytes */ RWErrorRecovery[23] = 0x00; } else { /* density code */ RWErrorRecovery[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ RWErrorRecovery[9] = 0x00; /* unspecified */ RWErrorRecovery[10] = 0x00; /* unspecified */ RWErrorRecovery[11] = 0x00; /* unspecified */ /* reserved */ RWErrorRecovery[12] = 0x00; /* reserved */ /* Block size */ RWErrorRecovery[13] = 0x00; RWErrorRecovery[14] = 0x02; /* Block size is always 512 bytes */ RWErrorRecovery[15] = 0x00; } if (LLBAA) { index = 24; } else { index = 16; } /* * Fill-up Read-Write Error Recovery mode page, SAT, Table 66 */ RWErrorRecovery[index+0] = 0x01; /* page code */ RWErrorRecovery[index+1] = 0x0A; /* page length */ RWErrorRecovery[index+2] = 0x40; /* ARRE is set */ RWErrorRecovery[index+3] = 0x00; RWErrorRecovery[index+4] = 0x00; RWErrorRecovery[index+5] = 0x00; RWErrorRecovery[index+6] = 0x00; RWErrorRecovery[index+7] = 0x00; RWErrorRecovery[index+8] = 0x00; RWErrorRecovery[index+9] = 0x00; RWErrorRecovery[index+10] = 0x00; RWErrorRecovery[index+11] = 0x00; osti_memcpy(pModeSense, &RWErrorRecovery, lenRead); } else if (page == MODESENSE_CACHING) { TI_DBG5(("satModeSense10: MODESENSE_CACHING\n")); Caching[0] = 0; Caching[1] = (bit8)(lenRead - 2); Caching[2] = 0x00; /* medium type: default medium type (currently mounted medium type) */ Caching[3] = 0x00; /* device-specific param: no write-protect, no support for DPO-FUA */ if (LLBAA) { Caching[4] = 0x00; /* reserved and LONGLBA */ Caching[4] = (bit8)(Caching[4] | 0x1); /* LONGLBA is set */ } else { Caching[4] = 0x00; /* reserved and LONGLBA: LONGLBA is not set */ } Caching[5] = 0x00; /* reserved */ Caching[6] = 0x00; /* block descriptot length */ if (LLBAA) { Caching[7] = 0x10; /* block descriptor length: LONGLBA is set. So, length is 16 */ } else { Caching[7] = 0x08; /* block descriptor length: LONGLBA is NOT set. So, length is 8 */ } /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ if (LLBAA) { /* density code */ Caching[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ Caching[9] = 0x00; /* unspecified */ Caching[10] = 0x00; /* unspecified */ Caching[11] = 0x00; /* unspecified */ Caching[12] = 0x00; /* unspecified */ Caching[13] = 0x00; /* unspecified */ Caching[14] = 0x00; /* unspecified */ Caching[15] = 0x00; /* unspecified */ /* reserved */ Caching[16] = 0x00; /* reserved */ Caching[17] = 0x00; /* reserved */ Caching[18] = 0x00; /* reserved */ Caching[19] = 0x00; /* reserved */ /* Block size */ Caching[20] = 0x00; Caching[21] = 0x00; Caching[22] = 0x02; /* Block size is always 512 bytes */ Caching[23] = 0x00; } else { /* density code */ Caching[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ Caching[9] = 0x00; /* unspecified */ Caching[10] = 0x00; /* unspecified */ Caching[11] = 0x00; /* unspecified */ /* reserved */ Caching[12] = 0x00; /* reserved */ /* Block size */ Caching[13] = 0x00; Caching[14] = 0x02; /* Block size is always 512 bytes */ Caching[15] = 0x00; } if (LLBAA) { index = 24; } else { index = 16; } /* * Fill-up Caching mode page, SAT, Table 67 */ /* length 20 */ Caching[index+0] = 0x08; /* page code */ Caching[index+1] = 0x12; /* page length */ #ifdef NOT_YET if (pSatDevData->satWriteCacheEnabled == agTRUE) { Caching[index+2] = 0x04;/* WCE bit is set */ } else { Caching[index+2] = 0x00;/* WCE bit is NOT set */ } #endif Caching[index+2] = 0x00;/* WCE bit is NOT set */ Caching[index+3] = 0x00; Caching[index+4] = 0x00; Caching[index+5] = 0x00; Caching[index+6] = 0x00; Caching[index+7] = 0x00; Caching[index+8] = 0x00; Caching[index+9] = 0x00; Caching[index+10] = 0x00; Caching[index+11] = 0x00; if (pSatDevData->satLookAheadEnabled == agTRUE) { Caching[index+12] = 0x00;/* DRA bit is NOT set */ } else { Caching[index+12] = 0x20;/* DRA bit is set */ } Caching[index+13] = 0x00; Caching[index+14] = 0x00; Caching[index+15] = 0x00; Caching[index+16] = 0x00; Caching[index+17] = 0x00; Caching[index+18] = 0x00; Caching[index+19] = 0x00; osti_memcpy(pModeSense, &Caching, lenRead); } else if (page == MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE) { TI_DBG5(("satModeSense10: MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE\n")); InfoExceptionCtrl[0] = 0; InfoExceptionCtrl[1] = (bit8)(lenRead - 2); InfoExceptionCtrl[2] = 0x00; /* medium type: default medium type (currently mounted medium type) */ InfoExceptionCtrl[3] = 0x00; /* device-specific param: no write-protect, no support for DPO-FUA */ if (LLBAA) { InfoExceptionCtrl[4] = 0x00; /* reserved and LONGLBA */ InfoExceptionCtrl[4] = (bit8)(InfoExceptionCtrl[4] | 0x1); /* LONGLBA is set */ } else { InfoExceptionCtrl[4] = 0x00; /* reserved and LONGLBA: LONGLBA is not set */ } InfoExceptionCtrl[5] = 0x00; /* reserved */ InfoExceptionCtrl[6] = 0x00; /* block descriptot length */ if (LLBAA) { InfoExceptionCtrl[7] = 0x10; /* block descriptor length: LONGLBA is set. So, length is 16 */ } else { InfoExceptionCtrl[7] = 0x08; /* block descriptor length: LONGLBA is NOT set. So, length is 8 */ } /* * Fill-up direct-access device block-descriptor, SAT, Table 19 */ if (LLBAA) { /* density code */ InfoExceptionCtrl[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ InfoExceptionCtrl[9] = 0x00; /* unspecified */ InfoExceptionCtrl[10] = 0x00; /* unspecified */ InfoExceptionCtrl[11] = 0x00; /* unspecified */ InfoExceptionCtrl[12] = 0x00; /* unspecified */ InfoExceptionCtrl[13] = 0x00; /* unspecified */ InfoExceptionCtrl[14] = 0x00; /* unspecified */ InfoExceptionCtrl[15] = 0x00; /* unspecified */ /* reserved */ InfoExceptionCtrl[16] = 0x00; /* reserved */ InfoExceptionCtrl[17] = 0x00; /* reserved */ InfoExceptionCtrl[18] = 0x00; /* reserved */ InfoExceptionCtrl[19] = 0x00; /* reserved */ /* Block size */ InfoExceptionCtrl[20] = 0x00; InfoExceptionCtrl[21] = 0x00; InfoExceptionCtrl[22] = 0x02; /* Block size is always 512 bytes */ InfoExceptionCtrl[23] = 0x00; } else { /* density code */ InfoExceptionCtrl[8] = 0x04; /* density-code : reserved for direct-access */ /* number of blocks */ InfoExceptionCtrl[9] = 0x00; /* unspecified */ InfoExceptionCtrl[10] = 0x00; /* unspecified */ InfoExceptionCtrl[11] = 0x00; /* unspecified */ /* reserved */ InfoExceptionCtrl[12] = 0x00; /* reserved */ /* Block size */ InfoExceptionCtrl[13] = 0x00; InfoExceptionCtrl[14] = 0x02; /* Block size is always 512 bytes */ InfoExceptionCtrl[15] = 0x00; } if (LLBAA) { index = 24; } else { index = 16; } /* * Fill-up informational-exceptions control mode page, SAT, Table 68 */ InfoExceptionCtrl[index+0] = 0x1C; /* page code */ InfoExceptionCtrl[index+1] = 0x0A; /* page length */ if (pSatDevData->satSMARTEnabled == agTRUE) { InfoExceptionCtrl[index+2] = 0x00;/* DEXCPT bit is NOT set */ } else { InfoExceptionCtrl[index+2] = 0x08;/* DEXCPT bit is set */ } InfoExceptionCtrl[index+3] = 0x00; /* We don't support MRIE */ InfoExceptionCtrl[index+4] = 0x00; /* Interval timer vendor-specific */ InfoExceptionCtrl[index+5] = 0x00; InfoExceptionCtrl[index+6] = 0x00; InfoExceptionCtrl[index+7] = 0x00; InfoExceptionCtrl[index+8] = 0x00; /* REPORT-COUNT */ InfoExceptionCtrl[index+9] = 0x00; InfoExceptionCtrl[index+10] = 0x00; InfoExceptionCtrl[index+11] = 0x00; osti_memcpy(pModeSense, &InfoExceptionCtrl, lenRead); } else { /* Error */ TI_DBG1(("satModeSense10: Error page %d\n", page)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (requestLen > lenRead) { TI_DBG1(("satModeSense10 reporting underrun lenRead=0x%x requestLen=0x%x tiIORequest=%p\n", lenRead, requestLen, tiIORequest)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, requestLen - lenRead, agNULL, satIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI VERIFY (10). * * SAT implementation for SCSI VERIFY (10). * * \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. */ /*****************************************************************************/ GLOBAL bit32 satVerify10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* For simple implementation, no byte comparison supported as of 4/5/06 */ scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ TI_DBG5(("satVerify10 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; /* checking BYTCHK */ if (scsiCmnd->cdb[1] & SCSI_VERIFY_BYTCHK_MASK) { /* should do the byte check but not supported in this version */ 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(("satVerify10: no byte checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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_DBG2(("satVerify10: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = scsiCmnd->cdb[7]; /* MSB */ TL[3] = scsiCmnd->cdb[8]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); /* cbd10; computing LBA and transfer length */ 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]; if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satVerify10: return LBA out of range, not EXT\n")); TI_DBG1(("satVerify10: cdb 0x%x 0x%x 0x%x 0x%x\n",scsiCmnd->cdb[2], scsiCmnd->cdb[3], scsiCmnd->cdb[4], scsiCmnd->cdb[5])); TI_DBG1(("satVerify10: lba 0x%x SAT_TR_LBA_LIMIT 0x%x\n", lba, SAT_TR_LBA_LIMIT)); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satVerify10: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } if (pSatDevData->sat48BitSupport == agTRUE) { TI_DBG5(("satVerify10: SAT_READ_VERIFY_SECTORS_EXT\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS_EXT; } else { TI_DBG5(("satVerify10: SAT_READ_VERIFY_SECTORS\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS; /* 0x40 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { TI_DBG1(("satVerify10: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satVerify10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedVerifyCB; } else { TI_DBG1(("satVerify10: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { TI_DBG1(("satVerify10: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } GLOBAL bit32 satChainedVerify( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; satIOContext_t *satOrgIOContext = agNULL; agsaFisRegHostToDevice_t *fis; bit32 agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; bit32 lba = 0; bit32 DenomTL = 0xFF; bit32 Remainder = 0; bit8 LBA[4]; /* 0 MSB, 3 LSB */ TI_DBG2(("satChainedVerify: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; osti_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_READ_VERIFY_SECTORS: DenomTL = 0xFF; break; case SAT_READ_VERIFY_SECTORS_EXT: DenomTL = 0xFFFF; break; default: TI_DBG1(("satChainedVerify: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xF000) >> (8 * 3)); /* MSB */ LBA[1] = (bit8)((lba & 0xF00) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xF0) >> 8); LBA[3] = (bit8)(lba & 0xF); /* LSB */ switch (satOrgIOContext->ATACmd) { case SAT_READ_VERIFY_SECTORS: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS; /* 0x40 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; break; case SAT_READ_VERIFY_SECTORS_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT; /* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; break; default: TI_DBG1(("satChainedVerify: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &satChainedVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satChainedVerify: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI VERIFY (12). * * SAT implementation for SCSI VERIFY (12). * * \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. */ /*****************************************************************************/ GLOBAL bit32 satVerify12( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* For simple implementation, no byte comparison supported as of 4/5/06 */ scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ TI_DBG5(("satVerify12 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; /* checking BYTCHK */ if (scsiCmnd->cdb[1] & SCSI_VERIFY_BYTCHK_MASK) { /* should do the byte check but not supported in this version */ 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(("satVerify12: no byte checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { 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(("satVerify12: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = scsiCmnd->cdb[6]; /* MSB */ TL[1] = scsiCmnd->cdb[7]; TL[2] = scsiCmnd->cdb[7]; TL[3] = scsiCmnd->cdb[8]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); lba = satComputeCDB12LBA(satIOContext); tl = satComputeCDB12TL(satIOContext); if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satVerify12: return LBA out of range, not EXT\n")); TI_DBG1(("satVerify12: cdb 0x%x 0x%x 0x%x 0x%x\n",scsiCmnd->cdb[2], scsiCmnd->cdb[3], scsiCmnd->cdb[4], scsiCmnd->cdb[5])); TI_DBG1(("satVerify12: lba 0x%x SAT_TR_LBA_LIMIT 0x%x\n", lba, SAT_TR_LBA_LIMIT)); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satVerify12: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } if (pSatDevData->sat48BitSupport == agTRUE) { TI_DBG5(("satVerify12: SAT_READ_VERIFY_SECTORS_EXT\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS_EXT; } else { TI_DBG5(("satVerify12: SAT_READ_VERIFY_SECTORS\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS; /* 0x40 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { TI_DBG1(("satVerify12: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satVerify12: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedVerifyCB; } else { TI_DBG1(("satVerify12: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { TI_DBG1(("satVerify10: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI VERIFY (16). * * SAT implementation for SCSI VERIFY (16). * * \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. */ /*****************************************************************************/ GLOBAL bit32 satVerify16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* For simple implementation, no byte comparison supported as of 4/5/06 */ scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 rangeChk = agFALSE; /* lba and tl range check */ bit32 limitChk = agFALSE; /* lba and tl range check */ TI_DBG5(("satVerify16 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; /* checking BYTCHK */ if (scsiCmnd->cdb[1] & SCSI_VERIFY_BYTCHK_MASK) { /* should do the byte check but not supported in this version */ 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(("satVerify16: no byte checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { 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_DBG2(("satVerify16: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; LBA[4] = scsiCmnd->cdb[6]; LBA[5] = scsiCmnd->cdb[7]; LBA[6] = scsiCmnd->cdb[8]; LBA[7] = scsiCmnd->cdb[9]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[10]; /* MSB */ TL[5] = scsiCmnd->cdb[11]; TL[6] = scsiCmnd->cdb[12]; TL[7] = scsiCmnd->cdb[13]; /* LSB */ rangeChk = satAddNComparebit64(LBA, TL); limitChk = satCompareLBALimitbit(LBA); lba = satComputeCDB16LBA(satIOContext); tl = satComputeCDB16TL(satIOContext); if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (limitChk) { TI_DBG1(("satVerify16: return LBA out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satVerify16: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } if (pSatDevData->sat48BitSupport == agTRUE) { TI_DBG5(("satVerify16: SAT_READ_VERIFY_SECTORS_EXT\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS_EXT; } else { TI_DBG5(("satVerify12: SAT_READ_VERIFY_SECTORS\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS; /* 0x40 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { TI_DBG1(("satVerify12: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satVerify12: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedVerifyCB; } else { TI_DBG1(("satVerify12: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { TI_DBG1(("satVerify10: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satFormatUnit. * * SAT implementation for SCSI satFormatUnit. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satFormatUnit( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* note: we don't support media certification in this version and IP bit satDevData->satFormatState will be agFalse since SAT does not actually sends any ATA command */ scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; bit32 index = 0; pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; TI_DBG5(("satFormatUnit:start\n")); /* checking opcode 1. FMTDATA bit == 0(no defect list header) 2. FMTDATA bit == 1 and DCRT bit == 1(defect list header is provided with DCRT bit set) */ if ( ((scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_FMTDATA_MASK) == 0) || ((scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_FMTDATA_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_DCRT_MASK)) ) { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); TI_DBG2(("satFormatUnit: return opcode\n")); return tiSuccess; } /* checking DEFECT LIST FORMAT and defect list length */ if ( (((scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_DEFECT_LIST_FORMAT_MASK) == 0x00) || ((scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_DEFECT_LIST_FORMAT_MASK) == 0x06)) ) { /* short parameter header */ if ((scsiCmnd->cdb[2] & SCSI_FORMAT_UNIT_LONGLIST_MASK) == 0x00) { index = 8; } /* long parameter header */ if ((scsiCmnd->cdb[2] & SCSI_FORMAT_UNIT_LONGLIST_MASK) == 0x01) { index = 10; } /* defect list length */ if ((scsiCmnd->cdb[index] != 0) || (scsiCmnd->cdb[index+1] != 0)) { 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(("satFormatUnit: return defect list format\n")); return tiSuccess; } } /* FMTDATA == 1 && CMPLIST == 1*/ if ( (scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_FMTDATA_MASK) && (scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_CMPLIST_MASK) ) { 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(("satFormatUnit: return cmplist\n")); return tiSuccess; } if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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(("satFormatUnit: return control\n")); return tiSuccess; } /* defect list header filed, if exists, SAT rev8, Table 37, p48 */ if (scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_FMTDATA_MASK) { /* case 1,2,3 */ /* IMMED 1; FOV 0; FOV 1, DCRT 1, IP 0 */ if ( (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IMMED_MASK) || ( !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_FOV_MASK)) || ( (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_FOV_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_DCRT_MASK) && !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IP_MASK)) ) { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); TI_DBG5(("satFormatUnit: return defect list case 1\n")); return tiSuccess; } /* case 4,5,6 */ /* 1. IMMED 0, FOV 1, DCRT 0, IP 0 2. IMMED 0, FOV 1, DCRT 0, IP 1 3. IMMED 0, FOV 1, DCRT 1, IP 1 */ if ( ( !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IMMED_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_FOV_MASK) && !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_DCRT_MASK) && !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IP_MASK) ) || ( !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IMMED_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_FOV_MASK) && !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_DCRT_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IP_MASK) ) || ( !(scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IMMED_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_FOV_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_DCRT_MASK) && (scsiCmnd->cdb[7] & SCSI_FORMAT_UNIT_IP_MASK) ) ) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG5(("satFormatUnit: return defect list case 2\n")); return tiSuccess; } } /* * Send the completion response now. */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); TI_DBG5(("satFormatUnit: return last\n")); return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satSendDiagnostic. * * SAT implementation for SCSI satSendDiagnostic. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSendDiagnostic( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 parmLen; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satSendDiagnostic:start\n")); /* reset satVerifyState */ pSatDevData->satVerifyState = 0; /* no pending diagnostic in background */ pSatDevData->satBGPendingDiag = agFALSE; /* table 27, 8.10 p39 SAT Rev8 */ /* 1. checking PF == 1 2. checking DEVOFFL == 1 3. checking UNITOFFL == 1 4. checking PARAMETER LIST LENGTH != 0 */ if ( (scsiCmnd->cdb[1] & SCSI_PF_MASK) || (scsiCmnd->cdb[1] & SCSI_DEVOFFL_MASK) || (scsiCmnd->cdb[1] & SCSI_UNITOFFL_MASK) || ( (scsiCmnd->cdb[3] != 0) || (scsiCmnd->cdb[4] != 0) ) ) { 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(("satSendDiagnostic: return PF, DEVOFFL, UNITOFFL, PARAM LIST\n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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_DBG2(("satSendDiagnostic: return control\n")); return tiSuccess; } parmLen = (scsiCmnd->cdb[3] << 8) + scsiCmnd->cdb[4]; /* checking SELFTEST bit*/ /* table 29, 8.10.3, p41 SAT Rev8 */ /* case 1 */ if ( !(scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agFALSE) ) { 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(("satSendDiagnostic: return Table 29 case 1\n")); return tiSuccess; } /* case 2 */ if ( !(scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agTRUE) && (pSatDevData->satSMARTEnabled == agFALSE) ) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_ATA_DEVICE_FEATURE_NOT_ENABLED, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG5(("satSendDiagnostic: return Table 29 case 2\n")); return tiSuccess; } /* case 3 see SELF TEST CODE later */ /* case 4 */ /* sends three ATA verify commands */ if ( ((scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agFALSE)) || ((scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agTRUE) && (pSatDevData->satSMARTEnabled == agFALSE)) ) { /* sector count 1, LBA 0 sector count 1, LBA MAX sector count 1, LBA random */ if (pSatDevData->sat48BitSupport == agTRUE) { /* sends READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: return Table 29 case 4\n")); return (status); } /* case 5 */ if ( (scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agTRUE) && (pSatDevData->satSMARTEnabled == agTRUE) ) { /* sends SMART EXECUTE OFF-LINE IMMEDIATE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE;/* 0xB0 */ fis->h.features = 0xD4; /* FIS features NA */ fis->d.lbaLow = 0x81; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: return Table 29 case 5\n")); return (status); } /* SAT rev8 Table29 p41 case 3*/ /* checking SELF TEST CODE*/ if ( !(scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agTRUE) && (pSatDevData->satSMARTEnabled == agTRUE) ) { /* SAT rev8 Table28 p40 */ /* finding self-test code */ switch ((scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_TEST_CODE_MASK) >> 5) { case 1: pSatDevData->satBGPendingDiag = agTRUE; ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); /* sends SMART EXECUTE OFF-LINE IMMEDIATE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE;/* 0x40 */ fis->h.features = 0xD4; /* FIS features NA */ fis->d.lbaLow = 0x01; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: return Table 28 case 1\n")); return (status); case 2: pSatDevData->satBGPendingDiag = agTRUE; ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); /* issuing SMART EXECUTE OFF-LINE IMMEDIATE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE;/* 0x40 */ fis->h.features = 0xD4; /* FIS features NA */ fis->d.lbaLow = 0x02; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: return Table 28 case 2\n")); return (status); case 4: /* For simplicity, no abort is supported Returns good status need a flag in device data for previously sent background Send Diagnostic */ if (parmLen != 0) { /* check condition */ 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(("satSendDiagnostic: case 4, non zero ParmLen %d\n", parmLen)); return tiSuccess; } if (pSatDevData->satBGPendingDiag == agTRUE) { /* sends SMART EXECUTE OFF-LINE IMMEDIATE abort */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE;/* 0x40 */ fis->h.features = 0xD4; /* FIS features NA */ fis->d.lbaLow = 0x7F; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: send SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE case 3\n")); TI_DBG5(("satSendDiagnostic: Table 28 case 4\n")); return (status); } else { /* check condition */ 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(("satSendDiagnostic: case 4, no pending diagnostic in background\n")); TI_DBG5(("satSendDiagnostic: Table 28 case 4\n")); return tiSuccess; } break; case 5: /* issuing SMART EXECUTE OFF-LINE IMMEDIATE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE;/* 0x40 */ fis->h.features = 0xD4; /* FIS features NA */ fis->d.lbaLow = 0x81; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: return Table 28 case 5\n")); return (status); case 6: /* issuing SMART EXECUTE OFF-LINE IMMEDIATE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE;/* 0x40 */ fis->h.features = 0xD4; /* FIS features NA */ fis->d.lbaLow = 0x82; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satSendDiagnostic: return Table 28 case 6\n")); return (status); case 0: case 3: /* fall through */ case 7: /* fall through */ default: break; }/* switch */ /* returns the results of default self-testing, which is good */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); TI_DBG5(("satSendDiagnostic: return Table 28 case 0,3,7 and default\n")); return tiSuccess; } ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); TI_DBG5(("satSendDiagnostic: return last\n")); return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satSendDiagnostic_1. * * SAT implementation for SCSI satSendDiagnostic_1. * Sub function of satSendDiagnostic. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSendDiagnostic_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* SAT Rev9, Table29, p41 send 2nd SAT_READ_VERIFY_SECTORS(_EXT) */ bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; TI_DBG5(("satSendDiagnostic_1 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; /* sector count 1, LBA MAX */ if (pSatDevData->sat48BitSupport == agTRUE) { /* sends READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = pSatDevData->satMaxLBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = pSatDevData->satMaxLBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = pSatDevData->satMaxLBA[5]; /* FIS LBA (23:16) */ fis->d.lbaLowExp = pSatDevData->satMaxLBA[4]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = pSatDevData->satMaxLBA[3]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = pSatDevData->satMaxLBA[2]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = pSatDevData->satMaxLBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = pSatDevData->satMaxLBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = pSatDevData->satMaxLBA[5]; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = (bit8)((0x4 << 4) | (pSatDevData->satMaxLBA[4] & 0xF)); /* DEV and LBA 27:24 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satSendDiagnostic_2. * * SAT implementation for SCSI satSendDiagnostic_2. * Sub function of satSendDiagnostic. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSendDiagnostic_2( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* SAT Rev9, Table29, p41 send 3rd SAT_READ_VERIFY_SECTORS(_EXT) */ bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; TI_DBG5(("satSendDiagnostic_2 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; /* sector count 1, LBA Random */ if (pSatDevData->sat48BitSupport == agTRUE) { /* sends READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0x7F; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0x7F; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satStartStopUnit. * * SAT implementation for SCSI satStartStopUnit. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satStartStopUnit( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satStartStopUnit:start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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(("satStartStopUnit: return control\n")); return tiSuccess; } /* Spec p55, Table 48 checking START and LOEJ bit */ /* case 1 */ if ( !(scsiCmnd->cdb[4] & SCSI_START_MASK) && !(scsiCmnd->cdb[4] & SCSI_LOEJ_MASK) ) { if ( (scsiCmnd->cdb[1] & SCSI_IMMED_MASK) ) { /* immed bit , SAT rev 8, 9.11.2.1 p 54*/ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); TI_DBG5(("satStartStopUnit: return table48 case 1-1\n")); return tiSuccess; } /* sends FLUSH CACHE or FLUSH CACHE EXT */ if (pSatDevData->sat48BitSupport == agTRUE) { /* FLUSH CACHE EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_FLUSH_CACHE_EXT; /* 0xEA */ fis->h.features = 0; /* FIS reserve */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; } else { /* FLUSH CACHE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_FLUSH_CACHE; /* 0xE7 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satStartStopUnit: return table48 case 1\n")); return (status); } /* case 2 */ else if ( (scsiCmnd->cdb[4] & SCSI_START_MASK) && !(scsiCmnd->cdb[4] & SCSI_LOEJ_MASK) ) { /* immed bit , SAT rev 8, 9.11.2.1 p 54*/ if ( (scsiCmnd->cdb[1] & SCSI_IMMED_MASK) ) { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); TI_DBG5(("satStartStopUnit: return table48 case 2 1\n")); return tiSuccess; } /* sends READ_VERIFY_SECTORS(_EXT) sector count 1, any LBA between zero to Maximum */ if (pSatDevData->sat48BitSupport == agTRUE) { /* READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0x01; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x00; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0x00; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0x00; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0x00; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0x00; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0x01; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x00; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0x00; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satStartStopUnit: return table48 case 2 2\n")); return status; } /* case 3 */ else if ( !(scsiCmnd->cdb[4] & SCSI_START_MASK) && (scsiCmnd->cdb[4] & SCSI_LOEJ_MASK) ) { if(pSatDevData->satRemovableMedia && pSatDevData->satRemovableMediaEnabled) { /* support for removal media */ /* immed bit , SAT rev 8, 9.11.2.1 p 54*/ if ( (scsiCmnd->cdb[1] & SCSI_IMMED_MASK) ) { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); TI_DBG5(("satStartStopUnit: return table48 case 3 1\n")); return tiSuccess; } /* sends MEDIA EJECT */ /* Media Eject fis */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_MEDIA_EJECT; /* 0xED */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; /* sector count zero */ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { /* no support for removal media */ 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_DBG5(("satStartStopUnit: return Table 29 case 3 2\n")); return tiSuccess; } } /* case 4 */ else /* ( (scsiCmnd->cdb[4] & SCSI_START_MASK) && (scsiCmnd->cdb[4] & SCSI_LOEJ_MASK) ) */ { 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_DBG5(("satStartStopUnit: return Table 29 case 4\n")); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satStartStopUnit_1. * * SAT implementation for SCSI satStartStopUnit_1. * Sub function of satStartStopUnit * * \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. */ /*****************************************************************************/ GLOBAL bit32 satStartStopUnit_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* SAT Rev 8, Table 48, 9.11.3 p55 sends STANDBY */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; TI_DBG5(("satStartStopUnit_1 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* STANDBY */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_STANDBY; /* 0xE2 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0; /* 0 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satStartStopUnit_1 return status %d\n", status)); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satRead10_2. * * SAT implementation for SCSI satRead10_2 * Sub function of satRead10 * * \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. */ /*****************************************************************************/ GLOBAL bit32 satRead10_2( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* externally generated ATA cmd, there is corresponding scsi cmnd called by satStartStopUnit() or maybe satRead10() */ bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; TI_DBG5(("satReadVerifySectorsNoChain: start\n")); /* specifying ReadVerifySectors has no chain */ pSatDevData->satVerifyState = 0xFFFFFFFF; if (pSatDevData->sat48BitSupport == agTRUE) { /* READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0x7F; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0x00; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0xF1; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0x5F; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0xFF; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x4E; /* 01001110 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0x7F; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0x00; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = 0x4E; /* 01001110 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satReadVerifySectorsNoChain: return last\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteSame10. * * SAT implementation for SCSI satWriteSame10. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteSame10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWriteSame10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satWriteSame10: return control\n")); return tiSuccess; } /* checking LBDATA and PBDATA */ /* case 1 */ if ( !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_LBDATA_MASK) && !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_PBDATA_MASK)) { TI_DBG5(("satWriteSame10: case 1\n")); /* spec 9.26.2, Table 62, p64, case 1*/ /* normal case just like write in 9.17.1 */ if ( pSatDevData->sat48BitSupport != agTRUE ) { /* writeSame10 but no support for 48 bit addressing -> problem in transfer length. Therefore, return check condition */ 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(("satWriteSame10: return internal checking\n")); return tiSuccess; } /* cdb10; computing LBA and transfer length */ 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]; /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b (footnote) When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) /* SAT_TR_LBA_LIMIT is 2^28, 0x10000000 */ { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWriteSame10: return LBA out of range\n")); return tiSuccess; } } if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA */ /* can't fit the transfer length since WRITE DMA has 1 byte for sector count */ TI_DBG5(("satWriteSame10: case 1-2 !!! error due to writeSame10\n")); 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 ); return tiSuccess; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS is chosen for easier implemetation */ /* can't fit the transfer length since WRITE DMA has 1 byte for sector count */ TI_DBG5(("satWriteSame10: case 1-1 !!! error due to writesame10\n")); 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 ); return tiSuccess; } } /* end of case 1 and 2 */ /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ /* WRITE DMA EXT is chosen since WRITE SAME does not have FUA bit */ TI_DBG5(("satWriteSame10: case 1-3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (tl == 0) { /* error check ATA spec, p125, 6.17.29 pSatDevData->satMaxUserAddrSectors should be 0x0FFFFFFF and allowed value is 0x0FFFFFFF - 1 */ if (pSatDevData->satMaxUserAddrSectors > 0x0FFFFFFF) { TI_DBG5(("satWriteSame10: case 3 !!! warning can't fit sectors\n")); 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 ); return tiSuccess; } } /* one sector at a time */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT is chosen for easier implemetation */ TI_DBG5(("satWriteSame10: case 1-4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (tl == 0) { /* error check ATA spec, p125, 6.17.29 pSatDevData->satMaxUserAddrSectors should be 0x0FFFFFFF and allowed value is 0x0FFFFFFF - 1 */ if (pSatDevData->satMaxUserAddrSectors > 0x0FFFFFFF) { TI_DBG5(("satWriteSame10: case 4 !!! warning can't fit sectors\n")); 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 ); return tiSuccess; } } /* one sector at a time */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWriteSame10: case 1-5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG5(("satWriteSame10: case 1-5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ if (tl == 0) { /* error check ATA spec, p125, 6.17.29 pSatDevData->satMaxUserAddrSectors should be 0x0FFFFFFF and allowed value is 0x0FFFFFFF - 1 */ if (pSatDevData->satMaxUserAddrSectors > 0x0FFFFFFF) { TI_DBG5(("satWriteSame10: case 4 !!! warning can't fit sectors\n")); 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 ); return tiSuccess; } } /* one sector at a time */ fis->h.features = 1; /* FIS sector count (7:0) */ fis->d.featuresExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* NO FUA bit in the WRITE SAME 10 */ fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /* end of case 1 */ else if ( !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_LBDATA_MASK) && (scsiCmnd->cdb[1] & SCSI_WRITE_SAME_PBDATA_MASK)) { /* spec 9.26.2, Table 62, p64, case 2*/ 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_DBG5(("satWriteSame10: return Table 62 case 2\n")); return tiSuccess; } else if ( (scsiCmnd->cdb[1] & SCSI_WRITE_SAME_LBDATA_MASK) && !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_PBDATA_MASK)) { TI_DBG5(("satWriteSame10: Table 62 case 3\n")); } else /* ( (scsiCmnd->cdb[1] & SCSI_WRITE_SAME_LBDATA_MASK) && (scsiCmnd->cdb[1] & SCSI_WRITE_SAME_PBDATA_MASK)) */ { /* spec 9.26.2, Table 62, p64, case 4*/ 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_DBG5(("satWriteSame10: return Table 62 case 4\n")); return tiSuccess; } return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteSame10_1. * * SAT implementation for SCSI WRITESANE10 and send FIS request to LL layer. * This is used when WRITESAME10 is divided into multiple ATA commands * * \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 * \param lba: LBA * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteSame10_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, bit32 lba ) { /* sends SAT_WRITE_DMA_EXT */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 lba1, lba2 ,lba3, lba4; TI_DBG5(("satWriteSame10_1 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* MSB */ lba1 = (bit8)((lba & 0xFF000000) >> (8*3)); lba2 = (bit8)((lba & 0x00FF0000) >> (8*2)); lba3 = (bit8)((lba & 0x0000FF00) >> (8*1)); /* LSB */ lba4 = (bit8)(lba & 0x000000FF); /* SAT_WRITE_DMA_EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = lba4; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = lba3; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = lba2; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = lba1; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ /* one sector at a time */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satWriteSame10_1 return status %d\n", status)); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteSame10_2. * * SAT implementation for SCSI WRITESANE10 and send FIS request to LL layer. * This is used when WRITESAME10 is divided into multiple ATA commands * * \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 * \param lba: LBA * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteSame10_2( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, bit32 lba ) { /* sends SAT_WRITE_SECTORS_EXT */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 lba1, lba2 ,lba3, lba4; TI_DBG5(("satWriteSame10_2 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* MSB */ lba1 = (bit8)((lba & 0xFF000000) >> (8*3)); lba2 = (bit8)((lba & 0x00FF0000) >> (8*2)); lba3 = (bit8)((lba & 0x0000FF00) >> (8*1)); /* LSB */ lba4 = (bit8)(lba & 0x000000FF); /* SAT_WRITE_SECTORS_EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = lba4; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = lba3; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = lba2; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = lba1; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ /* one sector at a time */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satWriteSame10_2 return status %d\n", status)); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteSame10_3. * * SAT implementation for SCSI WRITESANE10 and send FIS request to LL layer. * This is used when WRITESAME10 is divided into multiple ATA commands * * \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 * \param lba: LBA * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteSame10_3( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, bit32 lba ) { /* sends SAT_WRITE_FPDMA_QUEUED */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 lba1, lba2 ,lba3, lba4; TI_DBG5(("satWriteSame10_3 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* MSB */ lba1 = (bit8)((lba & 0xFF000000) >> (8*3)); lba2 = (bit8)((lba & 0x00FF0000) >> (8*2)); lba3 = (bit8)((lba & 0x0000FF00) >> (8*1)); /* LSB */ lba4 = (bit8)(lba & 0x000000FF); /* SAT_WRITE_FPDMA_QUEUED */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ /* one sector at a time */ fis->h.features = 1; /* FIS sector count (7:0) */ fis->d.featuresExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = lba4; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = lba3; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = lba2; /* FIS LBA (23:16) */ /* NO FUA bit in the WRITE SAME 10 */ fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = lba1; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satWriteSame10_2 return status %d\n", status)); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteSame16. * * SAT implementation for SCSI satWriteSame16. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteSame16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { scsiRspSense_t *pSense; pSense = satIOContext->pSense; TI_DBG5(("satWriteSame16:start\n")); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, /* == &satIntIo->satOrgTiIORequest */ tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG5(("satWriteSame16: return internal checking\n")); return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satLogSense_1. * * Part of SAT implementation for SCSI satLogSense. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satLogSense_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; TI_DBG5(("satLogSense_1: start\n")); /* SAT Rev 8, 10.2.4 p74 */ if ( pSatDevData->sat48BitSupport == agTRUE ) { TI_DBG5(("satLogSense_1: case 2-1 sends READ LOG EXT\n")); /* sends READ LOG EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_LOG_EXT; /* 0x2F */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0x07; /* 0x07 */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0x01; /* 1 sector counts */ fis->d.sectorCountExp = 0x00; /* 1 sector counts */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { TI_DBG5(("satLogSense_1: case 2-2 sends SMART READ LOG\n")); /* sends SMART READ LOG */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_READ_LOG; /* 0x2F */ fis->h.features = 0x00; /* 0xd5 */ fis->d.lbaLow = 0x06; /* 0x06 */ fis->d.lbaMid = 0x00; /* 0x4f */ fis->d.lbaHigh = 0x00; /* 0xc2 */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0x01; /* */ fis->d.sectorCountExp = 0x00; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satSMARTEnable. * * Part of SAT implementation for SCSI satLogSense. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSMARTEnable( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; TI_DBG4(("satSMARTEnable entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* * Send the SAT_SMART_ENABLE_OPERATIONS command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_ENABLE_OPERATIONS; /* 0xB0 */ fis->h.features = 0xD8; fis->d.lbaLow = 0; fis->d.lbaMid = 0x4F; fis->d.lbaHigh = 0xC2; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSMARTEnableCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satLogSense_3. * * Part of SAT implementation for SCSI satLogSense. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satLogSense_3( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; TI_DBG4(("satLogSense_3 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* sends READ LOG EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_READ_LOG; /* 0x2F */ fis->h.features = 0xD5; /* 0xd5 */ fis->d.lbaLow = 0x06; /* 0x06 */ fis->d.lbaMid = 0x4F; /* 0x4f */ fis->d.lbaHigh = 0xC2; /* 0xc2 */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0x01; /* 1 sector counts */ fis->d.sectorCountExp = 0x00; /* 1 sector counts */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satLogSense_2. * * Part of SAT implementation for SCSI satLogSense. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satLogSense_2( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; TI_DBG4(("satLogSense_2 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis = satIOContext->pFis; /* sends READ LOG EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_LOG_EXT; /* 0x2F */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0x07; /* 0x07 */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0x01; /* 1 sector counts */ fis->d.sectorCountExp = 0x00; /* 1 sector counts */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satLogSenseAllocate. * * Part of SAT implementation for SCSI satLogSense. * * \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 * \param payloadSize: size of payload to be allocated. * \param flag: flag value * * \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. * \note * - flag values: LOG_SENSE_0, LOG_SENSE_1, LOG_SENSE_2 */ /*****************************************************************************/ GLOBAL bit32 satLogSenseAllocate( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, bit32 payloadSize, bit32 flag ) { satDeviceData_t *pSatDevData; tdIORequestBody_t *tdIORequestBody; satInternalIo_t *satIntIo = agNULL; satIOContext_t *satIOContext2; bit32 status; TI_DBG4(("satLogSense_2 entry: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); pSatDevData = satIOContext->pSatDevData; /* create internal satIOContext */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, /* original request */ pSatDevData, payloadSize, satIntIo); if (satIntIo == agNULL) { /* memory allocation failure */ satFreeIntIoResource( tiRoot, pSatDevData, satIntIo); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, satIOContext->interruptContext ); TI_DBG4(("satLogSense_2: fail in allocation\n")); return tiSuccess; } /* end of memory allocation failure */ satIntIo->satOrgTiIORequest = tiIORequest; 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 = satIOContext->interruptContext; satIOContext2->satIntIoContext = satIntIo; satIOContext2->ptiDeviceHandle = tiDeviceHandle; satIOContext2->satOrgIOContext = satIOContext; if (flag == LOG_SENSE_0) { /* SAT_SMART_ENABLE_OPERATIONS */ status = satSMARTEnable( tiRoot, &(satIntIo->satIntTiIORequest), tiDeviceHandle, &(satIntIo->satIntTiScsiXchg), satIOContext2); } else if (flag == LOG_SENSE_1) { /* SAT_READ_LOG_EXT */ status = satLogSense_2( tiRoot, &(satIntIo->satIntTiIORequest), tiDeviceHandle, &(satIntIo->satIntTiScsiXchg), satIOContext2); } else { /* SAT_SMART_READ_LOG */ /* SAT_READ_LOG_EXT */ status = satLogSense_3( tiRoot, &(satIntIo->satIntTiIORequest), tiDeviceHandle, &(satIntIo->satIntTiScsiXchg), satIOContext2); } if (status != tiSuccess) { satFreeIntIoResource( tiRoot, pSatDevData, satIntIo); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, satIOContext->interruptContext ); return tiSuccess; } return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satLogSense. * * SAT implementation for SCSI satLogSense. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satLogSense( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pLogPage; /* Log Page data buffer */ bit32 flag = 0; bit16 AllocLen = 0; /* allocation length */ bit8 AllLogPages[8]; bit16 lenRead = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pLogPage = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG5(("satLogSense: start\n")); osti_memset(&AllLogPages, 0, 8); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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_DBG2(("satLogSense: return control\n")); return tiSuccess; } AllocLen = (bit8)((scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]); /* checking PC (Page Control) */ /* nothing */ /* special cases */ if (AllocLen == 4) { TI_DBG1(("satLogSense: AllocLen is 4\n")); switch (scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK) { case LOGSENSE_SUPPORTED_LOG_PAGES: TI_DBG5(("satLogSense: case LOGSENSE_SUPPORTED_LOG_PAGES\n")); /* SAT Rev 8, 10.2.5 p76 */ if (pSatDevData->satSMARTFeatureSet == agTRUE) { /* add informational exception log */ flag = 1; if (pSatDevData->satSMARTSelfTest == agTRUE) { /* add Self-Test results log page */ flag = 2; } } else { /* only supported, no informational exception log, no Self-Test results log page */ flag = 0; } lenRead = 4; AllLogPages[0] = LOGSENSE_SUPPORTED_LOG_PAGES; /* page code */ AllLogPages[1] = 0; /* reserved */ switch (flag) { case 0: /* only supported */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = 1; /* page length */ break; case 1: /* supported and informational exception log */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = 2; /* page length */ break; case 2: /* supported and informational exception log */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = 3; /* page length */ break; default: TI_DBG1(("satLogSense: error unallowed flag value %d\n", flag)); break; } osti_memcpy(pLogPage, &AllLogPages, lenRead); break; case LOGSENSE_SELFTEST_RESULTS_PAGE: TI_DBG5(("satLogSense: case LOGSENSE_SUPPORTED_LOG_PAGES\n")); lenRead = 4; AllLogPages[0] = LOGSENSE_SELFTEST_RESULTS_PAGE; /* page code */ AllLogPages[1] = 0; /* reserved */ /* page length = SELFTEST_RESULTS_LOG_PAGE_LENGTH - 1 - 3 = 400 = 0x190 */ AllLogPages[2] = 0x01; AllLogPages[3] = 0x90; /* page length */ osti_memcpy(pLogPage, &AllLogPages, lenRead); break; case LOGSENSE_INFORMATION_EXCEPTIONS_PAGE: TI_DBG5(("satLogSense: case LOGSENSE_SUPPORTED_LOG_PAGES\n")); lenRead = 4; AllLogPages[0] = LOGSENSE_INFORMATION_EXCEPTIONS_PAGE; /* page code */ AllLogPages[1] = 0; /* reserved */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = INFORMATION_EXCEPTIONS_LOG_PAGE_LENGTH - 1 - 3; /* page length */ osti_memcpy(pLogPage, &AllLogPages, lenRead); break; default: TI_DBG1(("satLogSense: default Page Code 0x%x\n", scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK)); 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 ); return tiSuccess; } ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } /* if */ /* SAT rev8 Table 11 p30*/ /* checking Page Code */ switch (scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK) { case LOGSENSE_SUPPORTED_LOG_PAGES: TI_DBG5(("satLogSense: case 1\n")); /* SAT Rev 8, 10.2.5 p76 */ if (pSatDevData->satSMARTFeatureSet == agTRUE) { /* add informational exception log */ flag = 1; if (pSatDevData->satSMARTSelfTest == agTRUE) { /* add Self-Test results log page */ flag = 2; } } else { /* only supported, no informational exception log, no Self-Test results log page */ flag = 0; } AllLogPages[0] = 0; /* page code */ AllLogPages[1] = 0; /* reserved */ switch (flag) { case 0: /* only supported */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = 1; /* page length */ AllLogPages[4] = 0x00; /* supported page list */ lenRead = (bit8)(MIN(AllocLen, 5)); break; case 1: /* supported and informational exception log */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = 2; /* page length */ AllLogPages[4] = 0x00; /* supported page list */ AllLogPages[5] = 0x10; /* supported page list */ lenRead = (bit8)(MIN(AllocLen, 6)); break; case 2: /* supported and informational exception log */ AllLogPages[2] = 0; /* page length */ AllLogPages[3] = 3; /* page length */ AllLogPages[4] = 0x00; /* supported page list */ AllLogPages[5] = 0x10; /* supported page list */ AllLogPages[6] = 0x2F; /* supported page list */ lenRead = (bit8)(MIN(AllocLen, 7)); break; default: TI_DBG1(("satLogSense: error unallowed flag value %d\n", flag)); break; } osti_memcpy(pLogPage, &AllLogPages, lenRead); /* comparing allocation length to Log Page byte size */ /* SPC-4, 4.3.4.6, p28 */ if (AllocLen > lenRead ) { TI_DBG1(("satLogSense reporting underrun lenRead=0x%x AllocLen=0x%x tiIORequest=%p\n", lenRead, AllocLen, tiIORequest)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, AllocLen - lenRead, agNULL, satIOContext->interruptContext ); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } break; case LOGSENSE_SELFTEST_RESULTS_PAGE: TI_DBG5(("satLogSense: case 2\n")); /* checking SMART self-test */ if (pSatDevData->satSMARTSelfTest == agFALSE) { TI_DBG5(("satLogSense: case 2 no SMART Self Test\n")); 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 ); } else { /* if satSMARTEnabled is false, send SMART_ENABLE_OPERATIONS */ if (pSatDevData->satSMARTEnabled == agFALSE) { TI_DBG5(("satLogSense: case 2 calling satSMARTEnable\n")); status = satLogSenseAllocate(tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext, 0, LOG_SENSE_0 ); return status; } else { /* SAT Rev 8, 10.2.4 p74 */ if ( pSatDevData->sat48BitSupport == agTRUE ) { TI_DBG5(("satLogSense: case 2-1 sends READ LOG EXT\n")); status = satLogSenseAllocate(tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext, 512, LOG_SENSE_1 ); return status; } else { TI_DBG5(("satLogSense: case 2-2 sends SMART READ LOG\n")); status = satLogSenseAllocate(tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext, 512, LOG_SENSE_2 ); return status; } } } break; case LOGSENSE_INFORMATION_EXCEPTIONS_PAGE: TI_DBG5(("satLogSense: case 3\n")); /* checking SMART feature set */ if (pSatDevData->satSMARTFeatureSet == agFALSE) { 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 ); } else { /* checking SMART feature enabled */ if (pSatDevData->satSMARTEnabled == agFALSE) { satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_ATA_DEVICE_FEATURE_NOT_ENABLED, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); } else { /* SAT Rev 8, 10.2.3 p72 */ TI_DBG5(("satLogSense: case 3 sends SMART RETURN STATUS\n")); /* sends SMART RETURN STATUS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_RETURN_STATUS;/* 0xB0 */ fis->h.features = 0xDA; /* FIS features */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMid = 0x4F; /* FIS LBA (15:8 ) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHigh = 0xC2; /* FIS LBA (23:16) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } break; default: TI_DBG1(("satLogSense: default Page Code 0x%x\n", scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK)); 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 ); break; } /* end switch */ return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satModeSelect6. * * SAT implementation for SCSI satModeSelect6. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satModeSelect6( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pLogPage; /* Log Page data buffer */ bit32 StartingIndex = 0; bit8 PageCode = 0; bit32 chkCnd = agFALSE; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pLogPage = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG5(("satModeSelect6: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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_DBG2(("satModeSelect6: return control\n")); return tiSuccess; } /* checking PF bit */ if ( !(scsiCmnd->cdb[1] & SCSI_MODE_SELECT6_PF_MASK)) { 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(("satModeSelect6: PF bit check \n")); return tiSuccess; } /* checking Block Descriptor Length on Mode parameter header(6)*/ if (pLogPage[3] == 8) { /* mode parameter block descriptor exists */ PageCode = (bit8)(pLogPage[12] & 0x3F); /* page code and index is 4 + 8 */ StartingIndex = 12; } else if (pLogPage[3] == 0) { /* mode parameter block descriptor does not exist */ PageCode = (bit8)(pLogPage[4] & 0x3F); /* page code and index is 4 + 0 */ StartingIndex = 4; ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } else { TI_DBG1(("satModeSelect6: return mode parameter block descriptor 0x%x\n", pLogPage[3])); /* no more than one mode parameter block descriptor shall be supported */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } switch (PageCode) /* page code */ { case MODESELECT_CONTROL_PAGE: TI_DBG1(("satModeSelect6: Control mode page\n")); /* compare pLogPage to expected value (SAT Table 65, p67) If not match, return check condition */ if ( pLogPage[StartingIndex+1] != 0x0A || pLogPage[StartingIndex+2] != 0x02 || (pSatDevData->satNCQ == agTRUE && pLogPage[StartingIndex+3] != 0x12) || (pSatDevData->satNCQ == agFALSE && pLogPage[StartingIndex+3] != 0x02) || (pLogPage[StartingIndex+4] & BIT3_MASK) != 0x00 || /* SWP bit */ (pLogPage[StartingIndex+4] & BIT4_MASK) != 0x00 || /* UA_INTLCK_CTRL */ (pLogPage[StartingIndex+4] & BIT5_MASK) != 0x00 || /* UA_INTLCK_CTRL */ (pLogPage[StartingIndex+5] & BIT0_MASK) != 0x00 || /* AUTOLOAD MODE */ (pLogPage[StartingIndex+5] & BIT1_MASK) != 0x00 || /* AUTOLOAD MODE */ (pLogPage[StartingIndex+5] & BIT2_MASK) != 0x00 || /* AUTOLOAD MODE */ (pLogPage[StartingIndex+5] & BIT6_MASK) != 0x00 || /* TAS bit */ pLogPage[StartingIndex+8] != 0xFF || pLogPage[StartingIndex+9] != 0xFF || pLogPage[StartingIndex+10] != 0x00 || pLogPage[StartingIndex+11] != 0x00 ) { chkCnd = agTRUE; } if (chkCnd == agTRUE) { 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(("satModeSelect10: unexpected values\n")); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return tiSuccess; break; case MODESELECT_READ_WRITE_ERROR_RECOVERY_PAGE: TI_DBG1(("satModeSelect6: Read-Write Error Recovery mode page\n")); if ( (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_AWRE_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_RC_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_EER_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_PER_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_DTE_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_DCR_MASK) || (pLogPage[StartingIndex + 10]) || (pLogPage[StartingIndex + 11]) ) { TI_DBG5(("satModeSelect6: return check condition \n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { TI_DBG5(("satModeSelect6: return GOOD \n")); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } break; case MODESELECT_CACHING: /* SAT rev8 Table67, p69*/ TI_DBG5(("satModeSelect6: Caching mode page\n")); if ( (pLogPage[StartingIndex + 2] & 0xFB) || /* 1111 1011 */ (pLogPage[StartingIndex + 3]) || (pLogPage[StartingIndex + 4]) || (pLogPage[StartingIndex + 5]) || (pLogPage[StartingIndex + 6]) || (pLogPage[StartingIndex + 7]) || (pLogPage[StartingIndex + 8]) || (pLogPage[StartingIndex + 9]) || (pLogPage[StartingIndex + 10]) || (pLogPage[StartingIndex + 11]) || (pLogPage[StartingIndex + 12] & 0xC1) || /* 1100 0001 */ (pLogPage[StartingIndex + 13]) || (pLogPage[StartingIndex + 14]) || (pLogPage[StartingIndex + 15]) ) { TI_DBG1(("satModeSelect6: return check condition \n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { /* sends ATA SET FEATURES based on WCE bit */ if ( !(pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_WCE_MASK) ) { TI_DBG5(("satModeSelect6: disable write cache\n")); /* sends SET FEATURES */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0x82; /* disable write cache */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { TI_DBG5(("satModeSelect6: enable write cache\n")); /* sends SET FEATURES */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0x02; /* enable write cache */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } break; case MODESELECT_INFORMATION_EXCEPTION_CONTROL_PAGE: TI_DBG5(("satModeSelect6: Informational Exception Control mode page\n")); if ( (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_PERF_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_TEST_MASK) ) { TI_DBG1(("satModeSelect6: return check condition \n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { /* sends either ATA SMART ENABLE/DISABLE OPERATIONS based on DEXCPT bit */ if ( !(pLogPage[StartingIndex + 2] & 0x08) ) { TI_DBG5(("satModeSelect6: enable information exceptions reporting\n")); /* sends SMART ENABLE OPERATIONS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_ENABLE_OPERATIONS; /* 0xB0 */ fis->h.features = 0xD8; /* enable */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0x4F; /* 0x4F */ fis->d.lbaHigh = 0xC2; /* 0xC2 */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { TI_DBG5(("satModeSelect6: disable information exceptions reporting\n")); /* sends SMART DISABLE OPERATIONS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_DISABLE_OPERATIONS; /* 0xB0 */ fis->h.features = 0xD9; /* disable */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0x4F; /* 0x4F */ fis->d.lbaHigh = 0xC2; /* 0xC2 */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } break; default: TI_DBG1(("satModeSelect6: Error unknown page code 0x%x\n", pLogPage[12])); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satModeSelect6n10_1. * * This function is part of implementation of ModeSelect6 and ModeSelect10. * When ModeSelect6 or ModeSelect10 is coverted into multiple ATA commands, * this function is used. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satModeSelect6n10_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* sends either ATA SET FEATURES based on DRA bit */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 *pLogPage; /* Log Page data buffer */ bit32 StartingIndex = 0; fis = satIOContext->pFis; pLogPage = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG5(("satModeSelect6_1: start\n")); /* checking Block Descriptor Length on Mode parameter header(6)*/ if (pLogPage[3] == 8) { /* mode parameter block descriptor exists */ StartingIndex = 12; } else { /* mode parameter block descriptor does not exist */ StartingIndex = 4; } /* sends ATA SET FEATURES based on DRA bit */ if ( !(pLogPage[StartingIndex + 12] & SCSI_MODE_SELECT6_DRA_MASK) ) { TI_DBG5(("satModeSelect6_1: enable read look-ahead feature\n")); /* sends SET FEATURES */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0xAA; /* enable read look-ahead */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { TI_DBG5(("satModeSelect6_1: disable read look-ahead feature\n")); /* sends SET FEATURES */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0x55; /* disable read look-ahead */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satModeSelect10. * * SAT implementation for SCSI satModeSelect10. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satModeSelect10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pLogPage; /* Log Page data buffer */ bit16 BlkDescLen = 0; /* Block Descriptor Length */ bit32 StartingIndex = 0; bit8 PageCode = 0; bit32 chkCnd = agFALSE; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pLogPage = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG5(("satModeSelect10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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_DBG2(("satModeSelect10: return control\n")); return tiSuccess; } /* checking PF bit */ if ( !(scsiCmnd->cdb[1] & SCSI_MODE_SELECT10_PF_MASK)) { 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(("satModeSelect10: PF bit check \n")); return tiSuccess; } BlkDescLen = (bit8)((pLogPage[6] << 8) + pLogPage[7]); /* checking Block Descriptor Length on Mode parameter header(10) and LONGLBA bit*/ if ( (BlkDescLen == 8) && !(pLogPage[4] & SCSI_MODE_SELECT10_LONGLBA_MASK) ) { /* mode parameter block descriptor exists and length is 8 byte */ PageCode = (bit8)(pLogPage[16] & 0x3F); /* page code and index is 8 + 8 */ StartingIndex = 16; } else if ( (BlkDescLen == 16) && (pLogPage[4] & SCSI_MODE_SELECT10_LONGLBA_MASK) ) { /* mode parameter block descriptor exists and length is 16 byte */ PageCode = (bit8)(pLogPage[24] & 0x3F); /* page code and index is 8 + 16 */ StartingIndex = 24; } else if (BlkDescLen == 0) { /* mode parameter block descriptor does not exist */ PageCode = (bit8)(pLogPage[8] & 0x3F); /* page code and index is 8 + 0 */ StartingIndex = 8; ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } else { TI_DBG1(("satModeSelect10: return mode parameter block descriptor 0x%x\n", BlkDescLen)); /* no more than one mode parameter block descriptor shall be supported */ satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } /* for debugging only */ if (StartingIndex == 8) { tdhexdump("startingindex 8", (bit8 *)pLogPage, 8); } else if(StartingIndex == 16) { if (PageCode == MODESELECT_CACHING) { tdhexdump("startingindex 16", (bit8 *)pLogPage, 16+20); } else { tdhexdump("startingindex 16", (bit8 *)pLogPage, 16+12); } } else { if (PageCode == MODESELECT_CACHING) { tdhexdump("startingindex 24", (bit8 *)pLogPage, 24+20); } else { tdhexdump("startingindex 24", (bit8 *)pLogPage, 24+12); } } switch (PageCode) /* page code */ { case MODESELECT_CONTROL_PAGE: TI_DBG5(("satModeSelect10: Control mode page\n")); /* compare pLogPage to expected value (SAT Table 65, p67) If not match, return check condition */ if ( pLogPage[StartingIndex+1] != 0x0A || pLogPage[StartingIndex+2] != 0x02 || (pSatDevData->satNCQ == agTRUE && pLogPage[StartingIndex+3] != 0x12) || (pSatDevData->satNCQ == agFALSE && pLogPage[StartingIndex+3] != 0x02) || (pLogPage[StartingIndex+4] & BIT3_MASK) != 0x00 || /* SWP bit */ (pLogPage[StartingIndex+4] & BIT4_MASK) != 0x00 || /* UA_INTLCK_CTRL */ (pLogPage[StartingIndex+4] & BIT5_MASK) != 0x00 || /* UA_INTLCK_CTRL */ (pLogPage[StartingIndex+5] & BIT0_MASK) != 0x00 || /* AUTOLOAD MODE */ (pLogPage[StartingIndex+5] & BIT1_MASK) != 0x00 || /* AUTOLOAD MODE */ (pLogPage[StartingIndex+5] & BIT2_MASK) != 0x00 || /* AUTOLOAD MODE */ (pLogPage[StartingIndex+5] & BIT6_MASK) != 0x00 || /* TAS bit */ pLogPage[StartingIndex+8] != 0xFF || pLogPage[StartingIndex+9] != 0xFF || pLogPage[StartingIndex+10] != 0x00 || pLogPage[StartingIndex+11] != 0x00 ) { chkCnd = agTRUE; } if (chkCnd == agTRUE) { 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(("satModeSelect10: unexpected values\n")); } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return tiSuccess; break; case MODESELECT_READ_WRITE_ERROR_RECOVERY_PAGE: TI_DBG5(("satModeSelect10: Read-Write Error Recovery mode page\n")); if ( (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_AWRE_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_RC_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_EER_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_PER_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_DTE_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_DCR_MASK) || (pLogPage[StartingIndex + 10]) || (pLogPage[StartingIndex + 11]) ) { TI_DBG1(("satModeSelect10: return check condition \n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { TI_DBG2(("satModeSelect10: return GOOD \n")); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } break; case MODESELECT_CACHING: /* SAT rev8 Table67, p69*/ TI_DBG5(("satModeSelect10: Caching mode page\n")); if ( (pLogPage[StartingIndex + 2] & 0xFB) || /* 1111 1011 */ (pLogPage[StartingIndex + 3]) || (pLogPage[StartingIndex + 4]) || (pLogPage[StartingIndex + 5]) || (pLogPage[StartingIndex + 6]) || (pLogPage[StartingIndex + 7]) || (pLogPage[StartingIndex + 8]) || (pLogPage[StartingIndex + 9]) || (pLogPage[StartingIndex + 10]) || (pLogPage[StartingIndex + 11]) || (pLogPage[StartingIndex + 12] & 0xC1) || /* 1100 0001 */ (pLogPage[StartingIndex + 13]) || (pLogPage[StartingIndex + 14]) || (pLogPage[StartingIndex + 15]) ) { TI_DBG1(("satModeSelect10: return check condition \n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { /* sends ATA SET FEATURES based on WCE bit */ if ( !(pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_WCE_MASK) ) { TI_DBG5(("satModeSelect10: disable write cache\n")); /* sends SET FEATURES */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0x82; /* disable write cache */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { TI_DBG5(("satModeSelect10: enable write cache\n")); /* sends SET FEATURES */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SET_FEATURES; /* 0xEF */ fis->h.features = 0x02; /* enable write cache */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } break; case MODESELECT_INFORMATION_EXCEPTION_CONTROL_PAGE: TI_DBG5(("satModeSelect10: Informational Exception Control mode page\n")); if ( (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_PERF_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_TEST_MASK) ) { TI_DBG1(("satModeSelect10: return check condition \n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { /* sends either ATA SMART ENABLE/DISABLE OPERATIONS based on DEXCPT bit */ if ( !(pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_DEXCPT_MASK) ) { TI_DBG5(("satModeSelect10: enable information exceptions reporting\n")); /* sends SMART ENABLE OPERATIONS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_ENABLE_OPERATIONS; /* 0xB0 */ fis->h.features = 0xD8; /* enable */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0x4F; /* 0x4F */ fis->d.lbaHigh = 0xC2; /* 0xC2 */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } else { TI_DBG5(("satModeSelect10: disable information exceptions reporting\n")); /* sends SMART DISABLE OPERATIONS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_SMART_DISABLE_OPERATIONS; /* 0xB0 */ fis->h.features = 0xD9; /* disable */ fis->d.lbaLow = 0; /* */ fis->d.lbaMid = 0x4F; /* 0x4F */ fis->d.lbaHigh = 0xC2; /* 0xC2 */ fis->d.device = 0; /* */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* */ fis->d.sectorCount = 0; /* */ fis->d.sectorCountExp = 0; /* */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } break; default: TI_DBG1(("satModeSelect10: Error unknown page code 0x%x\n", pLogPage[12])); satSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satSynchronizeCache10. * * SAT implementation for SCSI satSynchronizeCache10. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSynchronizeCache10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satSynchronizeCache10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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_DBG2(("satSynchronizeCache10: return control\n")); return tiSuccess; } /* checking IMMED bit */ if (scsiCmnd->cdb[1] & SCSI_SYNC_CACHE_IMMED_MASK) { TI_DBG1(("satSynchronizeCache10: GOOD status due to IMMED bit\n")); /* return GOOD status first here */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } /* sends FLUSH CACHE or FLUSH CACHE EXT */ if (pSatDevData->sat48BitSupport == agTRUE) { TI_DBG5(("satSynchronizeCache10: sends FLUSH CACHE EXT\n")); /* FLUSH CACHE EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_FLUSH_CACHE_EXT; /* 0xEA */ fis->h.features = 0; /* FIS reserve */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; } else { TI_DBG5(("satSynchronizeCache10: sends FLUSH CACHE\n")); /* FLUSH CACHE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_FLUSH_CACHE; /* 0xE7 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; } agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSynchronizeCache10n16CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satSynchronizeCache16. * * SAT implementation for SCSI satSynchronizeCache16. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSynchronizeCache16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satSynchronizeCache16: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { 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(("satSynchronizeCache16: return control\n")); return tiSuccess; } /* checking IMMED bit */ if (scsiCmnd->cdb[1] & SCSI_SYNC_CACHE_IMMED_MASK) { TI_DBG1(("satSynchronizeCache16: GOOD status due to IMMED bit\n")); /* return GOOD status first here */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } /* sends FLUSH CACHE or FLUSH CACHE EXT */ if (pSatDevData->sat48BitSupport == agTRUE) { TI_DBG5(("satSynchronizeCache16: sends FLUSH CACHE EXT\n")); /* FLUSH CACHE EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_FLUSH_CACHE_EXT; /* 0xEA */ fis->h.features = 0; /* FIS reserve */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; } else { TI_DBG5(("satSynchronizeCache16: sends FLUSH CACHE\n")); /* FLUSH CACHE */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_FLUSH_CACHE; /* 0xE7 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.device = 0; /* FIS DEV is discared in SATA */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved4 = 0; fis->d.reserved5 = 0; } agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satSynchronizeCache10n16CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteAndVerify10. * * SAT implementation for SCSI satWriteAndVerify10. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteAndVerify10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* combination of write10 and verify10 */ bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWriteAndVerify10: start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { 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(("satWriteAndVerify10: BYTCHK bit checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satWriteAndVerify10: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = scsiCmnd->cdb[7]; /* MSB */ TL[3] = scsiCmnd->cdb[8]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); /* cbd10; computing LBA and transfer length */ 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]; /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWriteAndVerify10: return LBA out of range\n")); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satWrite10: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ TI_DBG5(("satWriteAndVerify10: case 2 !!!\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* can't fit the transfer length */ TI_DBG5(("satWriteAndVerify10: case 1 !!!\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWriteAndVerify10: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA_EXT; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWriteAndVerify10: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWriteAndVerify10: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG5(("satWriteAndVerify10: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUED */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satWriteAndVerify10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedWriteNVerifyCB; } else { TI_DBG1(("satWriteAndVerify10: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } #ifdef REMOVED GLOBAL bit32 satWriteAndVerify10( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* combination of write10 and verify10 */ bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWriteAndVerify10: start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { 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(("satWriteAndVerify10: BYTCHK bit checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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_DBG2(("satWriteAndVerify10: return control\n")); return tiSuccess; } /* let's do write10 */ if ( pSatDevData->sat48BitSupport != agTRUE ) { /* writeandverify10 but no support for 48 bit addressing -> problem in transfer length(sector count) */ 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(("satWriteAndVerify10: return internal checking\n")); return tiSuccess; } /* cbd10; computing LBA and transfer length */ 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]; /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWriteAndVerify10: return LBA out of range\n")); return tiSuccess; } } /* case 1 and 2 */ if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ TI_DBG5(("satWriteAndVerify10: case 2 !!!\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (0x4 << 4) | (scsiCmnd->cdb[2] & 0xF); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* can't fit the transfer length */ TI_DBG5(("satWriteAndVerify10: case 1 !!!\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (0x4 << 4) | (scsiCmnd->cdb[2] & 0xF); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWriteAndVerify10: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWriteAndVerify10: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWriteAndVerify10: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG5(("satWriteAndVerify10: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satWriteAndVerify10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } #endif /* REMOVED */ #ifdef REMOVED /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteAndVerify10_1. * * SAT implementation for SCSI satWriteAndVerify10_1. * Sub function of satWriteAndVerify10 * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteAndVerify10_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWriteAndVerify10_1: start\n")); if (pSatDevData->sat48BitSupport == agTRUE) { fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satWriteAndVerify10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG1(("satWriteAndVerify10_1: return status %d\n", status)); return (status); } else { /* can't fit in SAT_READ_VERIFY_SECTORS becasue of Sector Count and LBA */ TI_DBG1(("satWriteAndVerify10_1: can't fit in SAT_READ_VERIFY_SECTORS\n")); return tiError; } return tiSuccess; } #endif /* REMOVED */ /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteAndVerify12. * * SAT implementation for SCSI satWriteAndVerify12. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteAndVerify12( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* combination of write12 and verify12 temp: since write12 is not support (due to internal checking), no support */ bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; bit32 rangeChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWriteAndVerify12: start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { 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(("satWriteAndVerify12: BYTCHK bit checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { 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_DBG2(("satWriteAndVerify12: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = scsiCmnd->cdb[6]; /* MSB */ TL[1] = scsiCmnd->cdb[7]; TL[2] = scsiCmnd->cdb[7]; TL[3] = scsiCmnd->cdb[8]; /* LSB */ rangeChk = satAddNComparebit32(LBA, TL); lba = satComputeCDB12LBA(satIOContext); tl = satComputeCDB12TL(satIOContext); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (lba > SAT_TR_LBA_LIMIT - 1) { satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); TI_DBG1(("satWriteAndVerify12: return LBA out of range, not EXT\n")); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satWriteAndVerify12: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWriteAndVerify12: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWriteAndVerify12: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWriteAndVerify12: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA_EXT; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWriteAndVerify12: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWriteAndVerify12: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satWriteAndVerify12: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[9]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE12_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[8]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } satIOContext->currentLBA = lba; // satIOContext->OrgLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; satIOContext->LoopNum2 = LoopNum; if (LoopNum == 1) { TI_DBG5(("satWriteAndVerify12: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedWriteNVerifyCB; } else { TI_DBG1(("satWriteAndVerify12: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } GLOBAL bit32 satNonChainedWriteNVerify_Verify( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satNonChainedWriteNVerify_Verify: start\n")); if (pSatDevData->sat48BitSupport == agTRUE) { fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedWriteNVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG1(("satNonChainedWriteNVerify_Verify: return status %d\n", status)); return (status); } else { /* can't fit in SAT_READ_VERIFY_SECTORS becasue of Sector Count and LBA */ TI_DBG1(("satNonChainedWriteNVerify_Verify: can't fit in SAT_READ_VERIFY_SECTORS\n")); return tiError; } } GLOBAL bit32 satChainedWriteNVerify_Write( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* Assumption: error check on lba and tl has been done in satWrite*() lba = lba + tl; */ bit32 status; satIOContext_t *satOrgIOContext = agNULL; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; bit32 lba = 0; bit32 DenomTL = 0xFF; bit32 Remainder = 0; bit8 LBA[4]; /* 0 MSB, 3 LSB */ TI_DBG1(("satChainedWriteNVerify_Write: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; scsiCmnd = satOrgIOContext->pScsiCmnd; osti_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_WRITE_DMA: DenomTL = 0xFF; break; case SAT_WRITE_SECTORS: DenomTL = 0xFF; break; case SAT_WRITE_DMA_EXT: DenomTL = 0xFFFF; break; case SAT_WRITE_DMA_FUA_EXT: DenomTL = 0xFFFF; break; case SAT_WRITE_SECTORS_EXT: DenomTL = 0xFFFF; break; case SAT_WRITE_FPDMA_QUEUED: DenomTL = 0xFFFF; break; default: TI_DBG1(("satChainedWriteNVerify_Write: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xF000) >> (8 * 3)); /* MSB */ LBA[1] = (bit8)((lba & 0xF00) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xF0) >> 8); LBA[3] = (bit8)(lba & 0xF); /* LSB */ switch (satOrgIOContext->ATACmd) { case SAT_WRITE_DMA: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; break; case SAT_WRITE_SECTORS: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; break; case SAT_WRITE_DMA_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x3D */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; break; case SAT_WRITE_SECTORS_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; break; case SAT_WRITE_FPDMA_QUEUED: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE10_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = LBA[0];; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->h.features = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.featuresExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->h.features = 0xFF; /* FIS sector count (7:0) */ fis->d.featuresExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; break; default: TI_DBG1(("satChainedWriteNVerify_Write: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &satChainedWriteNVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satChainedWriteNVerify_Write: return\n")); return (status); } /* similar to write12 and verify10; this will be similar to verify12 */ GLOBAL bit32 satChainedWriteNVerify_Start_Verify( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* deal with transfer length; others have been handled previously at this point; no LBA check; no range check; */ bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satDeviceData_t *pSatDevData; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satChainedWriteNVerify_Start_Verify: start\n")); osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = scsiCmnd->cdb[6]; /* MSB */ TL[1] = scsiCmnd->cdb[7]; TL[2] = scsiCmnd->cdb[7]; TL[3] = scsiCmnd->cdb[8]; /* LSB */ lba = satComputeCDB12LBA(satIOContext); tl = satComputeCDB12TL(satIOContext); if (pSatDevData->sat48BitSupport == agTRUE) { TI_DBG5(("satChainedWriteNVerify_Start_Verify: SAT_READ_VERIFY_SECTORS_EXT\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set 01000000 */ fis->d.lbaLowExp = scsiCmnd->cdb[2]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[7]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS_EXT; } else { TI_DBG5(("satChainedWriteNVerify_Start_Verify: SAT_READ_VERIFY_SECTORS\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS; /* 0x40 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[4]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[3]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[2] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[8]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; satIOContext->ATACmd = SAT_READ_VERIFY_SECTORS; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { TI_DBG1(("satChainedWriteNVerify_Start_Verify: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satChainedWriteNVerify_Start_Verify: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedWriteNVerifyCB; } else { TI_DBG1(("satChainedWriteNVerify_Start_Verify: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_VERIFY_SECTORS) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { TI_DBG1(("satChainedWriteNVerify_Start_Verify: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } GLOBAL bit32 satChainedWriteNVerify_Verify( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; satIOContext_t *satOrgIOContext = agNULL; agsaFisRegHostToDevice_t *fis; bit32 agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; bit32 lba = 0; bit32 DenomTL = 0xFF; bit32 Remainder = 0; bit8 LBA[4]; /* 0 MSB, 3 LSB */ TI_DBG2(("satChainedWriteNVerify_Verify: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; osti_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_READ_VERIFY_SECTORS: DenomTL = 0xFF; break; case SAT_READ_VERIFY_SECTORS_EXT: DenomTL = 0xFFFF; break; default: TI_DBG1(("satChainedWriteNVerify_Verify: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xF000) >> (8 * 3)); /* MSB */ LBA[1] = (bit8)((lba & 0xF00) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xF0) >> 8); LBA[3] = (bit8)(lba & 0xF); /* LSB */ switch (satOrgIOContext->ATACmd) { case SAT_READ_VERIFY_SECTORS: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS; /* 0x40 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[0] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)Remainder; /* FIS sector count (7:0) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ } fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; break; case SAT_READ_VERIFY_SECTORS_EXT: fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT; /* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[3]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[2]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[1]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[0]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ if (satOrgIOContext->LoopNum == 1) { /* last loop */ fis->d.sectorCount = (bit8)(Remainder & 0xFF); /* FIS sector count (7:0) */ fis->d.sectorCountExp = (bit8)((Remainder & 0xFF00) >> 8); /* FIS sector count (15:8) */ } else { fis->d.sectorCount = 0xFF; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0xFF; /* FIS sector count (15:8) */ } fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; break; default: TI_DBG1(("satChainedWriteNVerify_Verify: error incorrect ata command 0x%x\n", satIOContext->ATACmd)); return tiError; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &satChainedWriteNVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satChainedWriteNVerify_Verify: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteAndVerify16. * * SAT implementation for SCSI satWriteAndVerify16. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satWriteAndVerify16( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* combination of write16 and verify16 since write16 has 8 bytes LBA -> problem ATA LBA(upto 6 bytes), no support */ bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 rangeChk = agFALSE; /* lba and tl range check */ bit32 limitChk = agFALSE; /* lba and tl range check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; TI_DBG5(("satWriteAndVerify16:start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { 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(("satWriteAndVerify16: BYTCHK bit checking \n")); return tiSuccess; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { 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_DBG2(("satWriteAndVerify16: return control\n")); return tiSuccess; } osti_memset(LBA, 0, sizeof(LBA)); osti_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = scsiCmnd->cdb[2]; /* MSB */ LBA[1] = scsiCmnd->cdb[3]; LBA[2] = scsiCmnd->cdb[4]; LBA[3] = scsiCmnd->cdb[5]; LBA[4] = scsiCmnd->cdb[6]; LBA[5] = scsiCmnd->cdb[7]; LBA[6] = scsiCmnd->cdb[8]; LBA[7] = scsiCmnd->cdb[9]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[10]; /* MSB */ TL[5] = scsiCmnd->cdb[11]; TL[6] = scsiCmnd->cdb[12]; TL[7] = scsiCmnd->cdb[13]; /* LSB */ rangeChk = satAddNComparebit64(LBA, TL); limitChk = satCompareLBALimitbit(LBA); lba = satComputeCDB16LBA(satIOContext); tl = satComputeCDB16TL(satIOContext); /* Table 34, 9.1, p 46 */ /* note: As of 2/10/2006, no support for DMA QUEUED */ /* Table 34, 9.1, p 46, b When no 48-bit addressing support or NCQ, if LBA is beyond (2^28 - 1), return check condition */ if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { if (limitChk) { TI_DBG1(("satWriteAndVerify16: return LBA out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } if (rangeChk) // if (lba + tl > SAT_TR_LBA_LIMIT) { TI_DBG1(("satWriteAndVerify16: return LBA+TL out of range, not EXT\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /* case 1 and 2 */ if (!rangeChk) // if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWriteAndVerify16: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* In case that we can't fit the transfer length, we loop */ TI_DBG5(("satWriteAndVerify16: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (scsiCmnd->cdb[6] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satWriteAndVerify16: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA_EXT; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satWriteAndVerify16: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.sectorCountExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satWriteAndVerify16: case 5 !!! error NCQ but 28 bit address support \n")); 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 ); return tiSuccess; } TI_DBG6(("satWriteAndVerify16: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = scsiCmnd->cdb[13]; /* FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[9]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[8]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = scsiCmnd->cdb[7]; /* FIS LBA (23:16) */ /* Check FUA bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE16_FUA_MASK) fis->d.device = 0xC0; /* FIS FUA set */ else fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = scsiCmnd->cdb[6]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = scsiCmnd->cdb[5]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = scsiCmnd->cdb[4]; /* FIS LBA (47:40) */ fis->d.featuresExp = scsiCmnd->cdb[12]; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } satIOContext->currentLBA = lba; satIOContext->OrgTL = tl; /* computing number of loop and remainder for tl 0xFF in case not ext 0xFFFF in case EXT */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { LoopNum = satComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = satComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { TI_DBG5(("satWriteAndVerify16: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satNonChainedWriteNVerifyCB; } else { TI_DBG1(("satWriteAndVerify16: CHAINED data\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0xFF; } else if (fis->h.command == SAT_WRITE_SECTORS_EXT || fis->h.command == SAT_WRITE_DMA_EXT || fis->h.command == SAT_WRITE_DMA_FUA_EXT ) { fis->d.sectorCount = 0xFF; fis->d.sectorCountExp = 0xFF; } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReadMediaSerialNumber. * * SAT implementation for SCSI Read Media Serial Number. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satReadMediaSerialNumber( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; agsaSATAIdentifyData_t *pSATAIdData; bit8 *pSerialNumber; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pSATAIdData = &(pSatDevData->satIdentifyData); pSerialNumber = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG1(("satReadMediaSerialNumber: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { 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(("satReadMediaSerialNumber: return control\n")); return tiSuccess; } if (tiScsiRequest->scsiCmnd.expDataLength == 4) { if (pSATAIdData->commandSetFeatureDefault & 0x4) { TI_DBG1(("satReadMediaSerialNumber: Media serial number returning only length\n")); /* SPC-3 6.16 p192; filling in length */ pSerialNumber[0] = 0; pSerialNumber[1] = 0; pSerialNumber[2] = 0; pSerialNumber[3] = 0x3C; } else { /* 1 sector - 4 = 512 - 4 to avoid underflow; 0x1fc*/ pSerialNumber[0] = 0; pSerialNumber[1] = 0; pSerialNumber[2] = 0x1; pSerialNumber[3] = 0xfc; } ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } if ( pSatDevData->IDDeviceValid == agTRUE) { if (pSATAIdData->commandSetFeatureDefault & 0x4) { /* word87 bit2 Media serial number is valid */ /* read word 176 to 205; length is 2*30 = 60 = 0x3C*/ tdhexdump("ID satReadMediaSerialNumber", (bit8*)pSATAIdData->currentMediaSerialNumber, 2*30); /* SPC-3 6.16 p192; filling in length */ pSerialNumber[0] = 0; pSerialNumber[1] = 0; pSerialNumber[2] = 0; pSerialNumber[3] = 0x3C; osti_memcpy(&pSerialNumber[4], (void *)pSATAIdData->currentMediaSerialNumber, 60); tdhexdump("satReadMediaSerialNumber", (bit8*)pSerialNumber, 2*30 + 4); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } else { /* word87 bit2 Media serial number is NOT valid */ TI_DBG1(("satReadMediaSerialNumber: Media serial number is NOT valid \n")); if (pSatDevData->sat48BitSupport == agTRUE) { /* READ VERIFY SECTORS EXT */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS_EXT; /* 0x24 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = 0; /* FIS LBA (31:24) */ fis->d.lbaMidExp = 0; /* FIS LBA (39:32) */ fis->d.lbaHighExp = 0; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; } else { /* READ VERIFY SECTORS */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_SECTORS; /* 0x20 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; } satIOContext->satCompleteCB = &satReadMediaSerialNumberCB; satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } } else { /* temporary failure */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, satIOContext->interruptContext); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReadBuffer. * * SAT implementation for SCSI Read Buffer. * * \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. */ /*****************************************************************************/ /* SAT-2, Revision 00*/ GLOBAL bit32 satReadBuffer( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status = tiSuccess; bit32 agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 bufferOffset; bit32 tl; bit8 mode; bit8 bufferID; bit8 *pBuff; pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pBuff = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG2(("satReadBuffer: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satReadBuffer: return control\n")); return tiSuccess; } bufferOffset = (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; tl = (scsiCmnd->cdb[6] << (8*2)) + (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; mode = (bit8)(scsiCmnd->cdb[1] & SCSI_READ_BUFFER_MODE_MASK); bufferID = scsiCmnd->cdb[2]; if (mode == READ_BUFFER_DATA_MODE) /* 2 */ { if (bufferID == 0 && bufferOffset == 0 && tl == 512) { /* send ATA READ BUFFER */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_BUFFER; /* 0xE4 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; satIOContext->satCompleteCB = &satReadBufferCB; satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } if (bufferID == 0 && bufferOffset == 0 && tl != 512) { 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(("satReadBuffer: allocation length is not 512; it is %d\n", tl)); return tiSuccess; } if (bufferID == 0 && bufferOffset != 0) { 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(("satReadBuffer: buffer offset is not 0; it is %d\n", bufferOffset)); return tiSuccess; } /* all other cases unsupported */ TI_DBG1(("satReadBuffer: unsupported case 1\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else if (mode == READ_BUFFER_DESCRIPTOR_MODE) /* 3 */ { if (tl < READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN) /* 4 */ { 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(("satReadBuffer: tl < 4; tl is %d\n", tl)); return tiSuccess; } if (bufferID == 0) { /* SPC-4, 6.15.5, p189; SAT-2 Rev00, 8.7.2.3, p41*/ pBuff[0] = 0xFF; pBuff[1] = 0x00; pBuff[2] = 0x02; pBuff[3] = 0x00; if (READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN < tl) { /* underrrun */ TI_DBG1(("satReadBuffer: underrun tl %d data %d\n", tl, READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN)); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOUnderRun, tl - READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN, agNULL, satIOContext->interruptContext ); return tiSuccess; } else { ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } } else { /* We don't support other than bufferID 0 */ satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } else { /* We don't support any other mode */ TI_DBG1(("satReadBuffer: unsupported mode %d\n", mode)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satWriteBuffer. * * SAT implementation for SCSI Write Buffer. * * \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. */ /*****************************************************************************/ /* SAT-2, Revision 00*/ GLOBAL bit32 satWriteBuffer( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { #ifdef NOT_YET bit32 agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; #endif scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; bit32 bufferOffset; bit32 parmLen; bit8 mode; bit8 bufferID; bit8 *pBuff; pSense = satIOContext->pSense; scsiCmnd = &tiScsiRequest->scsiCmnd; pBuff = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG2(("satWriteBuffer: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { 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(("satWriteBuffer: return control\n")); return tiSuccess; } bufferOffset = (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; parmLen = (scsiCmnd->cdb[6] << (8*2)) + (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; mode = (bit8)(scsiCmnd->cdb[1] & SCSI_READ_BUFFER_MODE_MASK); bufferID = scsiCmnd->cdb[2]; /* for debugging only */ tdhexdump("satWriteBuffer pBuff", (bit8 *)pBuff, 24); if (mode == WRITE_BUFFER_DATA_MODE) /* 2 */ { if (bufferID == 0 && bufferOffset == 0 && parmLen == 512) { TI_DBG1(("satWriteBuffer: sending ATA WRITE BUFFER\n")); /* send ATA WRITE BUFFER */ #ifdef NOT_YET fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_BUFFER; /* 0xE8 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA (27:24) and FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->satCompleteCB = &satWriteBufferCB; satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; #endif /* temp */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return tiSuccess; } if ( (bufferID == 0 && bufferOffset != 0) || (bufferID == 0 && parmLen != 512) ) { 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(("satWriteBuffer: wrong buffer offset %d or parameter length parmLen %d\n", bufferOffset, parmLen)); return tiSuccess; } /* all other cases unsupported */ TI_DBG1(("satWriteBuffer: unsupported case 1\n")); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else if (mode == WRITE_BUFFER_DL_MICROCODE_SAVE_MODE) /* 5 */ { TI_DBG1(("satWriteBuffer: not yet supported mode %d\n", mode)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } else { /* We don't support any other mode */ TI_DBG1(("satWriteBuffer: unsupported mode %d\n", mode)); satSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReassignBlocks. * * SAT implementation for SCSI Reassign Blocks. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satReassignBlocks( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { /* assumes all LBA fits in ATA command; no boundary condition is checked here yet */ bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pParmList; /* Log Page data buffer */ bit8 LongLBA; bit8 LongList; bit32 defectListLen; bit8 LBA[8]; bit32 startingIndex; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pParmList = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG5(("satReassignBlocks: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { 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(("satReassignBlocks: return control\n")); return tiSuccess; } osti_memset(satIOContext->LBA, 0, 8); satIOContext->ParmIndex = 0; satIOContext->ParmLen = 0; LongList = (bit8)(scsiCmnd->cdb[1] & SCSI_REASSIGN_BLOCKS_LONGLIST_MASK); LongLBA = (bit8)(scsiCmnd->cdb[1] & SCSI_REASSIGN_BLOCKS_LONGLBA_MASK); osti_memset(LBA, 0, sizeof(LBA)); if (LongList == 0) { defectListLen = (pParmList[2] << 8) + pParmList[3]; } else { defectListLen = (pParmList[0] << (8*3)) + (pParmList[1] << (8*2)) + (pParmList[2] << 8) + pParmList[3]; } /* SBC 5.16.2, p61*/ satIOContext->ParmLen = defectListLen + 4 /* header size */; startingIndex = 4; if (LongLBA == 0) { LBA[4] = pParmList[startingIndex]; /* MSB */ LBA[5] = pParmList[startingIndex+1]; LBA[6] = pParmList[startingIndex+2]; LBA[7] = pParmList[startingIndex+3]; /* LSB */ startingIndex = startingIndex + 4; } else { LBA[0] = pParmList[startingIndex]; /* MSB */ LBA[1] = pParmList[startingIndex+1]; LBA[2] = pParmList[startingIndex+2]; LBA[3] = pParmList[startingIndex+3]; LBA[4] = pParmList[startingIndex+4]; LBA[5] = pParmList[startingIndex+5]; LBA[6] = pParmList[startingIndex+6]; LBA[7] = pParmList[startingIndex+7]; /* LSB */ startingIndex = startingIndex + 8; } tdhexdump("satReassignBlocks Parameter list", (bit8 *)pParmList, 4 + defectListLen); if (pSatDevData->sat48BitSupport == agTRUE) { /* sends READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ fis->d.lbaLowExp = LBA[4]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = LBA[3]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = LBA[2]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = (bit8)((0x4 << 4) | (LBA[4] & 0xF)); /* DEV and LBA 27:24 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } osti_memcpy(satIOContext->LBA, LBA, 8); satIOContext->ParmIndex = startingIndex; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satReassignBlocksCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReassignBlocks_1. * * SAT implementation for SCSI Reassign Blocks. This is helper function for * satReassignBlocks and satReassignBlocksCB. This sends ATA verify command. * * \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. */ /*****************************************************************************/ /* next LBA; sends READ VERIFY SECTOR; update LBA and ParmIdx */ GLOBAL bit32 satReassignBlocks_1( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, satIOContext_t *satOrgIOContext ) { /* assumes all LBA fits in ATA command; no boundary condition is checked here yet tiScsiRequest is OS generated; needs for accessing parameter list */ bit32 agRequestType; satDeviceData_t *pSatDevData; tiIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pParmList; /* Log Page data buffer */ bit8 LongLBA; bit8 LBA[8]; bit32 startingIndex; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &tiScsiRequest->scsiCmnd; fis = satIOContext->pFis; pParmList = (bit8 *) tiScsiRequest->sglVirtualAddr; TI_DBG5(("satReassignBlocks_1: start\n")); LongLBA = (bit8)(scsiCmnd->cdb[1] & SCSI_REASSIGN_BLOCKS_LONGLBA_MASK); osti_memset(LBA, 0, sizeof(LBA)); startingIndex = satOrgIOContext->ParmIndex; if (LongLBA == 0) { LBA[4] = pParmList[startingIndex]; LBA[5] = pParmList[startingIndex+1]; LBA[6] = pParmList[startingIndex+2]; LBA[7] = pParmList[startingIndex+3]; startingIndex = startingIndex + 4; } else { LBA[0] = pParmList[startingIndex]; LBA[1] = pParmList[startingIndex+1]; LBA[2] = pParmList[startingIndex+2]; LBA[3] = pParmList[startingIndex+3]; LBA[4] = pParmList[startingIndex+4]; LBA[5] = pParmList[startingIndex+5]; LBA[6] = pParmList[startingIndex+6]; LBA[7] = pParmList[startingIndex+7]; startingIndex = startingIndex + 8; } if (pSatDevData->sat48BitSupport == agTRUE) { /* sends READ VERIFY SECTOR(S) EXT*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS_EXT;/* 0x42 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ fis->d.lbaLowExp = LBA[4]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = LBA[3]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = LBA[2]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.device = 0x40; /* 01000000 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } else { /* READ VERIFY SECTOR(S)*/ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_VERIFY_SECTORS;/* 0x40 */ fis->h.features = 0; /* FIS features NA */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.device = (bit8)((0x4 << 4) | (LBA[4] & 0xF)); /* DEV and LBA 27:24 */ fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; } osti_memcpy(satOrgIOContext->LBA, LBA, 8); satOrgIOContext->ParmIndex = startingIndex; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satReassignBlocksCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext ); return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satReassignBlocks_2. * * SAT implementation for SCSI Reassign Blocks. This is helper function for * satReassignBlocks and satReassignBlocksCB. This sends ATA write command. * * \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 * \param LBA: Pointer to the LBA to be processed * * \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. */ /*****************************************************************************/ /* current LBA; sends WRITE */ GLOBAL bit32 satReassignBlocks_2( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, bit8 *LBA ) { /* assumes all LBA fits in ATA command; no boundary condition is checked here yet tiScsiRequest is TD generated for writing */ bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ TI_DBG5(("satReassignBlocks_2: case 2\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_DMA; /* 0xCA */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[4] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; satIOContext->ATACmd = SAT_WRITE_DMA; } else { /* case 1 */ /* WRITE MULTIPLE or WRITE SECTOR(S) */ /* WRITE SECTORS for easier implemetation */ /* can't fit the transfer length */ TI_DBG5(("satReassignBlocks_2: case 1\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C bit is set */ fis->h.command = SAT_WRITE_SECTORS; /* 0x30 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[7]; /* FIS LBA (23:16) */ /* FIS LBA mode set LBA (27:24) */ fis->d.device = (bit8)((0x4 << 4) | (LBA[4] & 0xF)); fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS; } /* case 3 and 4 */ if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ TI_DBG5(("satReassignBlocks_2: case 3\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ /* SAT_WRITE_DMA_FUA_EXT is optional and we don't support it */ fis->h.command = SAT_WRITE_DMA_EXT; /* 0x35 */ satIOContext->ATACmd = SAT_WRITE_DMA_EXT; fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[4]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = LBA[3]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = LBA[2]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; } else { /* case 4 */ /* WRITE MULTIPLE EXT or WRITE MULTIPLE FUA EXT or WRITE SECTOR(S) EXT */ /* WRITE SECTORS EXT for easier implemetation */ TI_DBG5(("satReassignBlocks_2: case 4\n")); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_SECTORS_EXT; /* 0x34 */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ fis->d.device = 0x40; /* FIS LBA mode set */ fis->d.lbaLowExp = LBA[4]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = LBA[3]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = LBA[2]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 1; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; /* FIS sector count (15:8) */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; satIOContext->ATACmd = SAT_WRITE_SECTORS_EXT; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { TI_DBG5(("satReassignBlocks_2: case 5 !!! error NCQ but 28 bit address support \n")); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, satIOContext->interruptContext ); return tiSuccess; } TI_DBG6(("satWrite10: case 5\n")); /* Support 48-bit FPDMA addressing, use WRITE FPDMA QUEUE command */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_WRITE_FPDMA_QUEUED; /* 0x61 */ fis->h.features = 1; /* FIS sector count (7:0) */ fis->d.lbaLow = LBA[7]; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = LBA[6]; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = LBA[5]; /* FIS LBA (23:16) */ /* Check FUA bit */ fis->d.device = 0x40; /* FIS FUA clear */ fis->d.lbaLowExp = LBA[4]; /* FIS LBA (31:24) */ fis->d.lbaMidExp = LBA[3]; /* FIS LBA (39:32) */ fis->d.lbaHighExp = LBA[2]; /* FIS LBA (47:40) */ fis->d.featuresExp = 0; /* FIS sector count (15:8) */ fis->d.sectorCount = 0; /* Tag (7:3) set by LL layer */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; satIOContext->ATACmd = SAT_WRITE_FPDMA_QUEUED; } satIOContext->satCompleteCB = &satReassignBlocksCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, /* not the original, should be the TD generated one */ tiScsiRequest, satIOContext); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI satPrepareNewIO. * * This function fills in the fields of internal IO generated by TD layer. * This is mostly used in the callback functions. * * \param satNewIntIo: Pointer to the internal IO structure. * \param tiOrgIORequest: Pointer to the original tiIOrequest sent by OS layer * \param satDevData: Pointer to the device data. * \param scsiCmnd: Pointer to SCSI command. * \param satOrgIOContext: Pointer to the original SAT IO Context * * \return * - \e Pointer to the new SAT IO Context */ /*****************************************************************************/ GLOBAL satIOContext_t *satPrepareNewIO( satInternalIo_t *satNewIntIo, tiIORequest_t *tiOrgIORequest, satDeviceData_t *satDevData, tiIniScsiCmnd_t *scsiCmnd, satIOContext_t *satOrgIOContext ) { satIOContext_t *satNewIOContext; tdIORequestBody_t *tdNewIORequestBody; TI_DBG2(("satPrepareNewIO: start\n")); /* the one to be used; good 8/2/07 */ satNewIntIo->satOrgTiIORequest = tiOrgIORequest; /* this is already done in satAllocIntIoResource() */ tdNewIORequestBody = (tdIORequestBody_t *)satNewIntIo->satIntRequestBody; satNewIOContext = &(tdNewIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(tdNewIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satNewIntIo->satIntTiScsiXchg.scsiCmnd); if (scsiCmnd != agNULL) { /* saves only CBD; not scsi command for LBA and number of blocks */ osti_memcpy(satNewIOContext->pScsiCmnd->cdb, scsiCmnd->cdb, 16); } 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 = satOrgIOContext->ptiDeviceHandle; satNewIOContext->satOrgIOContext = satOrgIOContext; /* saves tiScsiXchg; only for writesame10() */ satNewIOContext->tiScsiXchg = satOrgIOContext->tiScsiXchg; return satNewIOContext; } /***************************************************************************** *! \brief satIOAbort * * This routine is called to initiate a I/O abort to SATL. * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param taskTag: Pointer to TISA I/O request context/tag to be aborted. * * \return: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ GLOBAL bit32 satIOAbort( tiRoot_t *tiRoot, tiIORequest_t *taskTag ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *tdIONewRequestBody; agsaIORequest_t *agIORequest; bit32 status; agsaIORequest_t *agAbortIORequest; tdIORequestBody_t *tdAbortIORequestBody; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; satIOContext_t *satIOContext; satInternalIo_t *satIntIo; TI_DBG2(("satIOAbort: start\n")); agRoot = &(tdsaAllShared->agRootNonInt); tdIORequestBody = (tdIORequestBody_t *)taskTag->tdData; /* needs to distinguish internally generated or externally generated */ satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satIntIo = satIOContext->satIntIoContext; if (satIntIo == agNULL) { TI_DBG1(("satIOAbort: External, OS generated\n")); agIORequest = &(tdIORequestBody->agIORequest); } else { TI_DBG1(("satIOAbort: Internal, TD generated\n")); tdIONewRequestBody = (tdIORequestBody_t *)satIntIo->satIntRequestBody; agIORequest = &(tdIONewRequestBody->agIORequest); } /* 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(("satIOAbort: ostiAllocMemory failed...\n")); return tiError; } if (tdAbortIORequestBody == agNULL) { /* let os process IO */ TI_DBG1(("satIOAbort: ostiAllocMemory returned NULL tdAbortIORequestBody\n")); return tiError; } /* setup task management structure */ tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; tdAbortIORequestBody->tiDevHandle = tdIORequestBody->tiDevHandle; /* initialize agIORequest */ agAbortIORequest = &(tdAbortIORequestBody->agIORequest); agAbortIORequest->osData = (void *) tdAbortIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ /* remember IO to be aborted */ tdAbortIORequestBody->tiIOToBeAbortedRequest = taskTag; status = saSATAAbort( agRoot, agAbortIORequest, 0, agNULL, 0, agIORequest, agNULL ); TI_DBG5(("satIOAbort: return status=0x%x\n", status)); if (status == AGSA_RC_SUCCESS) return tiSuccess; else return tiError; } /***************************************************************************** *! \brief satTM * * This routine is called to initiate a TM request to SATL. * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param task: SAM-3 task management request. * \param lun: Pointer to LUN. * \param taskTag: Pointer to the associated task where the TM * command is to be applied. * \param currentTaskTag: Pointer to tag/context for this TM request. * * \return: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiIONoDevice: Invalid device handle. * \e tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ /* save task in satIOContext */ osGLOBAL bit32 satTM( tiRoot_t *tiRoot, tiDeviceHandle_t *tiDeviceHandle, bit32 task, tiLUN_t *lun, tiIORequest_t *taskTag, tiIORequest_t *currentTaskTag, tdIORequestBody_t *tiRequestBody, bit32 NotifyOS ) { tdIORequestBody_t *tdIORequestBody = agNULL; satIOContext_t *satIOContext = agNULL; tdsaDeviceData_t *oneDeviceData = agNULL; bit32 status; TI_DBG3(("satTM: tiDeviceHandle=%p task=0x%x\n", tiDeviceHandle, task )); /* set satIOContext fields and etc */ oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; tdIORequestBody = (tdIORequestBody_t *)tiRequestBody; satIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satIOContext->pSatDevData = &oneDeviceData->satDevData; satIOContext->pFis = &tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev; satIOContext->tiRequestBody = tiRequestBody; satIOContext->ptiDeviceHandle = tiDeviceHandle; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; /* followings are used only for internal IO */ satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; /* saving task in satIOContext */ satIOContext->TMF = task; satIOContext->satToBeAbortedIOContext = agNULL; if (NotifyOS == agTRUE) { satIOContext->NotifyOS = agTRUE; } else { satIOContext->NotifyOS = agFALSE; } /* * Our SAT supports RESET LUN and partially support ABORT TASK (only if there * is no more than one I/O pending on the drive. */ if (task == AG_LOGICAL_UNIT_RESET) { status = satTmResetLUN( tiRoot, currentTaskTag, tiDeviceHandle, agNULL, satIOContext, lun); return status; } #ifdef TO_BE_REMOVED else if (task == AG_TARGET_WARM_RESET) { status = satTmWarmReset( tiRoot, currentTaskTag, tiDeviceHandle, agNULL, satIOContext); return status; } #endif else if (task == AG_ABORT_TASK) { status = satTmAbortTask( tiRoot, currentTaskTag, tiDeviceHandle, agNULL, satIOContext, taskTag); return status; } else if (task == TD_INTERNAL_TM_RESET) { status = satTDInternalTmReset( tiRoot, currentTaskTag, tiDeviceHandle, agNULL, satIOContext); return status; } else { TI_DBG1(("satTM: tiDeviceHandle=%p UNSUPPORTED TM task=0x%x\n", tiDeviceHandle, task )); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tiRequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return tiError; } } /***************************************************************************** *! \brief satTmResetLUN * * This routine is called to initiate a TM RESET LUN request to SATL. * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param lun: Pointer to LUN. * \param currentTaskTag: Pointer to tag/context for this TM request. * * \return: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiIONoDevice: Invalid device handle. * \e tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ osGLOBAL bit32 satTmResetLUN( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* current task tag */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext, tiLUN_t *lun) { tdsaDeviceData_t *tdsaDeviceData; satDeviceData_t *satDevData; tdsaDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; satDevData = &tdsaDeviceData->satDevData; TI_DBG1(("satTmResetLUN: tiDeviceHandle=%p.\n", tiDeviceHandle )); /* * Only support LUN 0 */ if ( (lun->lun[0] | lun->lun[1] | lun->lun[2] | lun->lun[3] | lun->lun[4] | lun->lun[5] | lun->lun[6] | lun->lun[7] ) != 0 ) { TI_DBG1(("satTmResetLUN: *** REJECT *** LUN not zero, tiDeviceHandle=%p\n", tiDeviceHandle)); return tiError; } /* * Check if there is other TM request pending */ if (satDevData->satTmTaskTag != agNULL) { TI_DBG1(("satTmResetLUN: *** REJECT *** other TM pending, tiDeviceHandle=%p\n", tiDeviceHandle)); return tiError; } /* * Save tiIORequest, will be returned at device reset completion to return * the TM completion. */ satDevData->satTmTaskTag = tiIORequest; /* * Set flag to indicate device in recovery mode. */ satDevData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; /* * Issue SATA device reset. Set flag to indicate NOT to automatically abort * at the completion of SATA device reset. */ satDevData->satAbortAfterReset = agFALSE; /* SAT rev8 6.3.6 p22 */ satStartResetDevice( tiRoot, tiIORequest, /* currentTaskTag */ tiDeviceHandle, tiScsiRequest, satIOContext ); return tiSuccess; } /***************************************************************************** *! \brief satTmWarmReset * * This routine is called to initiate a TM warm RESET request to SATL. * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param currentTaskTag: Pointer to tag/context for this TM request. * * \return: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiIONoDevice: Invalid device handle. * \e tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ osGLOBAL bit32 satTmWarmReset( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* current task tag */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { tdsaDeviceData_t *tdsaDeviceData; satDeviceData_t *satDevData; tdsaDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; satDevData = &tdsaDeviceData->satDevData; TI_DBG1(("satTmWarmReset: tiDeviceHandle=%p.\n", tiDeviceHandle )); /* * Check if there is other TM request pending */ if (satDevData->satTmTaskTag != agNULL) { TI_DBG1(("satTmWarmReset: *** REJECT *** other TM pending, tiDeviceHandle=%p\n", tiDeviceHandle)); return tiError; } /* * Save tiIORequest, will be returned at device reset completion to return * the TM completion. */ satDevData->satTmTaskTag = tiIORequest; /* * Set flag to indicate device in recovery mode. */ satDevData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; /* * Issue SATA device reset. Set flag to indicate NOT to automatically abort * at the completion of SATA device reset. */ satDevData->satAbortAfterReset = agFALSE; /* SAT rev8 6.3.6 p22 */ satStartResetDevice( tiRoot, tiIORequest, /* currentTaskTag */ tiDeviceHandle, tiScsiRequest, satIOContext ); return tiSuccess; } osGLOBAL bit32 satTDInternalTmReset( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* current task tag */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { tdsaDeviceData_t *tdsaDeviceData; satDeviceData_t *satDevData; tdsaDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; satDevData = &tdsaDeviceData->satDevData; TI_DBG1(("satTmWarmReset: tiDeviceHandle=%p.\n", tiDeviceHandle )); /* * Check if there is other TM request pending */ if (satDevData->satTmTaskTag != agNULL) { TI_DBG1(("satTmWarmReset: *** REJECT *** other TM pending, tiDeviceHandle=%p\n", tiDeviceHandle)); return tiError; } /* * Save tiIORequest, will be returned at device reset completion to return * the TM completion. */ satDevData->satTmTaskTag = tiIORequest; /* * Set flag to indicate device in recovery mode. */ satDevData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; /* * Issue SATA device reset. Set flag to indicate NOT to automatically abort * at the completion of SATA device reset. */ satDevData->satAbortAfterReset = agFALSE; /* SAT rev8 6.3.6 p22 */ satStartResetDevice( tiRoot, tiIORequest, /* currentTaskTag */ tiDeviceHandle, tiScsiRequest, satIOContext ); return tiSuccess; } /***************************************************************************** *! \brief satTmAbortTask * * This routine is called to initiate a TM ABORT TASK request to SATL. * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param taskTag: Pointer to the associated task where the TM * command is to be applied. * \param currentTaskTag: Pointer to tag/context for this TM request. * * \return: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiIONoDevice: Invalid device handle. * \e tiError: Other errors that prevent the I/O request to be started. * * *****************************************************************************/ osGLOBAL bit32 satTmAbortTask( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* current task tag */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, /* NULL */ satIOContext_t *satIOContext, tiIORequest_t *taskTag) { tdsaDeviceData_t *tdsaDeviceData; satDeviceData_t *satDevData; satIOContext_t *satTempIOContext = agNULL; tdIORequestBody_t *tdIORequestBody; tdIORequestBody_t *TMtdIORequestBody; tdList_t *elementHdr; bit32 found = agFALSE; tiIORequest_t *tiIOReq; tdsaDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; satDevData = &tdsaDeviceData->satDevData; TMtdIORequestBody = (tdIORequestBody_t *)tiIORequest->tdData; TI_DBG1(("satTmAbortTask: tiDeviceHandle=%p taskTag=%p.\n", tiDeviceHandle, taskTag )); /* * Check if there is other TM request pending */ if (satDevData->satTmTaskTag != agNULL) { TI_DBG1(("satTmAbortTask: REJECT other TM pending, tiDeviceHandle=%p\n", tiDeviceHandle)); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, TMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return tiError; } #ifdef REMOVED /* * Check if there is only one I/O pending. */ if (satDevData->satPendingIO > 0) { TI_DBG1(("satTmAbortTask: REJECT num pending I/O, tiDeviceHandle=%p, satPendingIO=0x%x\n", tiDeviceHandle, satDevData->satPendingIO)); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, TMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return tiError; } #endif /* * Check that the only pending I/O matches taskTag. If not return tiError. */ elementHdr = satDevData->satIoLinkList.flink; while (elementHdr != &satDevData->satIoLinkList) { satTempIOContext = TDLIST_OBJECT_BASE( satIOContext_t, satIoContextLink, elementHdr ); tdIORequestBody = (tdIORequestBody_t *) satTempIOContext->tiRequestBody; tiIOReq = tdIORequestBody->tiIORequest; elementHdr = elementHdr->flink; /* for the next while loop */ /* * Check if the tag matches */ if ( tiIOReq == taskTag) { found = agTRUE; satIOContext->satToBeAbortedIOContext = satTempIOContext; TI_DBG1(("satTmAbortTask: found matching tag.\n")); break; } /* if matching tag */ } /* while loop */ if (found == agFALSE ) { TI_DBG1(("satTmAbortTask: *** REJECT *** no match, tiDeviceHandle=%p\n", tiDeviceHandle )); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, TMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return tiError; } /* * Save tiIORequest, will be returned at device reset completion to return * the TM completion. */ satDevData->satTmTaskTag = tiIORequest; /* * Set flag to indicate device in recovery mode. */ satDevData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; /* * Issue SATA device reset or check power mode. Set flag to to automatically abort * at the completion of SATA device reset. * SAT r09 p25 */ satDevData->satAbortAfterReset = agTRUE; if ( (satTempIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) || (satTempIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) ) { TI_DBG1(("satTmAbortTask: calling satStartCheckPowerMode\n")); /* send check power mode */ satStartCheckPowerMode( tiRoot, tiIORequest, /* currentTaskTag */ tiDeviceHandle, tiScsiRequest, satIOContext ); } else { TI_DBG1(("satTmAbortTask: calling satStartResetDevice\n")); /* send AGSA_SATA_PROTOCOL_SRST_ASSERT */ satStartResetDevice( tiRoot, tiIORequest, /* currentTaskTag */ tiDeviceHandle, tiScsiRequest, satIOContext ); } return tiSuccess; } /***************************************************************************** *! \brief osSatResetCB * * This routine is called to notify the completion of SATA device reset * which was initiated previously through the call to sataLLReset(). * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param resetStatus: Reset status either tiSuccess or tiError. * \param respFis: Pointer to the Register Device-To-Host FIS * received from the device. * * \return: None * *****************************************************************************/ osGLOBAL void osSatResetCB( tiRoot_t *tiRoot, tiDeviceHandle_t *tiDeviceHandle, bit32 resetStatus, void *respFis) { agsaRoot_t *agRoot; tdsaDeviceData_t *tdsaDeviceData; satDeviceData_t *satDevData; satIOContext_t *satIOContext; tdIORequestBody_t *tdIORequestBodyTmp; tdList_t *elementHdr; agsaIORequest_t *agAbortIORequest; tdIORequestBody_t *tdAbortIORequestBody; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; tdsaDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; agRoot = tdsaDeviceData->agRoot; satDevData = &tdsaDeviceData->satDevData; TI_DBG5(("osSatResetCB: tiDeviceHandle=%p resetStatus=0x%x\n", tiDeviceHandle, resetStatus )); /* We may need to check FIS to check device operating condition */ /* * Check if need to abort all pending I/Os */ if ( satDevData->satAbortAfterReset == agTRUE ) { /* * Issue abort to LL layer to all other pending I/Os for the same SATA drive */ elementHdr = satDevData->satIoLinkList.flink; while (elementHdr != &satDevData->satIoLinkList) { satIOContext = TDLIST_OBJECT_BASE( satIOContext_t, satIoContextLink, elementHdr ); tdIORequestBodyTmp = (tdIORequestBody_t *)satIOContext->tiRequestBody; /* * Issue abort */ TI_DBG5(("osSatResetCB: issuing ABORT tiDeviceHandle=%p agIORequest=%p\n", tiDeviceHandle, &tdIORequestBodyTmp->agIORequest )); /* 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(("osSatResetCB: ostiAllocMemory failed...\n")); return; } if (tdAbortIORequestBody == agNULL) { /* let os process IO */ TI_DBG1(("osSatResetCB: ostiAllocMemory returned NULL tdAbortIORequestBody\n")); return; } /* setup task management structure */ tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; tdAbortIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize agIORequest */ agAbortIORequest = &(tdAbortIORequestBody->agIORequest); agAbortIORequest->osData = (void *) tdAbortIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ saSATAAbort( agRoot, agAbortIORequest, 0, agNULL, 0, &(tdIORequestBodyTmp->agIORequest), agNULL ); elementHdr = elementHdr->flink; /* for the next while loop */ } /* while */ /* Reset flag */ satDevData->satAbortAfterReset = agFALSE; } /* * Check if the device reset if the result of TM request. */ if ( satDevData->satTmTaskTag != agNULL ) { TI_DBG5(("osSatResetCB: calling TM completion tiDeviceHandle=%p satTmTaskTag=%p\n", tiDeviceHandle, satDevData->satTmTaskTag )); ostiInitiatorEvent( tiRoot, agNULL, /* portalContext not used */ tiDeviceHandle, tiIntrEventTypeTaskManagement, tiTMOK, satDevData->satTmTaskTag); /* * Reset flag */ satDevData->satTmTaskTag = agNULL; } } /***************************************************************************** *! \brief osSatIOCompleted * * This routine is a callback for SATA completion that required FIS status * translation to SCSI status. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiIORequest: Pointer to TISA I/O request context for this I/O. * \param respFis: Pointer to status FIS to read. * \param respFisLen: Length of response FIS to read. * \param satIOContext: Pointer to SAT context. * \param interruptContext: Interrupt context * * \return: None * *****************************************************************************/ osGLOBAL void osSatIOCompleted( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, agsaFisHeader_t *agFirstDword, bit32 respFisLen, agsaFrameHandle_t agFrameHandle, satIOContext_t *satIOContext, bit32 interruptContext) { satDeviceData_t *pSatDevData; scsiRspSense_t *pSense; #ifdef TD_DEBUG_ENABLE tiIniScsiCmnd_t *pScsiCmnd; #endif agsaFisRegHostToDevice_t *hostToDevFis = agNULL; bit32 ataStatus = 0; bit32 ataError; satInternalIo_t *satIntIo = agNULL; bit32 status; tiDeviceHandle_t *tiDeviceHandle; satIOContext_t *satIOContext2; tdIORequestBody_t *tdIORequestBody; agsaFisRegD2HHeader_t *statDevToHostFisHeader = agNULL; agsaFisSetDevBitsHeader_t *statSetDevBitFisHeader = agNULL; tiIORequest_t tiIORequestTMP; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; #ifdef TD_DEBUG_ENABLE pScsiCmnd = satIOContext->pScsiCmnd; #endif hostToDevFis = satIOContext->pFis; tiDeviceHandle = &((tdsaDeviceData_t *)(pSatDevData->satSaDeviceData))->tiDeviceHandle; /* * Find out the type of response FIS: * Set Device Bit FIS or Reg Device To Host FIS. */ /* First assume it is Reg Device to Host FIS */ statDevToHostFisHeader = (agsaFisRegD2HHeader_t *)&(agFirstDword->D2H); ataStatus = statDevToHostFisHeader->status; /* ATA Status register */ ataError = statDevToHostFisHeader->error; /* ATA Eror register */ /* for debugging */ TI_DBG1(("osSatIOCompleted: H to D command 0x%x\n", hostToDevFis->h.command)); TI_DBG1(("osSatIOCompleted: D to H fistype 0x%x\n", statDevToHostFisHeader->fisType)); if (statDevToHostFisHeader->fisType == SET_DEV_BITS_FIS) { /* It is Set Device 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 */ ataError = statSetDevBitFisHeader->error; statDevToHostFisHeader = agNULL; } else if (statDevToHostFisHeader->fisType != REG_DEV_TO_HOST_FIS) { TI_DBG1(("osSatIOCompleted: *** UNEXPECTED RESP FIS TYPE 0x%x *** tiIORequest=%p\n", statDevToHostFisHeader->fisType, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, interruptContext ); return; } if ( ataStatus & DF_ATA_STATUS_MASK ) { pSatDevData->satDeviceFaultState = agTRUE; } else { pSatDevData->satDeviceFaultState = agFALSE; } TI_DBG5(("osSatIOCompleted: tiIORequest=%p CDB=0x%x ATA CMD =0x%x\n", tiIORequest, pScsiCmnd->cdb[0], hostToDevFis->h.command)); /* * Decide which ATA command is the translation needed */ switch(hostToDevFis->h.command) { case SAT_READ_FPDMA_QUEUED: case SAT_WRITE_FPDMA_QUEUED: /************************************************************************ * * !!!! See Section 13.5.2.4 of SATA 2.5 specs. !!!! * !!!! If the NCQ error ends up here, it means that the device sent !!!! * !!!! Set Device Bit FIS (which has SActive register) instead of !!!! * !!!! Register Device To Host FIS (which does not have SActive !!!! * !!!! register). The callback ossaSATAEvent() deals with the case !!!! * !!!! where Register Device To Host 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, note that due * to the SATA HW assist that we have, this sequence is slighly different * from the one described in SATA 2.5: * * 1. Set SATA device flag to indicate error condition and returning busy * for all new request. * return tiSuccess; * 2. Because the HW/LL layer received Set Device Bit FIS, it can get the * tag or I/O context for NCQ request, SATL would translate the ATA error * to SCSI status and return the original NCQ I/O with the appopriate * SCSI status. * * 3. Prepare READ LOG EXT page 10h command. Set flag to indicate that * the failed I/O has been returned to the OS Layer. Send command. * * 4. 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. * * 5. SATL receives the completion for READ LOG EXT command in * satReadLogExtCB(). Steps 6,7,8,9 below are the step 1,2,3,4 in * satReadLogExtCB(). * * 6. 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. * * 7. Issue abort to LL layer to all other pending I/Os for the same SATA * drive. * * 8. Free resource allocated for the internally generated READ LOG EXT. * * 9. 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. * ***********************************************************************/ TI_DBG1(("osSatIOCompleted: NCQ ERROR tiIORequest=%p ataStatus=0x%x ataError=0x%x\n", tiIORequest, ataStatus, ataError )); /* Set flag to indicate we are in recovery */ pSatDevData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; /* Return the failed NCQ I/O to OS-Apps Specifiic layer */ osSatDefaultTranslation( tiRoot, tiIORequest, satIOContext, pSense, (bit8)ataStatus, (bit8)ataError, interruptContext ); /* * Allocate resource for READ LOG EXT page 10h */ satIntIo = satAllocIntIoResource( tiRoot, &(tiIORequestTMP), /* anything but NULL */ pSatDevData, sizeof (satReadLogExtPage10h_t), satIntIo); if (satIntIo == agNULL) { TI_DBG1(("osSatIOCompleted: can't send RLE due to resource lack\n")); /* Abort I/O after completion of device reset */ pSatDevData->satAbortAfterReset = agTRUE; #ifdef NOT_YET /* needs further investigation */ /* no report to OS layer */ satSubTM(tiRoot, tiDeviceHandle, TD_INTERNAL_TM_RESET, agNULL, agNULL, agNULL, agFALSE); #endif TI_DBG1(("osSatIOCompleted: calling saSATADeviceReset 1\n")); return; } /* * Set flag to indicate that the failed I/O has been returned to the * OS-App specific Layer. */ satIntIo->satIntFlag = AG_SAT_INT_IO_FLAG_ORG_IO_COMPLETED; /* 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(("osSatIOCompleted: 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 further investigation */ /* no report to OS layer */ satSubTM(tiRoot, tiDeviceHandle, TD_INTERNAL_TM_RESET, agNULL, agNULL, agNULL, agFALSE); #endif TI_DBG1(("osSatIOCompleted: calling saSATADeviceReset 2\n")); return; } break; case SAT_READ_DMA_EXT: /* fall through */ /* Use default status/error translation */ case SAT_READ_DMA: /* fall through */ /* Use default status/error translation */ default: osSatDefaultTranslation( tiRoot, tiIORequest, satIOContext, pSense, (bit8)ataStatus, (bit8)ataError, interruptContext ); break; } /* end switch */ } /*****************************************************************************/ /*! \brief SAT implementation for SCSI STANDARD INQUIRY. * * SAT implementation for SCSI STANDARD INQUIRY. * * \param pInquiry: Pointer to Inquiry Data buffer. * \param pSATAIdData: Pointer to ATA IDENTIFY DEVICE data. * * \return None. */ /*****************************************************************************/ GLOBAL void satInquiryStandard( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData, tiIniScsiCmnd_t *scsiCmnd ) { tiLUN_t *pLun; pLun = &scsiCmnd->lun; /* Assumption: Basic Task Mangement is supported -> BQUE 1 and CMDQUE 0, SPC-4, Table96, p147 */ /* See SPC-4, 6.4.2, p 143 and SAT revision 8, 8.1.2, p 28 */ TI_DBG5(("satInquiryStandard: start\n")); if (pInquiry == agNULL) { TI_DBG1(("satInquiryStandard: pInquiry is NULL, wrong\n")); return; } else { TI_DBG5(("satInquiryStandard: pInquiry is NOT NULL\n")); } /* * Reject all other LUN other than LUN 0. */ if ( ((pLun->lun[0] | pLun->lun[1] | pLun->lun[2] | pLun->lun[3] | pLun->lun[4] | pLun->lun[5] | pLun->lun[6] | pLun->lun[7] ) != 0) ) { /* SAT Spec Table 8, p27, footnote 'a' */ pInquiry[0] = 0x7F; } else { pInquiry[0] = 0x00; } if (pSATAIdData->rm_ataDevice & ATA_REMOVABLE_MEDIA_DEVICE_MASK ) { pInquiry[1] = 0x80; } else { pInquiry[1] = 0x00; } pInquiry[2] = 0x05; /* SPC-3 */ pInquiry[3] = 0x12; /* set HiSup 1; resp data format set to 2 */ pInquiry[4] = 0x1F; /* 35 - 4 = 31; Additional length */ pInquiry[5] = 0x00; /* The following two are for task management. SAT Rev8, p20 */ if (pSATAIdData->sataCapabilities & 0x100) { /* NCQ supported; multiple outstanding SCSI IO are supported */ pInquiry[6] = 0x00; /* BQUE bit is not set */ pInquiry[7] = 0x02; /* CMDQUE bit is set */ } else { pInquiry[6] = 0x80; /* BQUE bit is set */ pInquiry[7] = 0x00; /* CMDQUE bit is not set */ } /* * Vendor ID. */ osti_strncpy((char*)&pInquiry[8], AG_SAT_VENDOR_ID_STRING,8); /* 8 bytes */ /* * Product ID */ /* when flipped by LL */ pInquiry[16] = pSATAIdData->modelNumber[1]; pInquiry[17] = pSATAIdData->modelNumber[0]; pInquiry[18] = pSATAIdData->modelNumber[3]; pInquiry[19] = pSATAIdData->modelNumber[2]; pInquiry[20] = pSATAIdData->modelNumber[5]; pInquiry[21] = pSATAIdData->modelNumber[4]; pInquiry[22] = pSATAIdData->modelNumber[7]; pInquiry[23] = pSATAIdData->modelNumber[6]; pInquiry[24] = pSATAIdData->modelNumber[9]; pInquiry[25] = pSATAIdData->modelNumber[8]; pInquiry[26] = pSATAIdData->modelNumber[11]; pInquiry[27] = pSATAIdData->modelNumber[10]; pInquiry[28] = pSATAIdData->modelNumber[13]; pInquiry[29] = pSATAIdData->modelNumber[12]; pInquiry[30] = pSATAIdData->modelNumber[15]; pInquiry[31] = pSATAIdData->modelNumber[14]; /* when flipped */ /* * Product Revision level. */ /* * If the IDENTIFY DEVICE data received in words 25 and 26 from the ATA * device are ASCII spaces (20h), do this translation. */ if ( (pSATAIdData->firmwareVersion[4] == 0x20 ) && (pSATAIdData->firmwareVersion[5] == 0x00 ) && (pSATAIdData->firmwareVersion[6] == 0x20 ) && (pSATAIdData->firmwareVersion[7] == 0x00 ) ) { pInquiry[32] = pSATAIdData->firmwareVersion[1]; pInquiry[33] = pSATAIdData->firmwareVersion[0]; pInquiry[34] = pSATAIdData->firmwareVersion[3]; pInquiry[35] = pSATAIdData->firmwareVersion[2]; } else { pInquiry[32] = pSATAIdData->firmwareVersion[5]; pInquiry[33] = pSATAIdData->firmwareVersion[4]; pInquiry[34] = pSATAIdData->firmwareVersion[7]; pInquiry[35] = pSATAIdData->firmwareVersion[6]; } #ifdef REMOVED /* * Product ID */ /* when flipped by LL */ pInquiry[16] = pSATAIdData->modelNumber[0]; pInquiry[17] = pSATAIdData->modelNumber[1]; pInquiry[18] = pSATAIdData->modelNumber[2]; pInquiry[19] = pSATAIdData->modelNumber[3]; pInquiry[20] = pSATAIdData->modelNumber[4]; pInquiry[21] = pSATAIdData->modelNumber[5]; pInquiry[22] = pSATAIdData->modelNumber[6]; pInquiry[23] = pSATAIdData->modelNumber[7]; pInquiry[24] = pSATAIdData->modelNumber[8]; pInquiry[25] = pSATAIdData->modelNumber[9]; pInquiry[26] = pSATAIdData->modelNumber[10]; pInquiry[27] = pSATAIdData->modelNumber[11]; pInquiry[28] = pSATAIdData->modelNumber[12]; pInquiry[29] = pSATAIdData->modelNumber[13]; pInquiry[30] = pSATAIdData->modelNumber[14]; pInquiry[31] = pSATAIdData->modelNumber[15]; /* when flipped */ /* * Product Revision level. */ /* * If the IDENTIFY DEVICE data received in words 25 and 26 from the ATA * device are ASCII spaces (20h), do this translation. */ if ( (pSATAIdData->firmwareVersion[4] == 0x20 ) && (pSATAIdData->firmwareVersion[5] == 0x00 ) && (pSATAIdData->firmwareVersion[6] == 0x20 ) && (pSATAIdData->firmwareVersion[7] == 0x00 ) ) { pInquiry[32] = pSATAIdData->firmwareVersion[0]; pInquiry[33] = pSATAIdData->firmwareVersion[1]; pInquiry[34] = pSATAIdData->firmwareVersion[2]; pInquiry[35] = pSATAIdData->firmwareVersion[3]; } else { pInquiry[32] = pSATAIdData->firmwareVersion[4]; pInquiry[33] = pSATAIdData->firmwareVersion[5]; pInquiry[34] = pSATAIdData->firmwareVersion[6]; pInquiry[35] = pSATAIdData->firmwareVersion[7]; } #endif TI_DBG5(("satInquiryStandard: end\n")); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY page 0. * * SAT implementation for SCSI INQUIRY page 0. * * \param pInquiry: Pointer to Inquiry Data buffer. * \param pSATAIdData: Pointer to ATA IDENTIFY DEVICE data. * * \return None. */ /*****************************************************************************/ GLOBAL void satInquiryPage0( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData) { TI_DBG5(("satInquiryPage0: entry\n")); /* See SPC-4, 7.6.9, p 345 and SAT revision 8, 10.3.2, p 77 */ pInquiry[0] = 0x00; pInquiry[1] = 0x00; /* page code */ pInquiry[2] = 0x00; /* reserved */ pInquiry[3] = 7 - 3; /* last index(in this case, 6) - 3; page length */ /* supported vpd page list */ pInquiry[4] = 0x00; /* page 0x00 supported */ pInquiry[5] = 0x80; /* page 0x80 supported */ pInquiry[6] = 0x83; /* page 0x83 supported */ pInquiry[7] = 0x89; /* page 0x89 supported */ } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY page 83. * * SAT implementation for SCSI INQUIRY page 83. * * \param pInquiry: Pointer to Inquiry Data buffer. * \param pSATAIdData: Pointer to ATA IDENTIFY DEVICE data. * * \return None. */ /*****************************************************************************/ GLOBAL void satInquiryPage83( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData, satDeviceData_t *pSatDevData) { satSimpleSATAIdentifyData_t *pSimpleData; /* * When translating the fields, in some cases using the simple form of SATA * Identify Device Data is easier. So we define it here. * Both pSimpleData and pSATAIdData points to the same data. */ pSimpleData = ( satSimpleSATAIdentifyData_t *)pSATAIdData; TI_DBG5(("satInquiryPage83: entry\n")); pInquiry[0] = 0x00; pInquiry[1] = 0x83; /* page code */ pInquiry[2] = 0; /* Reserved */ /* * If the ATA device returns word 87 bit 8 set to one in its IDENTIFY DEVICE * data indicating that it supports the WORLD WIDE NAME field * (i.e., words 108-111), the SATL shall include an identification descriptor * containing a logical unit name. */ if ( pSatDevData->satWWNSupport) { /* Fill in SAT Rev8 Table85 */ /* * Logical unit name derived from the world wide name. */ pInquiry[3] = 12; /* 15-3; page length, no addition ID descriptor assumed*/ /* * Identifier descriptor */ pInquiry[4] = 0x01; /* Code set: binary codes */ pInquiry[5] = 0x03; /* Identifier type : NAA */ pInquiry[6] = 0x00; /* Reserved */ pInquiry[7] = 0x08; /* Identifier length */ /* Bit 4-7 NAA field, bit 0-3 MSB of IEEE Company ID */ pInquiry[8] = (bit8)((pSATAIdData->namingAuthority) >> 8); pInquiry[9] = (bit8)((pSATAIdData->namingAuthority) & 0xFF); /* IEEE Company ID */ pInquiry[10] = (bit8)((pSATAIdData->namingAuthority1) >> 8); /* IEEE Company ID */ /* Bit 4-7 LSB of IEEE Company ID, bit 0-3 MSB of Vendor Specific ID */ pInquiry[11] = (bit8)((pSATAIdData->namingAuthority1) & 0xFF); pInquiry[12] = (bit8)((pSATAIdData->uniqueID_bit16_31) >> 8); /* Vendor Specific ID */ pInquiry[13] = (bit8)((pSATAIdData->uniqueID_bit16_31) & 0xFF); /* Vendor Specific ID */ pInquiry[14] = (bit8)((pSATAIdData->uniqueID_bit0_15) >> 8); /* Vendor Specific ID */ pInquiry[15] = (bit8)((pSATAIdData->uniqueID_bit0_15) & 0xFF); /* Vendor Specific ID */ } else { /* Fill in SAT Rev8 Table86 */ /* * Logical unit name derived from the model number and serial number. */ pInquiry[3] = 72; /* 75 - 3; page length */ /* * Identifier descriptor */ pInquiry[4] = 0x02; /* Code set: ASCII codes */ pInquiry[5] = 0x01; /* Identifier type : T10 vendor ID based */ pInquiry[6] = 0x00; /* Reserved */ pInquiry[7] = 0x44; /* 0x44, 68 Identifier length */ /* Byte 8 to 15 is the vendor id string 'ATA '. */ osti_strncpy((char *)&pInquiry[8], AG_SAT_VENDOR_ID_STRING, 8); /* * Byte 16 to 75 is vendor specific id */ pInquiry[16] = (bit8)((pSimpleData->word[27]) >> 8); pInquiry[17] = (bit8)((pSimpleData->word[27]) & 0x00ff); pInquiry[18] = (bit8)((pSimpleData->word[28]) >> 8); pInquiry[19] = (bit8)((pSimpleData->word[28]) & 0x00ff); pInquiry[20] = (bit8)((pSimpleData->word[29]) >> 8); pInquiry[21] = (bit8)((pSimpleData->word[29]) & 0x00ff); pInquiry[22] = (bit8)((pSimpleData->word[30]) >> 8); pInquiry[23] = (bit8)((pSimpleData->word[30]) & 0x00ff); pInquiry[24] = (bit8)((pSimpleData->word[31]) >> 8); pInquiry[25] = (bit8)((pSimpleData->word[31]) & 0x00ff); pInquiry[26] = (bit8)((pSimpleData->word[32]) >> 8); pInquiry[27] = (bit8)((pSimpleData->word[32]) & 0x00ff); pInquiry[28] = (bit8)((pSimpleData->word[33]) >> 8); pInquiry[29] = (bit8)((pSimpleData->word[33]) & 0x00ff); pInquiry[30] = (bit8)((pSimpleData->word[34]) >> 8); pInquiry[31] = (bit8)((pSimpleData->word[34]) & 0x00ff); pInquiry[32] = (bit8)((pSimpleData->word[35]) >> 8); pInquiry[33] = (bit8)((pSimpleData->word[35]) & 0x00ff); pInquiry[34] = (bit8)((pSimpleData->word[36]) >> 8); pInquiry[35] = (bit8)((pSimpleData->word[36]) & 0x00ff); pInquiry[36] = (bit8)((pSimpleData->word[37]) >> 8); pInquiry[37] = (bit8)((pSimpleData->word[37]) & 0x00ff); pInquiry[38] = (bit8)((pSimpleData->word[38]) >> 8); pInquiry[39] = (bit8)((pSimpleData->word[38]) & 0x00ff); pInquiry[40] = (bit8)((pSimpleData->word[39]) >> 8); pInquiry[41] = (bit8)((pSimpleData->word[39]) & 0x00ff); pInquiry[42] = (bit8)((pSimpleData->word[40]) >> 8); pInquiry[43] = (bit8)((pSimpleData->word[40]) & 0x00ff); pInquiry[44] = (bit8)((pSimpleData->word[41]) >> 8); pInquiry[45] = (bit8)((pSimpleData->word[41]) & 0x00ff); pInquiry[46] = (bit8)((pSimpleData->word[42]) >> 8); pInquiry[47] = (bit8)((pSimpleData->word[42]) & 0x00ff); pInquiry[48] = (bit8)((pSimpleData->word[43]) >> 8); pInquiry[49] = (bit8)((pSimpleData->word[43]) & 0x00ff); pInquiry[50] = (bit8)((pSimpleData->word[44]) >> 8); pInquiry[51] = (bit8)((pSimpleData->word[44]) & 0x00ff); pInquiry[52] = (bit8)((pSimpleData->word[45]) >> 8); pInquiry[53] = (bit8)((pSimpleData->word[45]) & 0x00ff); pInquiry[54] = (bit8)((pSimpleData->word[46]) >> 8); pInquiry[55] = (bit8)((pSimpleData->word[46]) & 0x00ff); pInquiry[56] = (bit8)((pSimpleData->word[10]) >> 8); pInquiry[57] = (bit8)((pSimpleData->word[10]) & 0x00ff); pInquiry[58] = (bit8)((pSimpleData->word[11]) >> 8); pInquiry[59] = (bit8)((pSimpleData->word[11]) & 0x00ff); pInquiry[60] = (bit8)((pSimpleData->word[12]) >> 8); pInquiry[61] = (bit8)((pSimpleData->word[12]) & 0x00ff); pInquiry[62] = (bit8)((pSimpleData->word[13]) >> 8); pInquiry[63] = (bit8)((pSimpleData->word[13]) & 0x00ff); pInquiry[64] = (bit8)((pSimpleData->word[14]) >> 8); pInquiry[65] = (bit8)((pSimpleData->word[14]) & 0x00ff); pInquiry[66] = (bit8)((pSimpleData->word[15]) >> 8); pInquiry[67] = (bit8)((pSimpleData->word[15]) & 0x00ff); pInquiry[68] = (bit8)((pSimpleData->word[16]) >> 8); pInquiry[69] = (bit8)((pSimpleData->word[16]) & 0x00ff); pInquiry[70] = (bit8)((pSimpleData->word[17]) >> 8); pInquiry[71] = (bit8)((pSimpleData->word[17]) & 0x00ff); pInquiry[72] = (bit8)((pSimpleData->word[18]) >> 8); pInquiry[73] = (bit8)((pSimpleData->word[18]) & 0x00ff); pInquiry[74] = (bit8)((pSimpleData->word[19]) >> 8); pInquiry[75] = (bit8)((pSimpleData->word[19]) & 0x00ff); } } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY page 89. * * SAT implementation for SCSI INQUIRY page 89. * * \param pInquiry: Pointer to Inquiry Data buffer. * \param pSATAIdData: Pointer to ATA IDENTIFY DEVICE data. * \param pSatDevData Pointer to internal device data structure * * \return None. */ /*****************************************************************************/ GLOBAL void satInquiryPage89( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData, satDeviceData_t *pSatDevData) { /* SAT revision 8, 10.3.5, p 83 */ satSimpleSATAIdentifyData_t *pSimpleData; /* * When translating the fields, in some cases using the simple form of SATA * Identify Device Data is easier. So we define it here. * Both pSimpleData and pSATAIdData points to the same data. */ pSimpleData = ( satSimpleSATAIdentifyData_t *)pSATAIdData; TI_DBG5(("satInquiryPage89: start\n")); pInquiry[0] = 0x00; /* Peripheral Qualifier and Peripheral Device Type */ pInquiry[1] = 0x89; /* page code */ /* Page length 0x238 */ pInquiry[2] = 0x02; pInquiry[3] = 0x38; pInquiry[4] = 0x0; /* reserved */ pInquiry[5] = 0x0; /* reserved */ pInquiry[6] = 0x0; /* reserved */ pInquiry[7] = 0x0; /* reserved */ /* SAT Vendor Identification */ osti_strncpy((char*)&pInquiry[8], "PMC-SIERRA", 8); /* 8 bytes */ /* SAT Product Idetification */ osti_strncpy((char*)&pInquiry[16], "Tachyon-SPC ", 16); /* 16 bytes */ /* SAT Product Revision Level */ osti_strncpy((char*)&pInquiry[32], "01", 4); /* 4 bytes */ /* Signature, SAT revision8, Table88, p85 */ pInquiry[36] = 0x34; /* FIS type */ if (pSatDevData->satDeviceType == SATA_ATA_DEVICE) { /* interrupt assume to be 0 */ pInquiry[37] = (bit8)((pSatDevData->satPMField) >> (4 * 7)); /* first four bits of PM field */ } else { /* interrupt assume to be 1 */ pInquiry[37] = (bit8)(0x40 + (bit8)(((pSatDevData->satPMField) >> (4 * 7)))); /* first four bits of PM field */ } pInquiry[38] = 0; pInquiry[39] = 0; if (pSatDevData->satDeviceType == SATA_ATA_DEVICE) { pInquiry[40] = 0x01; /* LBA Low */ pInquiry[41] = 0x00; /* LBA Mid */ pInquiry[42] = 0x00; /* LBA High */ pInquiry[43] = 0x00; /* Device */ pInquiry[44] = 0x00; /* LBA Low Exp */ pInquiry[45] = 0x00; /* LBA Mid Exp */ pInquiry[46] = 0x00; /* LBA High Exp */ pInquiry[47] = 0x00; /* Reserved */ pInquiry[48] = 0x01; /* Sector Count */ pInquiry[49] = 0x00; /* Sector Count Exp */ } else { pInquiry[40] = 0x01; /* LBA Low */ pInquiry[41] = 0x00; /* LBA Mid */ pInquiry[42] = 0x00; /* LBA High */ pInquiry[43] = 0x00; /* Device */ pInquiry[44] = 0x00; /* LBA Low Exp */ pInquiry[45] = 0x00; /* LBA Mid Exp */ pInquiry[46] = 0x00; /* LBA High Exp */ pInquiry[47] = 0x00; /* Reserved */ pInquiry[48] = 0x01; /* Sector Count */ pInquiry[49] = 0x00; /* Sector Count Exp */ } /* Reserved */ pInquiry[50] = 0x00; pInquiry[51] = 0x00; pInquiry[52] = 0x00; pInquiry[53] = 0x00; pInquiry[54] = 0x00; pInquiry[55] = 0x00; /* Command Code */ if (pSatDevData->satDeviceType == SATA_ATA_DEVICE) { pInquiry[56] = 0xEC; /* IDENTIFY DEVICE */ } else { pInquiry[56] = 0xA1; /* IDENTIFY PACKET DEVICE */ } /* Reserved */ pInquiry[57] = 0x0; pInquiry[58] = 0x0; pInquiry[59] = 0x0; /* Identify Device */ osti_memcpy(&pInquiry[60], pSimpleData, sizeof(satSimpleSATAIdentifyData_t)); return; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY page 0. * * SAT implementation for SCSI INQUIRY page 0. * * \param pInquiry: Pointer to Inquiry Data buffer. * \param pSATAIdData: Pointer to ATA IDENTIFY DEVICE data. * * \return None. */ /*****************************************************************************/ GLOBAL void satInquiryPage80( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData) { TI_DBG5(("satInquiryPage80: entry\n")); /* See SPC-4, 7.6.9, p 345 and SAT revision 8, 10.3.3, p 77 */ pInquiry[0] = 0x00; pInquiry[1] = 0x80; /* page code */ pInquiry[2] = 0x00; /* reserved */ pInquiry[3] = 0x14; /* page length */ /* supported vpd page list */ pInquiry[4] = pSATAIdData->serialNumber[1]; pInquiry[5] = pSATAIdData->serialNumber[0]; pInquiry[6] = pSATAIdData->serialNumber[3]; pInquiry[7] = pSATAIdData->serialNumber[2]; pInquiry[8] = pSATAIdData->serialNumber[5]; pInquiry[9] = pSATAIdData->serialNumber[4]; pInquiry[10] = pSATAIdData->serialNumber[7]; pInquiry[11] = pSATAIdData->serialNumber[6]; pInquiry[12] = pSATAIdData->serialNumber[9]; pInquiry[13] = pSATAIdData->serialNumber[8]; pInquiry[14] = pSATAIdData->serialNumber[11]; pInquiry[15] = pSATAIdData->serialNumber[10]; pInquiry[16] = pSATAIdData->serialNumber[13]; pInquiry[17] = pSATAIdData->serialNumber[12]; pInquiry[18] = pSATAIdData->serialNumber[15]; pInquiry[19] = pSATAIdData->serialNumber[14]; pInquiry[20] = pSATAIdData->serialNumber[17]; pInquiry[21] = pSATAIdData->serialNumber[16]; pInquiry[22] = pSATAIdData->serialNumber[19]; pInquiry[23] = pSATAIdData->serialNumber[18]; } /*****************************************************************************/ /*! \brief Send READ LOG EXT ATA PAGE 10h command to sata drive. * * Send READ LOG EXT ATA command PAGE 10h request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSendReadLogExt( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; TI_DBG1(("satSendReadLogExt: tiDeviceHandle=%p tiIORequest=%p\n", tiDeviceHandle, tiIORequest)); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_READ_LOG_EXT; /* 0x2F */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0x10; /* Page number */ fis->d.lbaMid = 0; /* */ fis->d.lbaHigh = 0; /* */ fis->d.device = 0; /* DEV is ignored in SATA */ fis->d.lbaLowExp = 0; /* */ fis->d.lbaMidExp = 0; /* */ fis->d.lbaHighExp = 0; /* */ fis->d.featuresExp = 0; /* FIS reserve */ fis->d.sectorCount = 0x01; /* 1 sector counts*/ fis->d.sectorCountExp = 0x00; /* 1 sector counts */ fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satReadLogExtCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG1(("satSendReadLogExt: end status %d\n", status)); return (status); } /*****************************************************************************/ /*! \brief SAT default ATA status and ATA error translation to SCSI. * * SSAT default ATA status and ATA error translation to SCSI. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiIORequest: Pointer to TISA I/O request context for this I/O. * \param satIOContext: Pointer to the SAT IO Context * \param pSense: Pointer to scsiRspSense_t * \param ataStatus: ATA status register * \param ataError: ATA error register * \param interruptContext: Interrupt context * * \return None */ /*****************************************************************************/ GLOBAL void osSatDefaultTranslation( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, satIOContext_t *satIOContext, scsiRspSense_t *pSense, bit8 ataStatus, bit8 ataError, bit32 interruptContext ) { /* * Check for device fault case */ if ( ataStatus & DF_ATA_STATUS_MASK ) { satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, interruptContext ); return; } /* * If status error bit it set, need to check the error register */ if ( ataStatus & ERR_ATA_STATUS_MASK ) { if ( ataError & NM_ATA_ERROR_MASK ) { TI_DBG1(("osSatDefaultTranslation: NM_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_MEDIUM_NOT_PRESENT, satIOContext); } else if (ataError & UNC_ATA_ERROR_MASK) { TI_DBG1(("osSatDefaultTranslation: UNC_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_MEDIUM_ERROR, 0, SCSI_SNSCODE_UNRECOVERED_READ_ERROR, satIOContext); } else if (ataError & IDNF_ATA_ERROR_MASK) { TI_DBG1(("osSatDefaultTranslation: IDNF_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_MEDIUM_ERROR, 0, SCSI_SNSCODE_RECORD_NOT_FOUND, satIOContext); } else if (ataError & MC_ATA_ERROR_MASK) { TI_DBG1(("osSatDefaultTranslation: MC_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_UNIT_ATTENTION, 0, SCSI_SNSCODE_NOT_READY_TO_READY_CHANGE, satIOContext); } else if (ataError & MCR_ATA_ERROR_MASK) { TI_DBG1(("osSatDefaultTranslation: MCR_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_UNIT_ATTENTION, 0, SCSI_SNSCODE_OPERATOR_MEDIUM_REMOVAL_REQUEST, satIOContext); } else if (ataError & ICRC_ATA_ERROR_MASK) { TI_DBG1(("osSatDefaultTranslation: ICRC_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_INFORMATION_UNIT_CRC_ERROR, satIOContext); } else if (ataError & ABRT_ATA_ERROR_MASK) { TI_DBG1(("osSatDefaultTranslation: ABRT_ATA_ERROR ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); } else { TI_DBG1(("osSatDefaultTranslation: **** UNEXPECTED ATA_ERROR **** ataError= 0x%x, tiIORequest=%p\n", ataError, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); } /* Send the completion response now */ ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, interruptContext ); return; } else /* (ataStatus & ERR_ATA_STATUS_MASK ) is false */ { /* This case should never happen */ TI_DBG1(("osSatDefaultTranslation: *** UNEXPECTED ATA status 0x%x *** tiIORequest=%p\n", ataStatus, tiIORequest)); satSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); ostiInitiatorIOCompleted( tiRoot, tiIORequest, tiIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pTiSenseData, interruptContext ); return; } } /*****************************************************************************/ /*! \brief Allocate resource for SAT intervally generated I/O. * * Allocate resource for SAT intervally generated I/O. * * \param tiRoot: Pointer to TISA driver/port instance. * \param satDevData: Pointer to SAT specific device data. * \param allocLength: Length in byte of the DMA mem to allocate, upto * one page size. * \param satIntIo: Pointer (output) to context for SAT internally * generated I/O that is allocated by this routine. * * \return If command is started successfully * - \e tiSuccess: Success. * - \e tiError: Failed allocating resource. */ /*****************************************************************************/ GLOBAL satInternalIo_t * satAllocIntIoResource( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, satDeviceData_t *satDevData, bit32 dmaAllocLength, satInternalIo_t *satIntIo) { tdList_t *tdList = agNULL; bit32 memAllocStatus; TI_DBG1(("satAllocIntIoResource: start\n")); TI_DBG6(("satAllocIntIoResource: satIntIo %p\n", satIntIo)); if (satDevData == agNULL) { TI_DBG1(("satAllocIntIoResource: ***** ASSERT satDevData is null\n")); return agNULL; } tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); if (!TDLIST_EMPTY(&(satDevData->satFreeIntIoLinkList))) { TDLIST_DEQUEUE_FROM_HEAD(&tdList, &(satDevData->satFreeIntIoLinkList)); } else { tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); TI_DBG1(("satAllocIntIoResource() no more internal free link.\n")); return agNULL; } if (tdList == agNULL) { tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); TI_DBG1(("satAllocIntIoResource() FAIL to alloc satIntIo.\n")); return agNULL; } satIntIo = TDLIST_OBJECT_BASE( satInternalIo_t, satIntIoLink, tdList); TI_DBG6(("satAllocIntIoResource: satDevData %p satIntIo id %d\n", satDevData, satIntIo->id)); /* Put in active list */ TDLIST_DEQUEUE_THIS (&(satIntIo->satIntIoLink)); TDLIST_ENQUEUE_AT_TAIL (&(satIntIo->satIntIoLink), &(satDevData->satActiveIntIoLinkList)); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); #ifdef REMOVED /* Put in active list */ tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); TDLIST_DEQUEUE_THIS (tdList); TDLIST_ENQUEUE_AT_TAIL (tdList, &(satDevData->satActiveIntIoLinkList)); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); satIntIo = TDLIST_OBJECT_BASE( satInternalIo_t, satIntIoLink, tdList); TI_DBG6(("satAllocIntIoResource: satDevData %p satIntIo id %d\n", satDevData, satIntIo->id)); #endif /* typedef struct { tdList_t satIntIoLink; tiIORequest_t satIntTiIORequest; void *satIntRequestBody; tiScsiInitiatorRequest_t satIntTiScsiXchg; tiMem_t satIntDmaMem; tiMem_t satIntReqBodyMem; bit32 satIntFlag; } satInternalIo_t; */ /* * Allocate mem for Request Body */ satIntIo->satIntReqBodyMem.totalLength = sizeof(tdIORequestBody_t); memAllocStatus = ostiAllocMemory( tiRoot, &satIntIo->satIntReqBodyMem.osHandle, (void **)&satIntIo->satIntRequestBody, &satIntIo->satIntReqBodyMem.physAddrUpper, &satIntIo->satIntReqBodyMem.physAddrLower, 8, satIntIo->satIntReqBodyMem.totalLength, agTRUE ); if (memAllocStatus != tiSuccess) { TI_DBG1(("satAllocIntIoResource() FAIL to alloc mem for Req Body.\n")); /* * Return satIntIo to the free list */ tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); TDLIST_DEQUEUE_THIS (&satIntIo->satIntIoLink); TDLIST_ENQUEUE_AT_HEAD(&satIntIo->satIntIoLink, &satDevData->satFreeIntIoLinkList); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); return agNULL; } /* * Allocate DMA memory if required */ if (dmaAllocLength != 0) { satIntIo->satIntDmaMem.totalLength = dmaAllocLength; memAllocStatus = ostiAllocMemory( tiRoot, &satIntIo->satIntDmaMem.osHandle, (void **)&satIntIo->satIntDmaMem.virtPtr, &satIntIo->satIntDmaMem.physAddrUpper, &satIntIo->satIntDmaMem.physAddrLower, 8, satIntIo->satIntDmaMem.totalLength, agFALSE); TI_DBG6(("satAllocIntIoResource: len %d \n", satIntIo->satIntDmaMem.totalLength)); TI_DBG6(("satAllocIntIoResource: pointer %p \n", satIntIo->satIntDmaMem.osHandle)); if (memAllocStatus != tiSuccess) { TI_DBG1(("satAllocIntIoResource() FAIL to alloc mem for DMA mem.\n")); /* * Return satIntIo to the free list */ tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); TDLIST_DEQUEUE_THIS (&satIntIo->satIntIoLink); TDLIST_ENQUEUE_AT_HEAD(&satIntIo->satIntIoLink, &satDevData->satFreeIntIoLinkList); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); /* * Free mem allocated for Req body */ ostiFreeMemory( tiRoot, satIntIo->satIntReqBodyMem.osHandle, satIntIo->satIntReqBodyMem.totalLength); return agNULL; } } /* typedef struct { tdList_t satIntIoLink; tiIORequest_t satIntTiIORequest; void *satIntRequestBody; tiScsiInitiatorRequest_t satIntTiScsiXchg; tiMem_t satIntDmaMem; tiMem_t satIntReqBodyMem; bit32 satIntFlag; } satInternalIo_t; */ /* * Initialize satIntTiIORequest field */ satIntIo->satIntTiIORequest.osData = agNULL; /* Not used for internal SAT I/O */ satIntIo->satIntTiIORequest.tdData = satIntIo->satIntRequestBody; /* * saves the original tiIOrequest */ satIntIo->satOrgTiIORequest = tiIORequest; /* typedef struct tiIniScsiCmnd { tiLUN_t lun; bit32 expDataLength; bit32 taskAttribute; bit32 crn; bit8 cdb[16]; } tiIniScsiCmnd_t; typedef struct tiScsiInitiatorExchange { void *sglVirtualAddr; tiIniScsiCmnd_t scsiCmnd; tiSgl_t agSgl1; tiSgl_t agSgl2; tiDataDirection_t dataDirection; } tiScsiInitiatorRequest_t; */ /* * Initialize satIntTiScsiXchg. Since the internal SAT request is NOT * originated from SCSI request, only the following fields are initialized: * - sglVirtualAddr if DMA transfer is involved * - agSgl1 if DMA transfer is involved * - expDataLength in scsiCmnd since this field is read by sataLLIOStart() */ if (dmaAllocLength != 0) { satIntIo->satIntTiScsiXchg.sglVirtualAddr = satIntIo->satIntDmaMem.virtPtr; OSSA_WRITE_LE_32(agNULL, &satIntIo->satIntTiScsiXchg.agSgl1.len, 0, satIntIo->satIntDmaMem.totalLength); satIntIo->satIntTiScsiXchg.agSgl1.lower = satIntIo->satIntDmaMem.physAddrLower; satIntIo->satIntTiScsiXchg.agSgl1.upper = satIntIo->satIntDmaMem.physAddrUpper; satIntIo->satIntTiScsiXchg.agSgl1.type = tiSgl; satIntIo->satIntTiScsiXchg.scsiCmnd.expDataLength = satIntIo->satIntDmaMem.totalLength; } else { satIntIo->satIntTiScsiXchg.sglVirtualAddr = agNULL; satIntIo->satIntTiScsiXchg.agSgl1.len = 0; satIntIo->satIntTiScsiXchg.agSgl1.lower = 0; satIntIo->satIntTiScsiXchg.agSgl1.upper = 0; satIntIo->satIntTiScsiXchg.agSgl1.type = tiSgl; satIntIo->satIntTiScsiXchg.scsiCmnd.expDataLength = 0; } TI_DBG5(("satAllocIntIoResource: satIntIo->satIntTiScsiXchg.agSgl1.len %d\n", satIntIo->satIntTiScsiXchg.agSgl1.len)); TI_DBG5(("satAllocIntIoResource: satIntIo->satIntTiScsiXchg.agSgl1.upper %d\n", satIntIo->satIntTiScsiXchg.agSgl1.upper)); TI_DBG5(("satAllocIntIoResource: satIntIo->satIntTiScsiXchg.agSgl1.lower %d\n", satIntIo->satIntTiScsiXchg.agSgl1.lower)); TI_DBG5(("satAllocIntIoResource: satIntIo->satIntTiScsiXchg.agSgl1.type %d\n", satIntIo->satIntTiScsiXchg.agSgl1.type)); TI_DBG5(("satAllocIntIoResource: return satIntIo %p\n", satIntIo)); return satIntIo; } /*****************************************************************************/ /*! \brief Free resource for SAT intervally generated I/O. * * Free resource for SAT intervally generated I/O that was previously * allocated in satAllocIntIoResource(). * * \param tiRoot: Pointer to TISA driver/port instance. * \param satDevData: Pointer to SAT specific device data. * \param satIntIo: Pointer to context for SAT internal I/O that was * previously allocated in satAllocIntIoResource(). * * \return None */ /*****************************************************************************/ GLOBAL void satFreeIntIoResource( tiRoot_t *tiRoot, satDeviceData_t *satDevData, satInternalIo_t *satIntIo) { TI_DBG6(("satFreeIntIoResource: start\n")); if (satIntIo == agNULL) { TI_DBG6(("satFreeIntIoResource: allowed call\n")); return; } /* sets the original tiIOrequest to agNULL for internally generated ATA cmnd */ satIntIo->satOrgTiIORequest = agNULL; /* * Free DMA memory if previosly alocated */ if (satIntIo->satIntTiScsiXchg.scsiCmnd.expDataLength != 0) { TI_DBG1(("satFreeIntIoResource: DMA len %d\n", satIntIo->satIntDmaMem.totalLength)); TI_DBG6(("satFreeIntIoResource: pointer %p\n", satIntIo->satIntDmaMem.osHandle)); ostiFreeMemory( tiRoot, satIntIo->satIntDmaMem.osHandle, satIntIo->satIntDmaMem.totalLength); satIntIo->satIntTiScsiXchg.scsiCmnd.expDataLength = 0; } if (satIntIo->satIntReqBodyMem.totalLength != 0) { TI_DBG1(("satFreeIntIoResource: req body len %d\n", satIntIo->satIntReqBodyMem.totalLength)); /* * Free mem allocated for Req body */ ostiFreeMemory( tiRoot, satIntIo->satIntReqBodyMem.osHandle, satIntIo->satIntReqBodyMem.totalLength); satIntIo->satIntReqBodyMem.totalLength = 0; } TI_DBG6(("satFreeIntIoResource: satDevData %p satIntIo id %d\n", satDevData, satIntIo->id)); /* * Return satIntIo to the free list */ tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); TDLIST_DEQUEUE_THIS (&(satIntIo->satIntIoLink)); TDLIST_ENQUEUE_AT_TAIL (&(satIntIo->satIntIoLink), &(satDevData->satFreeIntIoLinkList)); tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY. * * SAT implementation for SCSI INQUIRY. * This function sends ATA Identify Device data command for SCSI INQUIRY * * \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. */ /*****************************************************************************/ GLOBAL bit32 satSendIDDev( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE satInternalIo_t *satIntIoContext; tdsaDeviceData_t *oneDeviceData; tdIORequestBody_t *tdIORequestBody; #endif pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; TI_DBG5(("satSendIDDev: start\n")); #ifdef TD_DEBUG_ENABLE oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; #endif TI_DBG5(("satSendIDDev: did %d\n", oneDeviceData->id)); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; tdIORequestBody = satIntIoContext->satIntRequestBody; #endif TI_DBG5(("satSendIDDev: satIOContext %p tdIORequestBody %p\n", satIOContext, tdIORequestBody)); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE) fis->h.command = SAT_IDENTIFY_PACKET_DEVICE; /* 0x40 */ else fis->h.command = SAT_IDENTIFY_DEVICE; /* 0xEC */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satInquiryCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef TD_INTERNAL_DEBUG tdhexdump("satSendIDDev", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE tdhexdump("satSendIDDev LL", (bit8 *)&(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG6(("satSendIDDev: end status %d\n", status)); return status; } /*****************************************************************************/ /*! \brief SAT implementation for SCSI INQUIRY. * * SAT implementation for SCSI INQUIRY. * This function prepares TD layer internal resource to send ATA * Identify Device data command for SCSI INQUIRY * * \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. */ /*****************************************************************************/ /* prerequsite: tdsaDeviceData and agdevhandle must exist; in other words, LL discovered the device already */ /* convert OS generated IO to TD generated IO due to difference in sgl */ GLOBAL bit32 satStartIDDev( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { satInternalIo_t *satIntIo = agNULL; satDeviceData_t *satDevData = agNULL; tdIORequestBody_t *tdIORequestBody; satIOContext_t *satNewIOContext; bit32 status; TI_DBG6(("satStartIDDev: start\n")); satDevData = satIOContext->pSatDevData; TI_DBG6(("satStartIDDev: before alloc\n")); /* allocate identify device command */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, satDevData, sizeof(agsaSATAIdentifyData_t), /* 512; size of identify device data */ satIntIo); TI_DBG6(("satStartIDDev: before after\n")); if (satIntIo == agNULL) { TI_DBG1(("satStartIDDev: can't alloacate\n")); #if 0 ostiInitiatorIOCompleted ( tiRoot, tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, satIOContext->interruptContext ); #endif return tiError; } /* fill in fields */ /* real ttttttthe one worked and the same; 5/21/07/ */ satIntIo->satOrgTiIORequest = tiIORequest; /* changed */ tdIORequestBody = satIntIo->satIntRequestBody; satNewIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satIntIo->satIntTiScsiXchg.scsiCmnd); satNewIOContext->pSense = &(tdIORequestBody->transport.SATA.sensePayload); satNewIOContext->pTiSenseData = &(tdIORequestBody->transport.SATA.tiSenseData); satNewIOContext->tiRequestBody = satIntIo->satIntRequestBody; /* key fix */ satNewIOContext->interruptContext = tiInterruptContext; satNewIOContext->satIntIoContext = satIntIo; satNewIOContext->ptiDeviceHandle = agNULL; satNewIOContext->satOrgIOContext = satIOContext; /* changed */ /* this is valid only for TD layer generated (not triggered by OS at all) IO */ satNewIOContext->tiScsiXchg = &(satIntIo->satIntTiScsiXchg); TI_DBG6(("satStartIDDev: OS satIOContext %p \n", satIOContext)); TI_DBG6(("satStartIDDev: TD satNewIOContext %p \n", satNewIOContext)); TI_DBG6(("satStartIDDev: OS tiScsiXchg %p \n", satIOContext->tiScsiXchg)); TI_DBG6(("satStartIDDev: TD tiScsiXchg %p \n", satNewIOContext->tiScsiXchg)); TI_DBG1(("satStartIDDev: satNewIOContext %p tdIORequestBody %p\n", satNewIOContext, tdIORequestBody)); status = satSendIDDev( tiRoot, &satIntIo->satIntTiIORequest, /* New tiIORequest */ tiDeviceHandle, satNewIOContext->tiScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); if (status != tiSuccess) { TI_DBG1(("satStartIDDev: failed in sending\n")); satFreeIntIoResource( tiRoot, satDevData, satIntIo); #if 0 ostiInitiatorIOCompleted ( tiRoot, tiIORequest, tiIOFailed, tiDetailOtherError, agNULL, satIOContext->interruptContext ); #endif return tiError; } TI_DBG6(("satStartIDDev: end\n")); return status; } /*****************************************************************************/ /*! \brief satComputeCDB10LBA. * * This fuctions computes LBA of CDB10. * * \param satIOContext_t: Pointer to the SAT IO Context * * \return * - \e LBA */ /*****************************************************************************/ bit32 satComputeCDB10LBA(satIOContext_t *satIOContext) { tiIniScsiCmnd_t *scsiCmnd; tiScsiInitiatorRequest_t *tiScsiRequest; bit32 lba = 0; TI_DBG5(("satComputeCDB10LBA: start\n")); tiScsiRequest = satIOContext->tiScsiXchg; scsiCmnd = &(tiScsiRequest->scsiCmnd); lba = (scsiCmnd->cdb[2] << (8*3)) + (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; return lba; } /*****************************************************************************/ /*! \brief satComputeCDB10TL. * * This fuctions computes transfer length of CDB10. * * \param satIOContext_t: Pointer to the SAT IO Context * * \return * - \e TL */ /*****************************************************************************/ bit32 satComputeCDB10TL(satIOContext_t *satIOContext) { tiIniScsiCmnd_t *scsiCmnd; tiScsiInitiatorRequest_t *tiScsiRequest; bit32 tl = 0; TI_DBG5(("satComputeCDB10TL: start\n")); tiScsiRequest = satIOContext->tiScsiXchg; scsiCmnd = &(tiScsiRequest->scsiCmnd); tl = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; return tl; } /*****************************************************************************/ /*! \brief satComputeCDB12LBA. * * This fuctions computes LBA of CDB12. * * \param satIOContext_t: Pointer to the SAT IO Context * * \return * - \e LBA */ /*****************************************************************************/ bit32 satComputeCDB12LBA(satIOContext_t *satIOContext) { tiIniScsiCmnd_t *scsiCmnd; tiScsiInitiatorRequest_t *tiScsiRequest; bit32 lba = 0; TI_DBG5(("satComputeCDB10LBA: start\n")); tiScsiRequest = satIOContext->tiScsiXchg; scsiCmnd = &(tiScsiRequest->scsiCmnd); lba = (scsiCmnd->cdb[2] << (8*3)) + (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; return lba; } /*****************************************************************************/ /*! \brief satComputeCDB12TL. * * This fuctions computes transfer length of CDB12. * * \param satIOContext_t: Pointer to the SAT IO Context * * \return * - \e TL */ /*****************************************************************************/ bit32 satComputeCDB12TL(satIOContext_t *satIOContext) { tiIniScsiCmnd_t *scsiCmnd; tiScsiInitiatorRequest_t *tiScsiRequest; bit32 tl = 0; TI_DBG5(("satComputeCDB10TL: start\n")); tiScsiRequest = satIOContext->tiScsiXchg; scsiCmnd = &(tiScsiRequest->scsiCmnd); tl = (scsiCmnd->cdb[6] << (8*3)) + (scsiCmnd->cdb[7] << (8*2)) + (scsiCmnd->cdb[8] << 8) + scsiCmnd->cdb[9]; return tl; } /*****************************************************************************/ /*! \brief satComputeCDB16LBA. * * This fuctions computes LBA of CDB16. * * \param satIOContext_t: Pointer to the SAT IO Context * * \return * - \e LBA */ /*****************************************************************************/ /* CBD16 has bit64 LBA But it has to be less than (2^28 - 1) Therefore, use last four bytes to compute LBA is OK */ bit32 satComputeCDB16LBA(satIOContext_t *satIOContext) { tiIniScsiCmnd_t *scsiCmnd; tiScsiInitiatorRequest_t *tiScsiRequest; bit32 lba = 0; TI_DBG5(("satComputeCDB10LBA: start\n")); tiScsiRequest = satIOContext->tiScsiXchg; scsiCmnd = &(tiScsiRequest->scsiCmnd); lba = (scsiCmnd->cdb[6] << (8*3)) + (scsiCmnd->cdb[7] << (8*2)) + (scsiCmnd->cdb[8] << 8) + scsiCmnd->cdb[9]; return lba; } /*****************************************************************************/ /*! \brief satComputeCDB16TL. * * This fuctions computes transfer length of CDB16. * * \param satIOContext_t: Pointer to the SAT IO Context * * \return * - \e TL */ /*****************************************************************************/ bit32 satComputeCDB16TL(satIOContext_t *satIOContext) { tiIniScsiCmnd_t *scsiCmnd; tiScsiInitiatorRequest_t *tiScsiRequest; bit32 tl = 0; TI_DBG5(("satComputeCDB10TL: start\n")); tiScsiRequest = satIOContext->tiScsiXchg; scsiCmnd = &(tiScsiRequest->scsiCmnd); tl = (scsiCmnd->cdb[10] << (8*3)) + (scsiCmnd->cdb[11] << (8*2)) + (scsiCmnd->cdb[12] << 8) + scsiCmnd->cdb[13]; return tl; } /*****************************************************************************/ /*! \brief satComputeLoopNum. * * This fuctions computes the number of interation needed for a transfer * length with a specific number. * * \param a: a numerator * \param b: a denominator * * \return * - \e number of interation */ /*****************************************************************************/ /* (tl, denom) tl can be upto bit32 because CDB16 has bit32 tl Therefore, fine either (tl, 0xFF) or (tl, 0xFFFF) */ bit32 satComputeLoopNum(bit32 a, bit32 b) { bit32 quo = 0, rem = 0; bit32 LoopNum = 0; TI_DBG5(("satComputeLoopNum: start\n")); quo = a/b; if (quo == 0) { LoopNum = 1; } else { rem = a % b; if (rem == 0) { LoopNum = quo; } else { LoopNum = quo + 1; } } return LoopNum; } /*****************************************************************************/ /*! \brief satAddNComparebit64. * * * * * \param a: lba * \param b: tl * * \return * - \e TRUE if (lba + tl > SAT_TR_LBA_LIMIT) * - \e FALSE otherwise * \note: a and b must be in the same length */ /*****************************************************************************/ /* input: bit8 a[8], bit8 b[8] (lba, tl) must be in same length if (lba + tl > SAT_TR_LBA_LIMIT) then returns true else returns false (LBA,TL) */ bit32 satAddNComparebit64(bit8 *a, bit8 *b) { bit16 ans[8]; // 0 MSB, 8 LSB bit8 final_ans[9]; // 0 MSB, 9 LSB bit8 max[9]; int i; TI_DBG5(("satAddNComparebit64: start\n")); osti_memset(ans, 0, sizeof(ans)); osti_memset(final_ans, 0, sizeof(final_ans)); osti_memset(max, 0, sizeof(max)); max[0] = 0x1; //max = 0x1 0000 0000 0000 0000 // adding from LSB to MSB for(i=7;i>=0;i--) { ans[i] = (bit16)(a[i] + b[i]); if (i != 7) { ans[i] = (bit16)(ans[i] + ((ans[i+1] & 0xFF00) >> 8)); } } /* filling in the final answer */ final_ans[0] = (bit8)(((ans[0] & 0xFF00) >> 8)); final_ans[1] = (bit8)(ans[0] & 0xFF); for(i=2;i<=8;i++) { final_ans[i] = (bit8)(ans[i-1] & 0xFF); } //compare final_ans to max for(i=0;i<=8;i++) { if (final_ans[i] > max[i]) { TI_DBG5(("satAddNComparebit64: yes at %d\n", i)); return agTRUE; } else if (final_ans[i] < max[i]) { TI_DBG5(("satAddNComparebit64: no at %d\n", i)); return agFALSE; } else { continue; } } return agFALSE; } /*****************************************************************************/ /*! \brief satAddNComparebit32. * * * * * \param a: lba * \param b: tl * * \return * - \e TRUE if (lba + tl > SAT_TR_LBA_LIMIT) * - \e FALSE otherwise * \note: a and b must be in the same length */ /*****************************************************************************/ /* input: bit8 a[4], bit8 b[4] (lba, tl) must be in same length if (lba + tl > SAT_TR_LBA_LIMIT) then returns true else returns false (LBA,TL) */ bit32 satAddNComparebit32(bit8 *a, bit8 *b) { bit16 ans[4]; // 0 MSB, 4 LSB bit8 final_ans[5]; // 0 MSB, 5 LSB bit8 max[4]; int i; TI_DBG5(("satAddNComparebit32: start\n")); osti_memset(ans, 0, sizeof(ans)); osti_memset(final_ans, 0, sizeof(final_ans)); osti_memset(max, 0, sizeof(max)); max[0] = 0x10; // max =0x1000 0000 // adding from LSB to MSB for(i=3;i>=0;i--) { ans[i] = (bit16)(a[i] + b[i]); if (i != 3) { ans[i] = (bit16)(ans[i] + ((ans[i+1] & 0xFF00) >> 8)); } } /* filling in the final answer */ final_ans[0] = (bit8)(((ans[0] & 0xFF00) >> 8)); final_ans[1] = (bit8)(ans[0] & 0xFF); for(i=2;i<=4;i++) { final_ans[i] = (bit8)(ans[i-1] & 0xFF); } //compare final_ans to max if (final_ans[0] != 0) { TI_DBG5(("satAddNComparebit32: yes bigger and out of range\n")); return agTRUE; } for(i=1;i<=4;i++) { if (final_ans[i] > max[i-1]) { TI_DBG5(("satAddNComparebit32: yes at %d\n", i)); return agTRUE; } else if (final_ans[i] < max[i-1]) { TI_DBG5(("satAddNComparebit32: no at %d\n", i)); return agFALSE; } else { continue; } } return agFALSE; } /*****************************************************************************/ /*! \brief satCompareLBALimitbit. * * * * * \param lba: lba * * \return * - \e TRUE if (lba > SAT_TR_LBA_LIMIT - 1) * - \e FALSE otherwise * \note: a and b must be in the same length */ /*****************************************************************************/ /* lba */ /* input: bit8 lba[8] if (lba > SAT_TR_LBA_LIMIT - 1) then returns true else returns false (LBA,TL) */ bit32 satCompareLBALimitbit(bit8 *lba) { bit32 i; bit8 limit[8]; /* limit is 0xF FF FF = 2^28 - 1 */ limit[0] = 0x0; /* MSB */ limit[1] = 0x0; limit[2] = 0x0; limit[3] = 0x0; limit[4] = 0xF; limit[5] = 0xFF; limit[6] = 0xFF; limit[7] = 0xFF; /* LSB */ //compare lba to limit for(i=0;i<8;i++) { if (lba[i] > limit[i]) { TI_DBG5(("satCompareLBALimitbit64: yes at %d\n", i)); return agTRUE; } else if (lba[i] < limit[i]) { TI_DBG5(("satCompareLBALimitbit64: no at %d\n", i)); return agFALSE; } else { continue; } } return agFALSE; } /***************************************************************************** *! \brief * Purpose: bitwise set * * Parameters: * data - input output buffer * index - bit to set * * Return: * none * *****************************************************************************/ GLOBAL void satBitSet(bit8 *data, bit32 index) { data[index/8] |= (1 << (index%8)); } /***************************************************************************** *! \brief * Purpose: bitwise clear * * Parameters: * data - input output buffer * index - bit to clear * * Return: * none * *****************************************************************************/ GLOBAL void satBitClear(bit8 *data, bit32 index) { data[index/8] &= ~(1 << (index%8)); } /***************************************************************************** *! \brief * Purpose: bitwise test * * Parameters: * data - input output buffer * index - bit to test * * Return: * 0 - not set * 1 - set * *****************************************************************************/ GLOBAL agBOOLEAN satBitTest(bit8 *data, bit32 index) { return ( (BOOLEAN)((data[index/8] & (1 << (index%8)) ) ? 1: 0)); } /******************************************************************************/ /*! \brief allocate an available SATA tag * * allocate an available SATA tag * * \param tiRoot Pointer to TISA initiator driver/port instance. * \param pSatDevData * \param pTag * * \return -Success or fail- */ /*******************************************************************************/ GLOBAL bit32 satTagAlloc( tiRoot_t *tiRoot, satDeviceData_t *pSatDevData, bit8 *pTag ) { bit32 retCode = agFALSE; bit32 i; tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); for ( i = 0; i < pSatDevData->satNCQMaxIO; i ++ ) { if ( 0 == satBitTest((bit8 *)&pSatDevData->freeSATAFDMATagBitmap, i) ) { satBitSet((bit8*)&pSatDevData->freeSATAFDMATagBitmap, i); *pTag = (bit8) i; retCode = agTRUE; break; } } tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); return retCode; } /******************************************************************************/ /*! \brief release an SATA tag * * release an available SATA tag * * \param tiRoot Pointer to TISA initiator driver/port instance. * \param pSatDevData * \param Tag * * \return -the tag- */ /*******************************************************************************/ GLOBAL bit32 satTagRelease( tiRoot_t *tiRoot, satDeviceData_t *pSatDevData, bit8 tag ) { bit32 retCode = agFALSE; tdsaSingleThreadedEnter(tiRoot, TD_SATA_LOCK); if ( tag < pSatDevData->satNCQMaxIO ) { satBitClear( (bit8 *)&pSatDevData->freeSATAFDMATagBitmap, (bit32)tag); retCode = agTRUE; } tdsaSingleThreadedLeave(tiRoot, TD_SATA_LOCK); return retCode; } /***************************************************************************** *! \brief satSubTM * * This routine is called to initiate a TM request to SATL. * This routine is independent of HW/LL API. * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param tiDeviceHandle: Pointer to TISA device handle for this I/O. * \param task: SAM-3 task management request. * \param lun: Pointer to LUN. * \param taskTag: Pointer to the associated task where the TM * command is to be applied. * \param currentTaskTag: Pointer to tag/context for this TM request. * \param NotifyOS flag determines whether notify OS layer or not * * \return: * * \e tiSuccess: I/O request successfully initiated. * \e tiBusy: No resources available, try again later. * \e tiIONoDevice: Invalid device handle. * \e tiError: Other errors that prevent the I/O request to be started. * * \note: * This funcion is triggered bottom up. Not yet in use. *****************************************************************************/ /* called for bottom up */ osGLOBAL bit32 satSubTM( tiRoot_t *tiRoot, tiDeviceHandle_t *tiDeviceHandle, bit32 task, tiLUN_t *lun, tiIORequest_t *taskTag, tiIORequest_t *currentTaskTag, bit32 NotifyOS ) { void *osMemHandle; tdIORequestBody_t *TMtdIORequestBody; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; agsaIORequest_t *agIORequest = agNULL; TI_DBG6(("satSubTM: start\n")); /* allocation tdIORequestBody and pass it to satTM() */ memAllocStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&TMtdIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(tdIORequestBody_t), agTRUE ); if (memAllocStatus != tiSuccess) { TI_DBG1(("satSubTM: ostiAllocMemory failed... \n")); return tiError; } if (TMtdIORequestBody == agNULL) { TI_DBG1(("satSubTM: ostiAllocMemory returned NULL TMIORequestBody\n")); return tiError; } /* setup task management structure */ TMtdIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; TMtdIORequestBody->IOType.InitiatorTMIO.CurrentTaskTag = agNULL; TMtdIORequestBody->IOType.InitiatorTMIO.TaskTag = agNULL; /* initialize tiDevhandle */ TMtdIORequestBody->tiDevHandle = tiDeviceHandle; /* initialize tiIORequest */ TMtdIORequestBody->tiIORequest = agNULL; /* initialize agIORequest */ agIORequest = &(TMtdIORequestBody->agIORequest); agIORequest->osData = (void *) TMtdIORequestBody; agIORequest->sdkData = agNULL; /* SA takes care of this */ satTM(tiRoot, tiDeviceHandle, task, /* TD_INTERNAL_TM_RESET */ agNULL, agNULL, agNULL, TMtdIORequestBody, agFALSE); return tiSuccess; } /*****************************************************************************/ /*! \brief SAT implementation for satStartResetDevice. * * SAT implementation for sending SRT and send FIS request to LL layer. * * \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. * \note : triggerred by OS layer or bottom up */ /*****************************************************************************/ /* OS triggerred or bottom up */ GLOBAL bit32 satStartResetDevice( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* currentTaskTag */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, /* should be NULL */ satIOContext_t *satIOContext ) { satInternalIo_t *satIntIo = agNULL; satDeviceData_t *satDevData = agNULL; satIOContext_t *satNewIOContext; bit32 status; tiIORequest_t *currentTaskTag = agNULL; TI_DBG1(("satStartResetDevice: start\n")); currentTaskTag = tiIORequest; satDevData = satIOContext->pSatDevData; TI_DBG6(("satStartResetDevice: before alloc\n")); /* allocate any fis for seting SRT bit in device control */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, satDevData, 0, satIntIo); TI_DBG6(("satStartResetDevice: before after\n")); if (satIntIo == agNULL) { TI_DBG1(("satStartResetDevice: can't alloacate\n")); if (satIOContext->NotifyOS) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, currentTaskTag ); } return tiError; } satNewIOContext = satPrepareNewIO(satIntIo, tiIORequest, satDevData, agNULL, satIOContext); TI_DBG6(("satStartResetDevice: OS satIOContext %p \n", satIOContext)); TI_DBG6(("satStartResetDevice: TD satNewIOContext %p \n", satNewIOContext)); TI_DBG6(("satStartResetDevice: OS tiScsiXchg %p \n", satIOContext->tiScsiXchg)); TI_DBG6(("satStartResetDevice: TD tiScsiXchg %p \n", satNewIOContext->tiScsiXchg)); TI_DBG6(("satStartResetDevice: satNewIOContext %p \n", satNewIOContext)); if (satDevData->satDeviceType == SATA_ATAPI_DEVICE) { status = satDeviceReset(tiRoot, &satIntIo->satIntTiIORequest, /* New tiIORequest */ tiDeviceHandle, satNewIOContext->tiScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); } else { status = satResetDevice(tiRoot, &satIntIo->satIntTiIORequest, /* New tiIORequest */ tiDeviceHandle, satNewIOContext->tiScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); } if (status != tiSuccess) { TI_DBG1(("satStartResetDevice: failed in sending\n")); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satIOContext->NotifyOS) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, currentTaskTag ); } return tiError; } TI_DBG6(("satStartResetDevice: end\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for satResetDevice. * * SAT implementation for building SRT FIS and sends the request to LL layer. * * \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. */ /*****************************************************************************/ /* create any fis and set SRST bit in device control */ GLOBAL bit32 satResetDevice( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE tdIORequestBody_t *tdIORequestBody; satInternalIo_t *satIntIoContext; #endif fis = satIOContext->pFis; TI_DBG2(("satResetDevice: start\n")); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; tdIORequestBody = satIntIoContext->satIntRequestBody; #endif TI_DBG5(("satResetDevice: satIOContext %p tdIORequestBody %p\n", satIOContext, tdIORequestBody)); /* any fis should work */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0; /* C Bit is not set */ fis->h.command = 0; /* any command */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0x4; /* SRST bit is set */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_SRST_ASSERT; satIOContext->satCompleteCB = &satResetDeviceCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef TD_INTERNAL_DEBUG tdhexdump("satResetDevice", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE tdhexdump("satResetDevice LL", (bit8 *)&(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG6(("satResetDevice: end status %d\n", status)); return status; } /***************************************************************************** *! \brief satResetDeviceCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with SRT completion. This function send DSRT * * \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 * *****************************************************************************/ GLOBAL void satResetDeviceCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, 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; 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; TI_DBG1(("satResetDeviceCB: start\n")); TI_DBG6(("satResetDeviceCB: 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(("satResetDeviceCB: External, OS generated\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG6(("satResetDeviceCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG6(("satResetDeviceCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG6(("satResetDeviceCB: 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(("satResetDeviceCB: 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(("satResetDeviceCB: 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) { #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(("satResetDeviceCB: 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 */ satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { satDevData->satTmTaskTag = agNULL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); /* memory allocation failure */ satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); if (satOrgIOContext->NotifyOS == agTRUE) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, tiOrgIORequest ); } TI_DBG1(("satResetDeviceCB: momory allocation fails\n")); return; } /* end of memory allocation failure */ /* * Need to initialize all the fields within satIOContext */ satNewIOContext = satPrepareNewIO( satNewIntIo, tiOrgIORequest, satDevData, agNULL, satOrgIOContext ); /* send AGSA_SATA_PROTOCOL_SRST_DEASSERT */ status = satDeResetDevice(tiRoot, tiOrgIORequest, satOrgIOContext->ptiDeviceHandle, agNULL, satNewIOContext ); if (status != tiSuccess) { if (satOrgIOContext->NotifyOS == agTRUE) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, tiOrgIORequest ); } /* sending AGSA_SATA_PROTOCOL_SRST_DEASSERT fails */ satDevData->satTmTaskTag = agNULL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satNewIntIo); return; } satDevData->satTmTaskTag = agNULL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); TI_DBG5(("satResetDeviceCB: device %p pending IO %d\n", satDevData, satDevData->satPendingIO)); TI_DBG6(("satResetDeviceCB: end\n")); return; } /*****************************************************************************/ /*! \brief SAT implementation for satDeResetDevice. * * SAT implementation for building DSRT FIS and sends the request to LL layer. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satDeResetDevice( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE tdIORequestBody_t *tdIORequestBody; satInternalIo_t *satIntIoContext; #endif fis = satIOContext->pFis; TI_DBG6(("satDeResetDevice: start\n")); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; tdIORequestBody = satIntIoContext->satIntRequestBody; TI_DBG5(("satDeResetDevice: satIOContext %p tdIORequestBody %p\n", satIOContext, tdIORequestBody)); #endif /* any fis should work */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0; /* C Bit is not set */ fis->h.command = 0; /* any command */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* SRST bit is not set */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_SRST_DEASSERT; satIOContext->satCompleteCB = &satDeResetDeviceCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef TD_INTERNAL_DEBUG tdhexdump("satDeResetDevice", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE tdhexdump("satDeResetDevice LL", (bit8 *)&(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG6(("satDeResetDevice: end status %d\n", status)); return status; } /***************************************************************************** *! \brief satDeResetDeviceCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with DSRT 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 * *****************************************************************************/ GLOBAL void satDeResetDeviceCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { /* callback for satDeResetDevice */ 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; tiIORequest_t *tiOrgIORequest; #ifdef TD_DEBUG_ENABLE bit32 ataStatus = 0; bit32 ataError; agsaFisPioSetupHeader_t *satPIOSetupHeader = agNULL; #endif bit32 report = agFALSE; bit32 AbortTM = agFALSE; TI_DBG1(("satDeResetDeviceCB: start\n")); TI_DBG6(("satDeResetDeviceCB: 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(("satDeResetDeviceCB: External, OS generated\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG6(("satDeResetDeviceCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG6(("satDeResetDeviceCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG6(("satDeResetDeviceCB: 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(("satDeResetDeviceCB: 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(("satDeResetDeviceCB: 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) { #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(("satDeResetDeviceCB: 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 */ TI_DBG1(("satDeResetDeviceCB: success \n")); TI_DBG1(("satDeResetDeviceCB: TMF %d\n", satOrgIOContext->TMF)); 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(("satDeResetDeviceCB: satPendingIO %d satNCQMaxIO %d\n", satDevData->satPendingIO, satDevData->satNCQMaxIO )); TI_DBG1(("satDeResetDeviceCB: 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(("satDeResetDeviceCB: tdOrgIORequestBody is NULL, wrong\n")); } if (report) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMOK, tiOrgIORequest ); } TI_DBG5(("satDeResetDeviceCB: device %p pending IO %d\n", satDevData, satDevData->satPendingIO)); TI_DBG6(("satDeResetDeviceCB: end\n")); return; } /*****************************************************************************/ /*! \brief SAT implementation for satStartCheckPowerMode. * * SAT implementation for abort task management for non-ncq sata disk. * This function sends CHECK POWER MODE * * \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. */ /*****************************************************************************/ GLOBAL bit32 satStartCheckPowerMode( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, /* NULL */ satIOContext_t *satIOContext ) { satInternalIo_t *satIntIo = agNULL; satDeviceData_t *satDevData = agNULL; satIOContext_t *satNewIOContext; bit32 status; tiIORequest_t *currentTaskTag = agNULL; TI_DBG6(("satStartCheckPowerMode: start\n")); currentTaskTag = tiIORequest; satDevData = satIOContext->pSatDevData; TI_DBG6(("satStartCheckPowerMode: before alloc\n")); /* allocate any fis for seting SRT bit in device control */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, satDevData, 0, satIntIo); TI_DBG6(("satStartCheckPowerMode: before after\n")); if (satIntIo == agNULL) { TI_DBG1(("satStartCheckPowerMode: can't alloacate\n")); if (satIOContext->NotifyOS) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, currentTaskTag ); } return tiError; } satNewIOContext = satPrepareNewIO(satIntIo, tiIORequest, satDevData, agNULL, satIOContext); TI_DBG6(("satStartCheckPowerMode: OS satIOContext %p \n", satIOContext)); TI_DBG6(("satStartCheckPowerMode: TD satNewIOContext %p \n", satNewIOContext)); TI_DBG6(("satStartCheckPowerMode: OS tiScsiXchg %p \n", satIOContext->tiScsiXchg)); TI_DBG6(("satStartCheckPowerMode: TD tiScsiXchg %p \n", satNewIOContext->tiScsiXchg)); TI_DBG1(("satStartCheckPowerMode: satNewIOContext %p \n", satNewIOContext)); status = satCheckPowerMode(tiRoot, &satIntIo->satIntTiIORequest, /* New tiIORequest */ tiDeviceHandle, satNewIOContext->tiScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); if (status != tiSuccess) { TI_DBG1(("satStartCheckPowerMode: failed in sending\n")); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satIOContext->NotifyOS) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMFailed, currentTaskTag ); } return tiError; } TI_DBG6(("satStartCheckPowerMode: end\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for satCheckPowerMode. * * This function creates CHECK POWER MODE fis and sends the request to LL layer * * \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. */ /*****************************************************************************/ GLOBAL bit32 satCheckPowerMode( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { /* sends SAT_CHECK_POWER_MODE as a part of ABORT TASKMANGEMENT for NCQ commands internally generated - no directly corresponding scsi */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; TI_DBG5(("satCheckPowerMode: start\n")); /* * Send the ATA CHECK POWER MODE command. */ fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.command = SAT_CHECK_POWER_MODE; /* 0xE5 */ fis->h.features = 0; fis->d.lbaLow = 0; fis->d.lbaMid = 0; fis->d.lbaHigh = 0; fis->d.device = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satCheckPowerModeCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG5(("satCheckPowerMode: return\n")); return status; } /***************************************************************************** *! \brief satCheckPowerModeCB * * This routine is a callback function called from ossaSATACompleted(). * This CB routine deals with CHECK POWER MODE completion as abort task * management. * * \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 * *****************************************************************************/ GLOBAL void satCheckPowerModeCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle, void *ioContext ) { /* callback for satDeResetDevice */ 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; tiIORequest_t *tiOrgIORequest; #ifdef TD_DEBUG_ENABLE bit32 ataStatus = 0; bit32 ataError; agsaFisPioSetupHeader_t *satPIOSetupHeader = agNULL; #endif bit32 report = agFALSE; bit32 AbortTM = agFALSE; TI_DBG1(("satCheckPowerModeCB: start\n")); TI_DBG1(("satCheckPowerModeCB: 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(("satCheckPowerModeCB: External, OS generated\n")); satOrgIOContext = satIOContext; tiOrgIORequest = tdIORequestBody->tiIORequest; } else { TI_DBG6(("satCheckPowerModeCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG6(("satCheckPowerModeCB: satOrgIOContext is NULL, wrong\n")); return; } else { TI_DBG6(("satCheckPowerModeCB: 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(("satCheckPowerModeCB: 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(("satCheckPowerModeCB: 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) { #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(("satCheckPowerModeCB: 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 */ TI_DBG1(("satCheckPowerModeCB: success\n")); TI_DBG1(("satCheckPowerModeCB: TMF %d\n", satOrgIOContext->TMF)); if (satOrgIOContext->TMF == AG_ABORT_TASK) { AbortTM = agTRUE; } if (satOrgIOContext->NotifyOS == agTRUE) { report = agTRUE; } if (AbortTM == agTRUE) { TI_DBG1(("satCheckPowerModeCB: calling satAbort\n")); satAbort(agRoot, satOrgIOContext->satToBeAbortedIOContext); } satDevData->satTmTaskTag = agNULL; satDevData->satDriveState = SAT_DEV_STATE_NORMAL; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); TI_DBG1(("satCheckPowerModeCB: satPendingIO %d satNCQMaxIO %d\n", satDevData->satPendingIO, satDevData->satNCQMaxIO )); TI_DBG1(("satCheckPowerModeCB: 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(("satCheckPowerModeCB: tdOrgIORequestBody is NULL, wrong\n")); } if (report) { ostiInitiatorEvent( tiRoot, NULL, NULL, tiIntrEventTypeTaskManagement, tiTMOK, tiOrgIORequest ); } TI_DBG5(("satCheckPowerModeCB: device %p pending IO %d\n", satDevData, satDevData->satPendingIO)); TI_DBG2(("satCheckPowerModeCB: end\n")); return; } /*****************************************************************************/ /*! \brief SAT implementation for satAddSATAStartIDDev. * * This function sends identify device data to find out the uniqueness * of device. * * \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. */ /*****************************************************************************/ GLOBAL bit32 satAddSATAStartIDDev( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, // NULL satIOContext_t *satIOContext ) { satInternalIo_t *satIntIo = agNULL; satDeviceData_t *satDevData = agNULL; tdIORequestBody_t *tdIORequestBody; satIOContext_t *satNewIOContext; bit32 status; TI_DBG2(("satAddSATAStartIDDev: start\n")); satDevData = satIOContext->pSatDevData; TI_DBG2(("satAddSATAStartIDDev: before alloc\n")); /* allocate identify device command */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, satDevData, sizeof(agsaSATAIdentifyData_t), /* 512; size of identify device data */ satIntIo); TI_DBG2(("satAddSATAStartIDDev: after alloc\n")); if (satIntIo == agNULL) { TI_DBG1(("satAddSATAStartIDDev: can't alloacate\n")); return tiError; } /* fill in fields */ /* real ttttttthe one worked and the same; 5/21/07/ */ satIntIo->satOrgTiIORequest = tiIORequest; /* changed */ tdIORequestBody = satIntIo->satIntRequestBody; satNewIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satIntIo->satIntTiScsiXchg.scsiCmnd); satNewIOContext->pSense = &(tdIORequestBody->transport.SATA.sensePayload); satNewIOContext->pTiSenseData = &(tdIORequestBody->transport.SATA.tiSenseData); satNewIOContext->tiRequestBody = satIntIo->satIntRequestBody; /* key fix */ satNewIOContext->interruptContext = tiInterruptContext; satNewIOContext->satIntIoContext = satIntIo; satNewIOContext->ptiDeviceHandle = agNULL; satNewIOContext->satOrgIOContext = satIOContext; /* changed */ /* this is valid only for TD layer generated (not triggered by OS at all) IO */ satNewIOContext->tiScsiXchg = &(satIntIo->satIntTiScsiXchg); TI_DBG6(("satAddSATAStartIDDev: OS satIOContext %p \n", satIOContext)); TI_DBG6(("satAddSATAStartIDDev: TD satNewIOContext %p \n", satNewIOContext)); TI_DBG6(("satAddSATAStartIDDev: OS tiScsiXchg %p \n", satIOContext->tiScsiXchg)); TI_DBG6(("satAddSATAStartIDDev: TD tiScsiXchg %p \n", satNewIOContext->tiScsiXchg)); TI_DBG2(("satAddSATAStartIDDev: satNewIOContext %p tdIORequestBody %p\n", satNewIOContext, tdIORequestBody)); status = satAddSATASendIDDev( tiRoot, &satIntIo->satIntTiIORequest, /* New tiIORequest */ tiDeviceHandle, satNewIOContext->tiScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); if (status != tiSuccess) { TI_DBG1(("satAddSATAStartIDDev: failed in sending\n")); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return tiError; } TI_DBG6(("satAddSATAStartIDDev: end\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for satAddSATASendIDDev. * * This function creates identify device data fis and send it to LL * * \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. */ /*****************************************************************************/ GLOBAL bit32 satAddSATASendIDDev( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE tdIORequestBody_t *tdIORequestBody; satInternalIo_t *satIntIoContext; #endif pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; TI_DBG2(("satAddSATASendIDDev: start\n")); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; tdIORequestBody = satIntIoContext->satIntRequestBody; #endif TI_DBG5(("satAddSATASendIDDev: satIOContext %p tdIORequestBody %p\n", satIOContext, tdIORequestBody)); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE) fis->h.command = SAT_IDENTIFY_PACKET_DEVICE; /* 0x40 */ else fis->h.command = SAT_IDENTIFY_DEVICE; /* 0xEC */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &satAddSATAIDDevCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef TD_INTERNAL_DEBUG tdhexdump("satAddSATASendIDDev", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE tdhexdump("satAddSATASendIDDev LL", (bit8 *)&(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG2(("satAddSATASendIDDev: end status %d\n", status)); return status; } /***************************************************************************** *! \brief satAddSATAIDDevCB * * This routine is a callback function for satAddSATASendIDDev() * Using Identify Device Data, this function finds whether devicedata is * new or old. If new, add it to the devicelist. * * \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 satAddSATAIDDevCB( 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; satIOContext_t *satNewIOContext; satInternalIo_t *satIntIo; satInternalIo_t *satNewIntIo = agNULL; satDeviceData_t *satDevData; tiIORequest_t *tiOrgIORequest = agNULL; agsaSATAIdentifyData_t *pSATAIdData; bit16 *tmpptr, tmpptr_tmp; bit32 x; tdsaDeviceData_t *NewOneDeviceData = agNULL; tdsaDeviceData_t *oneDeviceData = agNULL; tdList_t *DeviceListList; int new_device = agTRUE; bit8 PhyID; void *sglVirtualAddr; bit32 retry_status; agsaContext_t *agContext; tdsaPortContext_t *onePortContext; bit32 status = 0; TI_DBG2(("satAddSATAIDDevCB: start\n")); TI_DBG6(("satAddSATAIDDevCB: 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; NewOneDeviceData = (tdsaDeviceData_t *)tdIORequestBody->tiDevHandle->tdData; TI_DBG2(("satAddSATAIDDevCB: NewOneDeviceData %p did %d\n", NewOneDeviceData, NewOneDeviceData->id)); PhyID = NewOneDeviceData->phyID; TI_DBG2(("satAddSATAIDDevCB: phyID %d\n", PhyID)); agContext = &(NewOneDeviceData->agDeviceResetContext); agContext->osData = agNULL; if (satIntIo == agNULL) { TI_DBG1(("satAddSATAIDDevCB: External, OS generated\n")); TI_DBG1(("satAddSATAIDDevCB: Not possible case\n")); satOrgIOContext = satIOContext; tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; tdsaAbortAll(tiRoot, agRoot, NewOneDeviceData); /* put onedevicedata back to free list */ osti_memset(&(NewOneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); TDLIST_DEQUEUE_THIS(&(NewOneDeviceData->MainLink)); TDLIST_ENQUEUE_AT_TAIL(&(NewOneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); /* 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; } else { TI_DBG1(("satAddSATAIDDevCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG6(("satAddSATAIDDevCB: satOrgIOContext is NULL\n")); return; } else { TI_DBG6(("satAddSATAIDDevCB: satOrgIOContext is NOT NULL\n")); tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; sglVirtualAddr = satIntIo->satIntTiScsiXchg.sglVirtualAddr; } } tiOrgIORequest = tdIORequestBody->tiIORequest; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; TI_DBG2(("satAddSATAIDDevCB: satOrgIOContext->pid %d\n", satOrgIOContext->pid)); /* protect against double completion for old port */ if (satOrgIOContext->pid != tdsaAllShared->Ports[PhyID].portContext->id) { TI_DBG2(("satAddSATAIDDevCB: incorrect pid\n")); TI_DBG2(("satAddSATAIDDevCB: satOrgIOContext->pid %d\n", satOrgIOContext->pid)); TI_DBG2(("satAddSATAIDDevCB: tiPortalContext pid %d\n", tdsaAllShared->Ports[PhyID].portContext->id)); tdsaAbortAll(tiRoot, agRoot, NewOneDeviceData); /* put onedevicedata back to free list */ osti_memset(&(NewOneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); TDLIST_DEQUEUE_THIS(&(NewOneDeviceData->MainLink)); TDLIST_ENQUEUE_AT_TAIL(&(NewOneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); /* no notification to OS layer */ return; } /* completion after portcontext is invalidated */ onePortContext = NewOneDeviceData->tdPortContext; if (onePortContext != agNULL) { if (onePortContext->valid == agFALSE) { TI_DBG1(("satAddSATAIDDevCB: portcontext is invalid\n")); TI_DBG1(("satAddSATAIDDevCB: onePortContext->id pid %d\n", onePortContext->id)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); /* no notification to OS layer */ return; } } else { TI_DBG1(("satAddSATAIDDevCB: onePortContext is NULL!!!\n")); return; } if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("satAddSATAIDDevCB: wrong. agFirstDword is NULL when error, status %d\n", agIOStatus)); if (tdsaAllShared->ResetInDiscovery != 0 && satDevData->ID_Retries < SATA_ID_DEVICE_DATA_RETRIES) { satDevData->satPendingNONNCQIO--; satDevData->satPendingIO--; retry_status = sataLLIOStart(tiRoot, &satIntIo->satIntTiIORequest, &(NewOneDeviceData->tiDeviceHandle), satIOContext->tiScsiXchg, satIOContext); if (retry_status != tiSuccess) { /* simply give up */ satDevData->ID_Retries = 0; satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); return; } satDevData->ID_Retries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; return; } else { if (tdsaAllShared->ResetInDiscovery == 0) { satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); } else /* ResetInDiscovery in on */ { /* RESET only one after ID retries */ if (satDevData->NumOfIDRetries <= 0) { satDevData->NumOfIDRetries++; satDevData->ID_Retries = 0; satAddSATAIDDevCBReset(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); /* send link reset */ saLocalPhyControl(agRoot, agContext, tdsaRotateQnumber(tiRoot, NewOneDeviceData), PhyID, AGSA_PHY_HARD_RESET, agNULL); } else { satDevData->ID_Retries = 0; satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); } } 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(("satAddSATAIDDevCB: OSSA_IO_OPEN_CNX_ERROR\n")); if (tdsaAllShared->ResetInDiscovery != 0 && satDevData->ID_Retries < SATA_ID_DEVICE_DATA_RETRIES) { satDevData->satPendingNONNCQIO--; satDevData->satPendingIO--; retry_status = sataLLIOStart(tiRoot, &satIntIo->satIntTiIORequest, &(NewOneDeviceData->tiDeviceHandle), satIOContext->tiScsiXchg, satIOContext); if (retry_status != tiSuccess) { /* simply give up */ satDevData->ID_Retries = 0; satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); return; } satDevData->ID_Retries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; return; } else { if (tdsaAllShared->ResetInDiscovery == 0) { satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); } else /* ResetInDiscovery in on */ { /* RESET only one after ID retries */ if (satDevData->NumOfIDRetries <= 0) { satDevData->NumOfIDRetries++; satDevData->ID_Retries = 0; satAddSATAIDDevCBReset(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); /* send link reset */ saLocalPhyControl(agRoot, agContext, tdsaRotateQnumber(tiRoot, NewOneDeviceData), PhyID, AGSA_PHY_HARD_RESET, agNULL); } else { satDevData->ID_Retries = 0; satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); } } return; } } if ( agIOStatus != OSSA_IO_SUCCESS || (agIOStatus == OSSA_IO_SUCCESS && agFirstDword != agNULL && agIOInfoLen != 0) ) { if (tdsaAllShared->ResetInDiscovery != 0 && satDevData->ID_Retries < SATA_ID_DEVICE_DATA_RETRIES) { satIOContext->pSatDevData->satPendingNONNCQIO--; satIOContext->pSatDevData->satPendingIO--; retry_status = sataLLIOStart(tiRoot, &satIntIo->satIntTiIORequest, &(NewOneDeviceData->tiDeviceHandle), satIOContext->tiScsiXchg, satIOContext); if (retry_status != tiSuccess) { /* simply give up */ satDevData->ID_Retries = 0; satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); return; } satDevData->ID_Retries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; return; } else { if (tdsaAllShared->ResetInDiscovery == 0) { satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); } else /* ResetInDiscovery in on */ { /* RESET only one after ID retries */ if (satDevData->NumOfIDRetries <= 0) { satDevData->NumOfIDRetries++; satDevData->ID_Retries = 0; satAddSATAIDDevCBReset(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); /* send link reset */ saLocalPhyControl(agRoot, agContext, tdsaRotateQnumber(tiRoot, NewOneDeviceData), PhyID, AGSA_PHY_HARD_RESET, agNULL); } else { satDevData->ID_Retries = 0; satAddSATAIDDevCBCleanup(agRoot, NewOneDeviceData, satIOContext, tdOrgIORequestBody); } } return; } } /* success */ TI_DBG2(("satAddSATAIDDevCB: Success\n")); /* Convert to host endian */ tmpptr = (bit16*)sglVirtualAddr; //tdhexdump("satAddSATAIDDevCB before", (bit8 *)sglVirtualAddr, sizeof(agsaSATAIdentifyData_t)); 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 *)sglVirtualAddr; //tdhexdump("satAddSATAIDDevCB after", (bit8 *)pSATAIdData, sizeof(agsaSATAIdentifyData_t)); TI_DBG5(("satAddSATAIDDevCB: OS satOrgIOContext %p \n", satOrgIOContext)); TI_DBG5(("satAddSATAIDDevCB: TD satIOContext %p \n", satIOContext)); TI_DBG5(("satAddSATAIDDevCB: OS tiScsiXchg %p \n", satOrgIOContext->tiScsiXchg)); TI_DBG5(("satAddSATAIDDevCB: TD tiScsiXchg %p \n", satIOContext->tiScsiXchg)); /* compare idenitfy device data to the exiting list */ DeviceListList = tdsaAllShared->MainDeviceList.flink; while (DeviceListList != &(tdsaAllShared->MainDeviceList)) { oneDeviceData = TDLIST_OBJECT_BASE(tdsaDeviceData_t, MainLink, DeviceListList); TI_DBG1(("satAddSATAIDDevCB: LOOP oneDeviceData %p did %d\n", oneDeviceData, oneDeviceData->id)); //tdhexdump("satAddSATAIDDevCB LOOP", (bit8 *)&oneDeviceData->satDevData.satIdentifyData, sizeof(agsaSATAIdentifyData_t)); /* what is unique ID for sata device -> response of identify devicedata; not really Let's compare serial number, firmware version, model number */ if ( oneDeviceData->DeviceType == TD_SATA_DEVICE && (osti_memcmp (oneDeviceData->satDevData.satIdentifyData.serialNumber, pSATAIdData->serialNumber, 20) == 0) && (osti_memcmp (oneDeviceData->satDevData.satIdentifyData.firmwareVersion, pSATAIdData->firmwareVersion, 8) == 0) && (osti_memcmp (oneDeviceData->satDevData.satIdentifyData.modelNumber, pSATAIdData->modelNumber, 40) == 0) ) { TI_DBG2(("satAddSATAIDDevCB: did %d\n", oneDeviceData->id)); new_device = agFALSE; break; } DeviceListList = DeviceListList->flink; } if (new_device == agFALSE) { TI_DBG2(("satAddSATAIDDevCB: old device data\n")); oneDeviceData->valid = agTRUE; oneDeviceData->valid2 = agTRUE; /* save data field from new device data */ oneDeviceData->agRoot = agRoot; oneDeviceData->agDevHandle = NewOneDeviceData->agDevHandle; oneDeviceData->agDevHandle->osData = oneDeviceData; /* TD layer */ oneDeviceData->tdPortContext = NewOneDeviceData->tdPortContext; oneDeviceData->phyID = NewOneDeviceData->phyID; /* one SATA directly attached device per phy; Therefore, deregister then register */ saDeregisterDeviceHandle(agRoot, agNULL, NewOneDeviceData->agDevHandle, 0); if (oneDeviceData->registered == agFALSE) { TI_DBG2(("satAddSATAIDDevCB: re-registering old device data\n")); /* already has old information; just register it again */ saRegisterNewDevice( /* satAddSATAIDDevCB */ agRoot, &oneDeviceData->agContext, tdsaRotateQnumber(tiRoot, oneDeviceData), &oneDeviceData->agDeviceInfo, oneDeviceData->tdPortContext->agPortContext, 0 ); } // tdsaAbortAll(tiRoot, agRoot, NewOneDeviceData); /* put onedevicedata back to free list */ osti_memset(&(NewOneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); TDLIST_DEQUEUE_THIS(&(NewOneDeviceData->MainLink)); TDLIST_ENQUEUE_AT_TAIL(&(NewOneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satDevData->satDeviceType == SATA_ATAPI_DEVICE) { /* send the Set Feature ATA command to ATAPI device for enbling PIO and DMA transfer mode*/ satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: momory allocation fails\n")); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO(satNewIntIo, tiOrgIORequest, satDevData, agNULL, satOrgIOContext ); /* enable PIO mode, then enable Ultra DMA mode in the satSetFeaturesCB callback function*/ status = satSetFeatures(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, /* orginal from OS layer */ satNewIOContext, agFALSE); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } } else { /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); TI_DBG2(("satAddSATAIDDevCB: pid %d\n", tdsaAllShared->Ports[PhyID].portContext->id)); /* notifying link up */ ostiPortEvent( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[PhyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[PhyID].tiPortalContext ); #endif } return; } TI_DBG2(("satAddSATAIDDevCB: new device data\n")); /* copy ID Dev data to satDevData */ satDevData->satIdentifyData = *pSATAIdData; satDevData->IDDeviceValid = agTRUE; #ifdef TD_INTERNAL_DEBUG tdhexdump("satAddSATAIDDevCB ID Dev data",(bit8 *)pSATAIdData, sizeof(agsaSATAIdentifyData_t)); tdhexdump("satAddSATAIDDevCB Device ID Dev data",(bit8 *)&satDevData->satIdentifyData, sizeof(agsaSATAIdentifyData_t)); #endif /* set satDevData fields from IndentifyData */ satSetDevInfo(satDevData,pSATAIdData); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satDevData->satDeviceType == SATA_ATAPI_DEVICE) { /* send the Set Feature ATA command to ATAPI device for enbling PIO and DMA transfer mode*/ satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: momory allocation fails\n")); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO(satNewIntIo, tiOrgIORequest, satDevData, agNULL, satOrgIOContext ); /* enable PIO mode, then enable Ultra DMA mode in the satSetFeaturesCB callback function*/ status = satSetFeatures(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, /* orginal from OS layer */ satNewIOContext, agFALSE); if (status != tiSuccess) { satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } } else { /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); TI_DBG2(("satAddSATAIDDevCB: pid %d\n", tdsaAllShared->Ports[PhyID].portContext->id)); /* notifying link up */ ostiPortEvent ( tiRoot, tiPortLinkUp, tiSuccess, (void *)tdsaAllShared->Ports[PhyID].tiPortalContext ); #ifdef INITIATOR_DRIVER /* triggers discovery */ ostiPortEvent( tiRoot, tiPortDiscoveryReady, tiSuccess, (void *) tdsaAllShared->Ports[PhyID].tiPortalContext ); #endif } TI_DBG2(("satAddSATAIDDevCB: end\n")); return; } /***************************************************************************** *! \brief satAddSATAIDDevCBReset * * This routine cleans up IOs for failed Identify device data * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param oneDeviceData: Pointer to the device data. * \param ioContext: Pointer to satIOContext_t. * \param tdIORequestBody: Pointer to the request body * \param flag: Decrement pending io or not * * \return: none * *****************************************************************************/ void satAddSATAIDDevCBReset( agsaRoot_t *agRoot, tdsaDeviceData_t *oneDeviceData, satIOContext_t *satIOContext, tdIORequestBody_t *tdIORequestBody ) { 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; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; TI_DBG2(("satAddSATAIDDevCBReset: start\n")); satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } /***************************************************************************** *! \brief satAddSATAIDDevCBCleanup * * This routine cleans up IOs for failed Identify device data * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param oneDeviceData: Pointer to the device data. * \param ioContext: Pointer to satIOContext_t. * \param tdIORequestBody: Pointer to the request body * * \return: none * *****************************************************************************/ void satAddSATAIDDevCBCleanup( agsaRoot_t *agRoot, tdsaDeviceData_t *oneDeviceData, satIOContext_t *satIOContext, tdIORequestBody_t *tdIORequestBody ) { 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; satInternalIo_t *satIntIo; satDeviceData_t *satDevData; bit8 PhyID; TI_DBG2(("satAddSATAIDDevCBCleanup: start\n")); satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; PhyID = oneDeviceData->phyID; tdsaAbortAll(tiRoot, agRoot, oneDeviceData); /* put onedevicedata back to free list */ osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); TDLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink)); TDLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(tdsaAllShared->FreeDeviceList)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); /* 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; } /*****************************************************************************/ /*! \brief SAT implementation for tdsaDiscoveryStartIDDev. * * This function sends identify device data to SATA device in discovery * * * \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 oneDeviceData : Pointer to the device data. * * \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. */ /*****************************************************************************/ GLOBAL bit32 tdsaDiscoveryStartIDDev(tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* agNULL */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, /* agNULL */ tdsaDeviceData_t *oneDeviceData ) { 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; /* allocate tdiorequestbody and call tdsaDiscoveryIntStartIDDev tdsaDiscoveryIntStartIDDev(tiRoot, agNULL, tiDeviceHandle, satIOContext); */ TI_DBG3(("tdsaDiscoveryStartIDDev: start\n")); TI_DBG3(("tdsaDiscoveryStartIDDev: did %d\n", oneDeviceData->id)); /* 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(("tdsaDiscoveryStartIDDev: ostiAllocMemory failed... loc 1\n")); return tiError; } if (tdIORequestBody == agNULL) { TI_DBG1(("tdsaDiscoveryStartIDDev: ostiAllocMemory returned NULL tdIORequestBody loc 2\n")); return tiError; } /* 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; /* saving port ID just in case of full discovery to full discovery transition */ satIOContext->pid = oneDeviceData->tdPortContext->id; osti_memset(&(oneDeviceData->satDevData.satIdentifyData), 0x0, sizeof(agsaSATAIdentifyData_t)); status = tdsaDiscoveryIntStartIDDev(tiRoot, tiIORequest, /* agNULL */ tiDeviceHandle, /* &(oneDeviceData->tiDeviceHandle)*/ agNULL, satIOContext ); if (status != tiSuccess) { TI_DBG1(("tdsaDiscoveryStartIDDev: failed in sending %d\n", status)); ostiFreeMemory(tiRoot, osMemHandle, sizeof(tdIORequestBody_t)); } return status; } /*****************************************************************************/ /*! \brief SAT implementation for tdsaDiscoveryIntStartIDDev. * * This function sends identify device data to SATA device. * * \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. */ /*****************************************************************************/ GLOBAL bit32 tdsaDiscoveryIntStartIDDev(tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, /* agNULL */ tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, /* agNULL */ satIOContext_t *satIOContext ) { satInternalIo_t *satIntIo = agNULL; satDeviceData_t *satDevData = agNULL; tdIORequestBody_t *tdIORequestBody; satIOContext_t *satNewIOContext; bit32 status; TI_DBG3(("tdsaDiscoveryIntStartIDDev: start\n")); satDevData = satIOContext->pSatDevData; /* allocate identify device command */ satIntIo = satAllocIntIoResource( tiRoot, tiIORequest, satDevData, sizeof(agsaSATAIdentifyData_t), /* 512; size of identify device data */ satIntIo); if (satIntIo == agNULL) { TI_DBG2(("tdsaDiscoveryIntStartIDDev: can't alloacate\n")); return tiError; } /* fill in fields */ /* real ttttttthe one worked and the same; 5/21/07/ */ satIntIo->satOrgTiIORequest = tiIORequest; /* changed */ tdIORequestBody = satIntIo->satIntRequestBody; satNewIOContext = &(tdIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satIntIo->satIntTiScsiXchg.scsiCmnd); satNewIOContext->pSense = &(tdIORequestBody->transport.SATA.sensePayload); satNewIOContext->pTiSenseData = &(tdIORequestBody->transport.SATA.tiSenseData); satNewIOContext->tiRequestBody = satIntIo->satIntRequestBody; /* key fix */ satNewIOContext->interruptContext = tiInterruptContext; satNewIOContext->satIntIoContext = satIntIo; satNewIOContext->ptiDeviceHandle = agNULL; satNewIOContext->satOrgIOContext = satIOContext; /* changed */ /* this is valid only for TD layer generated (not triggered by OS at all) IO */ satNewIOContext->tiScsiXchg = &(satIntIo->satIntTiScsiXchg); TI_DBG6(("tdsaDiscoveryIntStartIDDev: OS satIOContext %p \n", satIOContext)); TI_DBG6(("tdsaDiscoveryIntStartIDDev: TD satNewIOContext %p \n", satNewIOContext)); TI_DBG6(("tdsaDiscoveryIntStartIDDev: OS tiScsiXchg %p \n", satIOContext->tiScsiXchg)); TI_DBG6(("tdsaDiscoveryIntStartIDDev: TD tiScsiXchg %p \n", satNewIOContext->tiScsiXchg)); TI_DBG3(("tdsaDiscoveryIntStartIDDev: satNewIOContext %p tdIORequestBody %p\n", satNewIOContext, tdIORequestBody)); status = tdsaDiscoverySendIDDev(tiRoot, &satIntIo->satIntTiIORequest, /* New tiIORequest */ tiDeviceHandle, satNewIOContext->tiScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); if (status != tiSuccess) { TI_DBG1(("tdsaDiscoveryIntStartIDDev: failed in sending %d\n", status)); satFreeIntIoResource( tiRoot, satDevData, satIntIo); return tiError; } TI_DBG6(("tdsaDiscoveryIntStartIDDev: end\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for tdsaDiscoverySendIDDev. * * This function prepares identify device data FIS and sends it to SATA device. * * \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. */ /*****************************************************************************/ GLOBAL bit32 tdsaDiscoverySendIDDev(tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, satIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; satDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE tdIORequestBody_t *tdIORequestBody; satInternalIo_t *satIntIoContext; #endif pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; TI_DBG3(("tdsaDiscoverySendIDDev: start\n")); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; tdIORequestBody = satIntIoContext->satIntRequestBody; #endif TI_DBG5(("tdsaDiscoverySendIDDev: satIOContext %p tdIORequestBody %p\n", satIOContext, tdIORequestBody)); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE) fis->h.command = SAT_IDENTIFY_PACKET_DEVICE; /* 0xA1 */ else fis->h.command = SAT_IDENTIFY_DEVICE; /* 0xEC */ fis->h.features = 0; /* FIS reserve */ fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = 0; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0; /* FIS LBA (23:16) */ fis->d.device = 0; /* FIS LBA mode */ fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.featuresExp = 0; fis->d.sectorCount = 0; /* FIS sector count (7:0) */ fis->d.sectorCountExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &tdsaDiscoveryStartIDDevCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef TD_INTERNAL_DEBUG tdhexdump("tdsaDiscoverySendIDDev", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE tdhexdump("tdsaDiscoverySendIDDev LL", (bit8 *)&(tdIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = sataLLIOStart( tiRoot, tiIORequest, tiDeviceHandle, tiScsiRequest, satIOContext); TI_DBG3(("tdsaDiscoverySendIDDev: end status %d\n", status)); return status; } /***************************************************************************** *! \brief tdsaDiscoveryStartIDDevCB * * This routine is a callback function for tdsaDiscoverySendIDDev() * Using Identify Device Data, this function finds whether devicedata is * new or old. If new, add it to the devicelist. This is done as a part * of discovery. * * \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 tdsaDiscoveryStartIDDevCB( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, agsaFisHeader_t *agFirstDword, bit32 agIOInfoLen, void *agParam, void *ioContext ) { /* In the process of SAT_IDENTIFY_DEVICE during discovery */ 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 = agNULL; #ifdef TD_DEBUG_ENABLE bit32 ataStatus = 0; bit32 ataError; agsaFisPioSetupHeader_t *satPIOSetupHeader = agNULL; #endif agsaSATAIdentifyData_t *pSATAIdData; bit16 *tmpptr, tmpptr_tmp; bit32 x; tdsaDeviceData_t *oneDeviceData = agNULL; void *sglVirtualAddr; tdsaPortContext_t *onePortContext = agNULL; tiPortalContext_t *tiPortalContext = agNULL; bit32 retry_status; TI_DBG3(("tdsaDiscoveryStartIDDevCB: start\n")); tdIORequestBody = (tdIORequestBody_t *)agIORequest->osData; satIOContext = (satIOContext_t *) ioContext; satIntIo = satIOContext->satIntIoContext; satDevData = satIOContext->pSatDevData; oneDeviceData = (tdsaDeviceData_t *)tdIORequestBody->tiDevHandle->tdData; TI_DBG3(("tdsaDiscoveryStartIDDevCB: did %d\n", oneDeviceData->id)); onePortContext = oneDeviceData->tdPortContext; if (onePortContext == agNULL) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: onePortContext is NULL\n")); return; } tiPortalContext= onePortContext->tiPortalContext; satDevData->IDDeviceValid = agFALSE; if (satIntIo == agNULL) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: External, OS generated\n")); TI_DBG1(("tdsaDiscoveryStartIDDevCB: Not possible case\n")); satOrgIOContext = satIOContext; 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; } else { TI_DBG3(("tdsaDiscoveryStartIDDevCB: Internal, TD generated\n")); satOrgIOContext = satIOContext->satOrgIOContext; if (satOrgIOContext == agNULL) { TI_DBG6(("tdsaDiscoveryStartIDDevCB: satOrgIOContext is NULL\n")); return; } else { TI_DBG6(("tdsaDiscoveryStartIDDevCB: satOrgIOContext is NOT NULL\n")); tdOrgIORequestBody = (tdIORequestBody_t *)satOrgIOContext->tiRequestBody; sglVirtualAddr = satIntIo->satIntTiScsiXchg.sglVirtualAddr; } } tiOrgIORequest = tdIORequestBody->tiIORequest; tdIORequestBody->ioCompleted = agTRUE; tdIORequestBody->ioStarted = agFALSE; TI_DBG3(("tdsaDiscoveryStartIDDevCB: satOrgIOContext->pid %d\n", satOrgIOContext->pid)); /* protect against double completion for old port */ if (satOrgIOContext->pid != oneDeviceData->tdPortContext->id) { TI_DBG3(("tdsaDiscoveryStartIDDevCB: incorrect pid\n")); TI_DBG3(("tdsaDiscoveryStartIDDevCB: satOrgIOContext->pid %d\n", satOrgIOContext->pid)); TI_DBG3(("tdsaDiscoveryStartIDDevCB: tiPortalContext pid %d\n", oneDeviceData->tdPortContext->id)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } /* completion after portcontext is invalidated */ if (onePortContext != agNULL) { if (onePortContext->valid == agFALSE) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: portcontext is invalid\n")); TI_DBG1(("tdsaDiscoveryStartIDDevCB: onePortContext->id pid %d\n", onePortContext->id)); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); /* no notification to OS layer */ return; } } if (agFirstDword == agNULL && agIOStatus != OSSA_IO_SUCCESS) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: agFirstDword is NULL when error, status %d\n", agIOStatus)); TI_DBG1(("tdsaDiscoveryStartIDDevCB: did %d\n", oneDeviceData->id)); if (tdsaAllShared->ResetInDiscovery != 0 && satDevData->ID_Retries < SATA_ID_DEVICE_DATA_RETRIES) { satIOContext->pSatDevData->satPendingNONNCQIO--; satIOContext->pSatDevData->satPendingIO--; retry_status = sataLLIOStart(tiRoot, &satIntIo->satIntTiIORequest, &(oneDeviceData->tiDeviceHandle), satIOContext->tiScsiXchg, satIOContext); if (retry_status != tiSuccess) { /* simply give up */ satDevData->ID_Retries = 0; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } satDevData->ID_Retries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; return; } else { satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); if (tdsaAllShared->ResetInDiscovery != 0) { /* ResetInDiscovery in on */ if (satDevData->NumOfIDRetries <= 0) { satDevData->NumOfIDRetries++; satDevData->ID_Retries = 0; /* send link reset */ tdsaPhyControlSend(tiRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData) ); } } return; } } if (agIOStatus == OSSA_IO_ABORTED || agIOStatus == OSSA_IO_UNDERFLOW || agIOStatus == OSSA_IO_XFER_ERROR_BREAK || agIOStatus == OSSA_IO_XFER_ERROR_PHY_NOT_READY || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_PROTOCOL_NOT_SUPPORTED || 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_STP_RESOURCES_BUSY || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_WRONG_DESTINATION || agIOStatus == OSSA_IO_XFER_ERROR_NAK_RECEIVED || agIOStatus == OSSA_IO_XFER_ERROR_DMA || agIOStatus == OSSA_IO_XFER_ERROR_SATA_LINK_TIMEOUT || agIOStatus == OSSA_IO_XFER_ERROR_REJECTED_NCQ_MODE || agIOStatus == OSSA_IO_XFER_OPEN_RETRY_TIMEOUT || agIOStatus == OSSA_IO_NO_DEVICE || agIOStatus == OSSA_IO_OPEN_CNX_ERROR_ZONE_VIOLATION || agIOStatus == OSSA_IO_PORT_IN_RESET || agIOStatus == OSSA_IO_DS_NON_OPERATIONAL || agIOStatus == OSSA_IO_DS_IN_RECOVERY || agIOStatus == OSSA_IO_DS_IN_ERROR ) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: OSSA_IO_OPEN_CNX_ERROR 0x%x\n", agIOStatus)); if (tdsaAllShared->ResetInDiscovery != 0 && satDevData->ID_Retries < SATA_ID_DEVICE_DATA_RETRIES) { satIOContext->pSatDevData->satPendingNONNCQIO--; satIOContext->pSatDevData->satPendingIO--; retry_status = sataLLIOStart(tiRoot, &satIntIo->satIntTiIORequest, &(oneDeviceData->tiDeviceHandle), satIOContext->tiScsiXchg, satIOContext); if (retry_status != tiSuccess) { /* simply give up */ satDevData->ID_Retries = 0; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } satDevData->ID_Retries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; return; } else { satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); if (tdsaAllShared->ResetInDiscovery != 0) { /* ResetInDiscovery in on */ if (satDevData->NumOfIDRetries <= 0) { satDevData->NumOfIDRetries++; satDevData->ID_Retries = 0; /* send link reset */ tdsaPhyControlSend(tiRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData) ); } } 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(("tdsaDiscoveryStartIDDevCB: ataStatus 0x%x ataError 0x%x\n", ataStatus, ataError)); if (tdsaAllShared->ResetInDiscovery != 0 && satDevData->ID_Retries < SATA_ID_DEVICE_DATA_RETRIES) { satIOContext->pSatDevData->satPendingNONNCQIO--; satIOContext->pSatDevData->satPendingIO--; retry_status = sataLLIOStart(tiRoot, &satIntIo->satIntTiIORequest, &(oneDeviceData->tiDeviceHandle), satIOContext->tiScsiXchg, satIOContext); if (retry_status != tiSuccess) { /* simply give up */ satDevData->ID_Retries = 0; satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } satDevData->ID_Retries++; tdIORequestBody->ioCompleted = agFALSE; tdIORequestBody->ioStarted = agTRUE; return; } else { satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); if (tdsaAllShared->ResetInDiscovery != 0) { /* ResetInDiscovery in on */ if (satDevData->NumOfIDRetries <= 0) { satDevData->NumOfIDRetries++; satDevData->ID_Retries = 0; /* send link reset */ tdsaPhyControlSend(tiRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, agNULL, tdsaRotateQnumber(tiRoot, oneDeviceData) ); } } return; } } /* success */ TI_DBG3(("tdsaDiscoveryStartIDDevCB: Success\n")); TI_DBG3(("tdsaDiscoveryStartIDDevCB: Success did %d\n", oneDeviceData->id)); /* Convert to host endian */ tmpptr = (bit16*)sglVirtualAddr; for (x=0; x < sizeof(agsaSATAIdentifyData_t)/sizeof(bit16); x++) { OSSA_READ_LE_16(AGROOT, &tmpptr_tmp, tmpptr, 0); *tmpptr = tmpptr_tmp; tmpptr++; } pSATAIdData = (agsaSATAIdentifyData_t *)sglVirtualAddr; //tdhexdump("satAddSATAIDDevCB before", (bit8 *)pSATAIdData, sizeof(agsaSATAIdentifyData_t)); TI_DBG5(("tdsaDiscoveryStartIDDevCB: OS satOrgIOContext %p \n", satOrgIOContext)); TI_DBG5(("tdsaDiscoveryStartIDDevCB: TD satIOContext %p \n", satIOContext)); TI_DBG5(("tdsaDiscoveryStartIDDevCB: OS tiScsiXchg %p \n", satOrgIOContext->tiScsiXchg)); TI_DBG5(("tdsaDiscoveryStartIDDevCB: TD tiScsiXchg %p \n", satIOContext->tiScsiXchg)); /* copy ID Dev data to satDevData */ satDevData->satIdentifyData = *pSATAIdData; satDevData->IDDeviceValid = agTRUE; #ifdef TD_INTERNAL_DEBUG tdhexdump("tdsaDiscoveryStartIDDevCB ID Dev data",(bit8 *)pSATAIdData, sizeof(agsaSATAIdentifyData_t)); tdhexdump("tdsaDiscoveryStartIDDevCB Device ID Dev data",(bit8 *)&satDevData->satIdentifyData, sizeof(agsaSATAIdentifyData_t)); #endif /* set satDevData fields from IndentifyData */ satSetDevInfo(satDevData,pSATAIdData); satDecrementPendingIO(tiRoot, tdsaAllShared, satIOContext); satFreeIntIoResource( tiRoot, satDevData, satIntIo); if (satDevData->satDeviceType == SATA_ATAPI_DEVICE) { /* send the Set Feature ATA command to ATAPI device for enbling PIO and DMA transfer mode*/ satNewIntIo = satAllocIntIoResource( tiRoot, tiOrgIORequest, satDevData, 0, satNewIntIo); if (satNewIntIo == agNULL) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: momory allocation fails\n")); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); return; } /* end memory allocation */ satNewIOContext = satPrepareNewIO(satNewIntIo, tiOrgIORequest, satDevData, agNULL, satOrgIOContext ); /* enable PIO mode, then enable Ultra DMA mode in the satSetFeaturesCB callback function*/ retry_status = satSetFeatures(tiRoot, &satNewIntIo->satIntTiIORequest, satNewIOContext->ptiDeviceHandle, &satNewIntIo->satIntTiScsiXchg, /* orginal from OS layer */ satNewIOContext, agFALSE); if (retry_status != tiSuccess) { satFreeIntIoResource(tiRoot, satDevData, satIntIo); /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); } } else { /* clean up TD layer's IORequestBody */ ostiFreeMemory( tiRoot, tdOrgIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(tdIORequestBody_t) ); if (onePortContext != agNULL) { if (onePortContext->DiscoveryState == ITD_DSTATE_COMPLETED) { TI_DBG1(("tdsaDiscoveryStartIDDevCB: ID completed after discovery is done; tiDeviceArrival\n")); /* in case registration is finished after discovery is finished */ ostiInitiatorEvent( tiRoot, tiPortalContext, agNULL, tiIntrEventTypeDeviceChange, tiDeviceArrival, agNULL ); } } else { TI_DBG1(("tdsaDiscoveryStartIDDevCB: onePortContext is NULL, wrong\n")); } } TI_DBG3(("tdsaDiscoveryStartIDDevCB: end\n")); return; } /***************************************************************************** *! \brief satAbort * * This routine does local abort for outstanding FIS. * * \param agRoot: Handles for this instance of SAS/SATA hardware * \param satIOContext: Pointer to satIOContext_t. * * \return: none * *****************************************************************************/ GLOBAL void satAbort(agsaRoot_t *agRoot, satIOContext_t *satIOContext) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; tdIORequestBody_t *tdIORequestBody; /* io to be aborted */ tdIORequestBody_t *tdAbortIORequestBody; /* abort io itself */ agsaIORequest_t *agToBeAbortedIORequest; /* io to be aborted */ agsaIORequest_t *agAbortIORequest; /* abort io itself */ bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; TI_DBG1(("satAbort: start\n")); if (satIOContext == agNULL) { TI_DBG1(("satAbort: satIOContext is NULL, wrong\n")); return; } tdIORequestBody = (tdIORequestBody_t *)satIOContext->tiRequestBody; agToBeAbortedIORequest = (agsaIORequest_t *)&(tdIORequestBody->agIORequest); /* 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(("satAbort: ostiAllocMemory failed...\n")); return; } if (tdAbortIORequestBody == agNULL) { /* let os process IO */ TI_DBG1(("satAbort: ostiAllocMemory returned NULL tdAbortIORequestBody\n")); return; } /* setup task management structure */ tdAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; tdAbortIORequestBody->tiDevHandle = tdIORequestBody->tiDevHandle; /* initialize agIORequest */ agAbortIORequest = &(tdAbortIORequestBody->agIORequest); agAbortIORequest->osData = (void *) tdAbortIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ /* * Issue abort */ saSATAAbort( agRoot, agAbortIORequest, 0, agNULL, 0, agToBeAbortedIORequest, agNULL ); TI_DBG1(("satAbort: end\n")); return; } /***************************************************************************** *! \brief satSATADeviceReset * * This routine is called to reset all phys of port which a device belongs to * * \param tiRoot: Pointer to TISA initiator driver/port instance. * \param oneDeviceData: Pointer to the device data. * \param flag: reset flag * * \return: * * none * *****************************************************************************/ osGLOBAL void satSATADeviceReset( tiRoot_t *tiRoot, tdsaDeviceData_t *oneDeviceData, bit32 flag) { agsaRoot_t *agRoot; tdsaPortContext_t *onePortContext; bit32 i; TI_DBG1(("satSATADeviceReset: start\n")); agRoot = oneDeviceData->agRoot; onePortContext = oneDeviceData->tdPortContext; if (agRoot == agNULL) { TI_DBG1(("satSATADeviceReset: Error!!! agRoot is NULL\n")); return; } if (onePortContext == agNULL) { TI_DBG1(("satSATADeviceReset: Error!!! onePortContext is NULL\n")); return; } for(i=0;iPhyIDList[i] == agTRUE) { saLocalPhyControl(agRoot, agNULL, tdsaRotateQnumber(tiRoot, agNULL), i, flag, agNULL); } } return; } #endif /* #ifdef SATA_ENABLE */