⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mvialcommon.c

📁 此为marvell 6081芯片驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
*    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 + -