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

📄 mvsata.c

📁 此为marvell6081芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
									 compType, pUdmaCommandParams->commandId,
									 eDmaCause, response.timeStamp, &deviceRegs);
		removeCommand(pSataChannel,pCommandEntry);
		if (pSataChannel->queueCommandsEnabled == MV_FALSE)
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND,
					 "%d %d: Commands queuing is disabled\n",
					 pSataChannel->mvSataAdapter->adapterId,
					 pSataChannel->channelNumber);
			return;
		}
		if (pSataChannel->commandsQueueHead == NULL)
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_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_UDMA_COMMAND,
					 "%d %d: Next Command is PIO\n",
					 pSataChannel->mvSataAdapter->adapterId,
					 pSataChannel->channelNumber);
			deactivateEdma(pAdapter,channelIndex);
			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
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_UDMA_COMMAND,
					 "%d %d: Next Command is UDMA nothing to do\n",
					 pSataChannel->mvSataAdapter->adapterId,
					 pSataChannel->channelNumber);

		}
	}
}


#ifdef MV_SATA_C2C_COMM
/*******************************************************************************
* handleBmDmaInterrupt - handle DMA interrupt received for a given channel
*
* DESCRIPTION:
*   This function is called when response interrupt is issued when C2C DMA
*   completion event occurs.
*
* INPUT:
*   pAdapter   - pointer to the MV88SX50XX adapter data structure
*   ioBaseAddr  - adapter rbase address
*   pSataChannel  - SATA channel structure
*   channelIndex  - SATA channel index
*   edmaError   - if != zero then EDMA error happened.
*
* RETURN:
*   None.
*
* COMMENTS:
*   None
*
*******************************************************************************/

static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter,
								 MV_BUS_ADDR_T   ioBaseAddr,
								 MV_SATA_CHANNEL *pSataChannel,
								 MV_U8   channelIndex,
								 MV_U32 edmaError)
{
	MV_U32  val;
	MV_U32  eDmaErrorCause = 0;
	mvOsSemTake(&pSataChannel->semaphore);
	/*Reset BM dma*/
	val = MV_REG_READ_DWORD (ioBaseAddr,
							 getEdmaRegOffset(channelIndex) +
							 MV_BMDMA_COMMAND_OFFSET);
	val &= ~MV_BIT0;
	MV_REG_WRITE_DWORD (ioBaseAddr,
						getEdmaRegOffset(channelIndex) +
						MV_BMDMA_COMMAND_OFFSET, val);

	MV_REG_WRITE_DWORD(ioBaseAddr,
					   getEdmaRegOffset(channelIndex) +
					   MV_SATA_II_IF_CONTROL_REG_OFFSET,
					   0);
	if (edmaError)
	{
		eDmaErrorCause = (MV_U16)MV_REG_READ_DWORD(ioBaseAddr,
												   getEdmaRegOffset(channelIndex) +
												   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
	}
	mvOsSemRelease(&pSataChannel->semaphore);
	if (pSataChannel->C2CCallback)
	{
		if (!edmaError)
		{
			pSataChannel->C2CCallback(pAdapter,
									  pSataChannel,
									  MV_C2C_BM_DMA_DONE,
									  0,
									  NULL);
		}
		else
		{
			if (eDmaErrorCause & (MV_BIT17 | MV_BIT26))
			{
				pSataChannel->C2CCallback(pAdapter,
										  pSataChannel,
										  MV_C2C_BM_DMA_ERROR,
										  0,
										  NULL);
			}
			if (eDmaErrorCause & (MV_BIT13 | MV_BIT21))
			{
				pSataChannel->C2CCallback(pAdapter,
										  pSataChannel,
										  MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_ERROR,
										  0,
										  NULL);
			}
		}
	}
}
#endif


/*******************************************************************************
* handleEdmaInterrupt - handle EDMA interrupt receivd for a given channel
*
* DESCRIPTION:
*   this function called when response interrupt issuesed for a channel and it
*    handles all EDMA responses.
*
* INPUT:
*   *pAdapter   - pointer to the MV88SX50XX adapter data structure
*   sataUnit    - the SATAHC unit this channel belongs to
*   port        - the port number of the channel
*   rspInPtr    - the value of eRPQIP of the channel
*   responseDone   - if != zero then responses received on this channel
*   edmaError   - if != zero then EDMA error happened.
*
* RETURN:
*   None.
*
* COMMENTS:
*   None.
*
*******************************************************************************/
static void handleEdmaInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
								MV_U8 port,MV_U32 rspInPtr, MV_U32 responseDone,
								MV_U32 edmaError, MV_U32 unitCause)
{
	MV_U32  rspOutPtr;
	MV_U8   channelIndex;
	MV_BUS_ADDR_T   ioBaseAddr = pAdapter->adapterIoBaseAddress;
	MV_U32  eDmaRegsOffset;
	MV_SATA_CHANNEL *pSataChannel;
	MV_U32 eDmaErrorCause = 0;
	MV_BOOLEAN forceAutoFlush = MV_FALSE;

	channelIndex = MV_CHANNEL_INDEX(sataUnit, port);
	pSataChannel = pAdapter->sataChannel[channelIndex];


	if (responseDone && (pSataChannel != NULL))/* port Done*/
	{
		mvOsSemTake(&pSataChannel->semaphore);
#ifdef MV_SATA_C2C_COMM
		if (MV_FALSE == pSataChannel->C2CmodeEnabled)
		{
#endif
			eDmaRegsOffset = pSataChannel->eDmaRegsOffset;

			rspOutPtr = pSataChannel->rspOutPtr;
			/* here we should update the response out pointer though we didn't*/
			/* handled the new responses, these response entries will not be  */
			/* accessed again by the EDMA sinse the number of queued commands */
			/* (outstandingCommands) will be updated only after we handle each*/
			/* response entry                                                 */
			MV_REG_WRITE_DWORD(ioBaseAddr, eDmaRegsOffset +
							   MV_EDMA_RESPONSE_Q_OUTP_REG_OFFSET,
							   pSataChannel->responseQueuePciLowAddress |
							   (rspInPtr << MV_EDMA_RESPONSE_Q_OUTP_OFFSET));
			while (rspOutPtr != rspInPtr)
			{
				handleEdmaResponse(pAdapter, channelIndex,
								   &(pSataChannel->responseQueue[rspOutPtr]));
				rspOutPtr++;
				rspOutPtr &= MV_EDMA_QUEUE_MASK;
			}
			/*
			 * Check if queueCommandsEnabled flag is disabled.
			 * If so, then an error has occured and auto flush must be triggered.
			 * Basically it is enough to trigger auto flush upon edmaError flag,
			 * but since edmaError is set before handleEdmaResponse is called
			 * there could be a racing condition between the time edmaError is checked
			 * and the response queue is checked.
			 * The racing condition is that an error does not occur when setting
			 * edmaError to MV_FALSE, but in handlEdmaResponse, the hardware
			 * has completed a command with error.
			 * The racing condition will complete the error command (through callback)
			 * but will prevent the auto flush of all outstanding commands.
			 */
			if (pSataChannel->queueCommandsEnabled == MV_FALSE)
			{
				forceAutoFlush = MV_TRUE;
			}

			pSataChannel->rspOutPtr = rspOutPtr;
			mvOsSemRelease(&pSataChannel->semaphore);
#ifdef MV_SATA_C2C_COMM
		}
		else
		{
			mvOsSemRelease(&pSataChannel->semaphore);
			handleBmDMAInterrupt(pAdapter,
								 ioBaseAddr,
								 pSataChannel,
								 channelIndex,
								 edmaError);
		}
#endif
	}

	if ((edmaError) ||  (forceAutoFlush == MV_TRUE))	/* EDMA error interrupt*/
	{
		eDmaErrorCause = MV_REG_READ_DWORD(ioBaseAddr,
										   getEdmaRegOffset(channelIndex) +
										   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);

		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR | MV_DEBUG_INTERRUPTS,
				 "%d %d: Edma Error Reg 0x%x\n", pAdapter->adapterId,
				 channelIndex, MV_REG_READ_DWORD(ioBaseAddr,
												 getEdmaRegOffset(channelIndex) +
												 MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
		/* clear the channel's error cause register */
		MV_REG_WRITE_DWORD(ioBaseAddr,
						   getEdmaRegOffset(channelIndex) +
						   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,
						   ~eDmaErrorCause);
		if (MV_REG_READ_DWORD(ioBaseAddr,
							  getEdmaRegOffset(channelIndex) +
							  MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET))
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR | MV_DEBUG_INTERRUPTS,
					 "%d %d: Edma Error Reg 0x%x still set!!!!!!!!\n",
					 pAdapter->adapterId, channelIndex,
					 MV_REG_READ_DWORD(ioBaseAddr,
									   getEdmaRegOffset(channelIndex) +
									   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET));
			if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
			{
				/*wait 20ms till diconnect/connect interrupts finish*/
				mvMicroSecondsDelay(pAdapter, 20000);
				eDmaErrorCause |= MV_REG_READ_DWORD(ioBaseAddr,
													getEdmaRegOffset(channelIndex) +
													MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET);
				MV_REG_WRITE_DWORD(ioBaseAddr,
								   getEdmaRegOffset(channelIndex) +
								   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,
								   ~eDmaErrorCause);
			}
		}
		/* dump in case any kind of parity error*/
		if (eDmaErrorCause & (MV_BIT11 | MV_BIT10 | MV_BIT9 | MV_BIT1 | MV_BIT0))
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR," PARITY ERROR Detected\n");
			_dumpPCIRegs(pAdapter);
			_dumpEDMARegs(pAdapter,channelIndex);
			_dumpChannelQueues(pAdapter,channelIndex);
		}
		if (eDmaErrorCause & MV_BIT3) /*device disconneted*/
		{
			if (pSataChannel)
			{
				mvOsSemTake(&pSataChannel->semaphore);
				pSataChannel->queueCommandsEnabled = MV_FALSE;
				pSataChannel->EdmaActive = MV_FALSE;
			}
			/* If disk is disconnected, then disable the activity LED */
			if (pAdapter->implement50XXB1Workarounds == MV_TRUE ||
				pAdapter->implement50XXB2Workarounds == MV_TRUE)
			{
				MV_U32 regVal1, regVal2;
				/* First enable flash controller clocks*/
				regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
											MV_PCI_REGS_OFFSET +
											MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);

				regVal1 |= (MV_BIT0);
				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
								   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET,
								   regVal1);
				regVal1 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
											MV_PCI_REGS_OFFSET +
											MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET);
				/* Disable activity LEDs */
				regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
											MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
				regVal2 |= (MV_BIT8 << channelIndex);
				MV_REG_WRITE_DWORD (pAdapter->adapterIoBaseAddress,
									MV_FLASH_GPIO_PORT_CONTROL_OFFSET,
									regVal2);
				regVal2 = MV_REG_READ_DWORD(pAdapter->adapterIoBaseAddress,
											MV_FLASH_GPIO_PORT_CONTROL_OFFSET);
				/* Disable flash controller clocks */
				regVal1 &= ~(MV_BIT0);
				MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
								   MV_PCI_REGS_OFFSET + MV_PCI_EXPANSION_ROM_CONTROL_REG_OFFSET,
								   regVal1);
			}
			/* Fix for 88SX50XX FEr SATA#2 */
			if ((pAdapter->implement50XXB0Workarounds == MV_TRUE)||
				(pAdapter->implement50XXB1Workarounds == MV_TRUE) ||
				(pAdapter->implement50XXB2Workarounds == MV_TRUE))
			{
				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
						 "%d %d: Before Hard RESET Main Cause %x\n",
						 pAdapter->adapterId, channelIndex,
						 MV_REG_READ_DWORD(ioBaseAddr,
										   MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET));
				/* Hard Reset the channel so we can do re-connect*/
				_channelHardReset(pAdapter, channelIndex);
				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
						 "%d %d: After Hard RESET Main Cause %x\n",
						 pAdapter->adapterId, channelIndex,
						 MV_REG_READ_DWORD(ioBaseAddr,
										   MV_MAIN_INTERRUPT_CAUSE_REG_OFFSET));
			}
			else
			{
				if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_II)
				{
					_channelHardReset(pAdapter, channelIndex);
					_establishSataComm(pAdapter, channelIndex);
				}
			}
			/* after calling mvSataNotify we can not be sure that the channel*/
			/* data structure is still available so first we release the     */
			/* semaphore, after notifying the upper-layer with the disconnect*/
			/* event, nothing else is done with that channel                 */
			if (pSataChannel)
			{
				mvOsSemRelease(&pSataChannel->semaphore);
			}
			if (mvSataIsStorageDeviceConnected(pAdapter,channelIndex) == MV_FALSE)
			{
				pAdapter->mvSataEventNotify(pAdapter,
											MV_EVENT_TYPE_SATA_CABLE,
											MV_SATA_CABLE_EVENT_DISCONNECT,
											channelIndex);
			}
			/* continue only if we have also a connect interrupt*/
			if ((eDmaErrorCause & MV_BIT4) == 0)
			{
				return;
			}
		}
		if (eDmaErrorCause & MV_BIT4) /*device conneted*/
		{
			/* Fix for 88SX50xx FEr SATA#2 */
			if ((pAdapter->implement50XXB0Workarounds == MV_TRUE) ||
				(pAdapter->implement50XXB1Workarounds == MV_TRUE) ||
				(pAdapter->implement50XXB2Workarounds == MV_TRUE))
			{

⌨️ 快捷键说明

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