📄 core_exp.c
字号:
#else if( !IS_A_SMP_REQ(pReq) ) { MV_DASSERT( pDevice!=NULL ); orgWriteCache = (pDevice->Setting&DEVICE_SETTING_WRITECACHE_ENABLED)?MV_TRUE:MV_FALSE; orgPreread = MV_TRUE; /* No control yet. */ if ( pReq->Cdb[0]==SCSI_CMD_MARVELL_SPECIFIC ) { if ( pReq->Cdb[1]==CDB_CORE_MODULE ) { switch ( pReq->Cdb[2] ) { case CDB_CORE_ENABLE_SMART: pDevice->Setting |= DEVICE_SETTING_SMART_ENABLED; pReq->Scsi_Status = REQ_STATUS_SUCCESS; *pCommandRet = MV_QUEUE_COMMAND_RESULT_FINISHED; return MV_TRUE; case CDB_CORE_DISABLE_SMART: pDevice->Setting &= ~DEVICE_SETTING_SMART_ENABLED; pReq->Scsi_Status = REQ_STATUS_SUCCESS; *pCommandRet = MV_QUEUE_COMMAND_RESULT_FINISHED; return MV_TRUE; case CDB_CORE_SMART_RETURN_STATUS: if ( !SCSI_MakeSMARTReturnStatusCommand(pCore, pReq) ) { *pCommandRet = MV_QUEUE_COMMAND_RESULT_NO_RESOURCE; return MV_TRUE; } break; case CDB_CORE_OS_SMART_CMD: pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST; *pCommandRet = MV_QUEUE_COMMAND_RESULT_FINISHED; return MV_TRUE; case CDB_CORE_ENABLE_WRITE_CACHE: if ( !SCSI_MakeCacheCommand(pCore, pReq, MV_TRUE, orgPreread) ) { *pCommandRet = MV_QUEUE_COMMAND_RESULT_NO_RESOURCE; return MV_TRUE; } break; case CDB_CORE_DISABLE_WRITE_CACHE: if ( !SCSI_MakeCacheCommand(pCore, pReq, MV_FALSE, orgPreread) ) { *pCommandRet = MV_QUEUE_COMMAND_RESULT_NO_RESOURCE; return MV_TRUE; } break; case CDB_CORE_ENABLE_READ_AHEAD: if ( !SCSI_MakeCacheCommand(pCore, pReq, orgWriteCache, MV_TRUE) ) { *pCommandRet = MV_QUEUE_COMMAND_RESULT_NO_RESOURCE; return MV_TRUE; } break; case CDB_CORE_DISABLE_READ_AHEAD: if ( !SCSI_MakeCacheCommand(pCore, pReq, orgWriteCache, MV_FALSE) ) { *pCommandRet = MV_QUEUE_COMMAND_RESULT_NO_RESOURCE; return MV_TRUE; } break; case CDB_CORE_SHUTDOWN: SCSI_MakeSynchronizeCacheCommmand(pCore, pReq); break; case CDB_CORE_TASK_MGMT: break; case CDB_CORE_IDENTIFY: case CDB_CORE_SET_UDMA_MODE: case CDB_CORE_SET_PIO_MODE: case CDB_CORE_READ_LOG_EXT: case CDB_CORE_SMP: default: /* We shouldn't receive these commands or haven't implemented yet. */ MV_DASSERT( MV_FALSE ); pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST; *pCommandRet = MV_QUEUE_COMMAND_RESULT_FINISHED; return MV_TRUE; } } } else if ( pReq->Cdb[0]==APICDB0_LD && pReq->Cdb[1]==APICDB1_LD_SHUTDOWN ) { MV_DPRINT( ("Got APICDB1_LD_SHUTDOWN\n") ); SCSI_MakeSynchronizeCacheCommmand(pCore, pReq); } } #endif } if(Tag_IsEmpty(&pCore->Tag_Pool)) { *pCommandRet = MV_QUEUE_COMMAND_RESULT_FULL; return MV_TRUE; } if(pReq->Cdb[0]==SCSI_CMD_MARVELL_SPECIFIC) { if(pReq->Cdb[1]==CDB_CORE_MODULE) { switch(pReq->Cdb[2]) { case CDB_CORE_TASK_MGMT: if(pReq->Cdb[5]==ABORT_TASK_TMF) { Tag=(MV_U16)(pReq->Cdb[4]<<8) + (MV_U16)pReq->Cdb[3]; pOrgReq=FindRunningReqByTag(pCore, Tag); if( (pOrgReq != pReq->Org_Req) ||(pOrgReq == NULL) ) { pReq->Scsi_Status = REQ_STATUS_INVALID_REQUEST; *pCommandRet = MV_QUEUE_COMMAND_RESULT_FINISHED; return MV_TRUE; } } break; } } } return MV_FALSE;}MV_QUEUE_COMMAND_RESULTPrepareAndSendCommand( IN PCore_Driver_Extension pCore, IN PMV_Request pReq ){ MV_U16 SlotNo; MV_PHYSICAL_ADDR tmpPhyAddress; PMV_Command_Header pCmdHeader; PMV_Command_Table pCmdTbl = (PMV_Command_Table)pCore->Cmd_Table; DELIVERY_QUEUE_ENTRY DELV_Q_Entry; struct _Domain_Port *pPort = NULL; struct _Domain_Device *pDevice = NULL; ATA_TaskFile taskFile; struct _Domain_Expander *pTgt = NULL;#ifdef SUPPORT_PM PDomain_PM pPM = NULL;#endif MV_U16 deviceId; MV_U8 portId; MV_U64 Val64; MV_BOOLEAN ret; MV_U16 Tag = 0; MV_U32 ReqLen; struct SMPRequest *pSMPReq; MV_QUEUE_COMMAND_RESULT commandRet; PSG_Buffer pSGBuf; pReq->SlotNo=0xfff; /* Verify this command. May can be finished now. * Remove the verify code to this following function. */ if ( VerifyCommandBeforeSending(pCore, pReq, &commandRet) ) { return commandRet; } if( IS_A_SMP_REQ(pReq) ) {/* workaround for a HW SMP bug, HW will return with old response and corrupt the command table if we issue SMP too soon */ HBA_SleepMillisecond(pCore, 5); portId = MapPortId(pCore, pReq->Device_Id); pPort=&pCore->Ports[MapPortEntry(pCore,portId)]; pTgt=&pCore->Expanders[MapDeviceId(pCore, pReq->Device_Id)]; } else { if (!IS_PM_REQ(pReq)) { portId = MapPortId(pCore, pReq->Device_Id); deviceId = MapDeviceId(pCore, pReq->Device_Id); pPort=&pCore->Ports[MapPortEntry(pCore,portId)]; pDevice= &pCore->Devices[deviceId]; } else { deviceId = MapDeviceId(pCore, pReq->Device_Id); #ifdef SUPPORT_PM pPM = &(pCore->PMs[deviceId]); pPort = pPM->pPort; #endif } if ( !IS_PM_REQ(pReq) && !IS_SOFT_RESET_REQ(pReq) && ((deviceId==ID_NOT_MAPPED)||(!(pDevice->Status&DEVICE_STATUS_FUNCTIONAL))) ) { pReq->Scsi_Status = REQ_STATUS_NO_DEVICE; return MV_QUEUE_COMMAND_RESULT_FINISHED; } } SlotNo = GetOneCommandSlot(pCore, &pCmdHeader); pReq->SlotNo = SlotNo; pSGBuf = GetSGBufferFromPool(pCore); if (pSGBuf == NULL) { MV_DPRINT(("Ran out of SG buffers!\n")); return MV_QUEUE_COMMAND_RESULT_NO_RESOURCE; } pReq->SG_Buffer = pSGBuf; tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8) &pCmdTbl[SlotNo].Status_Buff - (MV_PU8) pCore->Cmd_Table); pCmdHeader->StatusBuff_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->StatusBuff_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); U64_ASSIGN_U64(tmpPhyAddress, pSGBuf->Buffer_DMA); pCmdHeader->PRD_Table_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->PRD_Table_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); pCmdHeader->Tag = MV_CPU_TO_LE16(SlotNo); MV_ZeroMemory(&pCmdTbl[SlotNo], sizeof(MV_Command_Table));// MV_ZeroMemory(&pCmdTbl[SlotNo].Status_Buff.Err_Info, 8); if (IS_PM_REQ(pReq)) { ret = ATA_CDB2TaskFile(pDevice, pReq, (MV_U8) pCmdHeader->Tag, &taskFile); if ( !ret ) { // TBD: handle this MV_DASSERT( MV_FALSE ); } tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8) &pCmdTbl[SlotNo].table.STP_CMD_Table - (MV_PU8)pCore->Cmd_Table); pCmdHeader->Table_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->Table_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); } else if (pPort->Type&PORT_TYPE_SATA || (!IS_A_SMP_REQ(pReq) && IS_STP_OR_SATA(pDevice))) { if (IS_ATAPI(pDevice)) { ret = ATAPI_CDB2TaskFile(pDevice, pReq, &taskFile); } else { if (pReq->Cmd_Flag & CMD_FLAG_ATA_PASS_THRU) { ret = Core_pass_thru_fill_taskfile( pReq, &taskFile ); } else { ret = ATA_CDB2TaskFile(pDevice, pReq, (MV_U8) pCmdHeader->Tag, &taskFile); } } if ( !ret ) { // TBD: handle this MV_DASSERT( MV_FALSE ); } tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8) &pCmdTbl[SlotNo].table.STP_CMD_Table - (MV_PU8)pCore->Cmd_Table); pCmdHeader->Table_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->Table_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); if (!IS_PM_REQ(pReq) && IS_STP(pDevice)) { tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8) &pCmdTbl[SlotNo].Open_Addr_Frame - (MV_PU8) pCore->Cmd_Table); pCmdHeader->OpenAddrFrame_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->OpenAddrFrame_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); } } else if( pPort->Type&PORT_TYPE_SAS ) { tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8) &pCmdTbl[SlotNo].Open_Addr_Frame - (MV_PU8)pCore->Cmd_Table); pCmdHeader->OpenAddrFrame_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->OpenAddrFrame_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); tmpPhyAddress.value = pCore->Cmd_Table_DMA.value + ((MV_PU8) &pCmdTbl[SlotNo].table.SSP_CMD_Table - (MV_PU8)pCore->Cmd_Table); pCmdHeader->Table_Address = MV_CPU_TO_LE32(tmpPhyAddress.parts.low); pCmdHeader->Table_Address_High = MV_CPU_TO_LE32(tmpPhyAddress.parts.high); } pCmdHeader->SSP_Retry = 1;#ifdef USE_NEW_SGTABLE if( pReq->SG_Table.Valid_Entry_Count ) { MV_U16 consumed = (MV_U16) sgdt_prepare_hwprd( pCore, &pReq->SG_Table, pSGBuf->Buffer_Vir, HW_SG_ENTRY_MAX ); if( consumed == 0 ) { // resource not enough... MV_DPRINT( ("Run out of PRD entry.\n") ); if( pReq->Req_Flag & REQ_FLAG_CONSOLIDATE ) { pReq->Scsi_Status = REQ_STATUS_BUSY; Tag_ReleaseOne(&pCore->Tag_Pool, SlotNo); return MV_QUEUE_COMMAND_RESULT_FINISHED; } else { /* check why upper layer send request with too many sg items... */ MV_DASSERT( MV_FALSE ); } } pCmdHeader->PRD_Entry_Count = consumed; } else pCmdHeader->PRD_Entry_Count = 0;#else pCmdHeader->PRD_Entry_Count = pReq->SG_Table.Valid_Entry_Count; for (i=0; i<pReq->SG_Table.Valid_Entry_Count; i++) { PMV_SG_Entry pSGEntry = ((PMV_SG_Entry) pSGBuf->Buffer_Vir) + i; pSGEntry->Base_Address = MV_CPU_TO_LE32(pReq->SG_Table.Entry_Ptr[i].Base_Address); pSGEntry->Base_Address_High = MV_CPU_TO_LE32(pReq->SG_Table.Entry_Ptr[i].Base_Address_High); pSGEntry->Size = MV_CPU_TO_LE32(pReq->SG_Table.Entry_Ptr[i].Size); }#endif pCmdHeader->DataXferLen = MV_CPU_TO_LE32(pReq->Data_Transfer_Length); if (IS_PM_REQ(pReq)) { SATA_PrepareCommandHeader(pPort, pReq, pCmdHeader, SlotNo); SATA_PrepareCommandTable(pPort, pReq, &pCmdTbl[SlotNo], &taskFile); pPort->Setting &= ~PORT_SETTING_NCQ_RUNNING; } else if(pPort->Type&PORT_TYPE_SAS) { if (sizeof(SSP_RESPONSE_IU) > MAX_SMP_RESP_SIZE) pCmdHeader->MaxRspFrameLength = (sizeof(SSP_RESPONSE_IU)>>2); else pCmdHeader->MaxRspFrameLength = (MAX_SMP_RESP_SIZE>>2); if ((pDevice != NULL) && IS_STP(pDevice)) { SATA_PrepareCommandHeader(pPort, pReq, pCmdHeader, SlotNo); if ( (!IS_ATAPI(pDevice)) && (pReq->Cmd_Flag & CMD_FLAG_NCQ )) taskFile.Sector_Count = (MV_U8) pCmdHeader->Tag<<3; SATA_PrepareCommandTable(pPort, pReq, &pCmdTbl[SlotNo], &taskFile); if (pReq->Cmd_Flag & CMD_FLAG_NCQ) pPort->Setting |= PORT_SETTING_NCQ_RUNNING; else pPort->Setting &= ~PORT_SETTING_NCQ_RUNNING; pCmdTbl[SlotNo].Open_Addr_Frame.Protocol = PROTOCOL_STP; pCmdTbl[SlotNo].Open_Addr_Frame.Frame_Type = ADDRESS_OPEN_FRAME; pCmdTbl[SlotNo].Open_Addr_Frame.Initiator = 1;// pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Rate=PHY_LINKRATE_3; pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Rate=pDevice->NegotiatedLinkRate; *(MV_U16 *)(pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Tag) = MV_CPU_TO_BE16(pDevice->Id+1); U64_ASSIGN(Val64, MV_CPU_TO_BE64(pDevice->SASAddr)); } else if ((pReq->Cdb[0] == SCSI_CMD_MARVELL_SPECIFIC) && (pReq->Cdb[1] == CDB_CORE_MODULE)) { switch (pReq->Cdb[2]) { case CDB_CORE_TASK_MGMT:/*CDB[3..4]=tagCDB[5]=Task FunctionCDB[6..13]=Lun*/ Tag=(MV_U16)(pReq->Cdb[4]<<8) + (MV_U16)pReq->Cdb[3]; pCmdHeader->FrameLength = ((sizeof(SSP_TASK_IU) + sizeof(SSP_Frame_Header))/4); DELV_Q_Entry.PRIORITY = 1; pCmdHeader->Tag |= pReq->Tag <<pCore->MaxCmdSlotWidth; pCmdHeader->SSP_SSPFrameType = FRAME_TYPE_TASK; MV_CopyMemory(&pCmdTbl[SlotNo].table.SSP_CMD_Table.data.task.LUN, &pReq->Cdb[6], 8); pCmdTbl[SlotNo].table.SSP_CMD_Table.data.task.Tag = MV_CPU_TO_BE16(Tag); pCmdTbl[SlotNo].table.SSP_CMD_Table.data.task.TaskFunction = pReq->Cdb[5]; pCmdTbl[SlotNo].Open_Addr_Frame.Protocol = PROTOCOL_SSP; pCmdTbl[SlotNo].Open_Addr_Frame.Frame_Type = ADDRESS_OPEN_FRAME; pCmdTbl[SlotNo].Open_Addr_Frame.Initiator = 1; *(MV_U16 *)(pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Tag) = MV_CPU_TO_BE16(pDevice->Id+1);// pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Rate=PHY_LINKRATE_3; pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Rate=pDevice->NegotiatedLinkRate; U64_ASSIGN(Val64, MV_CPU_TO_BE64(pDevice->SASAddr)); break; case CDB_CORE_SMP: pCmdHeader->Tag |= pReq->Tag <<pCore->MaxCmdSlotWidth; pCmdTbl[SlotNo].Open_Addr_Frame.Protocol = PROTOCOL_SMP; pCmdTbl[SlotNo].Open_Addr_Frame.Frame_Type = ADDRESS_OPEN_FRAME; pCmdTbl[SlotNo].Open_Addr_Frame.Initiator = 1; *(MV_U16 *)(pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Tag) = 0xffff;// pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Rate=PHY_LINKRATE_3; pCmdTbl[SlotNo].Open_Addr_Frame.Connect_Rate=pTgt->NegotiatedLinkRate; if (pReq->Data_Buffer == NULL) { pReq->Scsi_Status = REQ_STATUS_ERROR; return MV_QUEUE_COMMAND_RESULT_FINISHED; } if ((pReq->Cdb[3] & SMP_CDB_USE_ADDRESS) && (pReq->Sense_Info_Buffer != NULL)) { MV_CopyMemory(&Val64, pReq->Sense_Info_Buffer, 8); U64_ASSIGN(Val64, MV_CPU_TO_BE64(Val64)); } else { U64_ASSIGN(Val64, MV_CPU_TO_BE64(pTgt->SASAddr)); } ReqLen = 4; pSMPReq = (struct SMPRequest *) pReq->Data_Buffer; switch (pSMPReq->Function) { case REPORT_GENERAL: ReqLen += sizeof(pSMPReq->Request.ReportGeneral) - sizeof(MV_U32); break; case REPORT_MANUFACTURER_INFORMATION: ReqLen+= sizeof(pSMPReq->Request.ReportManufacturerInformation)-sizeof(MV_U32); break;// case READ_GPIO_REGISTER:// break; case REPORT_SELF_CONFGRIGRUATION_STATUS: ReqLen+= sizeof(pSMPReq->Request.ReportSelfConfigurationStatus)-sizeof(MV_U32); break; case DISCOVER: ReqLen+= sizeof(pSMPReq->Request.Discover)-sizeof(MV_U32); break; case REPORT_PHY_ERROR_LOG: ReqLen+= sizeof(pSMPReq->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -