scsi2sata.c
来自「6440linuxDriver的源代码」· C语言 代码 · 共 1,717 行 · 第 1/4 页
C
1,717 行
}}/**************************************************************************** SCSI_ATA_FillSelfTestLogPage* Purpose: Fill the right values for Caching Mode page ****************************************************************************/void SCSI_ATA_FillSelfTestLogPage( MV_PU8 pBuf, PDomain_Device pDevice, int pageNum ){ // Parameter Code pBuf[0] = 0; pBuf[1] = pageNum+1; // DU, DS, TSD, ETC, TMC, LBIN, LP set to 0 pBuf[2] = 0; // Parameter length pBuf[3] = 0x10; // Self-test code }/**************************************************************************** SCSI_ATA_FormatUnit* Purpose: Format Unit cmd translation****************************************************************************/void SCSI_ATA_FillFormatTaskFile( MV_U8 ataCmd, MV_U32 lbaCount, MV_U32 lbaLow, MV_U32 lbaHigh, OUT PATA_TaskFile pTaskFile ){ pTaskFile->Command = ataCmd; pTaskFile->Features = 0; pTaskFile->Feature_Exp = 0; if(ataCmd==ATA_CMD_WRITE_DMA || ataCmd==ATA_CMD_VERIFY) { pTaskFile->Sector_Count = (MV_U8)(lbaCount & 0xFF); pTaskFile->LBA_Low = (MV_U8)(lbaLow&0xFF); pTaskFile->LBA_Mid = (MV_U8)(lbaLow>>8) & 0xFF; pTaskFile->LBA_High = (MV_U8)(lbaLow>>16) & 0xFF; pTaskFile->Device = ((MV_U8)(lbaLow>>24) & 0xF ) | 0x40; } else if (ataCmd==ATA_CMD_WRITE_DMA_EXT || ataCmd==ATA_CMD_VERIFY_EXT) { pTaskFile->Sector_Count = (MV_U8)(lbaCount & 0xFF); pTaskFile->Sector_Count_Exp = (MV_U8)((lbaCount >> 8) & 0xFF); pTaskFile->LBA_Low = (MV_U8)(lbaLow&0xFF); pTaskFile->LBA_Mid = (MV_U8)(lbaLow>>8) & 0xFF; pTaskFile->LBA_High = (MV_U8)(lbaLow>>16) & 0xFF; pTaskFile->LBA_Low_Exp = (MV_U8)(lbaLow>>24) & 0xFF; pTaskFile->LBA_Mid_Exp = (MV_U8)(lbaHigh&0xFF); pTaskFile->LBA_High_Exp = (MV_U8)((lbaHigh>>8)&0xFF); pTaskFile->Device = 0x40; } TotalFormattedLbaCount += lbaCount;}/**************************************************************************** SCSI_ATA_FormatUnitTranslationCallback* Purpose: Format Unit cmd translation****************************************************************************/void SCSI_ATA_FormatUnitTranslationCallback( IN MV_PVOID This, IN PMV_Request pReq ){ PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; PDomain_Device pDevice = pCore->Devices; ATA_TaskFile taskFile; switch(pDevice->State) { case DEVICE_STATE_FORMAT_WRITE: if( TotalLbaCount!=TotalFormattedLbaCount ) { SCSI_ATA_FormatUnitTranslation( pDevice, pReq, &taskFile ); } else { pDevice->State = DEVICE_STATE_FORMAT_VERIFY; TotalFormattedLbaCount = 0; SCSI_ATA_FormatUnitTranslation( pDevice, pReq, &taskFile ); } break; case DEVICE_STATE_FORMAT_VERIFY: if( TotalLbaCount!=TotalFormattedLbaCount ) { SCSI_ATA_FormatUnitTranslation( pDevice, pReq, &taskFile ); break; } pDevice->State = DEVICE_STATE_FORMAT_DONE; case DEVICE_STATE_FORMAT_DONE: default: return; } /* Send this internal request */ Core_ModuleSendRequest(pCore, pReq);}/**************************************************************************** SCSI_ATA_FormatUnitTranslation* Purpose: Format Unit cmd translation****************************************************************************/void SCSI_ATA_FormatUnitTranslation( PDomain_Device pDevice, IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ MV_U8 defectList=0; MV_U8 cmpList = 0; MV_U8 fmtData = 0; MV_U8 ataCmd =0; MV_U32 lbaCount = 0; defectList = pReq->Cdb[1]&0x7; // Defect list format checking cmpList = pReq->Cdb[1]&0x8; // complete list bit checking if( defectList != 0 || defectList != 0x6 || (cmpList != 0 && fmtData != 0 ) || pReq->Cdb[2] != 0 || pReq->Cdb[3] != 0 || pReq->Cdb[4] != 0 ) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } if ( pDevice->Capacity&DEVICE_CAPACITY_48BIT_SUPPORTED ) { ataCmd = (pDevice->State == DEVICE_STATE_FORMAT_WRITE) ? ATA_CMD_WRITE_DMA_EXT : ATA_CMD_VERIFY_EXT; } else { ataCmd = (pDevice->State == DEVICE_STATE_FORMAT_WRITE) ? ATA_CMD_WRITE_DMA : ATA_CMD_VERIFY; }// TotalLbaCount = pDevice->Max_LBA.parts.low; TotalLbaCount = pDevice->Max_LBA.parts.low + 1; pReq->Completion = SCSI_ATA_FormatUnitTranslationCallback; lbaCount = (LBA_BLOCK_COUNT < (TotalLbaCount-TotalFormattedLbaCount)) ? LBA_BLOCK_COUNT : (TotalLbaCount-TotalFormattedLbaCount); SCSI_ATA_FillFormatTaskFile(ataCmd, 0, 0, lbaCount, pTaskFile); TotalFormattedLbaCount += lbaCount;}/**************************************************************************** SCSI_ATA_InquiryTranslationCallback* Purpose: Handles the Inquiry data after ATA_CMD_IDENTIFY is sent****************************************************************************/#ifdef _OS_WINDOWSvoid SCSI_ATA_InquiryTranslationCallback( IN MV_PVOID This, IN PMV_Request pReq ){ MV_U8 MV_T10_ATA_VENDOR_ID[8] = { 0x41, 0x54, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20 }; //'ATA ' MV_U8 MV_T10_SAT_VENDOR_ID[8] = {'M','A','R','V','E','L','L'}; MV_U8 MV_INQUIRY_STANDARD_DATA[36] = {0}; MV_U8 MV_INQUIRY_VPD_PAGE0_DATA[9] = {0x00, 0x00, 0x00, 0x05,0x00, 0x80, 0x83, 0x87, 0x89}; MV_U8 MV_INQUIRY_VPD_PAGE80_DATA[24] = {0}; MV_U8 MV_INQUIRY_VPD_PAGE83_DATA[88] = {0}; MV_U8 MV_INQUIRY_VPD_PAGE87_DATA[36] = {0}; MV_U8 MV_INQUIRY_VPD_PAGE89_DATA[572] = {0}; PSCSI_REQUEST_BLOCK Srb = (PSCSI_REQUEST_BLOCK) pReq->Org_Req; PCore_Driver_Extension pCore = (PCore_Driver_Extension)This; PSATA_FIS_REG_H2D pFIS = (PSATA_FIS_REG_H2D)pCore->RX_FIS; PATA_Identify_Data pATAIdentify; int i = 0; pATAIdentify = (PATA_Identify_Data)pReq->Data_Buffer; if( pReq->Cdb[1]&0x01 ) { // EVPD is 1 switch(pReq->Cdb[2]) { // Page Code is set as follows case 0x00: MV_CopyMemory( pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE0_DATA, sizeof(MV_INQUIRY_VPD_PAGE0_DATA) ); break; case 0x80: MV_INQUIRY_VPD_PAGE80_DATA[1] = 0x80; // Page Code MV_INQUIRY_VPD_PAGE80_DATA[3] = 0x14; // Page Length // 4-23 bytes hold the serial number of the device SCSI_ATA_FillDataField( &MV_INQUIRY_VPD_PAGE80_DATA[4], pATAIdentify->Serial_Number, sizeof(MV_INQUIRY_VPD_PAGE80_DATA));// len 20bytes MV_CopyMemory( pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE80_DATA, sizeof(MV_INQUIRY_VPD_PAGE80_DATA)); break; case 0x83: MV_INQUIRY_VPD_PAGE83_DATA[1] = 0x83; // Page Code MV_INQUIRY_VPD_PAGE83_DATA[3] = 88; // Page Length if( pATAIdentify->Command_Set_Default & 0x100 ) { //Support World wide name MV_INQUIRY_VPD_PAGE83_DATA[4] = 0x1; MV_INQUIRY_VPD_PAGE83_DATA[5] = 0x3; // MV_INQUIRY_VPD_PAGE83_DATA[6] is reserved MV_INQUIRY_VPD_PAGE83_DATA[7] = 0x8; MV_INQUIRY_VPD_PAGE83_DATA[8] = SCSI_ATA_UpperWord(pATAIdentify->NAA); MV_INQUIRY_VPD_PAGE83_DATA[9] = SCSI_ATA_LowerWord(pATAIdentify->NAA); MV_INQUIRY_VPD_PAGE83_DATA[10]= SCSI_ATA_UpperWord(pATAIdentify->Unique_ID1); MV_INQUIRY_VPD_PAGE83_DATA[11]= SCSI_ATA_LowerWord(pATAIdentify->Unique_ID1); MV_INQUIRY_VPD_PAGE83_DATA[12]= SCSI_ATA_UpperWord(pATAIdentify->Unique_ID2); MV_INQUIRY_VPD_PAGE83_DATA[13]= SCSI_ATA_LowerWord(pATAIdentify->Unique_ID2); MV_INQUIRY_VPD_PAGE83_DATA[14]= SCSI_ATA_UpperWord(pATAIdentify->Unique_ID3); MV_INQUIRY_VPD_PAGE83_DATA[15]= SCSI_ATA_LowerWord(pATAIdentify->Unique_ID3); } else { //Logical Unit name MV_INQUIRY_VPD_PAGE83_DATA[4] = 0x2; MV_INQUIRY_VPD_PAGE83_DATA[5] = 0x1; // MV_INQUIRY_VPD_PAGE83_DATA[6] is reserved MV_INQUIRY_VPD_PAGE83_DATA[7] = 68; MV_CopyMemory( &MV_INQUIRY_VPD_PAGE83_DATA[8], MV_T10_ATA_VENDOR_ID, sizeof(MV_T10_ATA_VENDOR_ID) ); // Fill Model Number SCSI_ATA_FillDataField( &MV_INQUIRY_VPD_PAGE83_DATA[16], pATAIdentify->Model_Number, sizeof(pATAIdentify->Model_Number) ); // Fill Serial Number SCSI_ATA_FillDataField( &MV_INQUIRY_VPD_PAGE83_DATA[46], pATAIdentify->Serial_Number, sizeof(pATAIdentify->Serial_Number) ); } MV_CopyMemory(pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE83_DATA, sizeof(MV_INQUIRY_VPD_PAGE83_DATA) ); break; case 0x87: MV_INQUIRY_VPD_PAGE87_DATA[1] = 0x87; // Page Code MV_INQUIRY_VPD_PAGE87_DATA[3] = Srb->Lun*4; MV_CopyMemory(pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE87_DATA, sizeof(MV_INQUIRY_VPD_PAGE87_DATA) ); break; case 0x89: MV_INQUIRY_VPD_PAGE89_DATA[1] = 0x89; // Page Code MV_INQUIRY_VPD_PAGE89_DATA[2] = 0x2; // Page Length MV_INQUIRY_VPD_PAGE89_DATA[3] = 0x38; MV_INQUIRY_VPD_PAGE89_DATA[56] = ATA_CMD_IDENTIFY_ATA; // Fill SAT Vendor ID MV_CopyMemory(&MV_INQUIRY_VPD_PAGE89_DATA[8], MV_T10_SAT_VENDOR_ID, sizeof(MV_T10_SAT_VENDOR_ID) ); // Fill ATA Signature MV_CopyMemory(&MV_INQUIRY_VPD_PAGE89_DATA[36], pFIS, sizeof(pFIS)); SCSI_ATA_FillDataField( &MV_INQUIRY_VPD_PAGE89_DATA[60], (char*)pATAIdentify, sizeof(pATAIdentify) ); MV_CopyMemory( pReq->Data_Buffer, MV_INQUIRY_VPD_PAGE89_DATA, sizeof(MV_INQUIRY_VPD_PAGE89_DATA) ); break; default: SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } } else { // Standard inquiry return data MV_INQUIRY_STANDARD_DATA[1] = 0x80; // Removable Medium MV_INQUIRY_STANDARD_DATA[2] = 0x05; // Version Supported MV_INQUIRY_STANDARD_DATA[3] |= 0x2; // Response Data Format based on Spec MV_INQUIRY_STANDARD_DATA[4] = 0x20; // 32 bytes left // Fill with Generic T10 (ATA) Vendor Identification MV_CopyMemory(&MV_INQUIRY_STANDARD_DATA[8], MV_T10_ATA_VENDOR_ID, sizeof(MV_T10_ATA_VENDOR_ID)); // Product Identification(SCSI)/Model Number(ATA) SCSI_ATA_FillDataField( &MV_INQUIRY_STANDARD_DATA[16], pATAIdentify->Model_Number, sizeof(pATAIdentify->Model_Number) ); // Product Revision Level(SCSI)/Firmware Revision(ATA) if( pATAIdentify->Firmware_Revision[5] == 0x20 && pATAIdentify->Firmware_Revision[4] == 0x20 && pATAIdentify->Firmware_Revision[7] == 0x20 && pATAIdentify->Firmware_Revision[6] == 0x20) { SCSI_ATA_FillDataField( &MV_INQUIRY_STANDARD_DATA[32], pATAIdentify->Firmware_Revision, 4 ); } else { SCSI_ATA_FillDataField( &MV_INQUIRY_STANDARD_DATA[32], &pATAIdentify->Firmware_Revision[5], 4 ); } MV_CopyMemory(pReq->Data_Buffer, MV_INQUIRY_STANDARD_DATA, sizeof(MV_INQUIRY_STANDARD_DATA)); }}#else /* _OS_WINDOWS */inline void SCSI_ATA_InquiryTranslationCallback(IN MV_PVOID This, IN PMV_Request pReq){}#endif /* _OS_WINDOWS *//**************************************************************************** SCSI_ATA_InquiryTranslation* Purpose: Translate Inquiry SCSI command and send ATA_CMD_IDENTIFY ****************************************************************************/void SCSI_ATA_InquiryTranslation( IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ if ( ( (pReq->Cdb[1]&0x1 ) == 0 )&& (pReq->Cdb[2] != 0)) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); return; } // determine the allocation length switch( pReq->Cdb[2] ) { case 0x00: pReq->Cdb[4] = 9; break; case 0x80: pReq->Cdb[4] = 24; break; case 0x83: pReq->Cdb[4] = 88; break; case 0x87: pReq->Cdb[4] = 36; break; case 0x89: /* FIXME : 572, for a u8? */ MV_DASSERT(MV_FALSE);// pReq->Cdb[4] = 572; break; default: pReq->Cdb[4] = 36; break; } pReq->Completion = SCSI_ATA_InquiryTranslationCallback; pTaskFile->Command = ATA_CMD_IDENTIFY_ATA;}/**************************************************************************** SCSI_ATA_LogSenseTranslation* Purpose: Translate Mode Sense SCSI command ****************************************************************************/void SCSI_ATA_LogSenseTranslation( IN PDomain_Device pDevice, IN PMV_Request pReq, OUT PATA_TaskFile pTaskFile ){ int i = 0; MV_U8 length = 0; MV_U8 MV_LOG_PAGE0_DATA[6]={0}; MV_U8 MV_LOG_PAGE10_DATA[194]={0}; // Check page control (PC) settings if( pReq->Cdb[2] != 0x40 ) { SCSI_ATA_CheckCondition( pReq, SCSI_SK_ILLEGAL_REQUEST, SCSI_ASC_INVALID_FEILD_IN_CDB ); } // Report log depending on page code switch( pReq->Cdb[2] & 0x3F ) { case SUPPORTED_LOG_PAGES_LOG_PAGE: length = 4; // Header length if( pDevice->Capacity & DEVICE_CAPACITY_SMART_SUPPORTED ) { /* MV_LOG_PAGE0_DATA[0]-[2] are all zero MV_LOG_PAGE0_DATA[0] = 0x00; page code MV_LOG_PAGE0_DATA[1] = reserved MV_LOG_PAGE0_DATA[2] = unspecified; page length MV_LOG_PAGE0_DATA[3] = 0x00; page0 supported */ MV_LOG_PAGE0_DATA[length]=0x10; length++; } if( pDevice->Capacity & DEVICE_CAPACITY_SMART_SELF_TEST_SUPPORTED ) { /* MV_LOG_PAGE0_DATA[0]-[2] are all zero MV_LOG_PAGE0_DATA[0] = 0x00; page code MV_LOG_PAGE0_DATA[1] = reserved MV_LOG_PAGE0_DATA[2] = unspecified; page length MV_LOG_PAGE0_DATA[3] = 0x00; page0 supported MV_LOG_PAGE0_DATA[4] = could be filled or empty*/ MV_LOG_PAGE0_DATA[length]=0x2F; length++; } MV_CopyMemory(pReq->Data_Buffer, MV_LOG_PAGE0_DATA, length); break; case SELF_TEST_RESULTS_LOG_PAGE: MV_LOG_PAGE10_DATA[0] = 0x10; // Page Code MV_LOG_PAGE10_DATA[2] = 0x1; MV_LOG_PAGE10_DATA[3] = 0x90; // Self-test Results log parameter for(i=0; i<20; i++) { SCSI_ATA_FillSelfTestLogPage(&MV_LOG_PAGE10_DATA[4+(i*20)], pDevice ,i); } break; case INFORMATIONAL_EXCEPTIONS_LOG_PAGE: break; default:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?