📄 mvialcommon.c
字号:
* to channel software queue. Otherwise return the result of
* mvSataExecuteScsiCommand function call
*******************************************************************************/
MV_SCSI_COMMAND_STATUS_TYPE mvExecuteScsiCommand(MV_SATA_SCSI_CMD_BLOCK *pScb,
MV_BOOLEAN canQueue)
{
MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt = pScb->pIalAdapterExtension;
MV_U8 channelIndex = pScb->bus;
if ((ialExt->adapterState == ADAPTER_READY) &&
(ialExt->channelState[channelIndex] == CHANNEL_READY))
{
mvCheckPMForError(ialExt, channelIndex);
}
if ((ialExt->adapterState == ADAPTER_READY) &&
((ialExt->channelState[channelIndex] == CHANNEL_READY) ||
(ialExt->channelState[channelIndex] == CHANNEL_NOT_CONNECTED)))
{
return mvSataExecuteScsiCommand(pScb);
}
if (canQueue == MV_FALSE)
{
pScb->ScsiStatus = MV_SCSI_STATUS_BUSY;
pScb->dataTransfered = 0;
pScb->ScsiCommandCompletion = MV_SCSI_COMPLETION_QUEUE_FULL;
if (pScb->completionCallBack)
{
pScb->completionCallBack(ialExt->pSataAdapter, pScb);
}
return MV_SCSI_COMMAND_STATUS_COMPLETED;
}
else
{
mvAddToSCSICommandQueue(ialExt, channelIndex, pScb);
return MV_SCSI_COMMAND_STATUS_QUEUED_BY_IAL;
}
}
/*******************************************************************************
* mvIALTimerCallback - IAL timer callback
*
* DESCRIPTION:
* The adapter/channel state machine is timer-driven.
* After being loaded, the IAL must call this callback every 0.5 seconds
* INPUT:
* pSataAdapter - pointer to the adapter data structure.
* scsiAdapterExt - SCSI to ATA layer adapter extension data structure
* OUTPUT:
* None.
*
* RETURN:
*
*******************************************************************************/
MV_BOOLEAN mvIALTimerCallback(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_SAL_ADAPTER_EXTENSION *scsiAdapterExt)
{
return mvAdapterStateMachine(ialExt,
scsiAdapterExt);
}
/*******************************************************************************
* mvCommandCompletionErrorHandler - IAL common command completion error handler
*
* DESCRIPTION:
* Called by whether SAL completion of SMART completion function. Check whether
* command is failed because of PM hot plug
*
* INPUT:
* pSataAdapter - pointer to the adapter data structure.
* channelIndex - channelNumber
* OUTPUT:
* None.
*
* RETURN:
*
*******************************************************************************/
void mvCommandCompletionErrorHandler(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex)
{
MV_SATA_ADAPTER* pSataAdapter = ialExt->pSataAdapter;
if (pSataAdapter->sataChannel[channelIndex] == NULL)
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
"Invalid channel data structure pointer.\n",
pSataAdapter->adapterId, channelIndex);
}
if ((ialExt->channelState[channelIndex] != CHANNEL_READY) ||
(mvStorageDevGetDeviceType(pSataAdapter,channelIndex) !=
MV_SATA_DEVICE_TYPE_PM) ||
(ialExt->IALChannelExt[channelIndex].pmAsyncNotifyEnabled == MV_TRUE))
{
return;
}
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: "
"Set completion error to MV_TRUE.\n",
pSataAdapter->adapterId, channelIndex);
ialExt->IALChannelExt[channelIndex].completionError = MV_TRUE;
}
/*Static functions*/
static void printAtaDeviceRegisters(
MV_STORAGE_DEVICE_REGISTERS *mvStorageDevRegisters)
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "ATA Drive Registers:\n");
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","Error",
mvStorageDevRegisters->errorRegister);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","SectorCount",
mvStorageDevRegisters->sectorCountRegister);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Low",
mvStorageDevRegisters->lbaLowRegister);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA Mid",
mvStorageDevRegisters->lbaMidRegister);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","LBA High",
mvStorageDevRegisters->lbaHighRegister);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","Device",
mvStorageDevRegisters->deviceRegister);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "%20s : %04x\n","Status",
mvStorageDevRegisters->statusRegister);
}
/*SCSI command queue functions*/
static void mvAddToSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SATA_SCSI_CMD_BLOCK *pScb)
{
MV_SATA_SCSI_CMD_BLOCK *cmdBlock = (MV_SATA_SCSI_CMD_BLOCK *)
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue;
pScb->pNext = NULL;
if (cmdBlock)
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Adding next command to SW queue\n",
ialExt->pSataAdapter->adapterId, channelIndex);
while (cmdBlock->pNext)
{
cmdBlock = cmdBlock->pNext;
}
cmdBlock->pNext = pScb;
}
else
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Adding first command to SW queue\n",
ialExt->pSataAdapter->adapterId, channelIndex);
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue =
(MV_VOID_PTR)pScb;
}
}
MV_BOOLEAN mvRemoveFromSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_SATA_SCSI_CMD_BLOCK *pScb)
{
MV_SATA_SCSI_CMD_BLOCK *cmdBlock = (MV_SATA_SCSI_CMD_BLOCK *)
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue;
pScb->pNext = NULL;
if (cmdBlock)
{
if (cmdBlock == pScb)
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Removing command"
" %p from head of SW queue\n",
ialExt->pSataAdapter->adapterId,channelIndex, pScb);
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue =
(MV_VOID_PTR) cmdBlock->pNext;
return MV_TRUE;
}
else
{
while (cmdBlock->pNext)
{
if (cmdBlock->pNext == pScb)
{
break;
}
cmdBlock = cmdBlock->pNext;
}
if (cmdBlock->pNext == NULL)
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d] Removing"
" command %p from SW queue failed. command not found\n",
ialExt->pSataAdapter->adapterId,channelIndex, pScb);
return MV_FALSE;
}
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d] Removing command"
" %p from SW queue\n", ialExt->pSataAdapter->adapterId,
channelIndex, pScb);
cmdBlock->pNext = cmdBlock->pNext->pNext;
return MV_TRUE;
}
}
else
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d] Removing"
" command %p from SW queue failed. queue empty\n",
ialExt->pSataAdapter->adapterId,channelIndex, pScb);
return MV_FALSE;
}
return MV_FALSE;
}
static void mvFlushSCSICommandQueue(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex)
{
/*Abort all pending commands in SW queue*/
MV_SATA_SCSI_CMD_BLOCK *cmdBlock = (MV_SATA_SCSI_CMD_BLOCK *)
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue;
while (cmdBlock)
{
MV_SATA_SCSI_CMD_BLOCK *nextBlock = cmdBlock->pNext;
if (cmdBlock->completionCallBack)
{
cmdBlock->ScsiStatus = MV_SCSI_STATUS_BUSY;
cmdBlock->dataTransfered = 0;
cmdBlock->ScsiCommandCompletion = MV_SCSI_COMPLETION_QUEUE_FULL;
cmdBlock->completionCallBack(ialExt->pSataAdapter, cmdBlock);
}
cmdBlock = nextBlock;
}
ialExt->IALChannelExt[channelIndex].IALChannelPendingCmdQueue = NULL;
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Flush command queue is done\n",
ialExt->pSataAdapter->adapterId, channelIndex);
}
/*Port Multilier related functions*/
static MV_BOOLEAN mvPMCommandCompletionCB(MV_SATA_ADAPTER *pSataAdapter,
MV_U8 channelIndex,
MV_COMPLETION_TYPE comp_type,
MV_VOID_PTR commandId,
MV_U16 responseFlags,
MV_U32 timeStamp,
MV_STORAGE_DEVICE_REGISTERS *registerStruct)
{
MV_U32 value;
MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt =
(MV_IAL_COMMON_ADAPTER_EXTENSION *)commandId;
ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_FALSE;
switch (comp_type)
{
case MV_COMPLETION_TYPE_NORMAL:
if (ialExt->IALChannelExt[channelIndex].pmAccessType
== MV_ATA_COMMAND_PM_READ_REG)
{
value = registerStruct->sectorCountRegister;
value |= (registerStruct->lbaLowRegister << 8);
value |= (registerStruct->lbaMidRegister << 16);
value |= (registerStruct->lbaMidRegister << 24);
if (ialExt->IALChannelExt[channelIndex].pmReg
== MV_SATA_GSCR_ERROR_REG_NUM)
{
if (value != 0)
{
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: PM GSCR[32] = 0x%X\n",
pSataAdapter->adapterId, channelIndex, value);
ialExt->IALChannelExt[channelIndex].PMdevsToInit =
(MV_U16)(value & 0x7FFF);
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: "
"PM Hot plug detected "
"Bitmask = 0x%X\n",
pSataAdapter->adapterId, channelIndex,
ialExt->IALChannelExt[channelIndex].PMdevsToInit);
mvSetChannelState(ialExt, channelIndex,
CHANNEL_PM_HOT_PLUG);
}
}
}
break;
case MV_COMPLETION_TYPE_ABORT:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: read PM register aborted!\n",
pSataAdapter->adapterId, channelIndex);
break;
case MV_COMPLETION_TYPE_ERROR:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: read PM register error!\n",
pSataAdapter->adapterId, channelIndex);
break;
default:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, "[%d %d]: Unknown completion type (%d)\n",
pSataAdapter->adapterId, channelIndex, comp_type);
return MV_FALSE;
}
return MV_TRUE;
}
static MV_BOOLEAN mvQueuePMAccessRegisterCommand(
MV_IAL_COMMON_ADAPTER_EXTENSION* ialExt,
MV_U8 channelIndex,
MV_U8 PMPort,
MV_U8 PMReg,
MV_U32 Value,
MV_BOOLEAN isRead)
{
MV_QUEUE_COMMAND_INFO commandParams;
MV_QUEUE_COMMAND_RESULT result;
MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
memset(&commandParams, 0, sizeof(commandParams));
commandParams.type = MV_QUEUED_COMMAND_TYPE_NONE_UDMA;
commandParams.commandParams.NoneUdmaCommand.protocolType =
MV_NON_UDMA_PROTOCOL_NON_DATA;
commandParams.commandParams.NoneUdmaCommand.isEXT = MV_FALSE;
commandParams.commandParams.NoneUdmaCommand.bufPtr = NULL;
commandParams.PMPort = MV_SATA_PM_CONTROL_PORT;
commandParams.commandParams.NoneUdmaCommand.count = 0;
commandParams.commandParams.NoneUdmaCommand.features = PMReg;
commandParams.commandParams.NoneUdmaCommand.device = (MV_U8)PMPort;
commandParams.commandParams.NoneUdmaCommand.callBack =
mvPMCommandCompletionCB;
ialExt->IALChannelExt[channelIndex].pmReg = PMReg;
if (isRead == MV_TRUE)
{
ialExt->IALChannelExt[channelIndex].pmAccessType =
MV_ATA_COMMAND_PM_READ_REG;
commandParams.commandParams.NoneUdmaCommand.command =
MV_ATA_COMMAND_PM_READ_REG;
commandParams.commandParams.NoneUdmaCommand.commandId =
(MV_VOID_PTR)ialExt;
commandParams.commandParams.NoneUdmaCommand.sectorCount = 0;
commandParams.commandParams.NoneUdmaCommand.lbaLow = 0;
commandParams.commandParams.NoneUdmaCommand.lbaMid = 0;
commandParams.commandParams.NoneUdmaCommand.lbaHigh = 0;
}
else
{
ialExt->IALChannelExt[channelIndex].pmAccessType =
MV_ATA_COMMAND_PM_WRITE_REG;
commandParams.commandParams.NoneUdmaCommand.command =
MV_ATA_COMMAND_PM_WRITE_REG;
commandParams.commandParams.NoneUdmaCommand.commandId =
(MV_VOID_PTR)ialExt;
commandParams.commandParams.NoneUdmaCommand.sectorCount =
(MV_U16)((Value) & 0xff),
commandParams.commandParams.NoneUdmaCommand.lbaLow =
(MV_U16)(((Value) & 0xff00) >> 8);
commandParams.commandParams.NoneUdmaCommand.lbaMid =
(MV_U16)(((Value) & 0xff0000) >> 16);
commandParams.commandParams.NoneUdmaCommand.lbaHigh =
(MV_U16)(((Value) & 0xff000000) >> 24);
}
ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_TRUE;
result = mvSataQueueCommand(pSataAdapter,
channelIndex,
&commandParams);
if (result != MV_QUEUE_COMMAND_RESULT_OK)
{
switch (result)
{
case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. Bad LBA "
"\n");
break;
case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. EDMA"
" disabled adapter %d channel %d\n",
pSataAdapter->adapterId, channelIndex);
break;
case MV_QUEUE_COMMAND_RESULT_FULL:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. Queue is"
" Full adapter %d channel %d\n",
pSataAdapter->adapterId, channelIndex);
break;
case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command failed. (Bad "
"Params), pMvSataAdapter: %p, pSataChannel: %p.\n",
pSataAdapter, pSataAdapter->sataChannel[channelIndex]);
break;
default:
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG_ERROR, ": Queue PM command bad result value (%d) "
"from queue command\n",
result);
}
ialExt->IALChannelExt[channelIndex].pmRegAccessInProgress = MV_FALSE;
return MV_FALSE;
}
return MV_TRUE;
}
static MV_BOOLEAN mvPMEnableCommStatusChangeBits(MV_IAL_COMMON_ADAPTER_EXTENSION *ialExt,
MV_U8 channelIndex,
MV_BOOLEAN enable)
{
MV_U32 regVal;
MV_SATA_ADAPTER *pSataAdapter = ialExt->pSataAdapter;
if (enable == MV_TRUE)
{
regVal = MV_BIT16 | MV_BIT26;
}
else
{
regVal = 0;
}
mvLogMsg(MV_IAL_COMMON_LOG_ID, MV_DEBUG, "[%d %d]: Set PM "
"GSCR[33] register to 0x%X\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -