/******************************************************************************* *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. * *Redistribution and use in source and binary forms, with or without modification, are permitted provided *that the following conditions are met: *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the *following disclaimer. *2. Redistributions in binary form must reproduce the above copyright notice, *this list of conditions and the following disclaimer in the documentation and/or other materials provided *with the distribution. * *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ********************************************************************************/ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* start smapi defined APIs */ osGLOBAL bit32 smRegisterDevice( smRoot_t *smRoot, agsaDevHandle_t *agDevHandle, smDeviceHandle_t *smDeviceHandle, agsaDevHandle_t *agExpDevHandle, bit32 phyID, bit32 DeviceType ) { smDeviceData_t *oneDeviceData = agNULL; SM_DBG2(("smRegisterDevice: start\n")); if (smDeviceHandle == agNULL) { SM_DBG1(("smRegisterDevice: smDeviceHandle is NULL!!!\n")); return SM_RC_FAILURE; } if (agDevHandle == agNULL) { SM_DBG1(("smRegisterDevice: agDevHandle is NULL!!!\n")); return SM_RC_FAILURE; } oneDeviceData = smAddToSharedcontext(smRoot, agDevHandle, smDeviceHandle, agExpDevHandle, phyID); if (oneDeviceData != agNULL) { oneDeviceData->satDeviceType = DeviceType; return SM_RC_SUCCESS; } else { return SM_RC_FAILURE; } } osGLOBAL bit32 smDeregisterDevice( smRoot_t *smRoot, agsaDevHandle_t *agDevHandle, smDeviceHandle_t *smDeviceHandle ) { bit32 status = SM_RC_FAILURE; SM_DBG2(("smDeregisterDevice: start\n")); if (smDeviceHandle == agNULL) { SM_DBG1(("smDeregisterDevice: smDeviceHandle is NULL!!!\n")); return SM_RC_FAILURE; } if (agDevHandle == agNULL) { SM_DBG1(("smDeregisterDevice: agDevHandle is NULL!!!\n")); return SM_RC_FAILURE; } status = smRemoveFromSharedcontext(smRoot, agDevHandle, smDeviceHandle); return status; } osGLOBAL bit32 smIOAbort( smRoot_t *smRoot, smIORequest_t *tasktag ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; agsaRoot_t *agRoot; smIORequestBody_t *smIORequestBody = agNULL; smIORequestBody_t *smIONewRequestBody = agNULL; agsaIORequest_t *agIORequest = agNULL; /* IO to be aborted */ bit32 status = SM_RC_FAILURE; agsaIORequest_t *agAbortIORequest; /* abort IO itself */ smIORequestBody_t *smAbortIORequestBody; #if 1 bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; #endif smSatIOContext_t *satIOContext; smSatInternalIo_t *satIntIo; smSatIOContext_t *satAbortIOContext; SM_DBG1(("smIOAbort: start\n")); SM_DBG2(("smIOAbort: tasktag %p\n", tasktag)); /* alloc smIORequestBody for abort itself call saSATAAbort() */ agRoot = smAllShared->agRoot; smIORequestBody = (smIORequestBody_t *)tasktag->smData; if (smIORequestBody == agNULL) { SM_DBG1(("smIOAbort: smIORequestBody is NULL!!!\n")); return SM_RC_FAILURE; } /* needs to distinguish internally generated or externally generated */ satIOContext = &(smIORequestBody->transport.SATA.satIOContext); satIntIo = satIOContext->satIntIoContext; if (satIntIo == agNULL) { SM_DBG2(("smIOAbort: External, OS generated\n")); agIORequest = &(smIORequestBody->agIORequest); } else { SM_DBG2(("smIOAbort: Internal, SM generated\n")); smIONewRequestBody = (smIORequestBody_t *)satIntIo->satIntRequestBody; agIORequest = &(smIONewRequestBody->agIORequest); } /* allocate smAbortIORequestBody for abort request itself */ #if 1 /* allocating agIORequest for abort itself */ memAllocStatus = tdsmAllocMemory( smRoot, &osMemHandle, (void **)&smAbortIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(smIORequestBody_t), agTRUE ); if (memAllocStatus != SM_RC_SUCCESS) { /* let os process IO */ SM_DBG1(("smIOAbort: tdsmAllocMemory failed...!!!\n")); return SM_RC_FAILURE; } if (smAbortIORequestBody == agNULL) { /* let os process IO */ SM_DBG1(("smIOAbort: tdsmAllocMemory returned NULL smAbortIORequestBody!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smAbortIORequestBody); /* setup task management structure */ smAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; satAbortIOContext = &(smAbortIORequestBody->transport.SATA.satIOContext); satAbortIOContext->smRequestBody = smAbortIORequestBody; smAbortIORequestBody->smDevHandle = smIORequestBody->smDevHandle; /* initialize agIORequest */ agAbortIORequest = &(smAbortIORequestBody->agIORequest); agAbortIORequest->osData = (void *) smAbortIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ /* remember IO to be aborted */ smAbortIORequestBody->smIOToBeAbortedRequest = tasktag; status = saSATAAbort(agRoot, agAbortIORequest, 0, agNULL, 0, agIORequest, smaSATAAbortCB); SM_DBG2(("smIOAbort: return status=0x%x\n", status)); #endif /* 1 */ if (status == AGSA_RC_SUCCESS) { return SM_RC_SUCCESS; } else { SM_DBG1(("smIOAbort: failed to call saSATAAbort, status=%d!!!\n", status)); tdsmFreeMemory(smRoot, smAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(smIORequestBody_t) ); return SM_RC_FAILURE; } } osGLOBAL bit32 smIOAbortAll( smRoot_t *smRoot, smDeviceHandle_t *smDeviceHandle ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; agsaRoot_t *agRoot; bit32 status = SM_RC_FAILURE; agsaIORequest_t *agAbortIORequest; smIORequestBody_t *smAbortIORequestBody; smSatIOContext_t *satAbortIOContext; smDeviceData_t *oneDeviceData = agNULL; agsaDevHandle_t *agDevHandle; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; SM_DBG2(("smIOAbortAll: start\n")); agRoot = smAllShared->agRoot; if (smDeviceHandle == agNULL) { SM_DBG1(("smIOAbortAll: smDeviceHandle is NULL!!!\n")); return SM_RC_FAILURE; } oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; if (oneDeviceData == agNULL) { SM_DBG1(("smIOAbortAll: oneDeviceData is NULL!!!\n")); return SM_RC_FAILURE; } if (oneDeviceData->valid == agFALSE) { SM_DBG1(("smIOAbortAll: oneDeviceData is not valid, did %d !!!\n", oneDeviceData->id)); return SM_RC_FAILURE; } agDevHandle = oneDeviceData->agDevHandle; if (agDevHandle == agNULL) { SM_DBG1(("smIOAbortAll: agDevHandle is NULL!!!\n")); return SM_RC_FAILURE; } /* smAbortIORequestBody = smDequeueIO(smRoot); if (smAbortIORequestBody == agNULL) { SM_DBG1(("smIOAbortAll: empty freeIOList!!!\n")); return SM_RC_FAILURE; } */ /* allocating agIORequest for abort itself */ memAllocStatus = tdsmAllocMemory( smRoot, &osMemHandle, (void **)&smAbortIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(smIORequestBody_t), agTRUE ); if (memAllocStatus != SM_RC_SUCCESS) { /* let os process IO */ SM_DBG1(("smIOAbortAll: tdsmAllocMemory failed...!!!\n")); return SM_RC_FAILURE; } if (smAbortIORequestBody == agNULL) { /* let os process IO */ SM_DBG1(("smIOAbortAll: tdsmAllocMemory returned NULL smAbortIORequestBody!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smAbortIORequestBody); /* setup task management structure */ smAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; satAbortIOContext = &(smAbortIORequestBody->transport.SATA.satIOContext); satAbortIOContext->smRequestBody = smAbortIORequestBody; smAbortIORequestBody->smDevHandle = smDeviceHandle; /* initialize agIORequest */ agAbortIORequest = &(smAbortIORequestBody->agIORequest); agAbortIORequest->osData = (void *) smAbortIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ oneDeviceData->OSAbortAll = agTRUE; /* abort all */ status = saSATAAbort(agRoot, agAbortIORequest, tdsmRotateQnumber(smRoot, smDeviceHandle), agDevHandle, 1, agNULL, smaSATAAbortCB); if (status != AGSA_RC_SUCCESS) { SM_DBG1(("smIOAbortAll: failed to call saSATAAbort, status=%d!!!\n", status)); tdsmFreeMemory(smRoot, smAbortIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(smIORequestBody_t) ); } return status; } osGLOBAL bit32 smSuperIOStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smSuperScsiInitiatorRequest_t *smSCSIRequest, bit32 AddrHi, bit32 AddrLo, bit32 interruptContext ) { smDeviceData_t *oneDeviceData = agNULL; smIORequestBody_t *smIORequestBody = agNULL; smSatIOContext_t *satIOContext = agNULL; bit32 status = SM_RC_FAILURE; SM_DBG2(("smSuperIOStart: start\n")); oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; if (oneDeviceData == agNULL) { SM_DBG1(("smSuperIOStart: oneDeviceData is NULL!!!\n")); return SM_RC_FAILURE; } if (oneDeviceData->valid == agFALSE) { SM_DBG1(("smSuperIOStart: oneDeviceData is not valid, did %d !!!\n", oneDeviceData->id)); return SM_RC_FAILURE; } smIORequestBody = (smIORequestBody_t*)smIORequest->smData;//smDequeueIO(smRoot); if (smIORequestBody == agNULL) { SM_DBG1(("smSuperIOStart: smIORequestBody is NULL!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smIORequestBody); SM_DBG3(("smSuperIOStart: io ID %d!!!\n", smIORequestBody->id )); oneDeviceData->sasAddressHi = AddrHi; oneDeviceData->sasAddressLo = AddrLo; smIORequestBody->smIORequest = smIORequest; smIORequestBody->smDevHandle = smDeviceHandle; satIOContext = &(smIORequestBody->transport.SATA.satIOContext); /* * Need to initialize all the fields within satIOContext except * reqType and satCompleteCB which will be set later in SM. */ smIORequestBody->transport.SATA.smSenseData.senseData = agNULL; smIORequestBody->transport.SATA.smSenseData.senseLen = 0; satIOContext->pSatDevData = oneDeviceData; satIOContext->pFis = &smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev; satIOContext->pScsiCmnd = &smSCSIRequest->scsiCmnd; satIOContext->pSense = &smIORequestBody->transport.SATA.sensePayload; satIOContext->pSmSenseData = &smIORequestBody->transport.SATA.smSenseData; satIOContext->pSmSenseData->senseData = satIOContext->pSense; /* satIOContext->pSense = (scsiRspSense_t *)satIOContext->pSmSenseData->senseData; */ satIOContext->smRequestBody = smIORequestBody; satIOContext->interruptContext = interruptContext; satIOContext->psmDeviceHandle = smDeviceHandle; satIOContext->smScsiXchg = smSCSIRequest; satIOContext->superIOFlag = agTRUE; // satIOContext->superIOFlag = agFALSE; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; /* satIOContext->tiIORequest = tiIORequest; */ /* save context if we need to abort later */ /*smIORequest->smData = smIORequestBody;*/ /* followings are used only for internal IO */ satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; status = smsatIOStart(smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)smSCSIRequest, satIOContext); return status; } /* osGLOBAL bit32 tiINIIOStart( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, void *tiRequestBody, bit32 interruptContext ) GLOBAL bit32 satIOStart( tiRoot_t *tiRoot, tiIORequest_t *tiIORequest, tiDeviceHandle_t *tiDeviceHandle, tiScsiInitiatorRequest_t *tiScsiRequest, smSatIOContext_t *satIOContext ) smIOStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, smIORequestBody_t *smRequestBody, bit32 interruptContext ) */ FORCEINLINE bit32 smIOStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, bit32 interruptContext ) { smDeviceData_t *oneDeviceData = agNULL; smIORequestBody_t *smIORequestBody = agNULL; smSatIOContext_t *satIOContext = agNULL; bit32 status = SM_RC_FAILURE; SM_DBG2(("smIOStart: start\n")); oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; if (oneDeviceData == agNULL) { SM_DBG1(("smIOStart: oneDeviceData is NULL!!!\n")); return SM_RC_FAILURE; } if (oneDeviceData->valid == agFALSE) { SM_DBG1(("smIOStart: oneDeviceData is not valid, did %d !!!\n", oneDeviceData->id)); return SM_RC_FAILURE; } smIORequestBody = (smIORequestBody_t*)smIORequest->smData;//smDequeueIO(smRoot); if (smIORequestBody == agNULL) { SM_DBG1(("smIOStart: smIORequestBody is NULL!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smIORequestBody); SM_DBG3(("smIOStart: io ID %d!!!\n", smIORequestBody->id )); smIORequestBody->smIORequest = smIORequest; smIORequestBody->smDevHandle = smDeviceHandle; satIOContext = &(smIORequestBody->transport.SATA.satIOContext); /* * Need to initialize all the fields within satIOContext except * reqType and satCompleteCB which will be set later in SM. */ smIORequestBody->transport.SATA.smSenseData.senseData = agNULL; smIORequestBody->transport.SATA.smSenseData.senseLen = 0; satIOContext->pSatDevData = oneDeviceData; satIOContext->pFis = &smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev; satIOContext->pScsiCmnd = &smSCSIRequest->scsiCmnd; satIOContext->pSense = &smIORequestBody->transport.SATA.sensePayload; satIOContext->pSmSenseData = &smIORequestBody->transport.SATA.smSenseData; satIOContext->pSmSenseData->senseData = satIOContext->pSense; /* satIOContext->pSense = (scsiRspSense_t *)satIOContext->pSmSenseData->senseData; */ satIOContext->smRequestBody = smIORequestBody; satIOContext->interruptContext = interruptContext; satIOContext->psmDeviceHandle = smDeviceHandle; satIOContext->smScsiXchg = smSCSIRequest; satIOContext->superIOFlag = agFALSE; satIOContext->satIntIoContext = agNULL; satIOContext->satOrgIOContext = agNULL; satIOContext->currentLBA = 0; satIOContext->OrgTL = 0; status = smsatIOStart(smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); return status; } osGLOBAL bit32 smTaskManagement( smRoot_t *smRoot, smDeviceHandle_t *smDeviceHandle, bit32 task, smLUN_t *lun, smIORequest_t *taskTag, /* io to be aborted */ smIORequest_t *currentTaskTag /* task management */ ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; agsaRoot_t *agRoot = smAllShared->agRoot; smDeviceData_t *oneDeviceData = agNULL; smIORequestBody_t *smIORequestBody = agNULL; bit32 status; agsaContext_t *agContext = agNULL; smSatIOContext_t *satIOContext; SM_DBG1(("smTaskManagement: start\n")); oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; if (task == SM_LOGICAL_UNIT_RESET || task == SM_TARGET_WARM_RESET || task == SM_ABORT_TASK) { if (task == AG_LOGICAL_UNIT_RESET) { 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 ) { SM_DBG1(("smTaskManagement: *** REJECT *** LUN not zero, did %d!!!\n", oneDeviceData->id)); return SM_RC_FAILURE; } } oneDeviceData->satDriveState = SAT_DEV_STATE_IN_RECOVERY; oneDeviceData->satAbortAfterReset = agFALSE; saSetDeviceState(agRoot, agNULL, tdsmRotateQnumber(smRoot, smDeviceHandle), oneDeviceData->agDevHandle, SA_DS_IN_RECOVERY ); if (oneDeviceData->directlyAttached == agFALSE) { /* expander attached */ SM_DBG1(("smTaskManagement: LUN reset or device reset expander attached!!!\n")); status = smPhyControlSend(smRoot, oneDeviceData, SMP_PHY_CONTROL_HARD_RESET, currentTaskTag, tdsmRotateQnumber(smRoot, smDeviceHandle) ); return status; } else { SM_DBG1(("smTaskManagement: LUN reset or device reset directly attached\n")); smIORequestBody = (smIORequestBody_t*)currentTaskTag->smData;//smDequeueIO(smRoot); if (smIORequestBody == agNULL) { SM_DBG1(("smTaskManagement: smIORequestBody is NULL!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smIORequestBody); satIOContext = &(smIORequestBody->transport.SATA.satIOContext); satIOContext->smRequestBody = smIORequestBody; smIORequestBody->smDevHandle = smDeviceHandle; agContext = &(oneDeviceData->agDeviceResetContext); agContext->osData = currentTaskTag; status = saLocalPhyControl(agRoot, agContext, tdsmRotateQnumber(smRoot, smDeviceHandle) &0xFFFF, oneDeviceData->phyID, AGSA_PHY_HARD_RESET, smLocalPhyControlCB ); if ( status == AGSA_RC_SUCCESS) { return SM_RC_SUCCESS; } else if (status == AGSA_RC_BUSY) { return SM_RC_BUSY; } else if (status == AGSA_RC_FAILURE) { return SM_RC_FAILURE; } else { SM_DBG1(("smTaskManagement: unknown status %d\n",status)); return SM_RC_FAILURE; } } } else { /* smsatsmTaskManagement() which is satTM() */ smIORequestBody = (smIORequestBody_t*)currentTaskTag->smData;//smDequeueIO(smRoot); if (smIORequestBody == agNULL) { SM_DBG1(("smTaskManagement: smIORequestBody is NULL!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smIORequestBody); /*currentTaskTag->smData = smIORequestBody;*/ status = smsatTaskManagement(smRoot, smDeviceHandle, task, lun, taskTag, currentTaskTag, smIORequestBody ); return status; } return SM_RC_SUCCESS; } /********************************************************* end smapi defined APIS */ /* counterpart is smEnqueueIO(smRoot_t *smRoot, smSatIOContext_t *satIOContext) */ osGLOBAL smIORequestBody_t * smDequeueIO(smRoot_t *smRoot) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; smIORequestBody_t *smIORequestBody = agNULL; smList_t *IOListList; SM_DBG2(("smDequeueIO: start\n")); tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK); if (SMLIST_EMPTY(&(smAllShared->freeIOList))) { SM_DBG1(("smDequeueIO: empty freeIOList!!!\n")); tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK); return agNULL; } SMLIST_DEQUEUE_FROM_HEAD(&IOListList, &(smAllShared->freeIOList)); smIORequestBody = SMLIST_OBJECT_BASE(smIORequestBody_t, satIoBodyLink, IOListList); SMLIST_DEQUEUE_THIS(&(smIORequestBody->satIoBodyLink)); SMLIST_ENQUEUE_AT_TAIL(&(smIORequestBody->satIoBodyLink), &(smAllShared->mainIOList)); tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK); if (smIORequestBody->InUse == agTRUE) { SM_DBG1(("smDequeueIO: wrong. already in USE ID %d!!!!\n", smIORequestBody->id)); } smIOReInit(smRoot, smIORequestBody); SM_DBG2(("smDequeueIO: io ID %d!\n", smIORequestBody->id)); /* debugging */ if (smIORequestBody->satIoBodyLink.flink == agNULL) { SM_DBG1(("smDequeueIO: io ID %d, flink is NULL!!!\n", smIORequestBody->id)); } if (smIORequestBody->satIoBodyLink.blink == agNULL) { SM_DBG1(("smDequeueIO: io ID %d, blink is NULL!!!\n", smIORequestBody->id)); } return smIORequestBody; } //start here //compare with ossaSATAAbortCB() //qqq1 osGLOBAL void smsatAbort( smRoot_t *smRoot, agsaRoot_t *agRoot, smSatIOContext_t *satIOContext ) { smIORequestBody_t *smIORequestBody = agNULL; /* abort itself */ smIORequestBody_t *smToBeAbortedIORequestBody; /* io to be aborted */ agsaIORequest_t *agToBeAbortedIORequest; /* io to be aborted */ agsaIORequest_t *agAbortIORequest; /* abort io itself */ smSatIOContext_t *satAbortIOContext; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; void *osMemHandle; SM_DBG2(("smsatAbort: start\n")); if (satIOContext == agNULL) { SM_DBG1(("smsatAbort: satIOContext is NULL, wrong!!!\n")); return; } smToBeAbortedIORequestBody = (smIORequestBody_t *)satIOContext->smRequestBody; agToBeAbortedIORequest = (agsaIORequest_t *)&(smToBeAbortedIORequestBody->agIORequest); /* smIORequestBody = smDequeueIO(smRoot); if (smIORequestBody == agNULL) { SM_DBG1(("smsatAbort: empty freeIOList!!!\n")); return; } */ /* allocating agIORequest for abort itself */ memAllocStatus = tdsmAllocMemory( smRoot, &osMemHandle, (void **)&smIORequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(smIORequestBody_t), agTRUE ); if (memAllocStatus != tiSuccess) { /* let os process IO */ SM_DBG1(("smsatAbort: ostiAllocMemory failed...\n")); return; } if (smIORequestBody == agNULL) { /* let os process IO */ SM_DBG1(("smsatAbort: ostiAllocMemory returned NULL smIORequestBody\n")); return; } smIOReInit(smRoot, smIORequestBody); smIORequestBody->IOType.InitiatorTMIO.osMemHandle = osMemHandle; smIORequestBody->smDevHandle = smToBeAbortedIORequestBody->smDevHandle; /* initialize agIORequest */ satAbortIOContext = &(smIORequestBody->transport.SATA.satIOContext); satAbortIOContext->smRequestBody = smIORequestBody; agAbortIORequest = &(smIORequestBody->agIORequest); agAbortIORequest->osData = (void *) smIORequestBody; agAbortIORequest->sdkData = agNULL; /* LL takes care of this */ /* * Issue abort */ saSATAAbort( agRoot, agAbortIORequest, 0, agNULL, 0, agToBeAbortedIORequest, smaSATAAbortCB); SM_DBG1(("satAbort: end!!!\n")); return; } osGLOBAL bit32 smsatStartCheckPowerMode( smRoot_t *smRoot, smIORequest_t *currentTaskTag, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smSatInternalIo_t *satIntIo = agNULL; smDeviceData_t *oneDeviceData = agNULL; smSatIOContext_t *satNewIOContext; bit32 status; SM_DBG1(("smsatStartCheckPowerMode: start\n")); oneDeviceData = satIOContext->pSatDevData; SM_DBG6(("smsatStartCheckPowerMode: before alloc\n")); /* allocate any fis for seting SRT bit in device control */ satIntIo = smsatAllocIntIoResource( smRoot, currentTaskTag, oneDeviceData, 0, satIntIo); SM_DBG6(("smsatStartCheckPowerMode: before after\n")); if (satIntIo == agNULL) { SM_DBG1(("smsatStartCheckPowerMode: can't alloacate!!!\n")); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } satNewIOContext = smsatPrepareNewIO(satIntIo, currentTaskTag, oneDeviceData, agNULL, satIOContext); SM_DBG6(("smsatStartCheckPowerMode: TD satIOContext %p \n", satIOContext)); SM_DBG6(("smsatStartCheckPowerMode: SM satNewIOContext %p \n", satNewIOContext)); SM_DBG6(("smsatStartCheckPowerMode: TD smScsiXchg %p \n", satIOContext->smScsiXchg)); SM_DBG6(("smsatStartCheckPowerMode: SM smScsiXchg %p \n", satNewIOContext->smScsiXchg)); SM_DBG2(("smsatStartCheckPowerMode: satNewIOContext %p \n", satNewIOContext)); status = smsatCheckPowerMode(smRoot, &satIntIo->satIntSmIORequest, /* New smIORequest */ smDeviceHandle, satNewIOContext->smScsiXchg, /* New tiScsiInitiatorRequest_t *smScsiRequest, */ satNewIOContext); if (status != SM_RC_SUCCESS) { SM_DBG1(("smsatStartCheckPowerMode: failed in sending!!!\n")); smsatFreeIntIoResource( smRoot, oneDeviceData, satIntIo); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } SM_DBG6(("smsatStartCheckPowerMode: end\n")); return status; } osGLOBAL bit32 smsatStartResetDevice( smRoot_t *smRoot, smIORequest_t *currentTaskTag, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smSatInternalIo_t *satIntIo = agNULL; smDeviceData_t *oneDeviceData = agNULL; smSatIOContext_t *satNewIOContext; bit32 status; SM_DBG1(("smsatStartResetDevice: start\n")); oneDeviceData = satIOContext->pSatDevData; SM_DBG6(("smsatStartResetDevice: before alloc\n")); /* allocate any fis for seting SRT bit in device control */ satIntIo = smsatAllocIntIoResource( smRoot, currentTaskTag, oneDeviceData, 0, satIntIo); SM_DBG6(("smsatStartResetDevice: before after\n")); if (satIntIo == agNULL) { SM_DBG1(("smsatStartResetDevice: can't alloacate!!!\n")); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } satNewIOContext = smsatPrepareNewIO(satIntIo, currentTaskTag, oneDeviceData, agNULL, satIOContext); SM_DBG6(("smsatStartResetDevice: TD satIOContext %p \n", satIOContext)); SM_DBG6(("smsatStartResetDevice: SM satNewIOContext %p \n", satNewIOContext)); SM_DBG6(("smsatStartResetDevice: TD smScsiXchg %p \n", satIOContext->smScsiXchg)); SM_DBG6(("smsatStartResetDevice: SM smScsiXchg %p \n", satNewIOContext->smScsiXchg)); SM_DBG6(("smsatStartResetDevice: satNewIOContext %p \n", satNewIOContext)); if (oneDeviceData->satDeviceType == SATA_ATAPI_DEVICE) { /*if ATAPI device, send DEVICE RESET command to ATAPI device*/ status = smsatDeviceReset(smRoot, &satIntIo->satIntSmIORequest, /* New smIORequest */ smDeviceHandle, satNewIOContext->smScsiXchg, /* New smScsiInitiatorRequest_t *smScsiRequest, NULL */ satNewIOContext); } else { status = smsatResetDevice(smRoot, &satIntIo->satIntSmIORequest, /* New smIORequest */ smDeviceHandle, satNewIOContext->smScsiXchg, /* New smScsiInitiatorRequest_t *smScsiRequest, NULL */ satNewIOContext); } if (status != SM_RC_SUCCESS) { SM_DBG1(("smsatStartResetDevice: failed in sending!!!\n")); smsatFreeIntIoResource( smRoot, oneDeviceData, satIntIo); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } SM_DBG6(("smsatStartResetDevice: end\n")); return status; } osGLOBAL bit32 smsatTmAbortTask( smRoot_t *smRoot, smIORequest_t *currentTaskTag, /* task management */ smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, /* NULL */ smSatIOContext_t *satIOContext, /* task management */ smIORequest_t *taskTag) /* io to be aborted */ { smDeviceData_t *oneDeviceData = agNULL; smSatIOContext_t *satTempIOContext = agNULL; smList_t *elementHdr; bit32 found = agFALSE; smIORequestBody_t *smIORequestBody = agNULL; smIORequest_t *smIOReq = agNULL; bit32 status; SM_DBG1(("smsatTmAbortTask: start\n")); oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; /* * Check that the only pending I/O matches taskTag. If not return tiError. */ tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK); elementHdr = oneDeviceData->satIoLinkList.flink; while (elementHdr != &oneDeviceData->satIoLinkList) { satTempIOContext = SMLIST_OBJECT_BASE( smSatIOContext_t, satIoContextLink, elementHdr ); if ( satTempIOContext != agNULL) { smIORequestBody = (smIORequestBody_t *) satTempIOContext->smRequestBody; smIOReq = smIORequestBody->smIORequest; } elementHdr = elementHdr->flink; /* for the next while loop */ /* * Check if the tag matches */ if ( smIOReq == taskTag) { found = agTRUE; satIOContext->satToBeAbortedIOContext = satTempIOContext; SM_DBG1(("smsatTmAbortTask: found matching tag.\n")); break; } /* if matching tag */ } /* while loop */ tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK); if (found == agFALSE ) { SM_DBG1(("smsatTmAbortTask: *** REJECT *** no match!!!\n")); /*smEnqueueIO(smRoot, satIOContext);*/ /* clean up TD layer's smIORequestBody */ if (smIORequestBody) { if (smIORequestBody->IOType.InitiatorTMIO.osMemHandle != agNULL) { tdsmFreeMemory( smRoot, smIORequestBody->IOType.InitiatorTMIO.osMemHandle, sizeof(smIORequestBody_t) ); } } else { SM_DBG1(("smsatTmAbortTask: smIORequestBody is NULL!!!\n")); } return SM_RC_FAILURE; } if (satTempIOContext == agNULL) { SM_DBG1(("smsatTmAbortTask: satTempIOContext is NULL!!!\n")); return SM_RC_FAILURE; } /* * Save smIORequest, will be returned at device reset completion to return * the TM completion. */ oneDeviceData->satTmTaskTag = currentTaskTag; /* * Set flag to indicate device in recovery mode. */ oneDeviceData->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 */ oneDeviceData->satAbortAfterReset = agTRUE; if ( (satTempIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_WRITE) || (satTempIOContext->reqType == AGSA_SATA_PROTOCOL_FPDMA_READ) ) { SM_DBG1(("smsatTmAbortTask: calling satStartCheckPowerMode!!!\n")); /* send check power mode */ status = smsatStartCheckPowerMode( smRoot, currentTaskTag, /* currentTaskTag */ smDeviceHandle, smScsiRequest, /* NULL */ satIOContext ); } else { SM_DBG1(("smsatTmAbortTask: calling satStartResetDevice!!!\n")); /* send AGSA_SATA_PROTOCOL_SRST_ASSERT */ status = smsatStartResetDevice( smRoot, currentTaskTag, /* currentTaskTag */ smDeviceHandle, smScsiRequest, /* NULL */ satIOContext ); } return status; } /* satTM() */ osGLOBAL bit32 smsatTaskManagement( smRoot_t *smRoot, smDeviceHandle_t *smDeviceHandle, bit32 task, smLUN_t *lun, smIORequest_t *taskTag, /* io to be aborted */ smIORequest_t *currentTaskTag, /* task management */ smIORequestBody_t *smIORequestBody ) { smSatIOContext_t *satIOContext = agNULL; smDeviceData_t *oneDeviceData = agNULL; bit32 status; SM_DBG1(("smsatTaskManagement: start\n")); oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; satIOContext = &(smIORequestBody->transport.SATA.satIOContext); satIOContext->pSatDevData = oneDeviceData; satIOContext->pFis = &(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext->smRequestBody = smIORequestBody; satIOContext->psmDeviceHandle = smDeviceHandle; 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 (task == AG_ABORT_TASK) { status = smsatTmAbortTask( smRoot, currentTaskTag, smDeviceHandle, agNULL, satIOContext, taskTag); return status; } else { SM_DBG1(("smsatTaskManagement: UNSUPPORTED TM task=0x%x!!!\n", task )); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } return SM_RC_SUCCESS; } osGLOBAL bit32 smPhyControlSend( smRoot_t *smRoot, smDeviceData_t *oneDeviceData, /* sata disk itself */ bit8 phyOp, smIORequest_t *CurrentTaskTag, bit32 queueNumber ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; agsaRoot_t *agRoot = smAllShared->agRoot; agsaDevHandle_t *agExpDevHandle; smpReqPhyControl_t smpPhyControlReq; void *osMemHandle; bit32 PhysUpper32; bit32 PhysLower32; bit32 memAllocStatus; bit32 expectedRspLen = 0; smSMPRequestBody_t *smSMPRequestBody; agsaSASRequestBody_t *agSASRequestBody; agsaSMPFrame_t *agSMPFrame; agsaIORequest_t *agIORequest; // agsaDevHandle_t *agDevHandle; smSMPFrameHeader_t smSMPFrameHeader; bit32 status; bit8 *pSmpBody; /* smp payload itself w/o first 4 bytes(header) */ bit32 smpBodySize; /* smp payload size w/o first 4 bytes(header) */ bit32 agRequestType; SM_DBG2(("smPhyControlSend: start\n")); agExpDevHandle = oneDeviceData->agExpDevHandle; if (agExpDevHandle == agNULL) { SM_DBG1(("smPhyControlSend: agExpDevHandle is NULL!!!\n")); return SM_RC_FAILURE; } SM_DBG5(("smPhyControlSend: phyID %d\n", oneDeviceData->phyID)); sm_memset(&smpPhyControlReq, 0, sizeof(smpReqPhyControl_t)); /* fill in SMP payload */ smpPhyControlReq.phyIdentifier = (bit8)oneDeviceData->phyID; smpPhyControlReq.phyOperation = phyOp; /* allocate smp and send it */ memAllocStatus = tdsmAllocMemory( smRoot, &osMemHandle, (void **)&smSMPRequestBody, &PhysUpper32, &PhysLower32, 8, sizeof(smSMPRequestBody_t), agTRUE ); if (memAllocStatus != SM_RC_SUCCESS) { SM_DBG1(("smPhyControlSend: tdsmAllocMemory failed...!!!\n")); return SM_RC_FAILURE; } if (smSMPRequestBody == agNULL) { SM_DBG1(("smPhyControlSend: tdsmAllocMemory returned NULL smSMPRequestBody!!!\n")); return SM_RC_FAILURE; } /* saves mem handle for freeing later */ smSMPRequestBody->osMemHandle = osMemHandle; /* saves oneDeviceData */ smSMPRequestBody->smDeviceData = oneDeviceData; /* sata disk */ /* saves oneDeviceData */ smSMPRequestBody->smDevHandle = oneDeviceData->smDevHandle; // agDevHandle = oneDeviceData->agDevHandle; /* save the callback funtion */ smSMPRequestBody->SMPCompletionFunc = smSMPCompleted; /* in satcb.c */ /* for simulate warm target reset */ smSMPRequestBody->CurrentTaskTag = CurrentTaskTag; if (CurrentTaskTag != agNULL) { CurrentTaskTag->smData = smSMPRequestBody; } /* initializes the number of SMP retries */ smSMPRequestBody->retries = 0; #ifdef TD_INTERNAL_DEBUG /* debugging */ SM_DBG4(("smPhyControlSend: SMPRequestbody %p\n", smSMPRequestBody)); SM_DBG4(("smPhyControlSend: callback fn %p\n", smSMPRequestBody->SMPCompletionFunc)); #endif agIORequest = &(smSMPRequestBody->agIORequest); agIORequest->osData = (void *) smSMPRequestBody; agIORequest->sdkData = agNULL; /* SALL takes care of this */ agSASRequestBody = &(smSMPRequestBody->agSASRequestBody); agSMPFrame = &(agSASRequestBody->smpFrame); SM_DBG3(("smPhyControlSend: agIORequest %p\n", agIORequest)); SM_DBG3(("smPhyControlSend: SMPRequestbody %p\n", smSMPRequestBody)); expectedRspLen = 4; pSmpBody = (bit8 *)&smpPhyControlReq; smpBodySize = sizeof(smpReqPhyControl_t); agRequestType = AGSA_SMP_INIT_REQ; if (SMIsSPC(agRoot)) { if ( (smpBodySize + 4) <= SMP_DIRECT_PAYLOAD_LIMIT) /* 48 */ { SM_DBG3(("smPhyControlSend: DIRECT smp payload\n")); sm_memset(&smSMPFrameHeader, 0, sizeof(smSMPFrameHeader_t)); sm_memset(smSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT); /* SMP header */ smSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ smSMPFrameHeader.smpFunction = (bit8)SMP_PHY_CONTROL; smSMPFrameHeader.smpFunctionResult = 0; smSMPFrameHeader.smpReserved = 0; sm_memcpy(smSMPRequestBody->smpPayload, &smSMPFrameHeader, 4); sm_memcpy((smSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize); /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */ agSMPFrame->outFrameBuf = smSMPRequestBody->smpPayload; agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */ /* to specify DIRECT SMP response */ agSMPFrame->inFrameLen = 0; /* temporary solution for T2D Combo*/ #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER) /* force smp repsonse to be direct */ agSMPFrame->expectedRespLen = 0; #else agSMPFrame->expectedRespLen = expectedRspLen; #endif // smhexdump("smPhyControlSend", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen); // smhexdump("smPhyControlSend new", (bit8*)smSMPRequestBody->smpPayload, agSMPFrame->outFrameLen); // smhexdump("smPhyControlSend - smSMPRequestBody", (bit8*)smSMPRequestBody, sizeof(smSMPRequestBody_t)); } else { SM_DBG1(("smPhyControlSend: INDIRECT smp payload, not supported!!!\n")); tdsmFreeMemory( smRoot, osMemHandle, sizeof(smSMPRequestBody_t) ); return SM_RC_FAILURE; } } else /* SPCv controller */ { /* only direct mode for both request and response */ SM_DBG3(("smPhyControlSend: DIRECT smp payload\n")); agSMPFrame->flag = 0; sm_memset(&smSMPFrameHeader, 0, sizeof(smSMPFrameHeader_t)); sm_memset(smSMPRequestBody->smpPayload, 0, SMP_DIRECT_PAYLOAD_LIMIT); /* SMP header */ smSMPFrameHeader.smpFrameType = SMP_REQUEST; /* SMP request */ smSMPFrameHeader.smpFunction = (bit8)SMP_PHY_CONTROL; smSMPFrameHeader.smpFunctionResult = 0; smSMPFrameHeader.smpReserved = 0; sm_memcpy(smSMPRequestBody->smpPayload, &smSMPFrameHeader, 4); sm_memcpy((smSMPRequestBody->smpPayload)+4, pSmpBody, smpBodySize); /* direct SMP payload eg) REPORT_GENERAL, DISCOVER etc */ agSMPFrame->outFrameBuf = smSMPRequestBody->smpPayload; agSMPFrame->outFrameLen = smpBodySize + 4; /* without last 4 byte crc */ /* to specify DIRECT SMP response */ agSMPFrame->inFrameLen = 0; /* temporary solution for T2D Combo*/ #if defined (INITIATOR_DRIVER) && defined (TARGET_DRIVER) /* force smp repsonse to be direct */ agSMPFrame->expectedRespLen = 0; #else agSMPFrame->expectedRespLen = expectedRspLen; #endif // smhexdump("smPhyControlSend", (bit8*)agSMPFrame->outFrameBuf, agSMPFrame->outFrameLen); // smhexdump("smPhyControlSend new", (bit8*)smSMPRequestBody->smpPayload, agSMPFrame->outFrameLen); // smhexdump("smPhyControlSend - smSMPRequestBody", (bit8*)smSMPRequestBody, sizeof(smSMPRequestBody_t)); } status = saSMPStart( agRoot, agIORequest, queueNumber, agExpDevHandle, agRequestType, agSASRequestBody, &smSMPCompletedCB ); if (status == AGSA_RC_SUCCESS) { return SM_RC_SUCCESS; } else if (status == AGSA_RC_BUSY) { SM_DBG1(("smPhyControlSend: saSMPStart is busy!!!\n")); tdsmFreeMemory( smRoot, osMemHandle, sizeof(smSMPRequestBody_t) ); return SM_RC_BUSY; } else /* AGSA_RC_FAILURE */ { SM_DBG1(("smPhyControlSend: saSMPStart is failed. status %d!!!\n", status)); tdsmFreeMemory( smRoot, osMemHandle, sizeof(smSMPRequestBody_t) ); return SM_RC_FAILURE; } } /* free IO which are internally completed within SM counterpart is osGLOBAL smIORequestBody_t * smDequeueIO(smRoot_t *smRoot) */ osGLOBAL void smEnqueueIO( smRoot_t *smRoot, smSatIOContext_t *satIOContext ) { smIntRoot_t *smIntRoot = agNULL; smIntContext_t *smAllShared = agNULL; smIORequestBody_t *smIORequestBody; SM_DBG3(("smEnqueueIO: start\n")); smIORequestBody = (smIORequestBody_t *)satIOContext->smRequestBody; smIntRoot = (smIntRoot_t *)smRoot->smData; smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; /* enque back to smAllShared->freeIOList */ if (satIOContext->satIntIoContext == agNULL) { SM_DBG2(("smEnqueueIO: external command!!!, io ID %d!!!\n", smIORequestBody->id)); /* debugging only */ if (smIORequestBody->satIoBodyLink.flink == agNULL) { SM_DBG1(("smEnqueueIO: external command!!!, io ID %d, flink is NULL!!!\n", smIORequestBody->id)); } if (smIORequestBody->satIoBodyLink.blink == agNULL) { SM_DBG1(("smEnqueueIO: external command!!!, io ID %d, blink is NULL!!!\n", smIORequestBody->id)); } } else { SM_DBG2(("smEnqueueIO: internal command!!!, io ID %d!!!\n", smIORequestBody->id)); /* debugging only */ if (smIORequestBody->satIoBodyLink.flink == agNULL) { SM_DBG1(("smEnqueueIO: internal command!!!, io ID %d, flink is NULL!!!\n", smIORequestBody->id)); } if (smIORequestBody->satIoBodyLink.blink == agNULL) { SM_DBG1(("smEnqueueIO: internal command!!!, io ID %d, blink is NULL!!!\n", smIORequestBody->id)); } } if (smIORequestBody->smIORequest == agNULL) { SM_DBG1(("smEnqueueIO: smIORequest is NULL, io ID %d!!!\n", smIORequestBody->id)); } if (smIORequestBody->InUse == agTRUE) { smIORequestBody->InUse = agFALSE; tdsmSingleThreadedEnter(smRoot, SM_EXTERNAL_IO_LOCK); SMLIST_DEQUEUE_THIS(&(smIORequestBody->satIoBodyLink)); SMLIST_ENQUEUE_AT_TAIL(&(smIORequestBody->satIoBodyLink), &(smAllShared->freeIOList)); tdsmSingleThreadedLeave(smRoot, SM_EXTERNAL_IO_LOCK); } else { SM_DBG2(("smEnqueueIO: check!!!, io ID %d!!!\n", smIORequestBody->id)); } return; } FORCEINLINE void smsatFreeIntIoResource( smRoot_t *smRoot, smDeviceData_t *satDevData, smSatInternalIo_t *satIntIo ) { SM_DBG3(("smsatFreeIntIoResource: start\n")); if (satIntIo == agNULL) { SM_DBG2(("smsatFreeIntIoResource: allowed call\n")); return; } /* sets the original smIOrequest to agNULL for internally generated ATA cmnd */ satIntIo->satOrgSmIORequest = agNULL; /* * Free DMA memory if previosly alocated */ if (satIntIo->satIntSmScsiXchg.scsiCmnd.expDataLength != 0) { SM_DBG3(("smsatFreeIntIoResource: DMA len %d\n", satIntIo->satIntDmaMem.totalLength)); SM_DBG3(("smsatFreeIntIoResource: pointer %p\n", satIntIo->satIntDmaMem.osHandle)); tdsmFreeMemory( smRoot, satIntIo->satIntDmaMem.osHandle, satIntIo->satIntDmaMem.totalLength); satIntIo->satIntSmScsiXchg.scsiCmnd.expDataLength = 0; } if (satIntIo->satIntReqBodyMem.totalLength != 0) { SM_DBG3(("smsatFreeIntIoResource: req body len %d\n", satIntIo->satIntReqBodyMem.totalLength)); /* * Free mem allocated for Req body */ tdsmFreeMemory( smRoot, satIntIo->satIntReqBodyMem.osHandle, satIntIo->satIntReqBodyMem.totalLength); satIntIo->satIntReqBodyMem.totalLength = 0; } SM_DBG3(("smsatFreeIntIoResource: satDevData %p satIntIo id %d\n", satDevData, satIntIo->id)); /* * Return satIntIo to the free list */ tdsmSingleThreadedEnter(smRoot, SM_INTERNAL_IO_LOCK); SMLIST_DEQUEUE_THIS (&(satIntIo->satIntIoLink)); SMLIST_ENQUEUE_AT_TAIL (&(satIntIo->satIntIoLink), &(satDevData->satFreeIntIoLinkList)); tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); return; } //start here osGLOBAL smSatInternalIo_t * smsatAllocIntIoResource( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceData_t *satDevData, bit32 dmaAllocLength, smSatInternalIo_t *satIntIo) { smList_t *smList = agNULL; bit32 memAllocStatus; SM_DBG3(("smsatAllocIntIoResource: start\n")); SM_DBG3(("smsatAllocIntIoResource: satIntIo %p\n", satIntIo)); if (satDevData == agNULL) { SM_DBG1(("smsatAllocIntIoResource: ***** ASSERT satDevData is null!!!\n")); return agNULL; } tdsmSingleThreadedEnter(smRoot, SM_INTERNAL_IO_LOCK); if (!SMLIST_EMPTY(&(satDevData->satFreeIntIoLinkList))) { SMLIST_DEQUEUE_FROM_HEAD(&smList, &(satDevData->satFreeIntIoLinkList)); } else { tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); SM_DBG1(("smsatAllocIntIoResource() no more internal free link!!!\n")); return agNULL; } if (smList == agNULL) { tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); SM_DBG1(("smsatAllocIntIoResource() FAIL to alloc satIntIo!!!\n")); return agNULL; } satIntIo = SMLIST_OBJECT_BASE( smSatInternalIo_t, satIntIoLink, smList); SM_DBG3(("smsatAllocIntIoResource: satDevData %p satIntIo id %d\n", satDevData, satIntIo->id)); /* Put in active list */ SMLIST_DEQUEUE_THIS (&(satIntIo->satIntIoLink)); SMLIST_ENQUEUE_AT_TAIL (&(satIntIo->satIntIoLink), &(satDevData->satActiveIntIoLinkList)); tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); #ifdef REMOVED /* Put in active list */ tdsmSingleThreadedEnter(smRoot, SM_INTERNAL_IO_LOCK); SMLIST_DEQUEUE_THIS (smList); SMLIST_ENQUEUE_AT_TAIL (smList, &(satDevData->satActiveIntIoLinkList)); tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); satIntIo = SMLIST_OBJECT_BASE( smSatInternalIo_t, satIntIoLink, smList); SM_DBG3(("smsatAllocIntIoResource: satDevData %p satIntIo id %d\n", satDevData, satIntIo->id)); #endif /* typedef struct { tdList_t satIntIoLink; smIORequest_t satIntSmIORequest; void *satIntRequestBody; smScsiInitiatorRequest_t satIntSmScsiXchg; smMem_t satIntDmaMem; smMem_t satIntReqBodyMem; bit32 satIntFlag; } smSatInternalIo_t; */ /* * Allocate mem for Request Body */ satIntIo->satIntReqBodyMem.totalLength = sizeof(smIORequestBody_t); memAllocStatus = tdsmAllocMemory( smRoot, &satIntIo->satIntReqBodyMem.osHandle, (void **)&satIntIo->satIntRequestBody, &satIntIo->satIntReqBodyMem.physAddrUpper, &satIntIo->satIntReqBodyMem.physAddrLower, 8, satIntIo->satIntReqBodyMem.totalLength, agTRUE ); if (memAllocStatus != SM_RC_SUCCESS) { SM_DBG1(("smsatAllocIntIoResource() FAIL to alloc mem for Req Body!!!\n")); /* * Return satIntIo to the free list */ tdsmSingleThreadedEnter(smRoot, SM_INTERNAL_IO_LOCK); SMLIST_DEQUEUE_THIS (&satIntIo->satIntIoLink); SMLIST_ENQUEUE_AT_HEAD(&satIntIo->satIntIoLink, &satDevData->satFreeIntIoLinkList); tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); return agNULL; } /* * Allocate DMA memory if required */ if (dmaAllocLength != 0) { satIntIo->satIntDmaMem.totalLength = dmaAllocLength; memAllocStatus = tdsmAllocMemory( smRoot, &satIntIo->satIntDmaMem.osHandle, (void **)&satIntIo->satIntDmaMem.virtPtr, &satIntIo->satIntDmaMem.physAddrUpper, &satIntIo->satIntDmaMem.physAddrLower, 8, satIntIo->satIntDmaMem.totalLength, agFALSE); SM_DBG3(("smsatAllocIntIoResource: len %d \n", satIntIo->satIntDmaMem.totalLength)); SM_DBG3(("smsatAllocIntIoResource: pointer %p \n", satIntIo->satIntDmaMem.osHandle)); if (memAllocStatus != SM_RC_SUCCESS) { SM_DBG1(("smsatAllocIntIoResource() FAIL to alloc mem for DMA mem!!!\n")); /* * Return satIntIo to the free list */ tdsmSingleThreadedEnter(smRoot, SM_INTERNAL_IO_LOCK); SMLIST_DEQUEUE_THIS (&satIntIo->satIntIoLink); SMLIST_ENQUEUE_AT_HEAD(&satIntIo->satIntIoLink, &satDevData->satFreeIntIoLinkList); tdsmSingleThreadedLeave(smRoot, SM_INTERNAL_IO_LOCK); /* * Free mem allocated for Req body */ tdsmFreeMemory( smRoot, satIntIo->satIntReqBodyMem.osHandle, satIntIo->satIntReqBodyMem.totalLength); return agNULL; } } /* typedef struct { smList_t satIntIoLink; smIORequest_t satIntSmIORequest; void *satIntRequestBody; smScsiInitiatorRequest_t satIntSmScsiXchg; smMem_t satIntDmaMem; smMem_t satIntReqBodyMem; bit32 satIntFlag; } smSatInternalIo_t; */ /* * Initialize satIntSmIORequest field */ satIntIo->satIntSmIORequest.tdData = agNULL; /* Not used for internal SAT I/O */ satIntIo->satIntSmIORequest.smData = satIntIo->satIntRequestBody; /* * saves the original smIOrequest */ satIntIo->satOrgSmIORequest = smIORequest; /* 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 satIntSmScsiXchg. 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 smsataLLIOStart() */ if (dmaAllocLength != 0) { satIntIo->satIntSmScsiXchg.sglVirtualAddr = satIntIo->satIntDmaMem.virtPtr; OSSA_WRITE_LE_32(agNULL, &satIntIo->satIntSmScsiXchg.smSgl1.len, 0, satIntIo->satIntDmaMem.totalLength); satIntIo->satIntSmScsiXchg.smSgl1.lower = satIntIo->satIntDmaMem.physAddrLower; satIntIo->satIntSmScsiXchg.smSgl1.upper = satIntIo->satIntDmaMem.physAddrUpper; satIntIo->satIntSmScsiXchg.smSgl1.type = tiSgl; satIntIo->satIntSmScsiXchg.scsiCmnd.expDataLength = satIntIo->satIntDmaMem.totalLength; } else { satIntIo->satIntSmScsiXchg.sglVirtualAddr = agNULL; satIntIo->satIntSmScsiXchg.smSgl1.len = 0; satIntIo->satIntSmScsiXchg.smSgl1.lower = 0; satIntIo->satIntSmScsiXchg.smSgl1.upper = 0; satIntIo->satIntSmScsiXchg.smSgl1.type = tiSgl; satIntIo->satIntSmScsiXchg.scsiCmnd.expDataLength = 0; } SM_DBG5(("smsatAllocIntIoResource: satIntIo->satIntSmScsiXchg.agSgl1.len %d\n", satIntIo->satIntSmScsiXchg.smSgl1.len)); SM_DBG5(("smsatAllocIntIoResource: satIntIo->satIntSmScsiXchg.agSgl1.upper %d\n", satIntIo->satIntSmScsiXchg.smSgl1.upper)); SM_DBG5(("smsatAllocIntIoResource: satIntIo->satIntSmScsiXchg.agSgl1.lower %d\n", satIntIo->satIntSmScsiXchg.smSgl1.lower)); SM_DBG5(("smsatAllocIntIoResource: satIntIo->satIntSmScsiXchg.agSgl1.type %d\n", satIntIo->satIntSmScsiXchg.smSgl1.type)); SM_DBG5(("smsatAllocIntIoResource: return satIntIo %p\n", satIntIo)); return satIntIo; } osGLOBAL smDeviceData_t * smAddToSharedcontext( smRoot_t *smRoot, agsaDevHandle_t *agDevHandle, smDeviceHandle_t *smDeviceHandle, agsaDevHandle_t *agExpDevHandle, bit32 phyID ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; smDeviceData_t *oneDeviceData = agNULL; smList_t *DeviceListList; bit32 new_device = agTRUE; SM_DBG2(("smAddToSharedcontext: start\n")); /* find a device's existence */ DeviceListList = smAllShared->MainDeviceList.flink; while (DeviceListList != &(smAllShared->MainDeviceList)) { oneDeviceData = SMLIST_OBJECT_BASE(smDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { SM_DBG1(("smAddToSharedcontext: oneDeviceData is NULL!!!\n")); return agNULL; } if (oneDeviceData->agDevHandle == agDevHandle) { SM_DBG2(("smAddToSharedcontext: did %d\n", oneDeviceData->id)); new_device = agFALSE; break; } DeviceListList = DeviceListList->flink; } /* new device */ if (new_device == agTRUE) { SM_DBG2(("smAddToSharedcontext: new device\n")); tdsmSingleThreadedEnter(smRoot, SM_DEVICE_LOCK); if (SMLIST_EMPTY(&(smAllShared->FreeDeviceList))) { tdsmSingleThreadedLeave(smRoot, SM_DEVICE_LOCK); SM_DBG1(("smAddToSharedcontext: empty DeviceData FreeLink!!!\n")); smDeviceHandle->smData = agNULL; return agNULL; } SMLIST_DEQUEUE_FROM_HEAD(&DeviceListList, &(smAllShared->FreeDeviceList)); tdsmSingleThreadedLeave(smRoot, SM_DEVICE_LOCK); oneDeviceData = SMLIST_OBJECT_BASE(smDeviceData_t, FreeLink, DeviceListList); oneDeviceData->smRoot = smRoot; oneDeviceData->agDevHandle = agDevHandle; oneDeviceData->valid = agTRUE; smDeviceHandle->smData = oneDeviceData; oneDeviceData->smDevHandle = smDeviceHandle; if (agExpDevHandle == agNULL) { oneDeviceData->directlyAttached = agTRUE; } else { oneDeviceData->directlyAttached = agFALSE; } oneDeviceData->agExpDevHandle = agExpDevHandle; oneDeviceData->phyID = phyID; oneDeviceData->satPendingIO = 0; oneDeviceData->satPendingNCQIO = 0; oneDeviceData->satPendingNONNCQIO = 0; /* add the devicedata to the portcontext */ tdsmSingleThreadedEnter(smRoot, SM_DEVICE_LOCK); SMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->MainLink), &(smAllShared->MainDeviceList)); tdsmSingleThreadedLeave(smRoot, SM_DEVICE_LOCK); SM_DBG2(("smAddToSharedcontext: new case did %d\n", oneDeviceData->id)); } else { SM_DBG2(("smAddToSharedcontext: old device\n")); oneDeviceData->smRoot = smRoot; oneDeviceData->agDevHandle = agDevHandle; oneDeviceData->valid = agTRUE; smDeviceHandle->smData = oneDeviceData; oneDeviceData->smDevHandle = smDeviceHandle; if (agExpDevHandle == agNULL) { oneDeviceData->directlyAttached = agTRUE; } else { oneDeviceData->directlyAttached = agFALSE; } oneDeviceData->agExpDevHandle = agExpDevHandle; oneDeviceData->phyID = phyID; oneDeviceData->satPendingIO = 0; oneDeviceData->satPendingNCQIO = 0; oneDeviceData->satPendingNONNCQIO = 0; SM_DBG2(("smAddToSharedcontext: old case did %d\n", oneDeviceData->id)); } return oneDeviceData; } osGLOBAL bit32 smRemoveFromSharedcontext( smRoot_t *smRoot, agsaDevHandle_t *agDevHandle, smDeviceHandle_t *smDeviceHandle ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; smDeviceData_t *oneDeviceData = agNULL; SM_DBG2(("smRemoveFromSharedcontext: start\n")); //due to device all and completion //smDeviceHandle->smData = agNULL; /* find oneDeviceData from MainLink */ oneDeviceData = smFindInSharedcontext(smRoot, agDevHandle); if (oneDeviceData == agNULL) { return SM_RC_FAILURE; } else { if (oneDeviceData->valid == agTRUE) { smDeviceDataReInit(smRoot, oneDeviceData); tdsmSingleThreadedEnter(smRoot, SM_DEVICE_LOCK); SMLIST_DEQUEUE_THIS(&(oneDeviceData->MainLink)); SMLIST_ENQUEUE_AT_TAIL(&(oneDeviceData->FreeLink), &(smAllShared->FreeDeviceList)); tdsmSingleThreadedLeave(smRoot, SM_DEVICE_LOCK); return SM_RC_SUCCESS; } else { SM_DBG1(("smRemoveFromSharedcontext: did %d bad case!!!\n", oneDeviceData->id)); return SM_RC_FAILURE; } } } osGLOBAL smDeviceData_t * smFindInSharedcontext( smRoot_t *smRoot, agsaDevHandle_t *agDevHandle ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; smDeviceData_t *oneDeviceData = agNULL; smList_t *DeviceListList; SM_DBG2(("smFindInSharedcontext: start\n")); tdsmSingleThreadedEnter(smRoot, SM_DEVICE_LOCK); if (SMLIST_EMPTY(&(smAllShared->MainDeviceList))) { SM_DBG1(("smFindInSharedcontext: empty MainDeviceList!!!\n")); tdsmSingleThreadedLeave(smRoot, SM_DEVICE_LOCK); return agNULL; } else { tdsmSingleThreadedLeave(smRoot, SM_DEVICE_LOCK); } DeviceListList = smAllShared->MainDeviceList.flink; while (DeviceListList != &(smAllShared->MainDeviceList)) { oneDeviceData = SMLIST_OBJECT_BASE(smDeviceData_t, MainLink, DeviceListList); if (oneDeviceData == agNULL) { SM_DBG1(("smFindInSharedcontext: oneDeviceData is NULL!!!\n")); return agNULL; } if ((oneDeviceData->agDevHandle == agDevHandle) && (oneDeviceData->valid == agTRUE) ) { SM_DBG2(("smFindInSharedcontext: found, did %d\n", oneDeviceData->id)); return oneDeviceData; } DeviceListList = DeviceListList->flink; } SM_DBG2(("smFindInSharedcontext: not found\n")); return agNULL; } osGLOBAL smSatIOContext_t * smsatPrepareNewIO( smSatInternalIo_t *satNewIntIo, smIORequest_t *smOrgIORequest, smDeviceData_t *satDevData, smIniScsiCmnd_t *scsiCmnd, smSatIOContext_t *satOrgIOContext ) { smSatIOContext_t *satNewIOContext; smIORequestBody_t *smNewIORequestBody; SM_DBG3(("smsatPrepareNewIO: start\n")); /* the one to be used; good 8/2/07 */ satNewIntIo->satOrgSmIORequest = smOrgIORequest; /* this is already done in smsatAllocIntIoResource() */ smNewIORequestBody = (smIORequestBody_t *)satNewIntIo->satIntRequestBody; satNewIOContext = &(smNewIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(smNewIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satNewIntIo->satIntSmScsiXchg.scsiCmnd); if (scsiCmnd != agNULL) { /* saves only CBD; not scsi command for LBA and number of blocks */ sm_memcpy(satNewIOContext->pScsiCmnd->cdb, scsiCmnd->cdb, 16); } satNewIOContext->pSense = &(smNewIORequestBody->transport.SATA.sensePayload); satNewIOContext->pSmSenseData = &(smNewIORequestBody->transport.SATA.smSenseData); satNewIOContext->pSmSenseData->senseData = satNewIOContext->pSense; satNewIOContext->smRequestBody = satNewIntIo->satIntRequestBody; satNewIOContext->interruptContext = satNewIOContext->interruptContext; satNewIOContext->satIntIoContext = satNewIntIo; satNewIOContext->psmDeviceHandle = satOrgIOContext->psmDeviceHandle; satNewIOContext->satOrgIOContext = satOrgIOContext; /* saves tiScsiXchg; only for writesame10() */ satNewIOContext->smScsiXchg = satOrgIOContext->smScsiXchg; return satNewIOContext; } osGLOBAL void smsatSetDevInfo( smDeviceData_t *oneDeviceData, agsaSATAIdentifyData_t *SATAIdData ) { SM_DBG3(("smsatSetDevInfo: start\n")); oneDeviceData->satDriveState = SAT_DEV_STATE_NORMAL; oneDeviceData->satFormatState = agFALSE; oneDeviceData->satDeviceFaultState = agFALSE; oneDeviceData->satTmTaskTag = agNULL; oneDeviceData->satAbortAfterReset = agFALSE; oneDeviceData->satAbortCalled = agFALSE; oneDeviceData->satSectorDone = 0; /* Qeueu depth, Word 75 */ oneDeviceData->satNCQMaxIO = SATAIdData->queueDepth + 1; SM_DBG3(("smsatSetDevInfo: max queue depth %d\n",oneDeviceData->satNCQMaxIO)); /* Support NCQ, if Word 76 bit 8 is set */ if (SATAIdData->sataCapabilities & 0x100) { SM_DBG3(("smsatSetDevInfo: device supports NCQ\n")); oneDeviceData->satNCQ = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no NCQ\n")); oneDeviceData->satNCQ = agFALSE; } /* Support 48 bit addressing, if Word 83 bit 10 and Word 86 bit 10 are set */ if ((SATAIdData->commandSetSupported1 & 0x400) && (SATAIdData->commandSetFeatureEnabled1 & 0x400) ) { SM_DBG3(("smsatSetDevInfo: support 48 bit addressing\n")); oneDeviceData->sat48BitSupport = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: NO 48 bit addressing\n")); oneDeviceData->sat48BitSupport = agFALSE; } /* Support SMART Self Test, word84 bit 1 */ if (SATAIdData->commandSetFeatureSupportedExt & 0x02) { SM_DBG3(("smsatSetDevInfo: SMART self-test supported \n")); oneDeviceData->satSMARTSelfTest = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no SMART self-test suppored\n")); oneDeviceData->satSMARTSelfTest = agFALSE; } /* Support SMART feature set, word82 bit 0 */ if (SATAIdData->commandSetSupported & 0x01) { SM_DBG3(("smsatSetDevInfo: SMART feature set supported \n")); oneDeviceData->satSMARTFeatureSet = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no SMART feature set suppored\n")); oneDeviceData->satSMARTFeatureSet = agFALSE; } /* Support SMART enabled, word85 bit 0 */ if (SATAIdData->commandSetFeatureEnabled & 0x01) { SM_DBG3(("smsatSetDevInfo: SMART enabled \n")); oneDeviceData->satSMARTEnabled = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no SMART enabled\n")); oneDeviceData->satSMARTEnabled = agFALSE; } oneDeviceData->satVerifyState = 0; /* Removable Media feature set support, word82 bit 2 */ if (SATAIdData->commandSetSupported & 0x4) { SM_DBG3(("smsatSetDevInfo: Removable Media supported \n")); oneDeviceData->satRemovableMedia = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no Removable Media suppored\n")); oneDeviceData->satRemovableMedia = agFALSE; } /* Removable Media feature set enabled, word 85, bit 2 */ if (SATAIdData->commandSetFeatureEnabled & 0x4) { SM_DBG3(("smsatSetDevInfo: Removable Media enabled\n")); oneDeviceData->satRemovableMediaEnabled = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no Removable Media enabled\n")); oneDeviceData->satRemovableMediaEnabled = agFALSE; } /* DMA Support, word49 bit8 */ if (SATAIdData->dma_lba_iod_ios_stimer & 0x100) { SM_DBG3(("smsatSetDevInfo: DMA supported \n")); oneDeviceData->satDMASupport = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no DMA suppored\n")); oneDeviceData->satDMASupport = agFALSE; } /* Support DMADIR, if Word 62 bit 8 is set */ if (SATAIdData->word62_74[0] & 0x8000) { SM_DBG3(("satSetDevInfo: DMADIR enabled\n")); oneDeviceData->satDMADIRSupport = agTRUE; } else { SM_DBG3(("satSetDevInfo: DMADIR disabled\n")); oneDeviceData->satDMADIRSupport = agFALSE; } /* DMA Enabled, word88 bit0-6, bit8-14*/ /* 0x7F7F = 0111 1111 0111 1111*/ if (SATAIdData->ultraDMAModes & 0x7F7F) { SM_DBG3(("smsatSetDevInfo: DMA enabled \n")); oneDeviceData->satDMAEnabled = agTRUE; if (SATAIdData->ultraDMAModes & 0x40) { oneDeviceData->satUltraDMAMode = 6; } else if (SATAIdData->ultraDMAModes & 0x20) { oneDeviceData->satUltraDMAMode = 5; } else if (SATAIdData->ultraDMAModes & 0x10) { oneDeviceData->satUltraDMAMode = 4; } else if (SATAIdData->ultraDMAModes & 0x08) { oneDeviceData->satUltraDMAMode = 3; } else if (SATAIdData->ultraDMAModes & 0x04) { oneDeviceData->satUltraDMAMode = 2; } else if (SATAIdData->ultraDMAModes & 0x01) { oneDeviceData->satUltraDMAMode = 1; } } else { SM_DBG3(("smsatSetDevInfo: no DMA enabled\n")); oneDeviceData->satDMAEnabled = agFALSE; oneDeviceData->satUltraDMAMode = 0; } /* setting MaxUserAddrSectors: max user addressable setctors word60 - 61, should be 0x 0F FF FF FF */ oneDeviceData->satMaxUserAddrSectors = (SATAIdData->numOfUserAddressableSectorsHi << (8*2) ) + SATAIdData->numOfUserAddressableSectorsLo; SM_DBG3(("smsatSetDevInfo: MaxUserAddrSectors 0x%x decimal %d\n", oneDeviceData->satMaxUserAddrSectors, oneDeviceData->satMaxUserAddrSectors)); /* Read Look-ahead is supported */ if (SATAIdData->commandSetSupported & 0x40) { SM_DBG3(("smsatSetDevInfo: Read Look-ahead is supported\n")); oneDeviceData->satReadLookAheadSupport= agTRUE; } else { SM_DBG3(("smsatSetDevInfo: Read Look-ahead is not supported\n")); oneDeviceData->satReadLookAheadSupport= agFALSE; } /* Volatile Write Cache is supported */ if (SATAIdData->commandSetSupported & 0x20) { SM_DBG3(("smsatSetDevInfo: Volatile Write Cache is supported\n")); oneDeviceData->satVolatileWriteCacheSupport = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: Volatile Write Cache is not supported\n")); oneDeviceData->satVolatileWriteCacheSupport = agFALSE; } /* write cache enabled for caching mode page SAT Table 67 p69, word85 bit5 */ if (SATAIdData->commandSetFeatureEnabled & 0x20) { SM_DBG3(("smsatSetDevInfo: write cache enabled\n")); oneDeviceData->satWriteCacheEnabled = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no write cache enabled\n")); oneDeviceData->satWriteCacheEnabled = agFALSE; } /* look ahead enabled for caching mode page SAT Table 67 p69, word85 bit6 */ if (SATAIdData->commandSetFeatureEnabled & 0x40) { SM_DBG3(("smsatSetDevInfo: look ahead enabled\n")); oneDeviceData->satLookAheadEnabled = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no look ahead enabled\n")); oneDeviceData->satLookAheadEnabled = agFALSE; } /* Support WWN, if Word 87 bit 8 is set */ if (SATAIdData->commandSetFeatureDefault & 0x100) { SM_DBG3(("smsatSetDevInfo: device supports WWN\n")); oneDeviceData->satWWNSupport = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no WWN\n")); oneDeviceData->satWWNSupport = agFALSE; } /* Support DMA Setup Auto-Activate, if Word 78 bit 2 is set */ if (SATAIdData->sataFeaturesSupported & 0x4) { SM_DBG3(("smsatSetDevInfo: device supports DMA Setup Auto-Activate\n")); oneDeviceData->satDMASetupAA = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no DMA Setup Auto-Activate\n")); oneDeviceData->satDMASetupAA = agFALSE; } /* Support NCQ Queue Management Command, if Word 77 bit 5 is set */ if (SATAIdData->word77 & 0x10) { SM_DBG3(("smsatSetDevInfo: device supports NCQ Queue Management Command\n")); oneDeviceData->satNCQQMgntCmd = agTRUE; } else { SM_DBG3(("smsatSetDevInfo: no NCQ Queue Management Command\n")); oneDeviceData->satNCQQMgntCmd = agFALSE; } return; } osGLOBAL void smsatInquiryStandard( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData, smIniScsiCmnd_t *scsiCmnd ) { smLUN_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 */ SM_DBG5(("smsatInquiryStandard: start\n")); if (pInquiry == agNULL) { SM_DBG1(("smsatInquiryStandard: pInquiry is NULL, wrong\n")); return; } else { SM_DBG5(("smsatInquiryStandard: 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. */ sm_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] == 0x20 ) && (pSATAIdData->firmwareVersion[6] == 0x20 ) && (pSATAIdData->firmwareVersion[7] == 0x20 ) ) { 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] == 0x20 ) && (pSATAIdData->firmwareVersion[6] == 0x20 ) && (pSATAIdData->firmwareVersion[7] == 0x20 ) ) { 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 SM_DBG5(("smsatInquiryStandard: end\n")); return; } osGLOBAL void smsatInquiryPage0( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData ) { SM_DBG5(("smsatInquiryPage0: start\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] = 8 - 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 */ pInquiry[8] = 0xB1; /* page 0xB1 supported */ return; } osGLOBAL void smsatInquiryPage83( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData, smDeviceData_t *oneDeviceData ) { 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; SM_DBG5(("smsatInquiryPage83: start\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 ( oneDeviceData->satWWNSupport) { #ifndef PMC_FREEBSD /* 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 /* For FreeBSD */ /* Fill in SAT Rev8 Table85 */ /* * Logical unit name derived from the world wide name. */ pInquiry[3] = 24; /* 35-3; page length, no addition ID descriptor assumed*/ /* * Identifier descriptor */ pInquiry[4] = 0x01; /* Code set: binary codes; this is proto_codeset in FreeBSD */ pInquiry[5] = 0x03; /* Identifier type : NAA ; this is id_type in FreeBSD*/ 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 */ pInquiry[16] = 0x61; /* Code set: binary codes; this is proto_codeset in FreeBSD; SCSI_PROTO_SAS and SVPD_ID_CODESET_BINARY */ pInquiry[17] = 0x93; /* Identifier type : NAA ; this is id_type in FreeBSD; PIV set, ASSOCIATION is 01b and NAA (3h) */ pInquiry[18] = 0x00; /* Reserved */ pInquiry[19] = 0x08; /* Identifier length */ SM_DBG5(("smsatInquiryPage83: sasAddressHi 0x%08x\n", oneDeviceData->sasAddressHi)); SM_DBG5(("smsatInquiryPage83: sasAddressLo 0x%08x\n", oneDeviceData->sasAddressLo)); /* SAS address of SATA */ pInquiry[20] = ((oneDeviceData->sasAddressHi) & 0xFF000000 ) >> 24; pInquiry[21] = ((oneDeviceData->sasAddressHi) & 0xFF0000 ) >> 16; pInquiry[22] = ((oneDeviceData->sasAddressHi) & 0xFF00 ) >> 8; pInquiry[23] = (oneDeviceData->sasAddressHi) & 0xFF; pInquiry[24] = ((oneDeviceData->sasAddressLo) & 0xFF000000 ) >> 24; pInquiry[25] = ((oneDeviceData->sasAddressLo) & 0xFF0000 ) >> 16; pInquiry[26] = ((oneDeviceData->sasAddressLo) & 0xFF00 ) >> 8; pInquiry[27] = (oneDeviceData->sasAddressLo) & 0xFF; #endif } else { #ifndef PMC_FREEBSD /* 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 '. */ sm_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); #else /* for the FreeBSD */ /* Fill in SAT Rev8 Table86 */ /* * Logical unit name derived from the model number and serial number. */ pInquiry[3] = 84; /* 87 - 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 '. */ sm_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); pInquiry[76] = 0x61; /* Code set: binary codes; this is proto_codeset in FreeBSD; SCSI_PROTO_SAS and SVPD_ID_CODESET_BINARY */ pInquiry[77] = 0x93; /* Identifier type : NAA ; this is id_type in FreeBSD; PIV set, ASSOCIATION is 01b and NAA (3h) */ pInquiry[78] = 0x00; /* Reserved */ pInquiry[79] = 0x08; /* Identifier length */ SM_DBG5(("smsatInquiryPage83: NO WWN sasAddressHi 0x%08x\n", oneDeviceData->sasAddressHi)); SM_DBG5(("smsatInquiryPage83: No WWN sasAddressLo 0x%08x\n", oneDeviceData->sasAddressLo)); /* SAS address of SATA */ pInquiry[80] = ((oneDeviceData->sasAddressHi) & 0xFF000000 ) >> 24; pInquiry[81] = ((oneDeviceData->sasAddressHi) & 0xFF0000 ) >> 16; pInquiry[82] = ((oneDeviceData->sasAddressHi) & 0xFF00 ) >> 8; pInquiry[83] = (oneDeviceData->sasAddressHi) & 0xFF; pInquiry[84] = ((oneDeviceData->sasAddressLo) & 0xFF000000 ) >> 24; pInquiry[85] = ((oneDeviceData->sasAddressLo) & 0xFF0000 ) >> 16; pInquiry[86] = ((oneDeviceData->sasAddressLo) & 0xFF00 ) >> 8; pInquiry[87] = (oneDeviceData->sasAddressLo) & 0xFF; #endif } return; } osGLOBAL void smsatInquiryPage89( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData, smDeviceData_t *oneDeviceData, bit32 len ) { /* 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; SM_DBG5(("smsatInquiryPage89: 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 */ sm_strncpy((char*)&pInquiry[8], "PMC-SIERRA", 8); /* 8 bytes */ /* SAT Product Idetification */ sm_strncpy((char*)&pInquiry[16], "Tachyon-SPC ", 16); /* 16 bytes */ /* SAT Product Revision Level */ sm_strncpy((char*)&pInquiry[32], "01", 4); /* 4 bytes */ /* Signature, SAT revision8, Table88, p85 */ pInquiry[36] = 0x34; /* FIS type */ if (oneDeviceData->satDeviceType == SATA_ATA_DEVICE) { /* interrupt assume to be 0 */ pInquiry[37] = (bit8)((oneDeviceData->satPMField) >> (4 * 7)); /* first four bits of PM field */ } else { /* interrupt assume to be 1 */ pInquiry[37] = (bit8)(0x40 + (bit8)(((oneDeviceData->satPMField) >> (4 * 7)))); /* first four bits of PM field */ } pInquiry[38] = 0; pInquiry[39] = 0; if (oneDeviceData->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 (oneDeviceData->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; /* check the length; len is assumed to be at least 60 */ if (len < SATA_PAGE89_INQUIRY_SIZE) { /* Identify Device */ sm_memcpy(&pInquiry[60], pSimpleData, MIN((len - 60), sizeof(satSimpleSATAIdentifyData_t))); } else { /* Identify Device */ sm_memcpy(&pInquiry[60], pSimpleData, sizeof(satSimpleSATAIdentifyData_t)); } return; } osGLOBAL void smsatInquiryPage80( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData ) { SM_DBG5(("smsatInquiryPage89: start\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 */ /* product serial number */ 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]; return; } osGLOBAL void smsatInquiryPageB1( bit8 *pInquiry, agsaSATAIdentifyData_t *pSATAIdData ) { bit32 i; satSimpleSATAIdentifyData_t *pSimpleData; SM_DBG5(("smsatInquiryPageB1: start\n")); pSimpleData = ( satSimpleSATAIdentifyData_t *)pSATAIdData; /* See SBC-3, revision31, Table193, p273 and SAT-3 revision 3, 10.3.6, p141 */ pInquiry[0] = 0x00; /* Peripheral Qualifier and Peripheral Device Type */ pInquiry[1] = 0xB1; /* page code */ /* page length */ pInquiry[2] = 0x0; pInquiry[3] = 0x3C; /* medium rotation rate */ pInquiry[4] = (bit8) ((pSimpleData->word[217]) >> 8); pInquiry[5] = (bit8) ((pSimpleData->word[217]) & 0xFF); /* reserved */ pInquiry[6] = 0x0; /* nominal form factor bits 3:0 */ pInquiry[7] = (bit8) ((pSimpleData->word[168]) & 0xF); /* reserved */ for (i=8;i<64;i++) { pInquiry[i] = 0x0; } return; } osGLOBAL void smsatDefaultTranslation( smRoot_t *smRoot, smIORequest_t *smIORequest, smSatIOContext_t *satIOContext, smScsiRspSense_t *pSense, bit8 ataStatus, bit8 ataError, bit32 interruptContext ) { SM_DBG5(("smsatDefaultTranslation: start\n")); /* * Check for device fault case */ if ( ataStatus & DF_ATA_STATUS_MASK ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, 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 ) { SM_DBG1(("smsatDefaultTranslation: NM_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_MEDIUM_NOT_PRESENT, satIOContext); } else if (ataError & UNC_ATA_ERROR_MASK) { SM_DBG1(("smsatDefaultTranslation: UNC_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_MEDIUM_ERROR, 0, SCSI_SNSCODE_UNRECOVERED_READ_ERROR, satIOContext); } else if (ataError & IDNF_ATA_ERROR_MASK) { SM_DBG1(("smsatDefaultTranslation: IDNF_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_MEDIUM_ERROR, 0, SCSI_SNSCODE_RECORD_NOT_FOUND, satIOContext); } else if (ataError & MC_ATA_ERROR_MASK) { SM_DBG1(("smsatDefaultTranslation: MC_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_UNIT_ATTENTION, 0, SCSI_SNSCODE_NOT_READY_TO_READY_CHANGE, satIOContext); } else if (ataError & MCR_ATA_ERROR_MASK) { SM_DBG1(("smsatDefaultTranslation: MCR_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_UNIT_ATTENTION, 0, SCSI_SNSCODE_OPERATOR_MEDIUM_REMOVAL_REQUEST, satIOContext); } else if (ataError & ICRC_ATA_ERROR_MASK) { SM_DBG1(("smsatDefaultTranslation: ICRC_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_INFORMATION_UNIT_CRC_ERROR, satIOContext); } else if (ataError & ABRT_ATA_ERROR_MASK) { SM_DBG1(("smsatDefaultTranslation: ABRT_ATA_ERROR ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); } else { SM_DBG1(("smsatDefaultTranslation: **** UNEXPECTED ATA_ERROR **** ataError= 0x%x, smIORequest=%p!!!\n", ataError, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); } /* Send the completion response now */ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, interruptContext ); return; } else /* (ataStatus & ERR_ATA_STATUS_MASK ) is false */ { /* This case should never happen */ SM_DBG1(("smsatDefaultTranslation: *** UNEXPECTED ATA status 0x%x *** smIORequest=%p!!!\n", ataStatus, smIORequest)); smsatSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_INTERNAL_TARGET_FAILURE, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, interruptContext ); return; } return; } osGLOBAL bit32 smIDStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle ) { smDeviceData_t *oneDeviceData = agNULL; smIORequestBody_t *smIORequestBody = agNULL; smSatIOContext_t *satIOContext = agNULL; bit32 status = SM_RC_FAILURE; SM_DBG2(("smIDStart: start, smIORequest %p\n", smIORequest)); oneDeviceData = (smDeviceData_t *)smDeviceHandle->smData; if (oneDeviceData == agNULL) { SM_DBG1(("smIDStart: oneDeviceData is NULL!!!\n")); return SM_RC_FAILURE; } if (oneDeviceData->valid == agFALSE) { SM_DBG1(("smIDStart: oneDeviceData is not valid, did %d !!!\n", oneDeviceData->id)); return SM_RC_FAILURE; } smIORequestBody = (smIORequestBody_t*)smIORequest->smData;//smDequeueIO(smRoot); if (smIORequestBody == agNULL) { SM_DBG1(("smIDStart: smIORequestBody is NULL!!!\n")); return SM_RC_FAILURE; } smIOReInit(smRoot, smIORequestBody); SM_DBG3(("smIDStart: io ID %d!!!\n", smIORequestBody->id )); smIORequestBody->smIORequest = smIORequest; smIORequestBody->smDevHandle = smDeviceHandle; satIOContext = &(smIORequestBody->transport.SATA.satIOContext); /* setting up satIOContext */ satIOContext->pSatDevData = oneDeviceData; satIOContext->pFis = &(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext->smRequestBody = smIORequestBody; satIOContext->psmDeviceHandle = smDeviceHandle; satIOContext->smScsiXchg = agNULL; /*smIORequest->smData = smIORequestBody;*/ SM_DBG3(("smIDStart: smIORequestBody %p smIORequestBody->smIORequest %p!!!\n", smIORequestBody, smIORequestBody->smIORequest)); SM_DBG1(("smIDStart: did %d\n", oneDeviceData->id)); status = smsatIDSubStart( smRoot, smIORequest, smDeviceHandle, agNULL, satIOContext); if (status != SM_RC_SUCCESS) { SM_DBG1(("smIDStart: smsatIDSubStart failure %d!!!\n", status)); /*smEnqueueIO(smRoot, satIOContext);*/ } SM_DBG2(("smIDStart: exit\n")); return status; } /* SM generated IO, needs to call smsatAllocIntIoResource() allocating using smsatAllocIntIoResource */ osGLOBAL bit32 smsatIDSubStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, /* agNULL */ smSatIOContext_t *satIOContext ) { smSatInternalIo_t *satIntIo = agNULL; smDeviceData_t *satDevData = agNULL; smIORequestBody_t *smIORequestBody; smSatIOContext_t *satNewIOContext; bit32 status; SM_DBG2(("smsatIDSubStart: start\n")); satDevData = satIOContext->pSatDevData; /* allocate identify device command */ satIntIo = smsatAllocIntIoResource( smRoot, smIORequest, satDevData, sizeof(agsaSATAIdentifyData_t), /* 512; size of identify device data */ satIntIo); if (satIntIo == agNULL) { SM_DBG1(("smsatIDSubStart: can't alloacate!!!\n")); return SM_RC_FAILURE; } satIOContext->satIntIoContext = satIntIo; /* fill in fields */ /* real ttttttthe one worked and the same; 5/21/07/ */ satIntIo->satOrgSmIORequest = smIORequest; /* changed */ smIORequestBody = satIntIo->satIntRequestBody; satNewIOContext = &(smIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satIntIo->satIntSmScsiXchg.scsiCmnd); satNewIOContext->pSense = &(smIORequestBody->transport.SATA.sensePayload); satNewIOContext->pSmSenseData = &(smIORequestBody->transport.SATA.smSenseData); satNewIOContext->smRequestBody = satIntIo->satIntRequestBody; /* key fix */ // satNewIOContext->interruptContext = tiInterruptContext; satNewIOContext->satIntIoContext = satIntIo; satNewIOContext->psmDeviceHandle = smDeviceHandle; satNewIOContext->satOrgIOContext = satIOContext; /* changed */ /* this is valid only for TD layer generated (not triggered by OS at all) IO */ satNewIOContext->smScsiXchg = &(satIntIo->satIntSmScsiXchg); SM_DBG6(("smsatIDSubStart: SM satIOContext %p \n", satIOContext)); SM_DBG6(("smsatIDSubStart: SM satNewIOContext %p \n", satNewIOContext)); SM_DBG6(("smsatIDSubStart: SM tiScsiXchg %p \n", satIOContext->smScsiXchg)); SM_DBG6(("smsatIDSubStart: SM tiScsiXchg %p \n", satNewIOContext->smScsiXchg)); SM_DBG3(("smsatIDSubStart: satNewIOContext %p smIORequestBody %p\n", satNewIOContext, smIORequestBody)); status = smsatIDStart(smRoot, &satIntIo->satIntSmIORequest, /* New smIORequest */ smDeviceHandle, satNewIOContext->smScsiXchg, /* New smScsiInitiatorRequest_t *smScsiRequest, */ satNewIOContext); if (status != SM_RC_SUCCESS) { SM_DBG1(("smsatIDSubStart: failed in sending %d!!!\n", status)); smsatFreeIntIoResource( smRoot, satDevData, satIntIo); return SM_RC_FAILURE; } SM_DBG2(("smsatIDSubStart: end\n")); return status; } osGLOBAL bit32 smsatIDStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; #ifdef SM_INTERNAL_DEBUG smIORequestBody_t *smIORequestBody; smSatInternalIo_t *satIntIoContext; #endif pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG2(("smsatIDStart: start\n")); #ifdef SM_INTERNAL_DEBUG satIntIoContext = satIOContext->satIntIoContext; smIORequestBody = satIntIoContext->satIntRequestBody; #endif fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE) { SM_DBG2(("smsatIDStart: IDENTIFY_PACKET_DEVICE\n")); fis->h.command = SAT_IDENTIFY_PACKET_DEVICE; /* 0x40 */ } else { SM_DBG2(("smsatIDStart: IDENTIFY_DEVICE\n")); 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 = &smsatIDStartCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef SM_INTERNAL_DEBUG smhexdump("smsatIDStart", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); smhexdump("smsatIDStart LL", (bit8 *)&(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); SM_DBG2(("smsatIDStart: end status %d\n", status)); return status; } osGLOBAL FORCEINLINE bit32 smsatIOStart( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, smSatIOContext_t *satIOContext ) { smDeviceData_t *pSatDevData = satIOContext->pSatDevData; smScsiRspSense_t *pSense = satIOContext->pSense; smIniScsiCmnd_t *scsiCmnd = &smSCSIRequest->scsiCmnd; smLUN_t *pLun = &scsiCmnd->lun; smSatInternalIo_t *pSatIntIo = agNULL; bit32 status = SM_RC_FAILURE; SM_DBG2(("smsatIOStart: start\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) && (scsiCmnd->cdb[0] != SCSIOPC_INQUIRY) ) { SM_DBG1(("smsatIOStart: *** REJECT *** LUN not zero, cdb[0]=0x%x did %d !!!\n", scsiCmnd->cdb[0], pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_NOT_SUPPORTED, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG2(("smsatIOStart: 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)) { SM_DBG1(("smsatIOStart: invalid identify device data did %d !!!\n", pSatDevData->id)); SM_DBG1(("smsatIOStart: satPendingIO %d satNCQMaxIO %d\n", pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); SM_DBG1(("smsatIOStart: satPendingNCQIO %d satPendingNONNCQIO %d\n", pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_NODEVICE; } /* * Check if we need to return BUSY, i.e. recovery in progress */ if (pSatDevData->satDriveState == SAT_DEV_STATE_IN_RECOVERY) { SM_DBG1(("smsatIOStart: IN RECOVERY STATE cdb[0]=0x%x did=%d !!!\n", scsiCmnd->cdb[0], pSatDevData->id)); SM_DBG2(("smsatIOStart: device %p satPendingIO %d satNCQMaxIO %d\n", pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); SM_DBG2(("smsatIOStart: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); /*smEnqueueIO(smRoot, satIOContext);*/ // return SM_RC_FAILURE; return SM_RC_DEVICE_BUSY; } if (pSatDevData->satDeviceType == SATA_ATAPI_DEVICE) { if (scsiCmnd->cdb[0] == SCSIOPC_REPORT_LUN) { return smsatReportLun(smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); } else { return smsatPacket(smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); } } else { /* Parse CDB */ switch(scsiCmnd->cdb[0]) { case SCSIOPC_READ_10: status = smsatRead10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_10: status = smsatWrite10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_6: status = smsatRead6( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_12: SM_DBG5(("smsatIOStart: SCSIOPC_READ_12\n")); status = smsatRead12( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_16: status = smsatRead16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_6: status = smsatWrite6( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_12: SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_12 \n")); status = smsatWrite12( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_16: SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_16 \n")); status = smsatWrite16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_VERIFY_10: status = smsatVerify10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_VERIFY_12: SM_DBG5(("smsatIOStart: SCSIOPC_VERIFY_12\n")); status = smsatVerify12( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_VERIFY_16: SM_DBG5(("smsatIOStart: SCSIOPC_VERIFY_16\n")); status = smsatVerify16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_TEST_UNIT_READY: status = smsatTestUnitReady( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_INQUIRY: status = smsatInquiry( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_REQUEST_SENSE: status = smsatRequestSense( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_MODE_SENSE_6: status = smsatModeSense6( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_MODE_SENSE_10: status = smsatModeSense10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_CAPACITY_10: status = smsatReadCapacity10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_CAPACITY_16: status = smsatReadCapacity16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_REPORT_LUN: status = smsatReportLun( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_FORMAT_UNIT: SM_DBG5(("smsatIOStart: SCSIOPC_FORMAT_UNIT\n")); status = smsatFormatUnit( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_SEND_DIAGNOSTIC: SM_DBG5(("smsatIOStart: SCSIOPC_SEND_DIAGNOSTIC\n")); status = smsatSendDiagnostic( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_START_STOP_UNIT: SM_DBG5(("smsatIOStart: SCSIOPC_START_STOP_UNIT\n")); status = smsatStartStopUnit( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_SAME_10: SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_SAME_10\n")); status = smsatWriteSame10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_SAME_16: /* no support due to transfer length(sector count) */ SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_SAME_16\n")); status = smsatWriteSame16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_LOG_SENSE: SM_DBG5(("smsatIOStart: SCSIOPC_LOG_SENSE\n")); status = smsatLogSense( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_MODE_SELECT_6: SM_DBG5(("smsatIOStart: SCSIOPC_MODE_SELECT_6\n")); status = smsatModeSelect6( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_MODE_SELECT_10: SM_DBG5(("smsatIOStart: SCSIOPC_MODE_SELECT_10\n")); status = smsatModeSelect10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_SYNCHRONIZE_CACHE_10: /* on error what to return, sharing CB with satSynchronizeCache16 */ SM_DBG5(("smsatIOStart: SCSIOPC_SYNCHRONIZE_CACHE_10\n")); status = smsatSynchronizeCache10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_SYNCHRONIZE_CACHE_16:/* on error what to return, sharing CB with satSynchronizeCache16 */ SM_DBG5(("smsatIOStart: SCSIOPC_SYNCHRONIZE_CACHE_16\n")); status = smsatSynchronizeCache16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_AND_VERIFY_10: /* single write and multiple writes */ SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_AND_VERIFY_10\n")); status = smsatWriteAndVerify10( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_AND_VERIFY_12: SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_AND_VERIFY_12\n")); status = smsatWriteAndVerify12( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_AND_VERIFY_16: SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_AND_VERIFY_16\n")); status = smsatWriteAndVerify16( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_MEDIA_SERIAL_NUMBER: SM_DBG5(("smsatIOStart: SCSIOPC_READ_MEDIA_SERIAL_NUMBER\n")); status = smsatReadMediaSerialNumber( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_READ_BUFFER: SM_DBG5(("smsatIOStart: SCSIOPC_READ_BUFFER\n")); status = smsatReadBuffer( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_WRITE_BUFFER: SM_DBG5(("smsatIOStart: SCSIOPC_WRITE_BUFFER\n")); status = smsatWriteBuffer( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_REASSIGN_BLOCKS: SM_DBG5(("smsatIOStart: SCSIOPC_REASSIGN_BLOCKS\n")); status = smsatReassignBlocks( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; case SCSIOPC_ATA_PASS_THROUGH12: /* fall through */ case SCSIOPC_ATA_PASS_THROUGH16: SM_DBG5(("smsatIOStart: SCSIOPC_ATA_PASS_THROUGH\n")); status = smsatPassthrough( smRoot, smIORequest, smDeviceHandle, smSCSIRequest, satIOContext); break; default: /* Not implemented SCSI cmd, set up error response */ SM_DBG1(("smsatIOStart: unsupported SCSI cdb[0]=0x%x did=%d !!!\n", scsiCmnd->cdb[0], pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); status = SM_RC_SUCCESS; break; } /* end switch */ } if (status == SM_RC_BUSY || status == SM_RC_DEVICE_BUSY) { SM_DBG1(("smsatIOStart: BUSY did %d!!!\n", pSatDevData->id)); SM_DBG2(("smsatIOStart: LL is busy or target queue is full\n")); SM_DBG2(("smsatIOStart: device %p satPendingIO %d satNCQMaxIO %d\n",pSatDevData, pSatDevData->satPendingIO, pSatDevData->satNCQMaxIO )); SM_DBG2(("smsatIOStart: device %p satPendingNCQIO %d satPendingNONNCQIO %d\n",pSatDevData, pSatDevData->satPendingNCQIO, pSatDevData->satPendingNONNCQIO)); pSatIntIo = satIOContext->satIntIoContext; /*smEnqueueIO(smRoot, satIOContext);*/ /* interal structure free */ smsatFreeIntIoResource( smRoot, pSatDevData, pSatIntIo); } return status; } osGLOBAL void smsatSetSensePayload( smScsiRspSense_t *pSense, bit8 SnsKey, bit32 SnsInfo, bit16 SnsCode, smSatIOContext_t *satIOContext) { /* for fixed format sense data, SPC-4, p37 */ bit32 i; bit32 senseLength; bit8 tmp = 0; SM_DBG2(("smsatSetSensePayload: start\n")); senseLength = sizeof(smScsiRspSense_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->pSmSenseData->senseLen = 18; } else { SM_DBG1(("smsatSetSensePayload: satIOContext is NULL!!!\n")); } /* Only for SCSI_SNSCODE_ATA_PASS_THROUGH_INFORMATION_AVAILABLE */ if (SnsCode == SCSI_SNSCODE_ATA_PASS_THROUGH_INFORMATION_AVAILABLE) { /* filling in COMMAND-SPECIFIC INFORMATION */ tmp = satIOContext->extend << 7 | satIOContext->Sector_Cnt_Upper_Nonzero << 6 | satIOContext->LBA_Upper_Nonzero << 5; SM_DBG3(("smsatSetSensePayload: extend 0x%x Sector_Cnt_Upper_Nonzero 0x%x LBA_Upper_Nonzero 0x%x\n", satIOContext->extend, satIOContext->Sector_Cnt_Upper_Nonzero, satIOContext->LBA_Upper_Nonzero)); SM_DBG3(("smsatSetSensePayload: tmp 0x%x\n", tmp)); pSense->cmdSpecific[0] = tmp; pSense->cmdSpecific[1] = satIOContext->LBAHigh07; pSense->cmdSpecific[2] = satIOContext->LBAMid07; pSense->cmdSpecific[3] = satIOContext->LBALow07; // smhexdump("smsatSetSensePayload: cmdSpecific",(bit8 *)pSense->cmdSpecific, 4); // smhexdump("smsatSetSensePayload: info",(bit8 *)pSense->info, 4); } return; } /***************************************************************************** *! \brief smsatDecodeSATADeviceType * * This routine decodes ATA signature * * \param pSignature: ATA signature * * * \return: * TRUE if ATA signature * FALSE otherwise * *****************************************************************************/ /* ATA p65 PM p65 SATAII p79, p80 */ GLOBAL bit32 smsatDecodeSATADeviceType( bit8 *pSignature ) { bit32 deviceType = UNKNOWN_DEVICE; if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x00 && (pSignature)[3] == 0x00 && (pSignature)[4] == 0xA0 ) /* this is the signature of a Hitachi SATA HDD*/ { deviceType = SATA_ATA_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x00 && (pSignature)[3] == 0x00 && (pSignature)[4] == 0x00 ) { deviceType = SATA_ATA_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x14 && (pSignature)[3] == 0xEB && ( (pSignature)[4] == 0x00 || (pSignature)[4] == 0x10) ) { deviceType = SATA_ATAPI_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x69 && (pSignature)[3] == 0x96 && (pSignature)[4] == 0x00 ) { deviceType = SATA_PM_DEVICE; } else if ( (pSignature)[0] == 0x01 && (pSignature)[1] == 0x01 && (pSignature)[2] == 0x3C && (pSignature)[3] == 0xC3 && (pSignature)[4] == 0x00 ) { deviceType = SATA_SEMB_DEVICE; } else if ( (pSignature)[0] == 0xFF && (pSignature)[1] == 0xFF && (pSignature)[2] == 0xFF && (pSignature)[3] == 0xFF && (pSignature)[4] == 0xFF ) { deviceType = SATA_SEMB_WO_SEP_DEVICE; } return deviceType; } /*****************************************************************************/ /*! \brief 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 smSatIOContext_t: Pointer to the SAT IO Context * * \return If command is started successfully * - \e smIOSuccess: I/O request successfully initiated. * - \e smIOBusy: No resources available, try again later. * - \e smIONoDevice: Invalid device handle. * - \e smIOError: Other errors. */ /*****************************************************************************/ osGLOBAL bit32 smsatPacket( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; smDeviceData_t *pSatDevData; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG3(("smsatPacket: 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 = (smScsiRequest->dataDirection == smDirectionIn)? 0x04 : 0; /* 1 for D2H, 0 for H2D */ } else { fis->h.features = 0; /* FIS reserve */ } if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /*DMA transfer mode*/ fis->h.features |= 0x01; } else { /*PIO transfer mode*/ fis->h.features |= 0x0; } /* Byte count low and byte count high */ if ( scsiCmnd->expDataLength > 0xFFFF ) { fis->d.lbaMid = 0xFF; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = 0xFF; /* FIS LBA (23:16) */ } else { fis->d.lbaMid = (bit8)scsiCmnd->expDataLength; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)(scsiCmnd->expDataLength>>8); /* FIS LBA (23:16) */ } 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 (smScsiRequest->dataDirection == smDirectionIn) { agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; } else { agRequestType = AGSA_SATA_PROTOCOL_H2D_PKT; } satIOContext->satCompleteCB = &smsatPacketCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG3(("smsatPacket: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for smsatSetFeaturePIO. * * This function creates Set Features 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 smSatIOContext_t: Pointer to the SAT IO Context * * \return If command is started successfully * - \e smIOSuccess: I/O request successfully initiated. * - \e smIOBusy: No resources available, try again later. * - \e smIONoDevice: Invalid device handle. * - \e smIOError: Other errors. */ /*****************************************************************************/ osGLOBAL bit32 smsatSetFeaturesPIO( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status = SM_RC_FAILURE; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG2(("smsatSetFeaturesPIO: 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. */ fis->d.sectorCount = 0x0C; /*enable PIO transfer mode */ satIOContext->satCompleteCB = &smsatSetFeaturesPIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG2(("smsatSetFeaturesPIO: return\n")); /* debugging code */ if (smIORequest->tdData == smIORequest->smData) { SM_DBG1(("smsatSetFeaturesPIO: incorrect smIORequest\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 smSatIOContext_t: Pointer to the SAT IO Context * * \return If command is started successfully * - \e smIOSuccess: I/O request successfully initiated. * - \e smIOBusy: No resources available, try again later. * - \e smIONoDevice: Invalid device handle. * - \e smIOError: Other errors. */ /*****************************************************************************/ osGLOBAL bit32 smsatRequestSenseForATAPI( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; smDeviceData_t *pSatDevData; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->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] = (bit8)scsiCmnd->expDataLength; scsiCmnd->cdb[5] = 0; SM_DBG3(("smsatRequestSenseForATAPI: 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 = (smScsiRequest->dataDirection == smDirectionIn)? 0x04 : 0; /* 1 for D2H, 0 for H2D */ } else { fis->h.features = 0; /* FIS reserve */ } if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { fis->h.features |= 0x01; } else { fis->h.features |= 0x0; } fis->d.lbaLow = 0; /* FIS LBA (7 :0 ) */ fis->d.lbaMid = (bit8)scsiCmnd->expDataLength; /* FIS LBA (15:8 ) */ fis->d.lbaHigh = (bit8)(scsiCmnd->expDataLength>>8); /* 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 = 0; satIOContext->ATACmd = SAT_PACKET; agRequestType = AGSA_SATA_PROTOCOL_D2H_PKT; satIOContext->satCompleteCB = &smsatRequestSenseForATAPICB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG3(("smsatRequestSenseForATAPI: return\n")); return (status); } /*****************************************************************************/ /*! \brief SAT implementation for smsatDeviceReset. * * This function creates DEVICE RESET fis and sends the request to LL layer * * \param smRoot: Pointer to TISA initiator driver/port instance. * \param smIORequest: Pointer to TISA I/O request context for this I/O. * \param smDeviceHandle: Pointer to TISA device handle for this I/O. * \param smScsiRequest: Pointer to TISA SCSI I/O request and SGL list. * \param smSatIOContext_t: Pointer to the SAT IO Context * * \return If command is started successfully * - \e smIOSuccess: I/O request successfully initiated. * - \e smIOBusy: No resources available, try again later. * - \e smIONoDevice: Invalid device handle. * - \e smIOError: Other errors. */ /*****************************************************************************/ osGLOBAL bit32 smsatDeviceReset( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG3(("smsatDeviceReset: 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; /* 0x08 */ 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 = &smsatDeviceResetCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG3(("smsatDeviceReset: return\n")); return status; } /*****************************************************************************/ /*! \brief SAT implementation for smsatExecuteDeviceDiagnostic. * * This function creates Execute Device Diagnostic fis and sends the request to LL layer * * \param smRoot: Pointer to TISA initiator driver/port instance. * \param smIORequest: Pointer to TISA I/O request context for this I/O. * \param smDeviceHandle: Pointer to TISA device handle for this I/O. * \param smScsiRequest: Pointer to TISA SCSI I/O request and SGL list. * \param smSatIOContext_t: Pointer to the SAT IO Context * * \return If command is started successfully * - \e smIOSuccess: I/O request successfully initiated. * - \e smIOBusy: No resources available, try again later. * - \e smIONoDevice: Invalid device handle. * - \e smIOError: Other errors. */ /*****************************************************************************/ osGLOBAL bit32 smsatExecuteDeviceDiagnostic( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG3(("smsatExecuteDeviceDiagnostic: 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 = &smsatExecuteDeviceDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG3(("smsatExecuteDeviceDiagnostic: return\n")); return status; } osGLOBAL void smsatSetDeferredSensePayload( smScsiRspSense_t *pSense, bit8 SnsKey, bit32 SnsInfo, bit16 SnsCode, smSatIOContext_t *satIOContext ) { SM_DBG2(("smsatSetDeferredSensePayload: start\n")); return; } GLOBAL bit32 smsatRead6( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit16 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG2(("smsatRead6: 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) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead6: return control!!!\n")); return SM_RC_SUCCESS; } /* 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) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead6: return LBA out of range!!!\n")); return SM_RC_SUCCESS; } } /* case 1 and 2 */ if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* READ DMA*/ SM_DBG5(("smsatRead6: 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 */ SM_DBG5(("smsatRead6: 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 */ SM_DBG5(("smsatRead6: 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 */ SM_DBG5(("smsatRead6: 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 */ SM_DBG1(("smsatRead6: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG5(("smsatRead6: 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 = &smsatNonChainedDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL FORCEINLINE bit32 smsatRead10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smDeviceData_t *pSatDevData = satIOContext->pSatDevData; smScsiRspSense_t *pSense = satIOContext->pSense; smIniScsiCmnd_t *scsiCmnd = &smScsiRequest->scsiCmnd; agsaFisRegHostToDevice_t *fis = satIOContext->pFis; bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ SM_DBG2(("smsatRead10: start\n")); SM_DBG2(("smsatRead10: pSatDevData did=%d\n", pSatDevData->id)); // smhexdump("smsatRead10", (bit8 *)scsiCmnd->cdb, 10); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead10: return FUA_NV!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead10: return control!!!\n")); return SM_RC_SUCCESS; } /* sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); */ /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = 0; TL[5] = 0; TL[6] = scsiCmnd->cdb[7]; TL[7] = scsiCmnd->cdb[8]; /* LSB */ /* cbd10; computing LBA and transfer length */ lba = (scsiCmnd->cdb[2] << 24) + (scsiCmnd->cdb[3] << 16) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; tl = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; SM_DBG5(("smsatRead10: lba %d functioned lba %d\n", lba, smsatComputeCDB10LBA(satIOContext))); SM_DBG5(("smsatRead10: lba 0x%x functioned lba 0x%x\n", lba, smsatComputeCDB10LBA(satIOContext))); SM_DBG5(("smsatRead10: tl %d functioned tl %d\n", tl, smsatComputeCDB10TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatRead10: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatRead10: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* READ FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { SM_DBG1(("smsatRead10: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatRead10: 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; } else if (pSatDevData->sat48BitSupport == agTRUE) /* case 3 and 4 */ { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* READ DMA EXT */ SM_DBG5(("smsatRead10: 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 */ SM_DBG5(("smsatRead10: 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 */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } 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; } } else/* case 1 and 2 */ { 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 */ SM_DBG5(("smsatRead10: 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 */ SM_DBG5(("smsatRead10: 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; } } // smhexdump("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 = smsatComputeLoopNum(tl, 0x100); } else { /* SAT_READ_FPDMA_QUEUED */ /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; /* Initialize CB for SATA completion. */ if (LoopNum == 1) { SM_DBG5(("smsatRead10: NON CHAINED data\n")); satIOContext->satCompleteCB = &smsatNonChainedDataIOCB; } else { SM_DBG2(("smsatRead10: CHAINED data!!!\n")); /* re-setting tl */ if (fis->h.command == SAT_READ_SECTORS || fis->h.command == SAT_READ_DMA) { fis->d.sectorCount = 0x0; smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, NON_BIT48_ADDRESS_TL_LIMIT*SATA_SECTOR_SIZE, /* 0x100 * 0x200 */ (satIOContext->OrgTL)*SATA_SECTOR_SIZE, agTRUE); } 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; smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, BIT48_ADDRESS_TL_LIMIT*SATA_SECTOR_SIZE, /* 0xFFFF * 0x200 */ (satIOContext->OrgTL)*SATA_SECTOR_SIZE, agTRUE); } else { /* SAT_READ_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, BIT48_ADDRESS_TL_LIMIT*SATA_SECTOR_SIZE, /* 0xFFFF * 0x200 */ (satIOContext->OrgTL)*SATA_SECTOR_SIZE, agTRUE); } /* chained data */ satIOContext->satCompleteCB = &smsatChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatRead10: return\n")); return (status); } osGLOBAL bit32 smsatRead12( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatRead12: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead12: return FUA_NV!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead12: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; /* MSB */ TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[6]; TL[5] = scsiCmnd->cdb[7]; TL[6] = scsiCmnd->cdb[8]; TL[7] = scsiCmnd->cdb[9]; /* LSB */ lba = smsatComputeCDB12LBA(satIOContext); tl = smsatComputeCDB12TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatRead12: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatRead12: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 1 and 2 */ 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 */ SM_DBG5(("smsatRead12: 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*/ SM_DBG5(("smsatRead12: 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 */ SM_DBG5(("smsatRead12: 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 */ SM_DBG5(("smsatRead12: 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 */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } 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) { SM_DBG1(("smsatRead12: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatRead12: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_READ_FPDMA_QUEUEDK */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatRead12: NON CHAINED data\n")); satIOContext->satCompleteCB = &smsatNonChainedDataIOCB; } else { SM_DBG1(("smsatRead12: 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 = &smsatChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatRead12: return\n")); return (status); } osGLOBAL bit32 smsatRead16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_READ; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ // bit32 limitExtChk = agFALSE; /* lba limit check for bit48 addressing check */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatRead16: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead16: return FUA_NV!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRead16: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_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 */ lba = smsatComputeCDB16LBA(satIOContext); tl = smsatComputeCDB16TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatRead16: return LBA out of range, not EXT!!!\n")); /*smEnqueueIO(smRoot, satIOContext);*/ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { // rangeChk = smsatAddNComparebit64(LBA, TL); AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatRead16: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 1 and 2 */ 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 */ SM_DBG5(("smsatRead16: 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*/ SM_DBG5(("smsatRead16: 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 */ SM_DBG5(("smsatRead16: 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 */ SM_DBG5(("smsatRead16: 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 */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } 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) { SM_DBG1(("smsatRead16: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatRead16: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_READ_FPDMA_QUEUEDK */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatRead16: NON CHAINED data\n")); satIOContext->satCompleteCB = &smsatNonChainedDataIOCB; } else { SM_DBG1(("smsatRead16: 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 = &smsatChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatRead16: return\n")); return (status); } osGLOBAL bit32 smsatWrite6( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit16 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWrite6: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite6: return control!!!\n")); return SM_RC_SUCCESS; } /* 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) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite6: return LBA out of range!!!\n")); return SM_RC_SUCCESS; } } /* case 1 and 2 */ if (lba + tl <= SAT_TR_LBA_LIMIT) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ SM_DBG5(("smsatWrite6: 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 */ SM_DBG5(("smsatWrite6: 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 */ SM_DBG5(("smsatWrite6: 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 */ SM_DBG5(("smsatWrite6: 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 */ SM_DBG5(("smsatWrite6: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG5(("smsatWrite6: 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 = &smsatNonChainedDataIOCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL FORCEINLINE bit32 smsatWrite10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smDeviceData_t *pSatDevData = satIOContext->pSatDevData; smScsiRspSense_t *pSense = satIOContext->pSense; smIniScsiCmnd_t *scsiCmnd = &smScsiRequest->scsiCmnd; agsaFisRegHostToDevice_t *fis = satIOContext->pFis; bit32 status = SM_RC_FAILURE; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ bit8 LBA[8]; bit8 TL[8]; SM_DBG2(("smsatWrite10: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite10: return FUA_NV!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite10: return control!!!\n")); return SM_RC_SUCCESS; } /* sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); */ /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = 0; TL[5] = 0; TL[6] = scsiCmnd->cdb[7]; TL[7] = scsiCmnd->cdb[8]; /* LSB */ /* cbd10; computing LBA and transfer length */ lba = (scsiCmnd->cdb[2] << (24)) + (scsiCmnd->cdb[3] << (16)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; tl = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; SM_DBG5(("smsatWrite10: lba %d functioned lba %d\n", lba, smsatComputeCDB10LBA(satIOContext))); SM_DBG5(("smsatWrite10: tl %d functioned tl %d\n", tl, smsatComputeCDB10TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWrite10: return LBA out of range, not EXT!!!\n")); SM_DBG1(("smsatWrite10: cdb 0x%x 0x%x 0x%x 0x%x!!!\n",scsiCmnd->cdb[2], scsiCmnd->cdb[3], scsiCmnd->cdb[4], scsiCmnd->cdb[5])); SM_DBG1(("smsatWrite10: lba 0x%x SAT_TR_LBA_LIMIT 0x%x!!!\n", lba, SAT_TR_LBA_LIMIT)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWrite10: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 5 */ if (pSatDevData->satNCQ == agTRUE) { /* WRITE FPDMA QUEUED */ if (pSatDevData->sat48BitSupport != agTRUE) { SM_DBG1(("smsatWrite10: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatWrite10: 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; } /* case 3 and 4 */ else if (pSatDevData->sat48BitSupport == agTRUE) { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 3 */ /* WRITE DMA EXT or WRITE DMA FUA EXT */ SM_DBG5(("smsatWrite10: 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 */ SM_DBG5(("smsatWrite10: 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; } } else /* case 1 and 2 */ { if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ SM_DBG5(("smsatWrite10: 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 */ SM_DBG5(("smsatWrite10: 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; } } // smhexdump("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 = smsatComputeLoopNum(tl, 0x100); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatWrite10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedDataIOCB; } else { SM_DBG2(("smsatWrite10: CHAINED data!!!\n")); /* re-setting tl */ if (fis->h.command == SAT_WRITE_SECTORS || fis->h.command == SAT_WRITE_DMA) { fis->d.sectorCount = 0x0; smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, NON_BIT48_ADDRESS_TL_LIMIT*SATA_SECTOR_SIZE, /* 0x100 * 0x200 */ (satIOContext->OrgTL)*SATA_SECTOR_SIZE, agTRUE); } 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; smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, BIT48_ADDRESS_TL_LIMIT*SATA_SECTOR_SIZE, /* 0xFFFF * 0x200 */ (satIOContext->OrgTL)*SATA_SECTOR_SIZE, agTRUE); } else { /* SAT_WRITE_FPDMA_QUEUED */ fis->h.features = 0xFF; fis->d.featuresExp = 0xFF; smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, BIT48_ADDRESS_TL_LIMIT*SATA_SECTOR_SIZE, /* 0xFFFF * 0x200 */ (satIOContext->OrgTL)*SATA_SECTOR_SIZE, agTRUE); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatWrite12( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWrite12: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite12: return FUA_NV!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite10: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; /* MSB */ TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[6]; TL[5] = scsiCmnd->cdb[7]; TL[6] = scsiCmnd->cdb[8]; TL[7] = scsiCmnd->cdb[9]; /* LSB */ lba = smsatComputeCDB12LBA(satIOContext); tl = smsatComputeCDB12TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); /*smEnqueueIO(smRoot, satIOContext);*/ if (AllChk) { SM_DBG1(("smsatWrite12: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWrite12: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ SM_DBG5(("smsatWrite10: 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 */ SM_DBG5(("smsatWrite10: 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 */ SM_DBG5(("smsatWrite10: 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 */ SM_DBG5(("smsatWrite10: 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) { SM_DBG5(("smsatWrite10: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatWrite10: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatWrite10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedDataIOCB; } else { SM_DBG1(("smsatWrite10: 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 = &smsatChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatWrite16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWrite16: start\n")); /* checking FUA_NV */ if (scsiCmnd->cdb[1] & SCSI_FUA_NV_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite16: return FUA_NV!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWrite16: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_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 */ lba = smsatComputeCDB16LBA(satIOContext); tl = smsatComputeCDB16TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWrite16: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWrite16: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 1 and 2 */ if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ SM_DBG5(("smsatWrite16: 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 */ SM_DBG5(("smsatWrite16: 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 */ SM_DBG5(("smsatWrite16: 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 */ SM_DBG5(("smsatWrite16: 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) { SM_DBG5(("smsatWrite16: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatWrite16: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatWrite16: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedDataIOCB; } else { SM_DBG1(("smsatWrite16: 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 = &smsatChainedDataIOCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatVerify10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* For simple implementation, no byte comparison supported as of 4/5/06 */ smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; smDeviceData_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 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG5(("smsatVerify10: start\n")); /* checking BYTCHK */ if (scsiCmnd->cdb[1] & SCSI_VERIFY_BYTCHK_MASK) { /* should do the byte check but not supported in this version */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatVerify10: no byte checking!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatVerify10: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = 0; TL[5] = 0; TL[6] = scsiCmnd->cdb[7]; TL[7] = scsiCmnd->cdb[8]; /* LSB */ /* 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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatVerify10: return LBA out of range, not EXT!!!\n")); SM_DBG1(("smsatVerify10: cdb 0x%x 0x%x 0x%x 0x%x!!!\n",scsiCmnd->cdb[2], scsiCmnd->cdb[3], scsiCmnd->cdb[4], scsiCmnd->cdb[5])); SM_DBG1(("smsatVerify10: lba 0x%x SAT_TR_LBA_LIMIT 0x%x!!!\n", lba, SAT_TR_LBA_LIMIT)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatVerify10: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } if (pSatDevData->sat48BitSupport == agTRUE) { SM_DBG5(("smsatVerify10: 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 { SM_DBG5(("smsatVerify10: 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 = smsatComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } else { SM_DBG1(("smsatVerify10: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatVerify10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedVerifyCB; } else { SM_DBG1(("smsatVerify10: 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 { SM_DBG1(("smsatVerify10: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatChainedVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatVerify12( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* For simple implementation, no byte comparison supported as of 4/5/06 */ smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; smDeviceData_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 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG5(("smsatVerify12: start\n")); /* checking BYTCHK */ if (scsiCmnd->cdb[1] & SCSI_VERIFY_BYTCHK_MASK) { /* should do the byte check but not supported in this version */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatVerify12: no byte checking!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatVerify12: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; /* MSB */ TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[6]; TL[5] = scsiCmnd->cdb[7]; TL[6] = scsiCmnd->cdb[8]; TL[7] = scsiCmnd->cdb[9]; /* LSB */ lba = smsatComputeCDB12LBA(satIOContext); tl = smsatComputeCDB12TL(satIOContext); if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatVerify12: return LBA out of range, not EXT!!!\n")); SM_DBG1(("smsatVerify12: cdb 0x%x 0x%x 0x%x 0x%x!!!\n",scsiCmnd->cdb[2], scsiCmnd->cdb[3], scsiCmnd->cdb[4], scsiCmnd->cdb[5])); SM_DBG1(("smsatVerify12: lba 0x%x SAT_TR_LBA_LIMIT 0x%x!!!\n", lba, SAT_TR_LBA_LIMIT)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatVerify12: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } if (pSatDevData->sat48BitSupport == agTRUE) { SM_DBG5(("smsatVerify12: 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 { SM_DBG5(("smsatVerify12: 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 = smsatComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } else { SM_DBG1(("smsatVerify12: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatVerify12: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedVerifyCB; } else { SM_DBG1(("smsatVerify12: 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 { SM_DBG1(("smsatVerify12: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatChainedVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatVerify16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* For simple implementation, no byte comparison supported as of 4/5/06 */ smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; smDeviceData_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 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG5(("smsatVerify16: start\n")); /* checking BYTCHK */ if (scsiCmnd->cdb[1] & SCSI_VERIFY_BYTCHK_MASK) { /* should do the byte check but not supported in this version */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatVerify16: no byte checking!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatVerify16: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_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 */ lba = smsatComputeCDB16LBA(satIOContext); tl = smsatComputeCDB16TL(satIOContext); if (pSatDevData->satNCQ != agTRUE && pSatDevData->sat48BitSupport != agTRUE ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatVerify16: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatVerify16: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } if (pSatDevData->sat48BitSupport == agTRUE) { SM_DBG5(("smsatVerify16: 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 { SM_DBG5(("smsatVerify16: 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 = smsatComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } else { SM_DBG1(("smsatVerify16: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatVerify16: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedVerifyCB; } else { SM_DBG1(("smsatVerify16: 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 { SM_DBG1(("smsatVerify16: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatChainedVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatTestUnitReady( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatTestUnitReady: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatTestUnitReady: return control!!!\n")); return SM_RC_SUCCESS; } /* SAT revision 8, 8.11.2, p42*/ if (pSatDevData->satStopState == agTRUE) { smsatSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_INITIALIZING_COMMAND_REQUIRED, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatTestUnitReady: stop state!!!\n")); return SM_RC_SUCCESS; } /* * Check if format is in progress */ if (pSatDevData->satDriveState == SAT_DEV_STATE_FORMAT_IN_PROGRESS) { SM_DBG1(("smsatTestUnitReady: FORMAT_IN_PROGRESS!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_NOT_READY, 0, SCSI_SNSCODE_LOGICAL_UNIT_NOT_READY_FORMAT_IN_PROGRESS, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatTestUnitReady: format in progress!!!\n")); return SM_RC_SUCCESS; } /* check previously issued ATA command */ if (pSatDevData->satPendingIO != 0) { if (pSatDevData->satDeviceFaultState == agTRUE) { smsatSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_LOGICAL_UNIT_FAILURE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatTestUnitReady: previous command ended in error!!!\n")); return SM_RC_SUCCESS; } } /* check removalbe media feature set */ if(pSatDevData->satRemovableMedia && pSatDevData->satRemovableMediaEnabled) { SM_DBG5(("smsatTestUnitReady: 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 = &smsatTestUnitReadyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } /* number 6) in SAT p42 send ATA CHECK POWER MODE */ SM_DBG5(("smsatTestUnitReady: sending check power mode cmnd\n")); status = smsatTestUnitReady_1( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatTestUnitReady_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; SM_DBG5(("smsatTestUnitReady_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 = &smsatTestUnitReadyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatTestUnitReady_1: return\n")); return status; } osGLOBAL bit32 smsatInquiry( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* CMDDT bit is obsolete in SPC-3 and this is assumed in SAT revision 8 */ smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; smDeviceData_t *pSatDevData; bit32 status; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; SM_DBG5(("smsatInquiry: start\n")); SM_DBG5(("smsatInquiry: pSatDevData did %d\n", pSatDevData->id)); //smhexdump("smsatInquiry", (bit8 *)scsiCmnd->cdb, 6); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatInquiry: return control!!!\n")); return SM_RC_SUCCESS; } /* 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) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatInquiry: return EVPD and PAGE CODE!!!\n")); return SM_RC_SUCCESS; } SM_DBG6(("smsatInquiry: 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 = smsatStartIDDev( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext ); SM_DBG6(("smsatInquiry: end status %d\n", status)); return status; } else { SM_DBG6(("smsatInquiry: calling satInquiryIntCB\n")); smsatInquiryIntCB( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext ); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatStartIDDev( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smSatInternalIo_t *satIntIo = agNULL; smDeviceData_t *satDevData = agNULL; smIORequestBody_t *smIORequestBody; smSatIOContext_t *satNewIOContext; bit32 status; SM_DBG5(("smsatStartIDDev: start\n")); satDevData = satIOContext->pSatDevData; SM_DBG6(("smsatStartIDDev: before alloc\n")); /* allocate identify device command */ satIntIo = smsatAllocIntIoResource( smRoot, smIORequest, satDevData, sizeof(agsaSATAIdentifyData_t), /* 512; size of identify device data */ satIntIo); SM_DBG6(("smsatStartIDDev: before after\n")); if (satIntIo == agNULL) { SM_DBG1(("smsatStartIDDev: can't alloacate!!!\n")); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } satIntIo->satOrgSmIORequest = smIORequest; /* changed */ smIORequestBody = satIntIo->satIntRequestBody; satNewIOContext = &(smIORequestBody->transport.SATA.satIOContext); satNewIOContext->pSatDevData = satDevData; satNewIOContext->pFis = &(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satNewIOContext->pScsiCmnd = &(satIntIo->satIntSmScsiXchg.scsiCmnd); satNewIOContext->pSense = &(smIORequestBody->transport.SATA.sensePayload); satNewIOContext->pSmSenseData = &(smIORequestBody->transport.SATA.smSenseData); satNewIOContext->smRequestBody = satIntIo->satIntRequestBody; /* key fix */ satNewIOContext->interruptContext = tiInterruptContext; satNewIOContext->satIntIoContext = satIntIo; satNewIOContext->psmDeviceHandle = agNULL; satNewIOContext->satOrgIOContext = satIOContext; /* changed */ /* this is valid only for TD layer generated (not triggered by OS at all) IO */ satNewIOContext->smScsiXchg = &(satIntIo->satIntSmScsiXchg); SM_DBG6(("smsatStartIDDev: OS satIOContext %p \n", satIOContext)); SM_DBG6(("smsatStartIDDev: TD satNewIOContext %p \n", satNewIOContext)); SM_DBG6(("smsatStartIDDev: OS tiScsiXchg %p \n", satIOContext->smScsiXchg)); SM_DBG6(("smsatStartIDDev: TD tiScsiXchg %p \n", satNewIOContext->smScsiXchg)); SM_DBG1(("smsatStartIDDev: satNewIOContext %p smIORequestBody %p!!!\n", satNewIOContext, smIORequestBody)); status = smsatSendIDDev( smRoot, &satIntIo->satIntSmIORequest, /* New smIORequest */ smDeviceHandle, satNewIOContext->smScsiXchg, /* New tiScsiInitiatorRequest_t *tiScsiRequest, */ satNewIOContext); if (status != SM_RC_SUCCESS) { SM_DBG1(("smsatStartIDDev: failed in sending!!!\n")); smsatFreeIntIoResource( smRoot, satDevData, satIntIo); /*smEnqueueIO(smRoot, satIOContext);*/ return SM_RC_FAILURE; } SM_DBG6(("smsatStartIDDev: end\n")); return status; } osGLOBAL bit32 smsatSendIDDev( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; #ifdef SM_INTERNAL_DEBUG smIORequestBody_t *smIORequestBody; smSatInternalIo_t *satIntIoContext; #endif pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG6(("smsatSendIDDev: start\n")); SM_DBG6(("smsatSendIDDev: did %d\n", pSatDevData->id)); #ifdef SM_INTERNAL_DEBUG satIntIoContext = satIOContext->satIntIoContext; smIORequestBody = satIntIoContext->satIntRequestBody; #endif 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 = &smsatInquiryCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef SM_INTERNAL_DEBUG smhexdump("smsatSendIDDev", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); smhexdump("smsatSendIDDev LL", (bit8 *)&(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG6(("smsatSendIDDev: end status %d\n", status)); return status; } osGLOBAL bit32 smsatRequestSense( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; smScsiRspSense_t *pSense; smDeviceData_t *pSatDevData; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; smIORequestBody_t *smIORequestBody; smSatInternalIo_t *satIntIo = agNULL; smSatIOContext_t *satIOContext2; bit8 *pDataBuffer = agNULL; bit32 allocationLen = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pDataBuffer = (bit8 *) smScsiRequest->sglVirtualAddr; allocationLen = scsiCmnd->cdb[4]; allocationLen = MIN(allocationLen, scsiCmnd->expDataLength); SM_DBG5(("smsatRequestSense: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); sm_memcpy(pDataBuffer, pSense, MIN(SENSE_DATA_LENGTH, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRequestSense: return control!!!\n")); return SM_RC_SUCCESS; } /* 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 ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); sm_memcpy(pDataBuffer, pSense, MIN(SENSE_DATA_LENGTH, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatRequestSense: DESC bit is set, which we don't support!!!\n")); return SM_RC_SUCCESS; } 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; /* 0xB0 */ fis->h.features = SAT_SMART_RETURN_STATUS; /* 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 = &smsatRequestSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG4(("smsatRequestSense: if return, status %d\n", status)); return (status); } else { /*allocate iocontext for xmitting xmit SAT_CHECK_POWER_MODE then call satRequestSense2 */ SM_DBG4(("smsatRequestSense: before satIntIo %p\n", satIntIo)); /* allocate iocontext */ satIntIo = smsatAllocIntIoResource( smRoot, smIORequest, /* original request */ pSatDevData, smScsiRequest->scsiCmnd.expDataLength, satIntIo); SM_DBG4(("smsatRequestSense: after satIntIo %p\n", satIntIo)); if (satIntIo == agNULL) { /* failed during sending SMART RETURN STATUS */ smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satIOContext); sm_memcpy(pDataBuffer, pSense, MIN(SENSE_DATA_LENGTH, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); SM_DBG1(("smsatRequestSense: else fail 1!!!\n")); return SM_RC_SUCCESS; } /* 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) { SM_DBG4(("smsatRequestSense: satIntIo is NULL\n")); } else { SM_DBG4(("smsatRequestSense: satIntIo is NOT NULL\n")); } /* use this --- tttttthe one the same */ satIntIo->satOrgSmIORequest = smIORequest; smIORequestBody = (smIORequestBody_t *)satIntIo->satIntRequestBody; satIOContext2 = &(smIORequestBody->transport.SATA.satIOContext); satIOContext2->pSatDevData = pSatDevData; satIOContext2->pFis = &(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext2->pScsiCmnd = &(satIntIo->satIntSmScsiXchg.scsiCmnd); satIOContext2->pSense = &(smIORequestBody->transport.SATA.sensePayload); satIOContext2->pSmSenseData = &(smIORequestBody->transport.SATA.smSenseData); satIOContext2->pSmSenseData->senseData = satIOContext2->pSense; satIOContext2->smRequestBody = satIntIo->satIntRequestBody; satIOContext2->interruptContext = satIOContext->interruptContext; satIOContext2->satIntIoContext = satIntIo; satIOContext2->psmDeviceHandle = smDeviceHandle; satIOContext2->satOrgIOContext = satIOContext; SM_DBG4(("smsatRequestSense: satIntIo->satIntSmScsiXchg.agSgl1.len %d\n", satIntIo->satIntSmScsiXchg.smSgl1.len)); SM_DBG4(("smsatRequestSense: satIntIo->satIntSmScsiXchg.agSgl1.upper %d\n", satIntIo->satIntSmScsiXchg.smSgl1.upper)); SM_DBG4(("smsatRequestSense: satIntIo->satIntSmScsiXchg.agSgl1.lower %d\n", satIntIo->satIntSmScsiXchg.smSgl1.lower)); SM_DBG4(("smsatRequestSense: satIntIo->satIntSmScsiXchg.agSgl1.type %d\n", satIntIo->satIntSmScsiXchg.smSgl1.type)); status = smsatRequestSense_1( smRoot, &(satIntIo->satIntSmIORequest), smDeviceHandle, &(satIntIo->satIntSmScsiXchg), satIOContext2); if (status != SM_RC_SUCCESS) { smsatFreeIntIoResource( smRoot, pSatDevData, satIntIo); /* failed during sending SMART RETURN STATUS */ smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_HARDWARE_IMPENDING_FAILURE, satIOContext); sm_memcpy(pDataBuffer, pSense, MIN(SENSE_DATA_LENGTH, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, agNULL, satIOContext->interruptContext ); SM_DBG1(("smsatRequestSense: else fail 2!!!\n")); return SM_RC_SUCCESS; } SM_DBG4(("smsatRequestSense: else return success\n")); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatRequestSense_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* sends SAT_CHECK_POWER_MODE */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG5(("smsatRequestSense_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 = &smsatRequestSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ SM_DBG4(("smsatRequestSense_1: smSgl1.len %d\n", smScsiRequest->smSgl1.len)); SM_DBG4(("smsatRequestSense_1: smSgl1.upper %d\n", smScsiRequest->smSgl1.upper)); SM_DBG4(("smsatRequestSense_1: smSgl1.lower %d\n", smScsiRequest->smSgl1.lower)); SM_DBG4(("smsatRequestSense_1: smSgl1.type %d\n", smScsiRequest->smSgl1.type)); // smhexdump("smsatRequestSense_1", (bit8 *)fis, sizeof(agsaFisRegHostToDevice_t)); status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatModeSense6( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; bit32 allocationLen; smIniScsiCmnd_t *scsiCmnd; bit32 pageSupported; bit8 page; bit8 *pModeSense; /* Mode Sense data buffer */ smDeviceData_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; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pModeSense = (bit8 *) smScsiRequest->sglVirtualAddr; pSatDevData = satIOContext->pSatDevData; //smhexdump("smsatModeSense6", (bit8 *)scsiCmnd->cdb, 6); SM_DBG5(("smsatModeSense6: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSense6: return control!!!\n")); return SM_RC_SUCCESS; } /* 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) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSense6: return due to PC value pc 0x%x!!!\n", PC >> 6)); return SM_RC_SUCCESS; } /* reading PAGE CODE */ page = (bit8)((scsiCmnd->cdb[2]) & SCSI_MODE_SENSE6_PAGE_CODE_MASK); SM_DBG5(("smsatModeSense6: page=0x%x\n", page)); allocationLen = scsiCmnd->cdb[4]; allocationLen = MIN(allocationLen, scsiCmnd->expDataLength); /* 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) { SM_DBG1(("smsatModeSense6 *** ERROR *** not supported page 0x%x did %d!!!\n", page, pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } switch(page) { case MODESENSE_RETURN_ALL_PAGES: lenRead = (bit8)MIN(allocationLen, MODE_SENSE6_RETURN_ALL_PAGES_LEN); break; case MODESENSE_CONTROL_PAGE: /* control */ lenRead = (bit8)MIN(allocationLen, MODE_SENSE6_CONTROL_PAGE_LEN); break; case MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE: /* Read-Write Error Recovery */ lenRead = (bit8)MIN(allocationLen, MODE_SENSE6_READ_WRITE_ERROR_RECOVERY_PAGE_LEN); break; case MODESENSE_CACHING: /* caching */ lenRead = (bit8)MIN(allocationLen, MODE_SENSE6_CACHING_LEN); break; case MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE: /* informational exceptions control*/ lenRead = (bit8)MIN(allocationLen, MODE_SENSE6_INFORMATION_EXCEPTION_CONTROL_PAGE_LEN); break; default: SM_DBG1(("smsatModeSense6: default error page %d!!!\n", page)); break; } if (page == MODESENSE_RETURN_ALL_PAGES) { SM_DBG5(("smsatModeSense6: 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 */ if (pSatDevData->satWriteCacheEnabled == agTRUE) { AllPages[26] = 0x04;/* WCE bit is set */ } else { 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; sm_memcpy(pModeSense, &AllPages, lenRead); } else if (page == MODESENSE_CONTROL_PAGE) { SM_DBG5(("smsatModeSense6: 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 */ sm_memcpy(pModeSense, &Control, lenRead); } else if (page == MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE) { SM_DBG5(("smsatModeSense6: 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; sm_memcpy(pModeSense, &RWErrorRecovery, lenRead); } else if (page == MODESENSE_CACHING) { SM_DBG5(("smsatModeSense6: MODESENSE_CACHING\n")); /* special case */ if (allocationLen == 4 && page == MODESENSE_CACHING) { SM_DBG5(("smsatModeSense6: linux 2.6.8.24 support\n")); Caching[0] = 0x20 - 1; /* 32 - 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 */ sm_memcpy(pModeSense, &Caching, 4); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } 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 */ if (pSatDevData->satWriteCacheEnabled == agTRUE) { Caching[14] = 0x04;/* WCE bit is set */ } else { 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; sm_memcpy(pModeSense, &Caching, lenRead); } else if (page == MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE) { SM_DBG5(("smsatModeSense6: 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; sm_memcpy(pModeSense, &InfoExceptionCtrl, lenRead); } else { /* Error */ SM_DBG1(("smsatModeSense6: Error page %d!!!\n", page)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* there can be only underrun not overrun in error case */ if (allocationLen > lenRead) { SM_DBG6(("smsatModeSense6 reporting underrun lenRead=0x%x allocationLen=0x%x\n", lenRead, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOUnderRun, allocationLen - lenRead, agNULL, satIOContext->interruptContext ); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return SM_RC_SUCCESS; } osGLOBAL bit32 smsatModeSense10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; bit32 allocationLen; smIniScsiCmnd_t *scsiCmnd; bit32 pageSupported; bit8 page; bit8 *pModeSense; /* Mode Sense data buffer */ smDeviceData_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; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pModeSense = (bit8 *) smScsiRequest->sglVirtualAddr; pSatDevData = satIOContext->pSatDevData; SM_DBG5(("smsatModeSense10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSense10: return control!!!\n")); return SM_RC_SUCCESS; } /* 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) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSense10: return due to PC value pc 0x%x!!!\n", PC)); return SM_RC_SUCCESS; } /* 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); SM_DBG5(("smsatModeSense10: page=0x%x, did %d\n", page, pSatDevData->id)); allocationLen = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; allocationLen = MIN(allocationLen, scsiCmnd->expDataLength); /* 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) { SM_DBG1(("smsatModeSense10 *** ERROR *** not supported page 0x%x did %d!!!\n", page, pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } switch(page) { case MODESENSE_RETURN_ALL_PAGES: if (LLBAA) { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_RETURN_ALL_PAGES_LLBAA_LEN); } else { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_RETURN_ALL_PAGES_LEN); } break; case MODESENSE_CONTROL_PAGE: /* control */ if (LLBAA) { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_CONTROL_PAGE_LLBAA_LEN); } else { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_CONTROL_PAGE_LEN); } break; case MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE: /* Read-Write Error Recovery */ if (LLBAA) { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_READ_WRITE_ERROR_RECOVERY_PAGE_LLBAA_LEN); } else { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_READ_WRITE_ERROR_RECOVERY_PAGE_LEN); } break; case MODESENSE_CACHING: /* caching */ if (LLBAA) { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_CACHING_LLBAA_LEN); } else { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_CACHING_LEN); } break; case MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE: /* informational exceptions control*/ if (LLBAA) { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_INFORMATION_EXCEPTION_CONTROL_PAGE_LLBAA_LEN); } else { lenRead = (bit8)MIN(allocationLen, MODE_SENSE10_INFORMATION_EXCEPTION_CONTROL_PAGE_LEN); } break; default: SM_DBG1(("smsatModeSense10: default error page %d!!!\n", page)); break; } if (page == MODESENSE_RETURN_ALL_PAGES) { SM_DBG5(("smsatModeSense10: 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 */ if (pSatDevData->satWriteCacheEnabled == agTRUE) { AllPages[index+14] = 0x04;/* WCE bit is set */ } else { 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; sm_memcpy(pModeSense, &AllPages, lenRead); } else if (page == MODESENSE_CONTROL_PAGE) { SM_DBG5(("smsatModeSense10: 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 */ sm_memcpy(pModeSense, &Control, lenRead); } else if (page == MODESENSE_READ_WRITE_ERROR_RECOVERY_PAGE) { SM_DBG5(("smsatModeSense10: 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; sm_memcpy(pModeSense, &RWErrorRecovery, lenRead); } else if (page == MODESENSE_CACHING) { SM_DBG5(("smsatModeSense10: 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 */ if (pSatDevData->satWriteCacheEnabled == agTRUE) { Caching[index+2] = 0x04;/* WCE bit is set */ } else { 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; sm_memcpy(pModeSense, &Caching, lenRead); } else if (page == MODESENSE_INFORMATION_EXCEPTION_CONTROL_PAGE) { SM_DBG5(("smsatModeSense10: 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; sm_memcpy(pModeSense, &InfoExceptionCtrl, lenRead); } else { /* Error */ SM_DBG1(("smsatModeSense10: Error page %d!!!\n", page)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } if (allocationLen > lenRead) { SM_DBG1(("smsatModeSense10: reporting underrun lenRead=0x%x allocationLen=0x%x smIORequest=%p\n", lenRead, allocationLen, smIORequest)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOUnderRun, allocationLen - lenRead, agNULL, satIOContext->interruptContext ); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return SM_RC_SUCCESS; } osGLOBAL bit32 smsatReadCapacity10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; bit8 dataBuffer[8] = {0}; bit32 allocationLen; bit8 *pVirtAddr = agNULL; smDeviceData_t *pSatDevData; agsaSATAIdentifyData_t *pSATAIdData; bit32 lastLba; bit32 word117_118; bit32 word117; bit32 word118; pSense = satIOContext->pSense; pVirtAddr = (bit8 *) smScsiRequest->sglVirtualAddr; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; pSATAIdData = &pSatDevData->satIdentifyData; allocationLen = scsiCmnd->expDataLength; SM_DBG5(("smsatReadCapacity10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadCapacity10: return control!!!\n")); return SM_RC_SUCCESS; } /* * If Logical block address is not set to zero, return error */ if ((scsiCmnd->cdb[2] || scsiCmnd->cdb[3] || scsiCmnd->cdb[4] || scsiCmnd->cdb[5])) { SM_DBG1(("smsatReadCapacity10: *** ERROR *** logical address non zero, did %d!!!\n", pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* * If PMI bit is not zero, return error */ if ( ((scsiCmnd->cdb[8]) & SCSI_READ_CAPACITY10_PMI_MASK) != 0 ) { SM_DBG1(("smsatReadCapacity10: *** ERROR *** PMI is not zero, did %d\n", pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* 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)) { dataBuffer[0] = 0xFF; /* MSB number of block */ dataBuffer[1] = 0xFF; dataBuffer[2] = 0xFF; dataBuffer[3] = 0xFF; /* LSB number of block */ SM_DBG1(("smsatReadCapacity10: 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; */ dataBuffer[0] = (bit8)((lastLba >> 24) & 0xFF); /* MSB */ dataBuffer[1] = (bit8)((lastLba >> 16) & 0xFF); dataBuffer[2] = (bit8)((lastLba >> 8) & 0xFF); dataBuffer[3] = (bit8)((lastLba ) & 0xFF); /* LSB */ SM_DBG3(("smsatReadCapacity10: lastLba is 0x%x %d\n", lastLba, lastLba)); SM_DBG3(("smsatReadCapacity10: LBA 0 is 0x%x %d\n", dataBuffer[0], dataBuffer[0])); SM_DBG3(("smsatReadCapacity10: LBA 1 is 0x%x %d\n", dataBuffer[1], dataBuffer[1])); SM_DBG3(("smsatReadCapacity10: LBA 2 is 0x%x %d\n", dataBuffer[2], dataBuffer[2])); SM_DBG3(("smsatReadCapacity10: LBA 3 is 0x%x %d\n", dataBuffer[3], dataBuffer[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 */ dataBuffer[0] = (bit8)((lastLba >> 24) & 0xFF); /* MSB */ dataBuffer[1] = (bit8)((lastLba >> 16) & 0xFF); dataBuffer[2] = (bit8)((lastLba >> 8) & 0xFF); dataBuffer[3] = (bit8)((lastLba ) & 0xFF); /* LSB */ } /* SAT Rev 8d */ if (((pSATAIdData->word104_107[2]) & 0x1000) == 0) { SM_DBG5(("smsatReadCapacity10: Default Block Length is 512\n")); /* * Set the block size, fixed at 512 bytes. */ dataBuffer[4] = 0x00; /* MSB block size in bytes */ dataBuffer[5] = 0x00; dataBuffer[6] = 0x02; dataBuffer[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; dataBuffer[4] = (bit8)((word117_118 >> 24) & 0xFF); /* MSB block size in bytes */ dataBuffer[5] = (bit8)((word117_118 >> 16) & 0xFF); dataBuffer[6] = (bit8)((word117_118 >> 8) & 0xFF); dataBuffer[7] = (bit8)(word117_118 & 0xFF); /* LSB block size in bytes */ SM_DBG1(("smsatReadCapacity10: Nondefault word118 %d 0x%x !!!\n", word118, word118)); SM_DBG1(("smsatReadCapacity10: Nondefault word117 %d 0x%x !!!\n", word117, word117)); SM_DBG1(("smsatReadCapacity10: 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] = dataBuffer[0]; pSatDevData->satMaxLBA[5] = dataBuffer[1]; pSatDevData->satMaxLBA[6] = dataBuffer[2]; pSatDevData->satMaxLBA[7] = dataBuffer[3]; /* LSB */ SM_DBG4(("smsatReadCapacity10: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x , did %d\n", dataBuffer[0], dataBuffer[1], dataBuffer[2], dataBuffer[3], dataBuffer[4], dataBuffer[5], dataBuffer[6], dataBuffer[7], pSatDevData->id)); sm_memcpy(pVirtAddr, dataBuffer, MIN(allocationLen, 8)); /* * Send the completion response now. */ /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } osGLOBAL bit32 smsatReadCapacity16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; bit8 dataBuffer[32] = {0}; bit8 *pVirtAddr = agNULL; smDeviceData_t *pSatDevData; agsaSATAIdentifyData_t *pSATAIdData; bit32 lastLbaLo; bit32 allocationLen; bit32 readCapacityLen = 32; bit32 i = 0; pSense = satIOContext->pSense; pVirtAddr = (bit8 *) smScsiRequest->sglVirtualAddr; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; pSATAIdData = &pSatDevData->satIdentifyData; SM_DBG5(("smsatReadCapacity16: start\n")); /* 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]) ); allocationLen = MIN(allocationLen, scsiCmnd->expDataLength); #ifdef REMOVED if (allocationLen < readCapacityLen) { SM_DBG1(("smsatReadCapacity16: *** ERROR *** insufficient len=0x%x readCapacityLen=0x%x!!!\n", allocationLen, readCapacityLen)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } #endif /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadCapacity16: return control!!!\n")); return SM_RC_SUCCESS; } /* * 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]) ) { SM_DBG1(("smsatReadCapacity16: *** ERROR *** logical address non zero, did %d\n", pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* * If PMI bit is not zero, return error */ if ( ((scsiCmnd->cdb[14]) & SCSI_READ_CAPACITY16_PMI_MASK) != 0 ) { SM_DBG1(("smsatReadCapacity16: *** ERROR *** PMI is not zero, did %d\n", pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* 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) { dataBuffer[0] = (bit8)(((pSATAIdData->maxLBA48_63) >> 8) & 0xff); /* MSB */ dataBuffer[1] = (bit8)((pSATAIdData->maxLBA48_63) & 0xff); dataBuffer[2] = (bit8)(((pSATAIdData->maxLBA32_47) >> 8) & 0xff); dataBuffer[3] = (bit8)((pSATAIdData->maxLBA32_47) & 0xff); lastLbaLo = (((pSATAIdData->maxLBA16_31) << 16) ) | (pSATAIdData->maxLBA0_15); lastLbaLo = lastLbaLo - 1; /* LBA starts from zero */ dataBuffer[4] = (bit8)((lastLbaLo >> 24) & 0xFF); dataBuffer[5] = (bit8)((lastLbaLo >> 16) & 0xFF); dataBuffer[6] = (bit8)((lastLbaLo >> 8) & 0xFF); dataBuffer[7] = (bit8)((lastLbaLo ) & 0xFF); /* LSB */ } /* * For 28-bit addressing, set capacity information from Identify * Device Word 60-61. */ else { dataBuffer[0] = 0; /* MSB */ dataBuffer[1] = 0; dataBuffer[2] = 0; dataBuffer[3] = 0; lastLbaLo = (((pSATAIdData->numOfUserAddressableSectorsHi) << 16) ) | (pSATAIdData->numOfUserAddressableSectorsLo); lastLbaLo = lastLbaLo - 1; /* LBA starts from zero */ dataBuffer[4] = (bit8)((lastLbaLo >> 24) & 0xFF); dataBuffer[5] = (bit8)((lastLbaLo >> 16) & 0xFF); dataBuffer[6] = (bit8)((lastLbaLo >> 8) & 0xFF); dataBuffer[7] = (bit8)((lastLbaLo ) & 0xFF); /* LSB */ } /* * Set the block size, fixed at 512 bytes. */ dataBuffer[8] = 0x00; /* MSB block size in bytes */ dataBuffer[9] = 0x00; dataBuffer[10] = 0x02; dataBuffer[11] = 0x00; /* LSB block size in bytes */ /* fill in MAX LBA, which is used in satSendDiagnostic_1() */ pSatDevData->satMaxLBA[0] = dataBuffer[0]; /* MSB */ pSatDevData->satMaxLBA[1] = dataBuffer[1]; pSatDevData->satMaxLBA[2] = dataBuffer[2]; pSatDevData->satMaxLBA[3] = dataBuffer[3]; pSatDevData->satMaxLBA[4] = dataBuffer[4]; pSatDevData->satMaxLBA[5] = dataBuffer[5]; pSatDevData->satMaxLBA[6] = dataBuffer[6]; pSatDevData->satMaxLBA[7] = dataBuffer[7]; /* LSB */ SM_DBG5(("smsatReadCapacity16: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x , did %d\n", dataBuffer[0], dataBuffer[1], dataBuffer[2], dataBuffer[3], dataBuffer[4], dataBuffer[5], dataBuffer[6], dataBuffer[7], dataBuffer[8], dataBuffer[9], dataBuffer[10], dataBuffer[11], pSatDevData->id)); if (allocationLen > 0xC) /* 0xc = 12 */ { for(i=12;i<=31;i++) { dataBuffer[i] = 0x00; } } sm_memcpy(pVirtAddr, dataBuffer, MIN(allocationLen, readCapacityLen)); /* * Send the completion response now. */ if (allocationLen > readCapacityLen) { /* underrun */ SM_DBG1(("smsatReadCapacity16: reporting underrun readCapacityLen=0x%x allocationLen=0x%x !!!\n", readCapacityLen, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOUnderRun, allocationLen - readCapacityLen, agNULL, satIOContext->interruptContext ); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return SM_RC_SUCCESS; } osGLOBAL bit32 smsatReportLun( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; bit8 dataBuffer[16] = {0}; bit32 allocationLen; bit32 reportLunLen; smScsiReportLun_t *pReportLun; smIniScsiCmnd_t *scsiCmnd; #ifdef TD_DEBUG_ENABLE smDeviceData_t *pSatDevData; #endif pSense = satIOContext->pSense; pReportLun = (smScsiReportLun_t *) dataBuffer; scsiCmnd = &smScsiRequest->scsiCmnd; #ifdef TD_DEBUG_ENABLE pSatDevData = satIOContext->pSatDevData; #endif SM_DBG5(("smsatReportLun: start\n")); // smhexdump("smsatReportLun: 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]) ); allocationLen = MIN(allocationLen, scsiCmnd->expDataLength); reportLunLen = 16; /* 8 byte header and 8 bytes of LUN0 */ if (allocationLen < reportLunLen) { SM_DBG1(("smsatReportLun: *** ERROR *** insufficient len=0x%x did %d\n", reportLunLen, pSatDevData->id)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* 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; sm_memcpy(smScsiRequest->sglVirtualAddr, dataBuffer, MIN(allocationLen, reportLunLen)); if (allocationLen > reportLunLen) { /* underrun */ SM_DBG1(("smsatReportLun: reporting underrun reportLunLen=0x%x allocationLen=0x%x !!!\n", reportLunLen, allocationLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOUnderRun, allocationLen - reportLunLen, agNULL, satIOContext->interruptContext ); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return SM_RC_SUCCESS; } osGLOBAL bit32 smsatFormatUnit( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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 */ smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; bit32 index = 0; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; SM_DBG5(("smsatFormatUnit: 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)) ) { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); SM_DBG1(("smsatFormatUnit: return opcode!!!\n")); return SM_RC_SUCCESS; } /* 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)) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatFormatUnit: return defect list format!!!\n")); return SM_RC_SUCCESS; } } if ( (scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_FMTDATA_MASK) && (scsiCmnd->cdb[1] & SCSI_FORMAT_UNIT_CMPLIST_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatFormatUnit: return cmplist!!!\n")); return SM_RC_SUCCESS; } if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatFormatUnit: return control!!!\n")); return SM_RC_SUCCESS; } /* 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)) ) { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); SM_DBG5(("smsatFormatUnit: return defect list case 1\n")); return SM_RC_SUCCESS; } /* 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) ) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG5(("smsatFormatUnit: return defect list case 2\n")); return SM_RC_SUCCESS; } } /* * Send the completion response now. */ /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); SM_DBG5(("smsatFormatUnit: return last\n")); return SM_RC_SUCCESS; } osGLOBAL bit32 smsatSendDiagnostic( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 parmLen; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatSendDiagnostic: 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) ) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSendDiagnostic: return PF, DEVOFFL, UNITOFFL, PARAM LIST!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSendDiagnostic: return control!!!\n")); return SM_RC_SUCCESS; } 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) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSendDiagnostic: return Table 29 case 1!!!\n")); return SM_RC_SUCCESS; } /* case 2 */ if ( !(scsiCmnd->cdb[1] & SCSI_SEND_DIAGNOSTIC_SELFTEST_MASK) && (pSatDevData->satSMARTSelfTest == agTRUE) && (pSatDevData->satSMARTEnabled == agFALSE) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_ATA_DEVICE_FEATURE_NOT_ENABLED, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG5(("smsatSendDiagnostic: return Table 29 case 2\n")); return SM_RC_SUCCESS; } /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: 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; /* 0xB0 */ fis->h.features = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE; /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: 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; tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, 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; /* 0x40 */ fis->h.features = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE; /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: return Table 28 case 1\n")); return (status); case 2: pSatDevData->satBGPendingDiag = agTRUE; tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, 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; /* 0x40 */ fis->h.features = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE; /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: return Table 28 case 2\n")); return (status); case 4: if (parmLen != 0) { /* check condition */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSendDiagnostic: case 4, non zero ParmLen %d!!!\n", parmLen)); return SM_RC_SUCCESS; } 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; /* 0x40 */ fis->h.features = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE; /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: send SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE case 3\n")); SM_DBG5(("smsatSendDiagnostic: Table 28 case 4\n")); return (status); } else { /* check condition */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSendDiagnostic: case 4, no pending diagnostic in background!!!\n")); SM_DBG5(("smsatSendDiagnostic: Table 28 case 4\n")); return SM_RC_SUCCESS; } 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; /* 0x40 */ fis->h.features = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE; /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: 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; /* 0x40 */ fis->h.features = SAT_SMART_EXEUTE_OFF_LINE_IMMEDIATE; /* 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatSendDiagnostic: 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 */ /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); SM_DBG5(("smsatSendDiagnostic: return Table 28 case 0,3,7 and default\n")); return SM_RC_SUCCESS; } /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); SM_DBG5(("smsatSendDiagnostic: return last\n")); return SM_RC_SUCCESS; } osGLOBAL bit32 smsatStartStopUnit( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatStartStopUnit: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatStartStopUnit: return control!!!\n")); return SM_RC_SUCCESS; } /* 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*/ /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); SM_DBG5(("smsatStartStopUnit: return table48 case 1-1\n")); return SM_RC_SUCCESS; } /* 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 = &smsatStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatStartStopUnit: 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) ) { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); SM_DBG5(("smsatStartStopUnit: return table48 case 2 1\n")); return SM_RC_SUCCESS; } /* 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 = &smsatStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatStartStopUnit: 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) ) { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext ); SM_DBG5(("smsatStartStopUnit: return table48 case 3 1\n")); return SM_RC_SUCCESS; } /* 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 = &smsatStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { /* no support for removal media */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG5(("smsatStartStopUnit: return Table 29 case 3 2\n")); return SM_RC_SUCCESS; } } /* case 4 */ else /* ( (scsiCmnd->cdb[4] & SCSI_START_MASK) && (scsiCmnd->cdb[4] & SCSI_LOEJ_MASK) ) */ { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG5(("smsatStartStopUnit: return Table 29 case 4\n")); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatWriteSame10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWriteSame10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteSame10: return control!!!\n")); return SM_RC_SUCCESS; } /* checking LBDATA and PBDATA */ /* case 1 */ if ( !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_LBDATA_MASK) && !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_PBDATA_MASK)) { SM_DBG5(("smsatWriteSame10: 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 */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteSame10: return internal checking!!!\n")); return SM_RC_SUCCESS; } /* 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 */ { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteSame10: return LBA out of range!!!\n")); return SM_RC_SUCCESS; } } 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 */ SM_DBG1(("smsatWriteSame10: case 1-2 !!! error due to writesame10!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } 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 */ SM_DBG1(("smsatWriteSame10: case 1-1 !!! error due to writesame10!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* 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 */ SM_DBG5(("smsatWriteSame10: 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) { SM_DBG1(("smsatWriteSame10: case 3 !!! warning can't fit sectors!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* 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 */ SM_DBG5(("smsatWriteSame10: 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) { SM_DBG1(("smsatWriteSame10: case 4 !!! warning can't fit sectors!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* 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) { SM_DBG1(("smsatWriteSame10: case 1-5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG5(("smsatWriteSame10: 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) { SM_DBG1(("smsatWriteSame10: case 4 !!! warning can't fit sectors!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* 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 = &smsatWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, 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*/ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG5(("smsatWriteSame10: return Table 62 case 2\n")); return SM_RC_SUCCESS; } else if ( (scsiCmnd->cdb[1] & SCSI_WRITE_SAME_LBDATA_MASK) && !(scsiCmnd->cdb[1] & SCSI_WRITE_SAME_PBDATA_MASK)) { SM_DBG5(("smsatWriteSame10: 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*/ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG5(("smsatWriteSame10: return Table 62 case 4\n")); return SM_RC_SUCCESS; } return SM_RC_SUCCESS; } osGLOBAL bit32 smsatWriteSame16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; pSense = satIOContext->pSense; SM_DBG5(("smsatWriteSame16: start\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, /* == &satIntIo->satOrgSmIORequest */ smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteSame16: return internal checking!!!\n")); return SM_RC_SUCCESS; } osGLOBAL bit32 smsatLogSense( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_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 = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pLogPage = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatLogSense: start\n")); sm_memset(&AllLogPages, 0, 8); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatLogSense: return control!!!\n")); return SM_RC_SUCCESS; } AllocLen = ((scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]); AllocLen = MIN(AllocLen, scsiCmnd->expDataLength); /* checking PC (Page Control) */ /* nothing */ /* special cases */ if (AllocLen == 4) { SM_DBG1(("smsatLogSense: AllocLen is 4!!!\n")); switch (scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK) { case LOGSENSE_SUPPORTED_LOG_PAGES: SM_DBG5(("smsatLogSense: case LOGSENSE_SUPPORTED_LOG_PAGES\n")); 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: SM_DBG1(("smsatLogSense: error unallowed flag value %d!!!\n", flag)); break; } sm_memcpy(pLogPage, &AllLogPages, lenRead); break; case LOGSENSE_SELFTEST_RESULTS_PAGE: SM_DBG5(("smsatLogSense: 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 */ sm_memcpy(pLogPage, &AllLogPages, lenRead); break; case LOGSENSE_INFORMATION_EXCEPTIONS_PAGE: SM_DBG5(("smsatLogSense: 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 */ sm_memcpy(pLogPage, &AllLogPages, lenRead); break; default: SM_DBG1(("smsatLogSense: default Page Code 0x%x!!!\n", scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } /* if */ /* SAT rev8 Table 11 p30*/ /* checking Page Code */ switch (scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK) { case LOGSENSE_SUPPORTED_LOG_PAGES: SM_DBG5(("smsatLogSense: case 1\n")); 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: SM_DBG1(("smsatLogSense: error unallowed flag value %d!!!\n", flag)); break; } sm_memcpy(pLogPage, &AllLogPages, lenRead); /* comparing allocation length to Log Page byte size */ /* SPC-4, 4.3.4.6, p28 */ if (AllocLen > lenRead ) { SM_DBG1(("smsatLogSense: reporting underrun lenRead=0x%x AllocLen=0x%x!!!\n", lenRead, AllocLen)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOUnderRun, AllocLen - lenRead, agNULL, satIOContext->interruptContext ); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } break; case LOGSENSE_SELFTEST_RESULTS_PAGE: SM_DBG5(("smsatLogSense: case 2\n")); /* checking SMART self-test */ if (pSatDevData->satSMARTSelfTest == agFALSE) { SM_DBG5(("smsatLogSense: case 2 no SMART Self Test\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); } else { /* if satSMARTEnabled is false, send SMART_ENABLE_OPERATIONS */ if (pSatDevData->satSMARTEnabled == agFALSE) { SM_DBG5(("smsatLogSense: case 2 calling satSMARTEnable\n")); status = smsatLogSenseAllocate(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, 0, LOG_SENSE_0 ); return status; } else { /* SAT Rev 8, 10.2.4 p74 */ if ( pSatDevData->sat48BitSupport == agTRUE ) { SM_DBG5(("smsatLogSense: case 2-1 sends READ LOG EXT\n")); status = smsatLogSenseAllocate(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, 512, LOG_SENSE_1 ); return status; } else { SM_DBG5(("smsatLogSense: case 2-2 sends SMART READ LOG\n")); status = smsatLogSenseAllocate(smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext, 512, LOG_SENSE_2 ); return status; } } } break; case LOGSENSE_INFORMATION_EXCEPTIONS_PAGE: SM_DBG5(("smsatLogSense: case 3\n")); /* checking SMART feature set */ if (pSatDevData->satSMARTFeatureSet == agFALSE) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); } else { /* checking SMART feature enabled */ if (pSatDevData->satSMARTEnabled == agFALSE) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ABORTED_COMMAND, 0, SCSI_SNSCODE_ATA_DEVICE_FEATURE_NOT_ENABLED, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); } else { /* SAT Rev 8, 10.2.3 p72 */ SM_DBG5(("smsatLogSense: 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; /* 0xB0 */ fis->h.features = SAT_SMART_RETURN_STATUS;/* 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 = &smsatLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } break; default: SM_DBG1(("smsatLogSense: default Page Code 0x%x!!!\n", scsiCmnd->cdb[2] & SCSI_LOG_SENSE_PAGE_CODE_MASK)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); break; } /* end switch */ return SM_RC_SUCCESS; } osGLOBAL bit32 smsatLogSenseAllocate( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smSCSIRequest, smSatIOContext_t *satIOContext, bit32 payloadSize, bit32 flag ) { smDeviceData_t *pSatDevData; smIORequestBody_t *smIORequestBody; smSatInternalIo_t *satIntIo = agNULL; smSatIOContext_t *satIOContext2; bit32 status; SM_DBG5(("smsatLogSenseAllocate: start\n")); pSatDevData = satIOContext->pSatDevData; /* create internal satIOContext */ satIntIo = smsatAllocIntIoResource( smRoot, smIORequest, /* original request */ pSatDevData, payloadSize, satIntIo); if (satIntIo == agNULL) { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOFailed, smDetailOtherError, agNULL, satIOContext->interruptContext ); SM_DBG1(("smsatLogSenseAllocate: fail in allocation!!!\n")); return SM_RC_SUCCESS; } /* end of memory allocation failure */ satIntIo->satOrgSmIORequest = smIORequest; smIORequestBody = (smIORequestBody_t *)satIntIo->satIntRequestBody; satIOContext2 = &(smIORequestBody->transport.SATA.satIOContext); satIOContext2->pSatDevData = pSatDevData; satIOContext2->pFis = &(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev); satIOContext2->pScsiCmnd = &(satIntIo->satIntSmScsiXchg.scsiCmnd); satIOContext2->pSense = &(smIORequestBody->transport.SATA.sensePayload); satIOContext2->pSmSenseData = &(smIORequestBody->transport.SATA.smSenseData); satIOContext2->pSmSenseData->senseData = satIOContext2->pSense; satIOContext2->smRequestBody = satIntIo->satIntRequestBody; satIOContext2->interruptContext = satIOContext->interruptContext; satIOContext2->satIntIoContext = satIntIo; satIOContext2->psmDeviceHandle = smDeviceHandle; satIOContext2->satOrgIOContext = satIOContext; if (flag == LOG_SENSE_0) { /* SAT_SMART_ENABLE_OPERATIONS */ status = smsatSMARTEnable( smRoot, &(satIntIo->satIntSmIORequest), smDeviceHandle, &(satIntIo->satIntSmScsiXchg), satIOContext2); } else if (flag == LOG_SENSE_1) { /* SAT_READ_LOG_EXT */ status = smsatLogSense_2( smRoot, &(satIntIo->satIntSmIORequest), smDeviceHandle, &(satIntIo->satIntSmScsiXchg), satIOContext2); } else { /* SAT_SMART_READ_LOG */ /* SAT_READ_LOG_EXT */ status = smsatLogSense_3( smRoot, &(satIntIo->satIntSmIORequest), smDeviceHandle, &(satIntIo->satIntSmScsiXchg), satIOContext2); } if (status != SM_RC_SUCCESS) { smsatFreeIntIoResource( smRoot, pSatDevData, satIntIo); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOFailed, smDetailOtherError, agNULL, satIOContext->interruptContext ); return SM_RC_SUCCESS; } return SM_RC_SUCCESS; } osGLOBAL bit32 smsatSMARTEnable( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG5(("smsatSMARTEnable: start\n")); /* * 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; /* 0xB0 */ fis->h.features = SAT_SMART_ENABLE_OPERATIONS; 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 = &smsatSMARTEnableCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatLogSense_2( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG5(("smsatLogSense_2: start\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 = &smsatLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatLogSense_3( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG5(("smsatLogSense_3: start\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_SMART; /* 0x2F */ fis->h.features = SAT_SMART_READ_LOG; /* 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 = &smsatLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatModeSelect6( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pLogPage; /* Log Page data buffer */ bit32 StartingIndex = 0; bit8 PageCode = 0; bit32 chkCnd = agFALSE; bit32 parameterListLen = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pLogPage = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatModeSelect6: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSelect6: return control!!!\n")); return SM_RC_SUCCESS; } /* checking PF bit */ if ( !(scsiCmnd->cdb[1] & SCSI_MODE_SELECT6_PF_MASK)) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSelect6: PF bit check!!!\n")); return SM_RC_SUCCESS; } parameterListLen = scsiCmnd->cdb[4]; parameterListLen = MIN(parameterListLen, scsiCmnd->expDataLength); if ((0 == parameterListLen) || (agNULL == pLogPage)) { tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } /* 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; /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } else { SM_DBG1(("smsatModeSelect6: return mode parameter block descriptor 0x%x!!!\n", pLogPage[3])); smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } switch (PageCode) /* page code */ { case MODESELECT_CONTROL_PAGE: SM_DBG1(("smsatModeSelect6: Control mode page!!!\n")); 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) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSelect6: unexpected values!!!\n")); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return SM_RC_SUCCESS; break; case MODESELECT_READ_WRITE_ERROR_RECOVERY_PAGE: SM_DBG1(("smsatModeSelect6: 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]) ) { SM_DBG5(("smsatModeSelect6: return check condition\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { SM_DBG5(("smsatModeSelect6: return GOOD \n")); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } break; case MODESELECT_CACHING: /* SAT rev8 Table67, p69*/ SM_DBG5(("smsatModeSelect6: 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]) ) { SM_DBG1(("smsatModeSelect6: return check condition!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { /* sends ATA SET FEATURES based on WCE bit */ if ( !(pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_WCE_MASK) ) { SM_DBG5(("smsatModeSelect6: 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG5(("smsatModeSelect6: 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } break; case MODESELECT_INFORMATION_EXCEPTION_CONTROL_PAGE: SM_DBG5(("smsatModeSelect6: Informational Exception Control mode page\n")); if ( (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_PERF_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT6_TEST_MASK) ) { SM_DBG1(("smsatModeSelect6: return check condition!!! \n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { /* sends either ATA SMART ENABLE/DISABLE OPERATIONS based on DEXCPT bit */ if ( !(pLogPage[StartingIndex + 2] & 0x08) ) { SM_DBG5(("smsatModeSelect6: 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; /* 0xB0 */ fis->h.features = SAT_SMART_ENABLE_OPERATIONS; /* 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG5(("smsatModeSelect6: 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; /* 0xB0 */ fis->h.features = SAT_SMART_DISABLE_OPERATIONS; /* 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } break; default: SM_DBG1(("smsatModeSelect6: Error unknown page code 0x%x!!!\n", pLogPage[12])); smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatModeSelect10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_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; bit32 parameterListLen = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pLogPage = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatModeSelect10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSelect10: return control!!!\n")); return SM_RC_SUCCESS; } /* checking PF bit */ if ( !(scsiCmnd->cdb[1] & SCSI_MODE_SELECT10_PF_MASK)) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSelect10: PF bit check!!!\n")); return SM_RC_SUCCESS; } parameterListLen = ((scsiCmnd->cdb[7]) << 8) + scsiCmnd->cdb[8]; parameterListLen = MIN(parameterListLen, scsiCmnd->expDataLength); if ((0 == parameterListLen) || (agNULL == pLogPage)) { tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } 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) { PageCode = (bit8)(pLogPage[8] & 0x3F); /* page code and index is 8 + 0 */ StartingIndex = 8; /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } else { SM_DBG1(("smsatModeSelect10: return mode parameter block descriptor 0x%x!!!\n", BlkDescLen)); /* no more than one mode parameter block descriptor shall be supported */ smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } /* for debugging only */ if (StartingIndex == 8) { smhexdump("startingindex 8", (bit8 *)pLogPage, 8); } else if(StartingIndex == 16) { if (PageCode == MODESELECT_CACHING) { smhexdump("startingindex 16", (bit8 *)pLogPage, 16+20); } else { smhexdump("startingindex 16", (bit8 *)pLogPage, 16+12); } } else { if (PageCode == MODESELECT_CACHING) { smhexdump("startingindex 24", (bit8 *)pLogPage, 24+20); } else { smhexdump("startingindex 24", (bit8 *)pLogPage, 24+12); } } switch (PageCode) /* page code */ { case MODESELECT_CONTROL_PAGE: SM_DBG5(("smsatModeSelect10: 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) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatModeSelect10: unexpected values!!!\n")); } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } return SM_RC_SUCCESS; break; case MODESELECT_READ_WRITE_ERROR_RECOVERY_PAGE: SM_DBG5(("smsatModeSelect10: 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]) ) { SM_DBG1(("smsatModeSelect10: return check condition!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { SM_DBG2(("smsatModeSelect10: return GOOD \n")); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } break; case MODESELECT_CACHING: /* SAT rev8 Table67, p69*/ SM_DBG5(("smsatModeSelect10: 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]) ) { SM_DBG1(("smsatModeSelect10: return check condition!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { /* sends ATA SET FEATURES based on WCE bit */ if ( !(pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_WCE_MASK) ) { SM_DBG5(("smsatModeSelect10: 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG5(("smsatModeSelect10: 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } break; case MODESELECT_INFORMATION_EXCEPTION_CONTROL_PAGE: SM_DBG5(("smsatModeSelect10: Informational Exception Control mode page\n")); if ( (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_PERF_MASK) || (pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_TEST_MASK) ) { SM_DBG1(("smsatModeSelect10: return check condition!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_PARAMETER_LIST, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { /* sends either ATA SMART ENABLE/DISABLE OPERATIONS based on DEXCPT bit */ if ( !(pLogPage[StartingIndex + 2] & SCSI_MODE_SELECT10_DEXCPT_MASK) ) { SM_DBG5(("smsatModeSelect10: 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; /* 0xB0 */ fis->h.features = SAT_SMART_ENABLE_OPERATIONS; /* 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG5(("smsatModeSelect10: 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; /* 0xB0 */ fis->h.features = SAT_SMART_DISABLE_OPERATIONS; /* 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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } break; default: SM_DBG1(("smsatModeSelect10: Error unknown page code 0x%x!!!\n", pLogPage[12])); smsatSetSensePayload( pSense, SCSI_SNSKEY_NO_SENSE, 0, SCSI_SNSCODE_NO_ADDITIONAL_INFO, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatSynchronizeCache10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatSynchronizeCache10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSynchronizeCache10: return control!!!\n")); return SM_RC_SUCCESS; } /* checking IMMED bit */ if (scsiCmnd->cdb[1] & SCSI_SYNC_CACHE_IMMED_MASK) { SM_DBG1(("smsatSynchronizeCache10: GOOD status due to IMMED bit!!!\n")); /* return GOOD status first here */ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } /* sends FLUSH CACHE or FLUSH CACHE EXT */ if (pSatDevData->sat48BitSupport == agTRUE) { SM_DBG5(("smsatSynchronizeCache10: 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 { SM_DBG5(("smsatSynchronizeCache10: 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 = &smsatSynchronizeCache10n16CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatSynchronizeCache16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatSynchronizeCache10: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatSynchronizeCache10: return control!!!\n")); return SM_RC_SUCCESS; } /* checking IMMED bit */ if (scsiCmnd->cdb[1] & SCSI_SYNC_CACHE_IMMED_MASK) { SM_DBG1(("smsatSynchronizeCache10: GOOD status due to IMMED bit!!!\n")); /* return GOOD status first here */ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); } /* sends FLUSH CACHE or FLUSH CACHE EXT */ if (pSatDevData->sat48BitSupport == agTRUE) { SM_DBG5(("smsatSynchronizeCache10: 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 { SM_DBG5(("smsatSynchronizeCache10: 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 = &smsatSynchronizeCache10n16CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatWriteAndVerify10( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* combination of write10 and verify10 */ bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWriteAndVerify10: start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteAndVerify10: BYTCHK bit checking!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteAndVerify10: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = 0; TL[5] = 0; TL[6] = scsiCmnd->cdb[7]; TL[7] = scsiCmnd->cdb[8]; /* LSB */ /* 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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWriteAndVerify10: return LBA out of range!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWriteAndVerify10: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 1 and 2 */ if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ SM_DBG5(("smsatWriteAndVerify10: 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 */ SM_DBG5(("smsatWriteAndVerify10: 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 */ SM_DBG5(("smsatWriteAndVerify10: 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 */ SM_DBG5(("smsatWriteAndVerify10: 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) { SM_DBG1(("smsatWriteAndVerify10: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG5(("smsatWriteAndVerify10: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUED */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatWriteAndVerify10: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedWriteNVerifyCB; } else { SM_DBG1(("smsatWriteAndVerify10: 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 = &smsatChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatWriteAndVerify12( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWriteAndVerify12: start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteAndVerify12: BYTCHK bit checking!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteAndVerify12: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_memset(TL, 0, sizeof(TL)); /* do not use memcpy due to indexing in LBA and TL */ LBA[0] = 0; /* MSB */ LBA[1] = 0; LBA[2] = 0; LBA[3] = 0; LBA[4] = scsiCmnd->cdb[2]; LBA[5] = scsiCmnd->cdb[3]; LBA[6] = scsiCmnd->cdb[4]; LBA[7] = scsiCmnd->cdb[5]; /* LSB */ TL[0] = 0; /* MSB */ TL[1] = 0; TL[2] = 0; TL[3] = 0; TL[4] = scsiCmnd->cdb[6]; TL[5] = scsiCmnd->cdb[7]; TL[6] = scsiCmnd->cdb[8]; TL[7] = scsiCmnd->cdb[9]; /* LSB */ lba = smsatComputeCDB12LBA(satIOContext); tl = smsatComputeCDB12TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { /*smEnqueueIO(smRoot, satIOContext);*/ SM_DBG1(("smsatWriteAndVerify12: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWriteAndVerify12: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ SM_DBG5(("smsatWriteAndVerify12: 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 */ SM_DBG5(("smsatWriteAndVerify12: 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 */ SM_DBG5(("smsatWriteAndVerify12: 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 */ SM_DBG5(("smsatWriteAndVerify12: 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) { SM_DBG1(("smsatWriteAndVerify12: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatWriteAndVerify12: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; satIOContext->LoopNum2 = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatWriteAndVerify12: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedWriteNVerifyCB; } else { SM_DBG1(("smsatWriteAndVerify12: 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 = &smsatChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatWriteAndVerify16( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[8]; bit8 TL[8]; bit32 AllChk = agFALSE; /* lba, lba+tl check against ATA limit and Disk capacity */ pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatWriteAndVerify16: start\n")); /* checking BYTCHK bit */ if (scsiCmnd->cdb[1] & SCSI_WRITE_N_VERIFY_BYTCHK_MASK) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteAndVerify16: BYTCHK bit checking!!!\n")); return SM_RC_SUCCESS; } /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[15] & SCSI_NACA_MASK) || (scsiCmnd->cdb[15] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteAndVerify16: return control!!!\n")); return SM_RC_SUCCESS; } sm_memset(LBA, 0, sizeof(LBA)); sm_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 */ lba = smsatComputeCDB16LBA(satIOContext); tl = smsatComputeCDB16TL(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 ) { AllChk = smsatCheckLimit(LBA, TL, agFALSE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWriteAndVerify16: return LBA out of range, not EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { AllChk = smsatCheckLimit(LBA, TL, agTRUE, pSatDevData); if (AllChk) { SM_DBG1(("smsatWriteAndVerify16: return LBA out of range, EXT!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } /* case 1 and 2 */ if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* In case that we can't fit the transfer length, we loop */ SM_DBG5(("smsatWriteAndVerify16: 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 */ SM_DBG5(("smsatWriteAndVerify16: 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 */ SM_DBG5(("smsatWriteAndVerify16: 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 */ SM_DBG5(("smsatWriteAndVerify16: 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) { SM_DBG1(("smsatWriteAndVerify16: case 5 !!! error NCQ but 28 bit address support!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_DBG6(("smsatWriteAndVerify16: 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 = smsatComputeLoopNum(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 = smsatComputeLoopNum(tl, 0xFFFF); } else { /* SAT_WRITE_FPDMA_QUEUEDK */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatWriteAndVerify16: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedWriteNVerifyCB; } else { SM_DBG1(("smsatWriteAndVerify16: 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 = &smsatChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatReadMediaSerialNumber( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; agsaSATAIdentifyData_t *pSATAIdData; bit8 *pSerialNumber; bit8 MediaSerialNumber[64] = {0}; bit32 allocationLen = 0; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pSATAIdData = &(pSatDevData->satIdentifyData); pSerialNumber = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatReadMediaSerialNumber: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[11] & SCSI_NACA_MASK) || (scsiCmnd->cdb[11] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadMediaSerialNumber: return control!!!\n")); return SM_RC_SUCCESS; } allocationLen = (((bit32)scsiCmnd->cdb[6]) << 24) | (((bit32)scsiCmnd->cdb[7]) << 16) | (((bit32)scsiCmnd->cdb[8]) << 8 ) | (((bit32)scsiCmnd->cdb[9])); allocationLen = MIN(allocationLen, scsiCmnd->expDataLength); if (allocationLen == 4) { if (pSATAIdData->commandSetFeatureDefault & 0x4) { SM_DBG1(("smsatReadMediaSerialNumber: Media serial number returning only length!!!\n")); /* SPC-3 6.16 p192; filling in length */ MediaSerialNumber[0] = 0; MediaSerialNumber[1] = 0; MediaSerialNumber[2] = 0; MediaSerialNumber[3] = 0x3C; } else { /* 1 sector - 4 = 512 - 4 to avoid underflow; 0x1fc*/ MediaSerialNumber[0] = 0; MediaSerialNumber[1] = 0; MediaSerialNumber[2] = 0x1; MediaSerialNumber[3] = 0xfc; } sm_memcpy(pSerialNumber, MediaSerialNumber, 4); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } 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*/ #ifdef LOG_ENABLE smhexdump("ID smsatReadMediaSerialNumber", (bit8*)pSATAIdData->currentMediaSerialNumber, 2*30); #endif /* SPC-3 6.16 p192; filling in length */ MediaSerialNumber[0] = 0; MediaSerialNumber[1] = 0; MediaSerialNumber[2] = 0; MediaSerialNumber[3] = 0x3C; sm_memcpy(&MediaSerialNumber[4], (void *)pSATAIdData->currentMediaSerialNumber, 60); #ifdef LOG_ENABLE smhexdump("smsatReadMediaSerialNumber", (bit8*)MediaSerialNumber, 2*30 + 4); #endif sm_memcpy(pSerialNumber, MediaSerialNumber, MIN(allocationLen, 64)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } else { /* word87 bit2 Media serial number is NOT valid */ SM_DBG1(("smsatReadMediaSerialNumber: 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 = &smsatReadMediaSerialNumberCB; satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } else { tdsmIOCompletedCB( smRoot, smIORequest, smIOFailed, smDetailOtherError, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatReadBuffer( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status = SM_RC_SUCCESS; bit32 agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 bufferOffset; bit32 tl; bit8 mode; bit8 bufferID; bit8 *pBuff; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pBuff = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatReadBuffer: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadBuffer: return control!!!\n")); return SM_RC_SUCCESS; } 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 = &smsatReadBufferCB; satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } if (bufferID == 0 && bufferOffset == 0 && tl != 512) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadBuffer: allocation length is not 512; it is %d!!!\n", tl)); return SM_RC_SUCCESS; } if (bufferID == 0 && bufferOffset != 0) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadBuffer: buffer offset is not 0; it is %d!!!\n", bufferOffset)); return SM_RC_SUCCESS; } /* all other cases unsupported */ SM_DBG1(("smsatReadBuffer: unsupported case 1!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else if (mode == READ_BUFFER_DESCRIPTOR_MODE) /* 3 */ { if (tl < READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN) /* 4 */ { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReadBuffer: tl < 4; tl is %d!!!\n", tl)); return SM_RC_SUCCESS; } 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 */ SM_DBG1(("smsatReadBuffer: underrun tl %d data %d!!!\n", tl, READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN)); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOUnderRun, tl - READ_BUFFER_DESCRIPTOR_MODE_DATA_LEN, agNULL, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } } else { /* We don't support other than bufferID 0 */ smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } else { /* We don't support any other mode */ SM_DBG1(("smsatReadBuffer: unsupported mode %d!!!\n", mode)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatWriteBuffer( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { #ifdef NOT_YET bit32 agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; #endif smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; #ifdef NOT_YET agsaFisRegHostToDevice_t *fis; #endif bit32 bufferOffset; bit32 parmLen; bit8 mode; bit8 bufferID; bit8 *pBuff; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; #ifdef NOT_YET fis = satIOContext->pFis; #endif pBuff = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatWriteBuffer: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[9] & SCSI_NACA_MASK) || (scsiCmnd->cdb[9] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteBuffer: return control!!!\n")); return SM_RC_SUCCESS; } 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 */ smhexdump("smsatWriteBuffer pBuff", (bit8 *)pBuff, 24); if (mode == WRITE_BUFFER_DATA_MODE) /* 2 */ { if (bufferID == 0 && bufferOffset == 0 && parmLen == 512) { SM_DBG1(("smsatWriteBuffer: 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 = &smsatWriteBufferCB; satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; #endif /* temp */ /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_GOOD, agNULL, satIOContext->interruptContext); return SM_RC_SUCCESS; } if ( (bufferID == 0 && bufferOffset != 0) || (bufferID == 0 && parmLen != 512) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatWriteBuffer: wrong buffer offset %d or parameter length parmLen %d!!!\n", bufferOffset, parmLen)); return SM_RC_SUCCESS; } /* all other cases unsupported */ SM_DBG1(("smsatWriteBuffer: unsupported case 1!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else if (mode == WRITE_BUFFER_DL_MICROCODE_SAVE_MODE) /* 5 */ { /* temporary */ SM_DBG1(("smsatWriteBuffer: not yet supported mode %d!!!\n", mode)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } else { /* We don't support any other mode */ SM_DBG1(("smsatWriteBuffer: unsupported mode %d!!!\n", mode)); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_COMMAND, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatReassignBlocks( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* assumes all LBA fits in ATA command; no boundary condition is checked here yet */ bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; smIniScsiCmnd_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 = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pParmList = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatReassignBlocks: start\n")); /* checking CONTROL */ /* NACA == 1 or LINK == 1*/ if ( (scsiCmnd->cdb[5] & SCSI_NACA_MASK) || (scsiCmnd->cdb[5] & SCSI_LINK_MASK) ) { smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatReassignBlocks: return control!!!\n")); return SM_RC_SUCCESS; } sm_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); sm_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; } smhexdump("smsatReassignBlocks 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; } sm_memcpy(satIOContext->LBA, LBA, 8); satIOContext->ParmIndex = startingIndex; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatReassignBlocksCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatRead_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* Assumption: error check on lba and tl has been done in satRead*() lba = lba + tl; */ bit32 status; smSatIOContext_t *satOrgIOContext = agNULL; smIniScsiCmnd_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 */ SM_DBG2(("smsatRead_1: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; scsiCmnd = satOrgIOContext->pScsiCmnd; sm_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_READ_DMA: DenomTL = 0x100; break; case SAT_READ_SECTORS: DenomTL = 0x100; 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: SM_DBG1(("smsatRead_1: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xFF000000) >> (8 * 3)); LBA[1] = (bit8)((lba & 0xFF0000) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xFF00) >> 8); LBA[3] = (bit8)(lba & 0xFF); 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 = 0x0; /* 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 = 0x0; /* 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: SM_DBG1(("smsatRead_1: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &smsatChainedDataIOCB; if (satOrgIOContext->ATACmd == SAT_READ_DMA || satOrgIOContext->ATACmd == SAT_READ_SECTORS) { smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)satOrgIOContext->smScsiXchg, satOrgIOContext, NON_BIT48_ADDRESS_TL_LIMIT * SATA_SECTOR_SIZE, /* 0x100 * 0x200*/ (satOrgIOContext->OrgTL) * SATA_SECTOR_SIZE, agFALSE); } else { smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)satOrgIOContext->smScsiXchg, satOrgIOContext, BIT48_ADDRESS_TL_LIMIT * SATA_SECTOR_SIZE, /* 0xFFFF * 0x200*/ (satOrgIOContext->OrgTL) * SATA_SECTOR_SIZE, agFALSE); } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)satOrgIOContext->smScsiXchg, //smScsiRequest, satIOContext); SM_DBG5(("smsatRead_1: return\n")); return (status); } osGLOBAL bit32 smsatWrite_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* Assumption: error check on lba and tl has been done in satWrite*() lba = lba + tl; */ bit32 status; smSatIOContext_t *satOrgIOContext = agNULL; smIniScsiCmnd_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 */ SM_DBG2(("smsatWrite_1: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; scsiCmnd = satOrgIOContext->pScsiCmnd; sm_memset(LBA,0, sizeof(LBA)); switch (satOrgIOContext->ATACmd) { case SAT_WRITE_DMA: DenomTL = 0x100; break; case SAT_WRITE_SECTORS: DenomTL = 0x100; 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: SM_DBG1(("smsatWrite_1: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; break; } Remainder = satOrgIOContext->OrgTL % DenomTL; satOrgIOContext->currentLBA = satOrgIOContext->currentLBA + DenomTL; lba = satOrgIOContext->currentLBA; LBA[0] = (bit8)((lba & 0xFF000000) >> (8 * 3)); LBA[1] = (bit8)((lba & 0xFF0000) >> (8 * 2)); LBA[2] = (bit8)((lba & 0xFF00) >> 8); LBA[3] = (bit8)(lba & 0xFF); 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 = 0x0; /* 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 = 0x0; /* 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: SM_DBG1(("smsatWrite_1: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &smsatChainedDataIOCB; if (satOrgIOContext->ATACmd == SAT_WRITE_DMA || satOrgIOContext->ATACmd == SAT_WRITE_SECTORS) { smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)satOrgIOContext->smScsiXchg, satOrgIOContext, NON_BIT48_ADDRESS_TL_LIMIT * SATA_SECTOR_SIZE, /* 0x100 * 0x200*/ (satOrgIOContext->OrgTL) * SATA_SECTOR_SIZE, agFALSE); } else { smsatSplitSGL(smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)satOrgIOContext->smScsiXchg, satOrgIOContext, BIT48_ADDRESS_TL_LIMIT * SATA_SECTOR_SIZE, /* 0xFFFF * 0x200*/ (satOrgIOContext->OrgTL) * SATA_SECTOR_SIZE, agFALSE); } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, (smScsiInitiatorRequest_t *)satOrgIOContext->smScsiXchg, //smScsiRequest, satIOContext); SM_DBG5(("smsatWrite_1: return\n")); return (status); } osGLOBAL bit32 smsatPassthrough( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { smScsiRspSense_t *pSense; smIniScsiCmnd_t *scsiCmnd; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; bit32 status; bit32 agRequestType; smAtaPassThroughHdr_t ataPassThroughHdr; pSense = satIOContext->pSense; scsiCmnd = &smScsiRequest->scsiCmnd; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG1(("smsatPassthrough: START!!!\n")); osti_memset(&ataPassThroughHdr, 0 , sizeof(smAtaPassThroughHdr_t)); ataPassThroughHdr.opc = scsiCmnd->cdb[0]; ataPassThroughHdr.mulCount = scsiCmnd->cdb[1] >> 5; ataPassThroughHdr.proto = (scsiCmnd->cdb[1] >> 1) & 0x0F; ataPassThroughHdr.extend = scsiCmnd->cdb[1] & 1; ataPassThroughHdr.offline = scsiCmnd->cdb[2] >> 6; ataPassThroughHdr.ckCond = (scsiCmnd->cdb[2] >> 5) & 1; ataPassThroughHdr.tType = (scsiCmnd->cdb[2] >> 4) & 1; ataPassThroughHdr.tDir = (scsiCmnd->cdb[2] >> 3) & 1; ataPassThroughHdr.byteBlock = (scsiCmnd->cdb[2] >> 2) & 1; ataPassThroughHdr.tlength = scsiCmnd->cdb[2] & 0x3; switch(ataPassThroughHdr.proto) { case 0: case 9: agRequestType = AGSA_SATA_PROTOCOL_DEV_RESET; //Device Reset break; case 1: agRequestType = AGSA_SATA_PROTOCOL_SRST_ASSERT; //Software reset break; case 3: agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; //Non Data mode break; case 4: agRequestType = AGSA_SATA_PROTOCOL_PIO_READ; //IO_Data_In mode break; case 5: agRequestType = AGSA_SATA_PROTOCOL_PIO_WRITE; //PIO_Data_out break; case 6: agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; //DMA READ and WRITE break; case 8: agRequestType = AGSA_SATA_ATAP_EXECDEVDIAG; //device diagnostic break; case 12: agRequestType = AGSA_SATA_PROTOCOL_FPDMA_WRITE; //FPDMA Read and Write break; default: agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; //Default Non Data Mode break; } if((ataPassThroughHdr.tlength == 0) && (agRequestType != AGSA_SATA_PROTOCOL_NON_DATA)) { SM_DBG1(("smsatPassthrough SCSI_SNSCODE_INVALID_FIELD_IN_CDB\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } if(scsiCmnd->cdb[0] == 0xA1) { SM_DBG1(("smsatPassthrough A1h: COMMAND: %x FEATURE: %x \n",scsiCmnd->cdb[9],scsiCmnd->cdb[3])); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ fis->h.features = scsiCmnd->cdb[3]; fis->d.sectorCount = scsiCmnd->cdb[4]; /* 0x01 FIS sector count (7:0) */ fis->d.lbaLow = scsiCmnd->cdb[5]; /* Reading LBA FIS LBA (7 :0 ) */ fis->d.lbaMid = scsiCmnd->cdb[6]; fis->d.lbaHigh = scsiCmnd->cdb[7]; fis->d.device = scsiCmnd->cdb[8]; fis->h.command = scsiCmnd->cdb[9]; fis->d.featuresExp = 0; fis->d.sectorCountExp = 0; fis->d.lbaLowExp = 0; fis->d.lbaMidExp = 0; fis->d.lbaHighExp = 0; fis->d.reserved4 = 0; fis->d.control = 0; /* FIS HOB bit clear */ fis->d.reserved5 = 0; /* Initialize CB for SATA completion*/ satIOContext->satCompleteCB = &smsatPassthroughCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else if(scsiCmnd->cdb[0] == 0x85) { SM_DBG1(("smsatPassthrough 85h: COMMAND: %x FEATURE: %x \n",scsiCmnd->cdb[14],scsiCmnd->cdb[4])); fis->h.fisType = 0x27; /* Reg host to device */ fis->h.c_pmPort = 0x80; /* C Bit is set */ if(1 == ataPassThroughHdr.extend) { fis->d.featuresExp = scsiCmnd->cdb[3]; fis->d.sectorCountExp = scsiCmnd->cdb[5]; fis->d.lbaMidExp = scsiCmnd->cdb[9]; fis->d.lbaHighExp = scsiCmnd->cdb[11]; fis->d.lbaLowExp = scsiCmnd->cdb[7]; } fis->h.features = scsiCmnd->cdb[4]; fis->d.sectorCount = scsiCmnd->cdb[6]; fis->d.lbaLow = scsiCmnd->cdb[8]; fis->d.lbaMid = scsiCmnd->cdb[10]; fis->d.lbaHigh = scsiCmnd->cdb[12]; fis->d.device = scsiCmnd->cdb[13]; fis->h.command = scsiCmnd->cdb[14]; fis->d.reserved4 = 0; fis->d.control = 0; fis->d.reserved5 = 0; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatPassthroughCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG1(("smsatPassthrough : INVALD PASSTHROUGH!!!\n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_ILLEGAL_REQUEST, 0, SCSI_SNSCODE_INVALID_FIELD_IN_CDB, satIOContext); tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); SM_DBG1(("smsatPassthrough : return control!!!\n")); return SM_RC_SUCCESS; } } osGLOBAL bit32 smsatNonChainedWriteNVerify_Verify( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType = AGSA_SATA_PROTOCOL_DMA_WRITE; smDeviceData_t *pSatDevData; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatNonChainedWriteNVerify_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 = &smsatNonChainedWriteNVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG1(("smsatNonChainedWriteNVerify_Verify: return status %d!!!\n", status)); return (status); } else { /* can't fit in SAT_READ_VERIFY_SECTORS becasue of Sector Count and LBA */ SM_DBG1(("smsatNonChainedWriteNVerify_Verify: can't fit in SAT_READ_VERIFY_SECTORS!!!\n")); return SM_RC_FAILURE; } } osGLOBAL bit32 smsatChainedWriteNVerify_Start_Verify( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; smDeviceData_t *pSatDevData; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit32 lba = 0; bit32 tl = 0; bit32 LoopNum = 1; bit8 LBA[4]; bit8 TL[4]; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; SM_DBG5(("smsatChainedWriteNVerify_Start_Verify: start\n")); sm_memset(LBA, 0, sizeof(LBA)); sm_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 = smsatComputeCDB12LBA(satIOContext); tl = smsatComputeCDB12TL(satIOContext); if (pSatDevData->sat48BitSupport == agTRUE) { SM_DBG5(("smsatChainedWriteNVerify_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 { SM_DBG5(("smsatChainedWriteNVerify_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 = smsatComputeLoopNum(tl, 0xFF); } else if (fis->h.command == SAT_READ_VERIFY_SECTORS_EXT) { /* SAT_READ_SECTORS_EXT, SAT_READ_DMA_EXT */ LoopNum = smsatComputeLoopNum(tl, 0xFFFF); } else { SM_DBG1(("smsatChainedWriteNVerify_Start_Verify: error case 1!!!\n")); LoopNum = 1; } satIOContext->LoopNum = LoopNum; if (LoopNum == 1) { SM_DBG5(("smsatChainedWriteNVerify_Start_Verify: NON CHAINED data\n")); /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatNonChainedWriteNVerifyCB; } else { SM_DBG1(("smsatChainedWriteNVerify_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 { SM_DBG1(("smsatChainedWriteNVerify_Start_Verify: error case 2!!!\n")); } /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatChainedWriteNVerifyCB; } /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatChainedWriteNVerify_Write( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* Assumption: error check on lba and tl has been done in satWrite*() lba = lba + tl; */ bit32 status; smSatIOContext_t *satOrgIOContext = agNULL; smIniScsiCmnd_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 */ SM_DBG1(("smsatChainedWriteNVerify_Write: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; scsiCmnd = satOrgIOContext->pScsiCmnd; sm_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: SM_DBG1(("satChainedWriteNVerify_Write: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; 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: SM_DBG1(("satChainedWriteNVerify_Write: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &smsatChainedWriteNVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("satChainedWriteNVerify_Write: return\n")); return (status); } osGLOBAL bit32 smsatChainedWriteNVerify_Verify( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; smSatIOContext_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 */ SM_DBG2(("smsatChainedWriteNVerify_Verify: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; sm_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: SM_DBG1(("smsatChainedWriteNVerify_Verify: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; 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: SM_DBG1(("smsatChainedWriteNVerify_Verify: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return SM_RC_FAILURE; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &smsatChainedWriteNVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatChainedWriteNVerify_Verify: return\n")); return (status); } osGLOBAL bit32 smsatChainedVerify( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; smSatIOContext_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 */ SM_DBG2(("smsatChainedVerify: start\n")); fis = satIOContext->pFis; satOrgIOContext = satIOContext->satOrgIOContext; sm_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: SM_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: SM_DBG1(("satChainedVerify: error incorrect ata command 0x%x!!!\n", satIOContext->ATACmd)); return tiError; break; } /* Initialize CB for SATA completion. */ /* chained data */ satIOContext->satCompleteCB = &smsatChainedVerifyCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("satChainedVerify: return\n")); return (status); } osGLOBAL bit32 smsatWriteSame10_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext, bit32 lba ) { /* sends SAT_WRITE_DMA_EXT */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 lba1, lba2 ,lba3, lba4; SM_DBG5(("smsatWriteSame10_1: start\n")); 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 = &smsatWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatWriteSame10_1 return status %d\n", status)); return status; } osGLOBAL bit32 smsatWriteSame10_2( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext, bit32 lba ) { /* sends SAT_WRITE_SECTORS_EXT */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 lba1, lba2 ,lba3, lba4; SM_DBG5(("smsatWriteSame10_2: start\n")); 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 = &smsatWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatWriteSame10_2 return status %d\n", status)); return status; } osGLOBAL bit32 smsatWriteSame10_3( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext, bit32 lba ) { /* sends SAT_WRITE_FPDMA_QUEUED */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; bit8 lba1, lba2 ,lba3, lba4; SM_DBG5(("smsatWriteSame10_3: start\n")); 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 = &smsatWriteSame10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatWriteSame10_3 return status %d\n", status)); return status; } osGLOBAL bit32 smsatStartStopUnit_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* SAT Rev 8, Table 48, 9.11.3 p55 sends STANDBY */ bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; SM_DBG5(("smsatStartStopUnit_1: start\n")); 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 = &smsatStartStopUnitCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatStartStopUnit_1 return status %d\n", status)); return status; } osGLOBAL bit32 smsatSendDiagnostic_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* SAT Rev9, Table29, p41 send 2nd SAT_READ_VERIFY_SECTORS(_EXT) */ bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; SM_DBG5(("smsatSendDiagnostic_1: start\n")); 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatSendDiagnostic_2( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { /* SAT Rev9, Table29, p41 send 3rd SAT_READ_VERIFY_SECTORS(_EXT) */ bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; SM_DBG5(("smsatSendDiagnostic_2: start\n")); 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 = &smsatSendDiagnosticCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } osGLOBAL bit32 smsatModeSelect6n10_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatModeSelect6n10_1: start\n")); 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) ) { SM_DBG5(("smsatModeSelect6n10_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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG5(("smsatModeSelect6n10_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 = &smsatModeSelect6n10CB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } osGLOBAL bit32 smsatLogSense_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG5(("smsatLogSense_1: start\n")); /* SAT Rev 8, 10.2.4 p74 */ if ( pSatDevData->sat48BitSupport == agTRUE ) { SM_DBG5(("smsatLogSense_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 = &smsatLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } else { SM_DBG5(("smsatLogSense_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; /* 0x2F */ fis->h.features = SAT_SMART_READ_LOG; /* 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 = &smsatLogSenseCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return status; } } osGLOBAL bit32 smsatReassignBlocks_2( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; smDeviceData_t *pSatDevData; smScsiRspSense_t *pSense; agsaFisRegHostToDevice_t *fis; pSense = satIOContext->pSense; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG5(("smsatReassignBlocks_2: start\n")); if (pSatDevData->satDMASupport == agTRUE && pSatDevData->satDMAEnabled == agTRUE) { /* case 2 */ /* WRITE DMA*/ /* can't fit the transfer length */ SM_DBG5(("smsatReassignBlocks_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 */ SM_DBG5(("smsatReassignBlocks_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 */ SM_DBG5(("smsatReassignBlocks_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 */ SM_DBG5(("smsatReassignBlocks_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) { SM_DBG5(("smsatReassignBlocks_2: case 5 !!! error NCQ but 28 bit address support \n")); smsatSetSensePayload( pSense, SCSI_SNSKEY_HARDWARE_ERROR, 0, SCSI_SNSCODE_WRITE_ERROR_AUTO_REALLOCATION_FAILED, satIOContext); /*smEnqueueIO(smRoot, satIOContext);*/ tdsmIOCompletedCB( smRoot, smIORequest, smIOSuccess, SCSI_STAT_CHECK_CONDITION, satIOContext->pSmSenseData, satIOContext->interruptContext ); return SM_RC_SUCCESS; } SM_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 = &smsatReassignBlocksCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, /* not the original, should be the TD generated one */ smScsiRequest, satIOContext); return (status); } osGLOBAL bit32 smsatReassignBlocks_1( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext, smSatIOContext_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; smDeviceData_t *pSatDevData; smIniScsiCmnd_t *scsiCmnd; agsaFisRegHostToDevice_t *fis; bit8 *pParmList; /* Log Page data buffer */ bit8 LongLBA; bit8 LBA[8]; bit32 startingIndex; pSatDevData = satIOContext->pSatDevData; scsiCmnd = &smScsiRequest->scsiCmnd; fis = satIOContext->pFis; pParmList = (bit8 *) smScsiRequest->sglVirtualAddr; SM_DBG5(("smsatReassignBlocks_1: start\n")); LongLBA = (bit8)(scsiCmnd->cdb[1] & SCSI_REASSIGN_BLOCKS_LONGLBA_MASK); sm_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; } sm_memcpy(satOrgIOContext->LBA, LBA, 8); satOrgIOContext->ParmIndex = startingIndex; agRequestType = AGSA_SATA_PROTOCOL_NON_DATA; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatReassignBlocksCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); return SM_RC_SUCCESS; } osGLOBAL bit32 smsatSendReadLogExt( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG1(("smsatSendReadLogExt: start\n")); 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 = &smsatReadLogExtCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG1(("smsatSendReadLogExt: end status %d!!!\n", status)); return (status); } osGLOBAL bit32 smsatCheckPowerMode( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_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; SM_DBG1(("smsatCheckPowerMode: 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 = &smsatCheckPowerModeCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG5(("smsatCheckPowerMode: return\n")); return status; } osGLOBAL bit32 smsatResetDevice( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, /* NULL */ smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE smIORequestBody_t *smIORequestBody; smSatInternalIo_t *satIntIoContext; #endif fis = satIOContext->pFis; SM_DBG1(("smsatResetDevice: start\n")); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; smIORequestBody = satIntIoContext->satIntRequestBody; #endif SM_DBG5(("smsatResetDevice: satIOContext %p smIORequestBody %p\n", satIOContext, smIORequestBody)); /* 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; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatResetDeviceCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef SM_INTERNAL_DEBUG smhexdump("smsatResetDevice", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE smhexdump("smsatResetDevice LL", (bit8 *)&(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG6(("smsatResetDevice: end status %d\n", status)); return status; } osGLOBAL bit32 smsatDeResetDevice( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; #ifdef TD_DEBUG_ENABLE smIORequestBody_t *smIORequestBody; smSatInternalIo_t *satIntIoContext; #endif fis = satIOContext->pFis; SM_DBG1(("smsatDeResetDevice: start\n")); #ifdef TD_DEBUG_ENABLE satIntIoContext = satIOContext->satIntIoContext; smIORequestBody = satIntIoContext->satIntRequestBody; #endif SM_DBG5(("smsatDeResetDevice: satIOContext %p smIORequestBody %p\n", satIOContext, smIORequestBody)); /* 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; /* Initialize CB for SATA completion. */ satIOContext->satCompleteCB = &smsatDeResetDeviceCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ #ifdef SM_INTERNAL_DEBUG smhexdump("smsatDeResetDevice", (bit8 *)satIOContext->pFis, sizeof(agsaFisRegHostToDevice_t)); #ifdef TD_DEBUG_ENABLE smhexdump("smsatDeResetDevice LL", (bit8 *)&(smIORequestBody->transport.SATA.agSATARequestBody.fis.fisRegHostToDev), sizeof(agsaFisRegHostToDevice_t)); #endif #endif status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); SM_DBG6(("smsatDeResetDevice: end status %d\n", status)); return status; } /* set feature for auto activate */ osGLOBAL bit32 smsatSetFeaturesAA( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status = SM_RC_FAILURE; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG2(("smsatSetFeaturesAA: start\n")); /* * Send the Set Features command. * See SATA II 1.0a spec */ 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 = 0x10; /* enable SATA feature */ 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 = 0x02; /* DMA Setup FIS Auto-Activate */ 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 = &smsatSetFeaturesAACB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); /* debugging code */ if (smIORequest->tdData == smIORequest->smData) { SM_DBG1(("smsatSetFeaturesAA: incorrect smIORequest\n")); } SM_DBG2(("smsatSetFeatures: return\n")); return status; } /* set feature for DMA transfer mode*/ osGLOBAL bit32 smsatSetFeaturesDMA( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status = SM_RC_FAILURE; bit32 agRequestType; smDeviceData_t *pSatDevData; agsaFisRegHostToDevice_t *fis; pSatDevData = satIOContext->pSatDevData; fis = satIOContext->pFis; SM_DBG2(("smsatSetFeaturesDMA: start\n")); /* * Send the Set Features command. * See SATA II 1.0a spec */ 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; /* enable ATA 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.sectorCount = 0x40 |(bit8)pSatDevData->satUltraDMAMode; /* enable Ultra DMA mode */ 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 = &smsatSetFeaturesDMACB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); /* debugging code */ if (smIORequest->tdData == smIORequest->smData) { SM_DBG1(("smsatSetFeaturesDMA: incorrect smIORequest\n")); } SM_DBG2(("smsatSetFeaturesDMA: return\n")); return status; } /* set feature for Read Look Ahead*/ osGLOBAL bit32 smsatSetFeaturesReadLookAhead( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status = SM_RC_FAILURE; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG2(("smsatSetFeaturesReadLookAhead: start\n")); /* * Send the Set Features command. * See SATA II 1.0a spec */ 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 feature */ 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 = &smsatSetFeaturesReadLookAheadCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); /* debugging code */ if (smIORequest->tdData == smIORequest->smData) { SM_DBG1(("smsatSetFeaturesReadLookAhead: incorrect smIORequest\n")); } SM_DBG2(("smsatSetFeaturesReadLookAhead: return\n")); return status; } /* set feature for Volatile Write Cache*/ osGLOBAL bit32 smsatSetFeaturesVolatileWriteCache( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext ) { bit32 status = SM_RC_FAILURE; bit32 agRequestType; agsaFisRegHostToDevice_t *fis; fis = satIOContext->pFis; SM_DBG2(("smsatSetFeaturesVolatileWriteCache: start\n")); /* * Send the Set Features command. * See SATA II 1.0a spec */ 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 Volatile Write Cache feature */ 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 = &smsatSetFeaturesVolatileWriteCacheCB; /* * Prepare SGL and send FIS to LL layer. */ satIOContext->reqType = agRequestType; /* Save it */ status = smsataLLIOStart( smRoot, smIORequest, smDeviceHandle, smScsiRequest, satIOContext); /* debugging code */ if (smIORequest->tdData == smIORequest->smData) { SM_DBG1(("smsatSetFeaturesVolatileWriteCache: incorrect smIORequest\n")); } SM_DBG2(("smsatSetFeaturesVolatileWriteCache: return\n")); return status; } /******************************** start of utils ***********************************************************/ osGLOBAL FORCEINLINE void smsatBitSet(smRoot_t *smRoot, bit8 *data, bit32 index) { data[index>>3] |= (1 << (index&7)); } osGLOBAL FORCEINLINE void smsatBitClear(smRoot_t *smRoot, bit8 *data, bit32 index) { data[index>>3] &= ~(1 << (index&7)); } osGLOBAL FORCEINLINE BOOLEAN smsatBitTest(smRoot_t *smRoot, bit8 *data, bit32 index) { return ( (BOOLEAN)((data[index>>3] & (1 << (index&7)) ) ? 1: 0)); } FORCEINLINE bit32 smsatTagAlloc( smRoot_t *smRoot, smDeviceData_t *pSatDevData, bit8 *pTag ) { bit32 retCode = agFALSE; bit32 i; tdsmSingleThreadedEnter(smRoot, SM_NCQ_TAG_LOCK); #ifdef CCFLAG_OPTIMIZE_SAT_LOCK if (tdsmBitScanForward(smRoot, &i, ~(pSatDevData->freeSATAFDMATagBitmap))) { smsatBitSet(smRoot, (bit8*)&pSatDevData->freeSATAFDMATagBitmap, i); *pTag = (bit8)i; retCode = agTRUE; } #else for ( i = 0; i < pSatDevData->satNCQMaxIO; i ++ ) { if ( 0 == smsatBitTest(smRoot, (bit8 *)&pSatDevData->freeSATAFDMATagBitmap, i) ) { smsatBitSet(smRoot, (bit8*)&pSatDevData->freeSATAFDMATagBitmap, i); *pTag = (bit8) i; retCode = agTRUE; break; } } #endif tdsmSingleThreadedLeave(smRoot, SM_NCQ_TAG_LOCK); return retCode; } FORCEINLINE bit32 smsatTagRelease( smRoot_t *smRoot, smDeviceData_t *pSatDevData, bit8 tag ) { bit32 retCode = agFALSE; if ( tag < pSatDevData->satNCQMaxIO ) { tdsmSingleThreadedEnter(smRoot, SM_NCQ_TAG_LOCK); smsatBitClear(smRoot, (bit8 *)&pSatDevData->freeSATAFDMATagBitmap, (bit32)tag); tdsmSingleThreadedLeave(smRoot, SM_NCQ_TAG_LOCK); /*tdsmInterlockedAnd(smRoot, (volatile LONG *)(&pSatDevData->freeSATAFDMATagBitmap), ~(1 << (tag&31)));*/ retCode = agTRUE; } else { SM_DBG1(("smsatTagRelease: tag %d >= satNCQMaxIO %d!!!!\n", tag, pSatDevData->satNCQMaxIO)); } return retCode; } osGLOBAL bit32 smsatComputeCDB10LBA(smSatIOContext_t *satIOContext) { smIniScsiCmnd_t *scsiCmnd; smScsiInitiatorRequest_t *smScsiRequest; bit32 lba = 0; SM_DBG5(("smsatComputeCDB10LBA: start\n")); smScsiRequest = satIOContext->smScsiXchg; scsiCmnd = &(smScsiRequest->scsiCmnd); lba = (scsiCmnd->cdb[2] << (8*3)) + (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; return lba; } osGLOBAL bit32 smsatComputeCDB10TL(smSatIOContext_t *satIOContext) { smIniScsiCmnd_t *scsiCmnd; smScsiInitiatorRequest_t *smScsiRequest; bit32 tl = 0; SM_DBG5(("smsatComputeCDB10TL: start\n")); smScsiRequest = satIOContext->smScsiXchg; scsiCmnd = &(smScsiRequest->scsiCmnd); tl = (scsiCmnd->cdb[7] << 8) + scsiCmnd->cdb[8]; return tl; } osGLOBAL bit32 smsatComputeCDB12LBA(smSatIOContext_t *satIOContext) { smIniScsiCmnd_t *scsiCmnd; smScsiInitiatorRequest_t *smScsiRequest; bit32 lba = 0; SM_DBG5(("smsatComputeCDB12LBA: start\n")); smScsiRequest = satIOContext->smScsiXchg; scsiCmnd = &(smScsiRequest->scsiCmnd); lba = (scsiCmnd->cdb[2] << (8*3)) + (scsiCmnd->cdb[3] << (8*2)) + (scsiCmnd->cdb[4] << 8) + scsiCmnd->cdb[5]; return lba; } osGLOBAL bit32 smsatComputeCDB12TL(smSatIOContext_t *satIOContext) { smIniScsiCmnd_t *scsiCmnd; smScsiInitiatorRequest_t *smScsiRequest; bit32 tl = 0; SM_DBG5(("smsatComputeCDB12TL: start\n")); smScsiRequest = satIOContext->smScsiXchg; scsiCmnd = &(smScsiRequest->scsiCmnd); tl = (scsiCmnd->cdb[6] << (8*3)) + (scsiCmnd->cdb[7] << (8*2)) + (scsiCmnd->cdb[8] << 8) + scsiCmnd->cdb[9]; return tl; } /* CBD16 has bit64 LBA But it has to be less than (2^28 - 1) Therefore, use last four bytes to compute LBA is OK */ osGLOBAL bit32 smsatComputeCDB16LBA(smSatIOContext_t *satIOContext) { smIniScsiCmnd_t *scsiCmnd; smScsiInitiatorRequest_t *smScsiRequest; bit32 lba = 0; SM_DBG5(("smsatComputeCDB16LBA: start\n")); smScsiRequest = satIOContext->smScsiXchg; scsiCmnd = &(smScsiRequest->scsiCmnd); lba = (scsiCmnd->cdb[6] << (8*3)) + (scsiCmnd->cdb[7] << (8*2)) + (scsiCmnd->cdb[8] << 8) + scsiCmnd->cdb[9]; return lba; } osGLOBAL bit32 smsatComputeCDB16TL(smSatIOContext_t *satIOContext) { smIniScsiCmnd_t *scsiCmnd; smScsiInitiatorRequest_t *smScsiRequest; bit32 tl = 0; SM_DBG5(("smsatComputeCDB16TL: start\n")); smScsiRequest = satIOContext->smScsiXchg; scsiCmnd = &(smScsiRequest->scsiCmnd); tl = (scsiCmnd->cdb[10] << (8*3)) + (scsiCmnd->cdb[11] << (8*2)) + (scsiCmnd->cdb[12] << 8) + scsiCmnd->cdb[13]; return tl; } /* (tl, denom) tl can be upto bit32 because CDB16 has bit32 tl Therefore, fine either (tl, 0xFF) or (tl, 0xFFFF) */ osGLOBAL FORCEINLINE bit32 smsatComputeLoopNum(bit32 a, bit32 b) { bit32 LoopNum = 0; SM_DBG5(("smsatComputeLoopNum: start\n")); if (a < b || a == 0) { LoopNum = 1; } else { if (a == b || a == 0) { LoopNum = a/b; } else { LoopNum = a/b + 1; } } return LoopNum; } /* Generic new function for checking LBA itself, LBA+TL < SAT_TR_LBA_LIMIT or SAT_EXT_TR_LBA_LIMIT and LBA+TL < Read Capacity Limit flag: false - not 48BitSupport; true - 48BitSupport returns TRUE when over the limit */ osGLOBAL FORCEINLINE bit32 smsatCheckLimit(bit8 *lba, bit8 *tl, int flag, smDeviceData_t *pSatDevData) { bit32 lbaCheck = agFALSE; int i; bit8 limit[8]; bit32 rangeCheck = agFALSE; bit16 ans[8]; // 0 MSB, 8 LSB bit8 final_ans[9]; // 0 MSB, 9 LSB bit8 Bit28max[8]; bit8 Bit48max[8]; bit32 ReadCapCheck = agFALSE; bit32 ret; bit8 final_satMaxLBA[9]; bit8 oneTL[8]; bit8 temp_satMaxLBA[8]; // 0 MSB, 8 LSB /* check LBA */ if (flag == agFALSE) { /* 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 */ } else { /* limit is 0xF FF FF = 2^48 - 1 */ limit[0] = 0x0; /* MSB */ limit[1] = 0x0; limit[2] = 0xFF; limit[3] = 0xFF; limit[4] = 0xFF; 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]) { SM_DBG1(("smsatCheckLimit: LBA check True at %d\n", i)); lbaCheck = agTRUE; break; } else if (lba[i] < limit[i]) { SM_DBG5(("smsatCheckLimit: LBA check False at %d\n", i)); lbaCheck = agFALSE; break; } else { continue; } } if (lbaCheck == agTRUE) { SM_DBG1(("smsatCheckLimit: return LBA check True\n")); return agTRUE; } /* check LBA+TL < SAT_TR_LBA_LIMIT or SAT_EXT_TR_LBA_LIMIT */ sm_memset(ans, 0, sizeof(ans)); sm_memset(final_ans, 0, sizeof(final_ans)); // adding from LSB to MSB for(i=7;i>=0;i--) { ans[i] = (bit16)(lba[i] + tl[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)); for(i=1;i<=8;i++) { final_ans[i] = (bit8)(ans[i-1] & 0xFF); } if (flag == agFALSE) { sm_memset(Bit28max, 0, sizeof(Bit28max)); Bit28max[4] = 0x10; // max =0x1000 0000 //compare final_ans to max if (final_ans[0] != 0 || final_ans[1] != 0 || final_ans[2] != 0 || final_ans[3] != 0 || final_ans[4] != 0) { SM_DBG1(("smsatCheckLimit: before 28Bit addressing TRUE\n")); rangeCheck = agTRUE; } else { for(i=5;i<=8;i++) { if (final_ans[i] > Bit28max[i-1]) { SM_DBG1(("smsatCheckLimit: 28Bit addressing TRUE at %d\n", i)); rangeCheck = agTRUE; break; } else if (final_ans[i] < Bit28max[i-1]) { SM_DBG5(("smsatCheckLimit: 28Bit addressing FALSE at %d\n", i)); rangeCheck = agFALSE; break; } else { continue; } } } } else { sm_memset(Bit48max, 0, sizeof(Bit48max)); Bit48max[1] = 0x1; //max = 0x1 0000 0000 0000 //compare final_ans to max if (final_ans[0] != 0 || final_ans[1] != 0) { SM_DBG1(("smsatCheckLimit: before 48Bit addressing TRUE\n")); rangeCheck = agTRUE; } else { for(i=2;i<=8;i++) { if (final_ans[i] > Bit48max[i-1]) { SM_DBG1(("smsatCheckLimit: 48Bit addressing TRUE at %d\n", i)); rangeCheck = agTRUE; break; } else if (final_ans[i] < Bit48max[i-1]) { SM_DBG5(("smsatCheckLimit: 48Bit addressing FALSE at %d\n", i)); rangeCheck = agFALSE; break; } else { continue; } } } } if (rangeCheck == agTRUE) { SM_DBG1(("smsatCheckLimit: return rangeCheck True\n")); return agTRUE; } /* LBA+TL < Read Capacity Limit */ sm_memset(temp_satMaxLBA, 0, sizeof(temp_satMaxLBA)); sm_memset(oneTL, 0, sizeof(oneTL)); sm_memset(final_satMaxLBA, 0, sizeof(final_satMaxLBA)); sm_memset(ans, 0, sizeof(ans)); sm_memcpy(&temp_satMaxLBA, &pSatDevData->satMaxLBA, sizeof(temp_satMaxLBA)); oneTL[7] = 1; // adding temp_satMaxLBA to oneTL for(i=7;i>=0;i--) { ans[i] = (bit16)(temp_satMaxLBA[i] + oneTL[i]); if (i != 7) { ans[i] = (bit16)(ans[i] + ((ans[i+1] & 0xFF00) >> 8)); } } /* filling in the final answer */ final_satMaxLBA[0] = (bit8)(((ans[0] & 0xFF00) >> 8)); for(i=1;i<=8;i++) { final_satMaxLBA[i] = (bit8)(ans[i-1] & 0xFF); } if ( pSatDevData->ReadCapacity == 10) { for (i=0;i<=8;i++) { if (final_ans[i] > final_satMaxLBA[i]) { SM_DBG1(("smsatCheckLimit: Read Capacity 10 TRUE at %d\n", i)); ReadCapCheck = agTRUE; break; } else if (final_ans[i] < final_satMaxLBA[i]) { SM_DBG5(("smsatCheckLimit: Read Capacity 10 FALSE at %d\n", i)); ReadCapCheck = agFALSE; break; } else { continue; } } if ( ReadCapCheck) { SM_DBG1(("smsatCheckLimit: after Read Capacity 10 TRUE\n")); } else { SM_DBG5(("smsatCheckLimit: after Read Capacity 10 FALSE\n")); } } else if ( pSatDevData->ReadCapacity == 16) { for (i=0;i<=8;i++) { if (final_ans[i] > final_satMaxLBA[i]) { SM_DBG1(("smsatCheckLimit: Read Capacity 16 TRUE at %d\n", i)); ReadCapCheck = agTRUE; break; } else if (final_ans[i] < final_satMaxLBA[i]) { SM_DBG5(("smsatCheckLimit: Read Capacity 16 FALSE at %d\n", i)); ReadCapCheck = agFALSE; break; } else { continue; } } if ( ReadCapCheck) { SM_DBG1(("smsatCheckLimit: after Read Capacity 16 TRUE\n")); } else { SM_DBG5(("smsatCheckLimit: after Read Capacity 16 FALSE\n")); } } else { SM_DBG5(("smsatCheckLimit: unknown pSatDevData->ReadCapacity %d\n", pSatDevData->ReadCapacity)); } if (ReadCapCheck == agTRUE) { SM_DBG1(("smsatCheckLimit: return ReadCapCheck True\n")); return agTRUE; } ret = (lbaCheck | rangeCheck | ReadCapCheck); if (ret == agTRUE) { SM_DBG1(("smsatCheckLimit: final check TRUE\n")); } else { SM_DBG5(("smsatCheckLimit: final check FALSE\n")); } return ret; } osGLOBAL void smsatPrintSgl( smRoot_t *smRoot, agsaEsgl_t *agEsgl, bit32 idx ) { bit32 i=0; #ifdef TD_DEBUG_ENABLE agsaSgl_t *agSgl; #endif for (i=0;idescriptor[i]); #endif SM_DBG3(("smsatPrintSgl: agSgl %d upperAddr 0x%08x lowerAddr 0x%08x len 0x%08x ext 0x%08x\n", i, agSgl->sgUpper, agSgl->sgLower, agSgl->len, agSgl->extReserved)); } return; } osGLOBAL void smsatSplitSGL( smRoot_t *smRoot, smIORequest_t *smIORequest, smDeviceHandle_t *smDeviceHandle, smScsiInitiatorRequest_t *smScsiRequest, smSatIOContext_t *satIOContext, bit32 split, /*in sector number, depeding on IO value */ bit32 tl, /* in sector number */ bit32 flag ) { agsaSgl_t *agSgl; agsaEsgl_t *agEsgl; bit32 i=0; smIniScsiCmnd_t *scsiCmnd; bit32 totalLen=0; /* in bytes */ bit32 splitLen=0; /* in bytes */ bit32 splitDiffByte = 0; /* in bytes */ bit32 splitDiffExtra = 0; /* in bytes */ bit32 splitIdx = 0; bit32 UpperAddr, LowerAddr; bit32 tmpLowerAddr; void *sglVirtualAddr; void *sglSplitVirtualAddr; scsiCmnd = &smScsiRequest->scsiCmnd; SM_DBG3(("smsatSplitSGL: start\n")); if (smScsiRequest->smSgl1.type == 0x80000000) /* esgl */ { if (flag == agFALSE) { SM_DBG3(("smsatSplitSGL: Not first time\n")); SM_DBG3(("smsatSplitSGL: UpperAddr 0x%08x LowerAddr 0x%08x\n", satIOContext->UpperAddr, satIOContext->LowerAddr)); SM_DBG3(("smsatSplitSGL: SplitIdx %d AdjustBytes 0x%08x\n", satIOContext->SplitIdx, satIOContext->AdjustBytes)); sglVirtualAddr = smScsiRequest->sglVirtualAddr; agEsgl = (agsaEsgl_t *)smScsiRequest->sglVirtualAddr; sglSplitVirtualAddr = &(agEsgl->descriptor[satIOContext->SplitIdx]); agEsgl = (agsaEsgl_t *)sglSplitVirtualAddr; if (agEsgl == agNULL) { SM_DBG1(("smsatSplitSGL: error!\n")); return; } /* first sgl ajustment */ agSgl = &(agEsgl->descriptor[0]); agSgl->sgUpper = satIOContext->UpperAddr; agSgl->sgLower = satIOContext->LowerAddr; agSgl->len = satIOContext->AdjustBytes; sm_memcpy(sglVirtualAddr, sglSplitVirtualAddr, (satIOContext->EsglLen) * sizeof(agsaSgl_t)); agEsgl = (agsaEsgl_t *)smScsiRequest->sglVirtualAddr; smsatPrintSgl(smRoot, (agsaEsgl_t *)sglVirtualAddr, satIOContext->EsglLen); } else { /* first time */ SM_DBG3(("smsatSplitSGL: first time\n")); satIOContext->EsglLen = smScsiRequest->smSgl1.len; agEsgl = (agsaEsgl_t *)smScsiRequest->sglVirtualAddr; if (agEsgl == agNULL) { return; } smsatPrintSgl(smRoot, agEsgl, satIOContext->EsglLen); } if (tl > split) { /* split */ SM_DBG3(("smsatSplitSGL: split case\n")); i = 0; while (1) { agSgl = &(agEsgl->descriptor[i]); splitLen = splitLen + agSgl->len; if (splitLen >= split) { splitDiffExtra = splitLen - split; splitDiffByte = agSgl->len - splitDiffExtra; splitIdx = i; break; } i++; } SM_DBG3(("smsatSplitSGL: splitIdx %d\n", splitIdx)); SM_DBG3(("smsatSplitSGL: splitDiffByte 0x%8x\n", splitDiffByte)); SM_DBG3(("smsatSplitSGL: splitDiffExtra 0x%8x \n", splitDiffExtra)); agSgl = &(agEsgl->descriptor[splitIdx]); UpperAddr = agSgl->sgUpper; LowerAddr = agSgl->sgLower; tmpLowerAddr = LowerAddr + splitDiffByte; if (tmpLowerAddr < LowerAddr) { UpperAddr = UpperAddr + 1; } SM_DBG3(("smsatSplitSGL: UpperAddr 0x%08x tmpLowerAddr 0x%08x\n", UpperAddr, tmpLowerAddr)); agSgl->len = splitDiffByte; /* Esgl len adjustment */ smScsiRequest->smSgl1.len = splitIdx; /* expected data lent adjustment */ scsiCmnd->expDataLength = 0x20000; /* remeber for the next round */ satIOContext->UpperAddr = UpperAddr; satIOContext->LowerAddr = tmpLowerAddr; satIOContext->SplitIdx = splitIdx; satIOContext->AdjustBytes = splitDiffExtra; satIOContext->EsglLen = satIOContext->EsglLen - smScsiRequest->smSgl1.len; satIOContext->OrgTL = satIOContext->OrgTL - 0x100; // smsatPrintSgl(smRoot, agEsgl, satIOContext->EsglLen); } else { /* no split */ SM_DBG3(("smsatSplitSGL: no split case\n")); /* Esgl len adjustment */ smScsiRequest->smSgl1.len = satIOContext->EsglLen; for (i=0;i< smScsiRequest->smSgl1.len;i++) { agSgl = &(agEsgl->descriptor[i]); totalLen = totalLen + (agSgl->len); } /* expected data lent adjustment */ scsiCmnd->expDataLength = totalLen; // smsatPrintSgl(smRoot, agEsgl, satIOContext->EsglLen); } } else { SM_DBG1(("not exntened esgl\n")); } return; } /******************************** end of utils ***********************************************************/