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

📄 mvsata.c

📁 此为marvell6081芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;
	default: /* never reached */
		break;
	}
}
static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel,
								  MV_NONE_UDMA_COMMAND_PARAMS   *pNoneUdmaCommandParams)
{
	MV_U32  i;

	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
			 "%d %d: xfer data for PIO Data command.count %d\n",
			 pSataChannel->mvSataAdapter->adapterId,
			 pSataChannel->channelNumber, pNoneUdmaCommandParams->count);

	switch (pNoneUdmaCommandParams->protocolType)
	{
	case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:
		for (i = 0; i < 256; i++)
		{
			if (pNoneUdmaCommandParams->count == 0)
			{
				return MV_TRUE;
			}
			pNoneUdmaCommandParams->count--;
			MV_REG_WRITE_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
							  pSataChannel->eDmaRegsOffset +
							  MV_ATA_DEVICE_PIO_DATA_REG_OFFSET,
							  *pNoneUdmaCommandParams->bufPtr++);
		}
		break;
	case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN:
		for (i = 0; i < 256; i++)
		{
			if (pNoneUdmaCommandParams->count == 0)
			{
				return MV_TRUE;
			}
			pNoneUdmaCommandParams->count--;
			*pNoneUdmaCommandParams->bufPtr++ =
			MV_REG_READ_WORD(pSataChannel->mvSataAdapter->adapterIoBaseAddress,
							 pSataChannel->eDmaRegsOffset +
							 MV_ATA_DEVICE_PIO_DATA_REG_OFFSET);
		}
		break;
	case MV_NON_UDMA_PROTOCOL_NON_DATA:
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: in xfer data "
				 "PIO command is None Data \n",
				 pSataChannel->mvSataAdapter->adapterId,
				 pSataChannel->channelNumber);
		return MV_FALSE;
	}
	return MV_TRUE;
}

static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel,
							   MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
							   MV_BOOLEAN failed)
{
	MV_COMPLETION_TYPE              compType = MV_COMPLETION_TYPE_NORMAL;
	MV_STORAGE_DEVICE_REGISTERS     deviceRegs;
	MV_NONE_UDMA_COMMAND_PARAMS     *pParams =
	&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand;

	dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
						   pSataChannel->channelNumber, pParams->isEXT,
						   &deviceRegs);
	if (failed == MV_TRUE)
	{
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Command completed "
				 "with error\n", pSataChannel->mvSataAdapter->adapterId,
				 pSataChannel->channelNumber);

		compType = MV_COMPLETION_TYPE_ERROR;
		pSataChannel->queueCommandsEnabled = MV_FALSE;
	}
	else
	{
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
				 "%d %d: PIO Command completed successfully\n",
				 pSataChannel->mvSataAdapter->adapterId,
				 pSataChannel->channelNumber);
	}
	pParams->callBack(pSataChannel->mvSataAdapter, pSataChannel->channelNumber,
					  compType, pParams->commandId, 0, 0, &deviceRegs);

	removeCommand(pSataChannel,pCommandEntry);
	if ((failed == MV_TRUE) && (mvAutoFlushOnError == MV_TRUE))
	{
		_doAutoFlush(pSataChannel);
	}

	if (pSataChannel->commandsQueueHead == NULL)
	{
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
				 "%d %d: Commands queue is empty\n",
				 pSataChannel->mvSataAdapter->adapterId,
				 pSataChannel->channelNumber);
		return;
	}

	if (pSataChannel->commandsQueueHead->commandInfo.type ==
		MV_QUEUED_COMMAND_TYPE_NONE_UDMA)
	{
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
				 "%d %d: Next Command is PIO\n",
				 pSataChannel->mvSataAdapter->adapterId,
				 pSataChannel->channelNumber);
		if (pSataChannel->PMSupported == MV_TRUE)
		{
			_setActivePMPort(pSataChannel,
							 pSataChannel->commandsQueueHead->commandInfo.PMPort);
		}
		if (sendNoneUdmaCommand(pSataChannel,
								pSataChannel->commandsQueueHead) == MV_FALSE)
		{
			completePIOCommand(pSataChannel, pSataChannel->commandsQueueHead,
							   MV_FALSE);
		}

	}
	else
	{
		MV_QUEUED_COMMAND_ENTRY *pEntry;
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
				 "%d %d: Next Command is UDMA\n",
				 pSataChannel->mvSataAdapter->adapterId,
				 pSataChannel->channelNumber);
		activateEdma(pSataChannel->mvSataAdapter,pSataChannel->channelNumber);
		pEntry = pSataChannel->commandsQueueHead;
		while ((pEntry != NULL) &&
			   (pEntry->commandInfo.type == MV_QUEUED_COMMAND_TYPE_UDMA))
		{
			EdmaReqQueueInsert(pSataChannel, pEntry,
							   &pEntry->commandInfo.commandParams.udmaCommand);
			pEntry = pEntry->next;
		}

	}

}
/*******************************************************************************
* resetEdmaChannel - resets the channel data stucture and EDMA registers
*
*
* DESCRIPTION:
*   this function resets the low level EDMA fields of Sata channel data
*   structure and initialize the EDMA register accourdingly
*
* INPUT:
*   *pSataChannel   - pointer to the Sata channel data structure
*
* RETURN:
*   MV_TRUE on success, MV_FALSE otherwise.
*
* COMMENTS:
*   this function assumes that the channel semaphore is locked
*
*******************************************************************************/
static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel)
{
	MV_BUS_ADDR_T       ioBaseAddr =
	pSataChannel->mvSataAdapter->adapterIoBaseAddress;
	MV_U32 eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
	int i;

	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG, "%d %d: resetEdmaChannel\n",
			 pSataChannel->mvSataAdapter->adapterId,
			 pSataChannel->channelNumber);

	if (MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset +
						  MV_EDMA_COMMAND_REG_OFFSET) &
		MV_EDMA_COMMAND_HARD_RST_MASK)
	{
		MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
						   MV_EDMA_COMMAND_REG_OFFSET,
						   MV_EDMA_COMMAND_DISABLE_MASK);

		MV_REG_READ_DWORD(ioBaseAddr, eDmaRegsOffset +
						  MV_EDMA_COMMAND_REG_OFFSET);
		mvMicroSecondsDelay(pSataChannel->mvSataAdapter,
							MV_HARD_RESET_WAIT_NEGATE);
		_fixPhyParams(pSataChannel->mvSataAdapter, pSataChannel->channelNumber);
	}
	else
	{
		MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
						   MV_EDMA_COMMAND_REG_OFFSET,
						   MV_EDMA_COMMAND_DISABLE_MASK);
	}

	pSataChannel->outstandingCommands = 0;
	pSataChannel->noneUdmaOutstandingCommands = 0;
	pSataChannel->EdmaQueuedCommands = 0;
	pSataChannel->reqInPtr = 0;
	pSataChannel->rspOutPtr = 0;
	pSataChannel->EdmaActive = MV_FALSE;

	/* init free entries stack*/
	pSataChannel->freeIDsNum = MV_SATA_SW_QUEUE_SIZE;
	for (i = 0; i < MV_SATA_SW_QUEUE_SIZE; i++)
	{
		pSataChannel->freeIDsStack[i] = MV_SATA_SW_QUEUE_SIZE - 1 - i;
		pSataChannel->commandsQueue[i].isFreeEntry = MV_TRUE;
	}

	pSataChannel->commandsQueueHead = NULL;
	pSataChannel->commandsQueueTail = NULL;
	pSataChannel->queueCommandsEnabled = MV_FALSE;
#ifdef MV_SATA_C2C_COMM

	/* C2C */
	pSataChannel->C2CmodeEnabled = MV_FALSE;
#endif

	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET, 0);
	/* enable connect/disconnet and selfDisable, the rest of errors will    */
	/* eventually cause selfDisable interrupt                               */

	if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
	{
		MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
						   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
						   MV_BIT8 | MV_BIT4 | MV_BIT3);
	}
	else
	{
		MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
						   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
						   MV_BIT8 | MV_BIT7 | MV_BIT4 | MV_BIT3);
	}
	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_REQUEST_Q_BAH_REG_OFFSET,
					   pSataChannel->requestQueuePciHiAddress);
	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_REQUEST_Q_INP_REG_OFFSET,
					   pSataChannel->requestQueuePciLowAddress &
					   MV_EDMA_REQUEST_Q_BA_MASK);
	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_REQUEST_Q_OUTP_REG_OFFSET, 0);
	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_RESPONSE_Q_BAH_REG_OFFSET,
					   pSataChannel->responseQueuePciHiAddress);
	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_RESPONSE_Q_INP_REG_OFFSET, 0);
	MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
					   MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET,
					   pSataChannel->responseQueuePciLowAddress &
					   MV_EDMA_RESPONSE_Q_BA_MASK);

	return MV_TRUE;
}

static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel,MV_FLUSH_TYPE flushType,
						  MV_COMPLETION_TYPE completionType, MV_U16 eDmaCause)
{
	mvSataCommandCompletionCallBack_t callBackFunc;
	int i;


	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: Flush DMA, type=%s, commands"
			 " %d (on EDMA %d)\n", pSataChannel->mvSataAdapter->adapterId,
			 pSataChannel->channelNumber,
			 (flushType==MV_FLUSH_TYPE_CALLBACK)?"CALLBACK":"NONE",
			 pSataChannel->outstandingCommands,pSataChannel->EdmaQueuedCommands);

	if (flushType == MV_FLUSH_TYPE_CALLBACK)
	{
		for (i=0;i < MV_SATA_SW_QUEUE_SIZE; i++)
		{
			if (pSataChannel->commandsQueue[i].isFreeEntry == MV_FALSE)
			{
				MV_STORAGE_DEVICE_REGISTERS deviceRegisters;
				MV_BOOLEAN  isEXT;
				MV_VOID_PTR commandId;
				if (pSataChannel->commandsQueue[i].commandInfo.type == MV_QUEUED_COMMAND_TYPE_NONE_UDMA)
				{
					isEXT = pSataChannel->commandsQueue[i].commandInfo.commandParams.NoneUdmaCommand.isEXT;
					commandId = pSataChannel->commandsQueue[i].commandInfo.commandParams.NoneUdmaCommand.commandId;
					callBackFunc = pSataChannel->commandsQueue[i].commandInfo.commandParams.NoneUdmaCommand.callBack;
				}
				else
				{
					isEXT = pSataChannel->commandsQueue[i].commandInfo.commandParams.udmaCommand.isEXT;
					commandId = pSataChannel->commandsQueue[i].commandInfo.commandParams.udmaCommand.commandId;
					callBackFunc = pSataChannel->commandsQueue[i].commandInfo.commandParams.udmaCommand.callBack;
				}

				dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
									   pSataChannel->channelNumber, isEXT,
									   &deviceRegisters);
				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_ERROR,
						 "%d %d: Calling callBackFunc - command index %d at %p,"
						 " next %p, prev %p\n",
						 pSataChannel->mvSataAdapter->adapterId,
						 pSataChannel->channelNumber,
						 i,
						 &pSataChannel->commandsQueue[i],
						 pSataChannel->commandsQueue[i].next,
						 pSataChannel->commandsQueue[i].prev);
				callBackFunc(pSataChannel->mvSataAdapter,
							 pSataChannel->channelNumber, completionType,
							 commandId, eDmaCause, 0, &deviceRegisters);
			}
		}
	}
}

static void _fixPhyParams(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
{
	/* Set unit 0 or 1 */
	MV_U8       sataUnit = (channelIndex & MV_BIT2) >> 2;
	/* Set port 0-3 */
	MV_U8       port = channelIndex & (MV_BIT0 | MV_BIT1);
	MV_U32      regVal;

	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
	{

		if (pAdapter->implement50XXB0Workarounds == MV_TRUE)
		{
			/* Fix for 88SX50xx FEr SATA#12 */
			/* Disable auto-power management*/
			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
									   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
									   MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port));
			regVal |= MV_BIT19;	/* disbale auto-power management*/
			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
							   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
							   MV_SATA_I_HC_LT_MODES_PORT_REG_OFFSET(port),
							   regVal);
			/* 88SX50xx FEr SATA#9*/
			/*Fix squelch threshold*/
			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
									   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
									   MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port));

			regVal &= ~0x3;
			regVal |= 0x1;
			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
							   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
							   MV_SATA_I_HC_PHY_CONTROL_BRIDGE_PORT_OFFSET(port),
							   regVal);
		}
		/* Revert values of pre-emphasis and signal amps to the saved ones */
		{
			regVal = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
									   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
									   MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port));
			regVal &= ~MV_SATA_I_PHY_MODE_AMP_MASK;
			regVal |= (pAdapter->signalAmps[channelIndex] << MV_SATA_I_PHY_MODE_AMP_OFFSET) &
					  MV_SATA_I_PHY_MODE_AMP_MASK;
			regVal &= ~MV_SATA_I_PHY_MODE_PRE_MASK;
			regVal |= (pAdapter->pre[channelIndex] << MV_SATA_I_PHY_MODE_PRE_OFFSET) &
					  MV_SATA_I_PHY_MODE_PRE_MASK;
			MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
							   MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
							   MV_SATA_I_HC_PHY_MODE_BRIDGE_PORT_REG_OFFSET(port),
							   regVal);
		}
	}
	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
	{
		MV_U32 phyMode2Offset = getEdmaRegOffset(channelIndex) +
								MV_SATA_II_PHY_MODE_2_REG_OFFSET;

		/* Fix values in phyMode 4 register.*/
		/* 88SX60x1 FEr SATA#10 */
		if ((pAdapter->implement60X1A1Workarounds == MV_TRUE) ||
			(pAdapter->implement60X1B0Workarounds == MV_TRUE))
		{
			MV_U32 phyMode4Value;
			MV_U32 tempRegOffset, tempRe

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -