scsi2sata.c
来自「6440linuxDriver的源代码」· C语言 代码 · 共 1,717 行 · 第 1/4 页
C
1,717 行
break; }}/**************************************************************************** SCSI_ATA_ModeSenseTranslation* Purpose: Translate Mode Sense SCSI command ****************************************************************************/void SCSI_ATA_ModeSenseTranslation( IN PDomain_Device pDevice, IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ MV_PU8 pModePageBuf = NULL;// PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK) pReq->Org_Req; MV_U8 length = 0; // DBD bit field if( (pReq->Cdb[1] & 0x8) !=0 ) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB|SCSI_ASC_INVALID_FIELD_IN_PARAMETER ); } // PC bit field if( (pReq->Cdb[2] & 0xC0) != 0) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); } /* * SAT translation for mode sense/select 6 from spec * modePageBuf[0] = Mode Data length (Unspecified) * modePageBuf[1] = Medium Type (support 00h only) * modePageBuf[2] = Device Specific Parameter (Sense 0 only and select is unspecified) * modePageBuf[3] = Block Descriptor length (00h) * * mode sense/select 8 is similar with extended fields of 0 */ // Move pointer to the array location and find the size of the parameter header if( pReq->Cdb[0] == SCSI_CMD_MODE_SELECT_6) { pModePageBuf = &modePageBuf[4]; length = 4; // size of header } else if( pReq->Cdb[0] == SCSI_CMD_MODE_SELECT_10 ){ pModePageBuf = &modePageBuf[8]; length = 8; // size of header } // Page Code handling switch(pReq->Cdb[2] & 0x3F) { case 0x0A: SCSI_ATA_FillCtrlModePage(pModePageBuf, pDevice); length += 12; break; case 0x01: SCSI_ATA_FillRWErrorRecoveryModePage(pModePageBuf); length += 12; break; case 0x08: SCSI_ATA_FillCachingModePage(pModePageBuf, pDevice); length += 20; break; case 0x1C: SCSI_ATA_FillInfoExcepCtrlModePage(pModePageBuf, pDevice, pReq); length += 12; break; default: SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } pReq->Cdb[4] = length; // allocation length MV_CopyMemory(pReq->Data_Buffer, &modePageBuf, sizeof(modePageBuf));}/**************************************************************************** SCSI_ATA_ModeSelectTranslation* Purpose: Translate Mode Sense SCSI command ****************************************************************************/void SCSI_ATA_ModeSelectTranslation( IN IN PDomain_Device pDevice, IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ MV_PU8 pModePageBuf = NULL; int length = 0; if( (pReq->Cdb[1] & 0x10)==0) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); } /* * SAT translation for mode sense/select 6 from spec * modePageBuf[0] = Mode Data length (Unspecified) * modePageBuf[1] = Medium Type (support 00h only) * modePageBuf[2] = Device Specific Parameter (Sense 0 only and select is unspecified) * modePageBuf[3] = Block Descriptor length (00h) * * mode sense/select 8 is similar with extended fields of 0 */ // Move pointer to the array location and find the size of the parameter header if( pReq->Cdb[0] == SCSI_CMD_MODE_SENSE_6) { pModePageBuf = &modePageBuf[4]; length = 4; // size of header } else if( pReq->Cdb[0] == SCSI_CMD_MODE_SENSE_10 ){ pModePageBuf = &modePageBuf[8]; length = 8; // size of header } // Page Code handling switch(pReq->Cdb[2] & 0x3F) { case 0x0A: break; case 0x01: break; case 0x08: if( pModePageBuf[2] & 0x4 ) { SCSI_ATA_EnableDisableFeature(pDevice->pPort,pDevice, CDB_CORE_ENABLE_WRITE_CACHE); } else { SCSI_ATA_EnableDisableFeature(pDevice->pPort,pDevice, CDB_CORE_DISABLE_WRITE_CACHE); } if( pModePageBuf[2] & 0x20 ) { SCSI_ATA_EnableDisableFeature(pDevice->pPort,pDevice, CDB_CORE_ENABLE_READ_AHEAD); } else { SCSI_ATA_EnableDisableFeature(pDevice->pPort,pDevice, CDB_CORE_DISABLE_READ_AHEAD); } break; case 0x1C: if(!(pDevice->Capacity & DEVICE_CAPACITY_SMART_SUPPORTED)) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); } break; default: SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } if( modePageBuf[0] != 0 ) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); }}/**************************************************************************** SCSI_ATA_ReadWriteTranslation* Purpose: Handles read/write SCSI commands ****************************************************************************/void SCSI_ATA_ReadWriteTranslation( IN PMV_Request pReq, IN MV_U8 tag, OUT PATA_TaskFile pTaskFile ){ MV_U8 tempSC, tempSC_exp; // temp sector count switch(pReq->Cdb[0]) { case SCSI_CMD_READ_10: case SCSI_CMD_WRITE_10: tempSC = pReq->Cdb[8]; tempSC_exp = pReq->Cdb[7]; SCSI_ATA_FillLBACdb10( pReq, pTaskFile ); break; case SCSI_CMD_READ_16: case SCSI_CMD_WRITE_16: tempSC = pReq->Cdb[13]; tempSC_exp = pReq->Cdb[12]; SCSI_ATA_FillLBACdb16( pReq, pTaskFile ); break; default: return; } pTaskFile->Device = MV_BIT(6); if ( pReq->Cmd_Flag&CMD_FLAG_NCQ ) { pTaskFile->Features = tempSC; pTaskFile->Feature_Exp = tempSC_exp; pTaskFile->Sector_Count = tag<<3; if ( pReq->Cdb[0]==SCSI_CMD_READ_10 || pReq->Cdb[0]==SCSI_CMD_READ_16 ) pTaskFile->Command = ATA_CMD_READ_FPDMA_QUEUED; else pTaskFile->Command = ATA_CMD_WRITE_FPDMA_QUEUED; } else if ( pReq->Cmd_Flag&CMD_FLAG_48BIT ) { pTaskFile->Sector_Count = tempSC; pTaskFile->Sector_Count_Exp = tempSC_exp; if ( pReq->Cdb[0]==SCSI_CMD_READ_10 || pReq->Cdb[0]==SCSI_CMD_READ_16 ) pTaskFile->Command = ATA_CMD_READ_DMA_EXT; else pTaskFile->Command = ATA_CMD_WRITE_DMA_EXT; } else { pTaskFile->Sector_Count = tempSC; /* Could be zero */ pTaskFile->Device |= (pReq->Cdb[2]&0xF); MV_DASSERT( (pReq->Cdb[2]&0xF0)==0 ); if ( pReq->Cdb[0]==SCSI_CMD_READ_10 || pReq->Cdb[0]==SCSI_CMD_READ_16 ) pTaskFile->Command = ATA_CMD_READ_DMA; else pTaskFile->Command = ATA_CMD_WRITE_DMA; }}/**************************************************************************** SCSI_ATA_ReadCapacityTranslationCallback* Purpose: Handles read capacity SCSI command callback data****************************************************************************/void SCSI_ATA_ReadCapacityTranslationCallback( IN MV_PVOID This, IN PMV_Request pReq ){ PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; PDomain_Device pDevice = pCore->Devices; PATA_Identify_Data pATAIdentify = (PATA_Identify_Data)pReq->Data_Buffer; /* Disk size */ if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED ) { pDevice->Max_LBA.parts.low = *((MV_PU32)&pATAIdentify->Max_LBA[0]); pDevice->Max_LBA.parts.high = *((MV_PU32)&pATAIdentify->Max_LBA[2]); }else { pDevice->Max_LBA.parts.low = *((MV_PU32)&pATAIdentify->User_Addressable_Sectors[0]); pDevice->Max_LBA.parts.high = 0; } /* * The disk size as indicated by the ATA spec is the total addressable * sectors on the drive ; while Max LBA is the LBA of the last logical block on the drive */ pDevice->Max_LBA = U64_SUBTRACT_U32(pDevice->Max_LBA, 1); MV_CopyMemory(pReq->Data_Buffer, &pDevice->Max_LBA, sizeof(pDevice->Max_LBA) );}/**************************************************************************** SCSI_ATA_ReadCapacityTranslation* Purpose: Handles read capacity SCSI commands ****************************************************************************/void SCSI_ATA_ReadCapacityTranslation( IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ if( (pReq->Cdb[2]|pReq->Cdb[3]|pReq->Cdb[4]|pReq->Cdb[5]|(pReq->Cdb[8]&0x1)) != 0) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB); return; } pTaskFile->Command = ATA_CMD_IDENTIFY_ATA; pReq->Completion = SCSI_ATA_ReadCapacityTranslationCallback;}/**************************************************************************** SCSI_ATA_VerifyTranslation* Purpose: Handles verify SCSI commands ****************************************************************************/void SCSI_ATA_VerifyTranslation( IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ MV_U8 tempSC, tempSC_exp; // temp sector count switch(pReq->Cdb[0]) { case SCSI_CMD_VERIFY_10: tempSC = pReq->Cdb[8]; tempSC_exp = pReq->Cdb[7]; SCSI_ATA_FillLBACdb10( pReq, pTaskFile ); break; case SCSI_CMD_VERIFY_16: tempSC = pReq->Cdb[13]; tempSC_exp = pReq->Cdb[12]; SCSI_ATA_FillLBACdb16( pReq, pTaskFile ); break; default: return; } pTaskFile->Device = MV_BIT(6); if ( pReq->Cmd_Flag&CMD_FLAG_48BIT ) { pTaskFile->Sector_Count = tempSC; pTaskFile->Sector_Count_Exp = tempSC_exp; pTaskFile->Command = ATA_CMD_VERIFY_EXT; } else { pTaskFile->Sector_Count = tempSC; /* Could be zero */ pTaskFile->Device |= (pReq->Cdb[2]&0xF); MV_DASSERT( (pReq->Cdb[2]&0xF0)==0 ); pTaskFile->Command = ATA_CMD_VERIFY; }}/**************************************************************************** SCSI_ATA_SyncCacheTranslation* Purpose: Syncronize cache 10/16****************************************************************************/void SCSI_ATA_SyncCacheTranslation( IN PDomain_Device pDevice, IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ pTaskFile->Device = MV_BIT(6); switch(pReq->Cdb[0]) { case SCSI_CMD_SYNCHRONIZE_CACHE_10: if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED ) pTaskFile->Command = ATA_CMD_FLUSH_EXT; else pTaskFile->Command = ATA_CMD_FLUSH; break; case SCSI_CMD_SYNCHRONIZE_CACHE_16: pTaskFile->Command = ATA_CMD_FLUSH_EXT; break; default: SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } if( (pReq->Cdb[1]&0x2)!=0 ) { pReq->Scsi_Status = SCSI_STATUS_GOOD; }}/**************************************************************************** SCSI_ATA_SendDiagTranslationCallback* Purpose: handles callback****************************************************************************/void SCSI_ATA_SendDiagTraslationCallback( IN MV_PVOID This, IN PMV_Request pReq ){ }/**************************************************************************** SCSI_ATA_SendDiagTranslation* Purpose: Sends Diagnostic cmd ****************************************************************************/void SCSI_ATA_SendDiagTranslation( IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ // CDB[1] checks if DevOffL and UnitOffL bits are set // CDB[3] & CDB[4] checks for parameter list length equal to 0 if( ((pReq->Cdb[1]&0xFC)!=0) || (pReq->Cdb[3]!=0) || (pReq->Cdb[4]!=0) ) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } pTaskFile->Command = ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC; switch(pReq->Cdb[1]&0xE0) { case DEFAULT_SELF_TEST: break; case BACKGROUND_SHORT_SELF_TEST: break; case BACKGROUND_EXTENDED_SELF_TEST: break; case ABORT_BACKGROUND_SELF_TEST: break; case FOREGROUND_SHORT_SELF_TEST: break; case FOREGROUND_EXTENDED_SELF_TEST: break; default: break; }}/**************************************************************************** SCSI_ATA_StartStopTranslation* Purpose: Start and Stop cmd translation****************************************************************************/void SCSI_ATA_StartStopTranslation( IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?