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

📄 mvsata.c

📁 此为marvell6081芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
				_fixPhyParams(pAdapter, channelIndex);/*TBD*/
				/* The following link re-establishment is due to non	*/
				/* Marvell driven hard drives							*/
				_establishSataComm(pAdapter, channelIndex);
				_establishSataComm(pAdapter, channelIndex);
			}

			/* If disk is connected, then enable 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);
				/* Enable 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);
			}
			if (mvSataIsStorageDeviceConnected(pAdapter,channelIndex) == MV_TRUE)
			{
				pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE,
											MV_SATA_CABLE_EVENT_CONNECT,
											channelIndex);
			}
			return;
		}
		/*PM hot plug*/
		if ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_II) &&
			(eDmaErrorCause & MV_BIT8))
		{
			MV_U32 regVal1;
			if (pSataChannel != NULL)
			{
				mvOsSemTake(&pSataChannel->semaphore);
			}
			regVal1 = MV_REG_READ_DWORD(ioBaseAddr,
										getEdmaRegOffset(channelIndex) +
										MV_SATA_II_IF_STATUS_REG_OFFSET);
			/*Clear status*/
			if ((regVal1 & (MV_BIT31 | MV_BIT30))||
				(pAdapter->implement60X1A1Workarounds == MV_TRUE))
			{
				MV_U32 regVal2 = MV_REG_READ_DWORD(ioBaseAddr,
												   getEdmaRegOffset(channelIndex) +
												   MV_SATA_II_IF_CONTROL_REG_OFFSET);
				regVal2 |= MV_BIT24;
				MV_REG_WRITE_DWORD(ioBaseAddr,
								   getEdmaRegOffset(channelIndex) +
								   MV_SATA_II_IF_CONTROL_REG_OFFSET, regVal2);
			}
			if (pSataChannel != NULL)
			{
				mvOsSemRelease(&pSataChannel->semaphore);
			}
			if ((((regVal1 & MV_BIT30) == 0) &&
				 ((regVal1 & MV_BIT31) == MV_BIT31)) ||
				(pAdapter->implement60X1A1Workarounds == MV_TRUE))
			{


				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_INTERRUPTS,
						 "%d %d: PM asynchronous notification interrupt.\n",
						 pAdapter->adapterId, channelIndex);

				pAdapter->mvSataEventNotify(pAdapter, MV_EVENT_TYPE_SATA_CABLE,
											MV_SATA_CABLE_EVENT_PM_HOT_PLUG,
											channelIndex);
			}
			return;
		}
		if ((((pAdapter->sataAdapterGeneration == MV_SATA_GEN_I) && (eDmaErrorCause & MV_BIT8)) ||
			 ((pAdapter->sataAdapterGeneration == MV_SATA_GEN_II) && (eDmaErrorCause & MV_BIT7)))
			&&
			(pSataChannel != NULL))	/* edma self disable */
		{
			mvOsSemTake(&pSataChannel->semaphore);
			if (pSataChannel->EdmaActive == MV_TRUE) /* if no completion done */
			{
				/* with that error       */
				mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR |MV_DEBUG_INTERRUPTS,
						 "%d %d: Edma Interrupt received without completion\n",
						 pAdapter->adapterId, channelIndex);
				pSataChannel->queueCommandsEnabled = MV_FALSE;
				pSataChannel->EdmaActive = MV_FALSE;
				handleEdmaFailedCommand(pAdapter, channelIndex,
										(MV_U16)eDmaErrorCause);
			}

			if (mvAutoFlushOnError == MV_TRUE)
			{
				_doAutoFlush(pSataChannel);
			}
			mvOsSemRelease(&pSataChannel->semaphore);
		}
	}
}


#ifdef MV_SATA_C2C_COMM
/*******************************************************************************
* handleC2CInterrupt - channel 2 channel interrupt handler
*
*
* DESCRIPTION:
*   Handles channel 2 channel interrupt (register device 2 host FIS) and
*   convert ATA registers values to user specific 10 bytes message
*
* INPUT:
*   pSataChannel   - pointer to the Sata channel data structure
*
* RETURN:
*   None
*
* COMMENTS:
*   None
*
*******************************************************************************/

static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel)
{
	MV_BUS_ADDR_T   ioBaseAddr =
	pSataChannel->mvSataAdapter->adapterIoBaseAddress;
	MV_U32      eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
	MV_U8       port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
	MV_U8       sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
	MV_U8       ATAstatus;
	MV_STORAGE_DEVICE_REGISTERS     deviceRegs;

	mvOsSemTake(&pSataChannel->semaphore);

	MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
					 MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);

	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
								 MV_ATA_DEVICE_STATUS_REG_OFFSET);
	/* clear DevInterrupt*/
	MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
					   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));

	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
			 "%d %d: C2C Interrupt: status 0x%02x\n",
			 pSataChannel->mvSataAdapter->adapterId,
			 pSataChannel->channelNumber, ATAstatus);

	dumpAtaDeviceRegisters(pSataChannel->mvSataAdapter,
						   pSataChannel->channelNumber,
						   MV_TRUE,
						   &deviceRegs);
	mvOsSemRelease(&pSataChannel->semaphore);
	if (pSataChannel->C2CCallback)
	{
		MV_U8 msg[MV_C2C_MESSAGE_SIZE];
		msg[0] = deviceRegs.errorRegister;
		msg[1] = deviceRegs.lbaLowRegister & 0xFF;
		msg[2] = deviceRegs.lbaMidRegister & 0xFF;
		msg[3] = deviceRegs.lbaHighRegister & 0xFF;
		msg[4] = deviceRegs.deviceRegister;
		msg[5] = deviceRegs.lbaLowRegister >> 8;
		msg[6] = deviceRegs.lbaMidRegister >> 8;
		msg[7] = deviceRegs.lbaHighRegister >> 8;
		msg[8] = deviceRegs.sectorCountRegister & 0xFF;
		msg[9] = deviceRegs.sectorCountRegister >> 8;
		pSataChannel->C2CCallback(pSataChannel->mvSataAdapter,
								  pSataChannel,
								  MV_C2C_REGISTER_DEVICE_TO_HOST_FIS_DONE,
								  MV_C2C_MESSAGE_SIZE,
								  msg);
	}
}
#endif



static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
								  MV_U8 port)
{
	MV_SATA_CHANNEL *pSataChannel;
	MV_QUEUED_COMMAND_ENTRY *pCommandEntry;
	MV_U8   channelIndex;

	channelIndex = MV_CHANNEL_INDEX(sataUnit, port);
	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
			 "%d %d: SaDevInterrupt Received\n", pAdapter->adapterId,
			 channelIndex);

	pSataChannel = pAdapter->sataChannel[channelIndex];
	if (pSataChannel == NULL)
	{
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
				 "%d %d: SaDevInterrupt Received for disconnected channel\n",
				 pAdapter->adapterId, channelIndex);
		/* disable SaDevInterrupts from this channel */
		disableSaDevInterrutps(pAdapter,channelIndex);
		return;
	}
#ifdef MV_SATA_C2C_COMM
	/*handle channel 2 channel communication mode*/
	if (pSataChannel->C2CmodeEnabled == MV_TRUE)
	{
		handleC2CInterrupt(pSataChannel);
		return;
	}
#endif

	mvOsSemTake(&pSataChannel->semaphore);
	/* clear interrupt */

	pCommandEntry = pSataChannel->commandsQueueHead;
	if (pCommandEntry == NULL)
	{
		mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
				 "%d %d: SaDevInterrupt: No command is running!!!\n",
				 pAdapter->adapterId, channelIndex);
		_dumpSataRegs(pAdapter, channelIndex);
        /* disable SaDevInterrupts from this channel */
		disableSaDevInterrutps(pAdapter,channelIndex);
		mvOsSemRelease(&pSataChannel->semaphore);
		return;
	}
	if ((pCommandEntry->isFreeEntry == MV_TRUE) ||
		(pCommandEntry->commandInfo.type != MV_QUEUED_COMMAND_TYPE_NONE_UDMA))
	{
		if (pCommandEntry->isFreeEntry == MV_TRUE)
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
					 "%d %d: SaDevInterrupt: current command is free ???\n",
					 pAdapter->adapterId, channelIndex);
		}
		else
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR|MV_DEBUG_NON_UDMA_COMMAND,
					 "%d %d: SaDevInterrupt: current command is Not PIO ???\n",
					 pAdapter->adapterId, channelIndex);
		}
		/* disable SaDevInterrupts from this channel */
		disableSaDevInterrutps(pAdapter,channelIndex);
		mvOsSemRelease(&pSataChannel->semaphore);
		return;
	}
	handlePIOInterrupt(pSataChannel, pCommandEntry);
	mvOsSemRelease(&pSataChannel->semaphore);
}

static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel,
							   MV_QUEUED_COMMAND_ENTRY *pCommandEntry)
{
	MV_BUS_ADDR_T   ioBaseAddr = pSataChannel->mvSataAdapter->adapterIoBaseAddress;
	MV_U32      eDmaRegsOffset = pSataChannel->eDmaRegsOffset;
	MV_U8       port = pSataChannel->channelNumber & (MV_BIT0 | MV_BIT1);
	MV_U8       sataUnit = (pSataChannel->channelNumber & MV_BIT2) >> 2;
	MV_U8       ATAstatus;

	MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
					 MV_ATA_DEVICE_ALTERNATE_REG_OFFSET);

	ATAstatus = MV_REG_READ_BYTE(ioBaseAddr, eDmaRegsOffset +
								 MV_ATA_DEVICE_STATUS_REG_OFFSET);
	/* clear DevInterrupt*/
	MV_REG_WRITE_DWORD(ioBaseAddr, MV_SATAHC_REGS_BASE_OFFSET(sataUnit) +
					   MV_SATAHC_INTERRUPT_CAUSE_REG_OFFSET, ~(MV_BIT8 << port));

	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG|MV_DEBUG_NON_UDMA_COMMAND,
			 "%d %d: PIO Interrupt: cmd 0x%02X, type %d. status 0x%02x\n",
			 pSataChannel->mvSataAdapter->adapterId,
			 pSataChannel->channelNumber,
			 pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.command,
			 pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.protocolType,
			 ATAstatus);

	if (ATAstatus & MV_ATA_BUSY_STATUS)
	{
		if (pSataChannel->mvSataAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: "
					 "PIO Interrupt: drive is BUSY!!!! status 0x%02x\n",
					 pSataChannel->mvSataAdapter->adapterId,
					 pSataChannel->channelNumber, ATAstatus);
		}
		return;
	}
	if (ATAstatus & MV_ATA_ERROR_STATUS)
	{
		completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
		return;
	}
	switch (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.protocolType)
	{
	case MV_NON_UDMA_PROTOCOL_NON_DATA:
		/* command is successfully completed*/
		completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
		break;
	case MV_NON_UDMA_PROTOCOL_PIO_DATA_IN:
		if (ATAstatus & MV_ATA_READY_STATUS)
		{
			if (transferPIOData(pSataChannel,
								&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand) == MV_TRUE)
			{
				if (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.count == 0)
				{
					completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
				}
#ifdef MV_SATA_SUPPORT_READ_WRITE_LONG

				/* for Read long only*/
				if (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.count == 4)
				{
					if (transferPIOData(pSataChannel,
										&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand) == MV_TRUE)
					{
						completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
					}
					else
					{
						completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
					}
				}
#endif /*MV_SATA_SUPPORT_READ_WRITE_LONG*/

			}
			else
			{
				completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
			}
		}
		else	/* when BUSY and DRQ cleared to zero then the device has*/
		{
			/* completed the command with error                     */
			completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
			return;
		}
		break;
	case MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:
		if ((ATAstatus & MV_ATA_READY_STATUS) &&
			!(ATAstatus & MV_ATA_DEVICE_FAULT_STATUS))
		{
			if (pCommandEntry->commandInfo.commandParams.NoneUdmaCommand.count == 0)
			{
				completePIOCommand(pSataChannel, pCommandEntry, MV_FALSE);
			}
			else
			{
				if (transferPIOData(pSataChannel,
									&pCommandEntry->commandInfo.commandParams.NoneUdmaCommand) == MV_FALSE)
				{
					completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
				}
			}
		}
		else
		{
			mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, "%d %d: PIO Interrupt: PIO"
					 " Data Out command failed status 0x%02x\n",
					 pSataChannel->mvSataAdapter->adapterId,
					 pSataChannel->channelNumber, ATAstatus);
			completePIOCommand(pSataChannel, pCommandEntry, MV_TRUE);
		}

⌨️ 快捷键说明

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