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

📄 mvsata.c

📁 此为marvell6081芯片的驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*******************************************************************************
*
*                   Copyright 2003,MARVELL SEMICONDUCTOR ISRAEL, LTD.
* THIS CODE CONTAINS CONFIDENTIAL INFORMATION OF MARVELL.
* NO RIGHTS ARE GRANTED HEREIN UNDER ANY PATENT, MASK WORK RIGHT OR COPYRIGHT
* OF MARVELL OR ANY THIRD PARTY. MARVELL RESERVES THE RIGHT AT ITS SOLE
* DISCRETION TO REQUEST THAT THIS CODE BE IMMEDIATELY RETURNED TO MARVELL.
* THIS CODE IS PROVIDED "AS IS". MARVELL MAKES NO WARRANTIES, EXPRESSED,
* IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, COMPLETENESS OR PERFORMANCE.
*
* MARVELL COMPRISES MARVELL TECHNOLOGY GROUP LTD. (MTGL) AND ITS SUBSIDIARIES,
* MARVELL INTERNATIONAL LTD. (MIL), MARVELL TECHNOLOGY, INC. (MTI), MARVELL
* SEMICONDUCTOR, INC. (MSI), MARVELL ASIA PTE LTD. (MAPL), MARVELL JAPAN K.K.
* (MJKK), MARVELL SEMICONDUCTOR ISRAEL. (MSIL),  MARVELL TAIWAN, LTD. AND
* SYSKONNECT GMBH.
********************************************************************************
* mvSata - C File for implementation of the core driver for MV88SX50XX.
*
* DESCRIPTION:
*       None.
*
* DEPENDENCIES:
*   mvOs.h
*   mvSata.h.
*   mvStorageDev.h
*   mvRegs.h
*
* FILE REVISION NUMBER:
*       $Revision: 1.21 $
*******************************************************************************/
#include "mvOs.h"
#include "mvSata.h"
#include "mvStorageDev.h"
#include "mvRegs.h"

/* Defines */
#define MV_SATA_PORT_PER_UNIT                   4

#define MV_PHY_DET_STATE_NO_DEVICE              0
#define MV_PHY_DET_STATE_DEVICE_NO_PHY_COM      1
#define MV_PHY_DET_STATE_DEVICE_AND_PHY_COM     3
#define MV_PHY_DET_STATE_PHY_OFFLINE            4
#define MV_PHY_DET_CONTROL_START_NEGOTIATION    1
#define MV_PHY_DET_CONTROL_SHUTDOWN             4
#define MV_NEAR_END_LOOPBACK_TEST_WAIT_TIME     100 /* 100 uSec */
#define MV_FAR_END_LOOPBACK_TEST_WAIT_TIME      5   /* 5 uSec */
#define MV_PHY_COM_SETUP_WAIT                   5000 /* 5 mili seconds */
#define MV_HARD_RESET_WAIT_ASSERT               25    /* 25 uSec */
#define MV_HARD_RESET_WAIT_NEGATE               2000  /* 2  mSec*/
#define MV_HARD_RESET_WAIT_READY                2000 /* ms to wait after HR*/
/* before disk access */
#define MV_HARD_RESET_WAIT_FOR_BUSY_LOOPS       10000
#define MV_HARD_RESET_WAIT_FOR_BUSY_LOOP_DELAY  1000

/* for the command result */
#define MV_EDMA_REQUEST_COMMANDS_NUM            11

/* Fix the watermark to the following default value */
#define MV_WATER_MARK_FIX                       29 /* write 5'b11101 to bits 12:8*/

extern MV_BOOLEAN waitWhileStorageDevIsBusy(MV_SATA_ADAPTER *pAdapter,
											MV_BUS_ADDR_T ioBaseAddr,
											MV_U32 eDmaRegsOffset, MV_U32 loops,
											MV_U32 delay);

extern void dumpAtaDeviceRegisters(MV_SATA_ADAPTER *pAdapter,
								   MV_U8 channelIndex, MV_BOOLEAN isEXT,
								   MV_STORAGE_DEVICE_REGISTERS *pRegisters);

extern MV_BOOLEAN _doSoftReset(MV_SATA_CHANNEL *pSataChannel);

MV_BOOLEAN isStorageDevReadyForPIO(MV_SATA_CHANNEL *pSataChannel);

MV_BOOLEAN executeNonUDMACommand(MV_SATA_ADAPTER *pAdapter,
								 MV_U8 channelIndex,
								 MV_NON_UDMA_PROTOCOL protocolType,
								 MV_BOOLEAN  isEXT,
								 MV_U16_PTR bufPtr, MV_U32 count,
								 MV_U16 features,
								 MV_U16 sectorCount,
								 MV_U16 lbaLow, MV_U16 lbaMid,
								 MV_U16 lbaHigh, MV_U8 device,
								 MV_U8 command);

extern MV_BOOLEAN waitForDRQ(MV_SATA_ADAPTER* pAdapter,
							 MV_BUS_ADDR_T ioBaseAddr,
							 MV_U32 eDmaRegsOffset, MV_U32 loops,
							 MV_U32 delay);

static MV_BOOLEAN _checkSStatusAfterHReset(MV_SATA_ADAPTER* pAdapter,
										   MV_U8 channelIndex);
#ifdef MV_LOGGER
void _dumpPCIRegs(MV_SATA_ADAPTER *pAdapter);

void _dumpEDMARegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

void _dumpChannelQueues(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

void _dumpSataRegs(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);
#else

#define _dumpPCIRegs(p)
#define _dumpEDMARegs(p,i)
#define _dumpChannelQueues(p,i)
#define _dumpSataRegs(p,i)

#endif

/* write ATA command register entry in a request entry */
#define WRITE_ATA_COMMAND_REG(addr, data, reg, isLast)              \
do{                                                                 \
    *(addr) = MV_CPU_TO_LE16((((MV_U8)(data)) & 0xff) | ((reg) << 8) | (isLast));   \
} while(0)

#define MV_CHANNEL_INDEX(unit, port)    (((unit) << 2) | (port))


/* Typedefs */

typedef struct mvDmaRequestQueueEntry
{
	/* Fields set by CORE driver */
	volatile MV_U32       prdLowAddr;
	volatile MV_U32       prdHighAddr;
	volatile MV_U16       controlFlags;
	volatile MV_U16       command[MV_EDMA_REQUEST_COMMANDS_NUM];

} MV_DMA_REQUEST_QUEUE_ENTRY;

typedef struct mvDmaResponseQueueEntry
{
	/* Fields set by  hardware */
	volatile MV_U16 commandTag;
	volatile MV_U16 responseFlags;
	volatile MV_U32 timeStamp;
} MV_DMA_RESPONSE_QUEUE_ENTRY;


/* local functions  */

/*static*/ MV_BOOLEAN waitForBusyAfterHReset(MV_SATA_ADAPTER *pAdapter,
											 MV_U8 channelIndex);

static void unmaskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void maskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void writeEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry,
								  MV_SATA_CHANNEL *mvSataChannel,
								  MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
								  MV_UDMA_COMMAND_PARAMS  *pUdmaParams);

static void handleEdmaFailedCommand(MV_SATA_ADAPTER *pAdapter,
									MV_U8 channelIndex, MV_U16 eDmaErrorCause);

static void handleEdmaResponse(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
							   MV_DMA_RESPONSE_QUEUE_ENTRY *eDmaResponse);

#ifdef MV_SATA_C2C_COMM
static void handleBmDMAInterrupt(MV_SATA_ADAPTER *pAdapter,
								 MV_BUS_ADDR_T   ioBaseAddr,
								 MV_SATA_CHANNEL *pSataChannel,
								 MV_U8   channelIndex,
								 MV_U32 edmaError);
#endif

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);

static void handleDeviceInterrupt(MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit,
								  MV_U8 port);
#ifdef MV_SATA_C2C_COMM
static void handleC2CInterrupt(MV_SATA_CHANNEL *pSataChannel);
#endif

static void handlePIOInterrupt(MV_SATA_CHANNEL *pSataChannel,
							   MV_QUEUED_COMMAND_ENTRY *pCommandEntry);

static MV_BOOLEAN transferPIOData(MV_SATA_CHANNEL *pSataChannel,
								  MV_NONE_UDMA_COMMAND_PARAMS   *pNoneUdmaCommandParams);

static void completePIOCommand(MV_SATA_CHANNEL *pSataChannel,
							   MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
							   MV_BOOLEAN failed);

static MV_BOOLEAN resetEdmaChannel(MV_SATA_CHANNEL *pSataChannel);

static void flushDmaQueue(MV_SATA_CHANNEL *pSataChannel,
						  MV_FLUSH_TYPE flushType, MV_COMPLETION_TYPE, MV_U16);

static void _fixPhyParams(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelIndex);

static void _channelHardReset(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void _establishSataComm(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void _establishSataCommAll(MV_SATA_ADAPTER *pAdapter);

void _setActivePMPort(MV_SATA_CHANNEL *pSataChannel, MV_U8 PMPort);

static void revertSataHCRegs (MV_SATA_ADAPTER *pAdapter);

static void revertFlashInterfaceRegs (MV_SATA_ADAPTER *pAdapter);

static void revertPCIInterfaceRegs (MV_SATA_ADAPTER *pAdapter);

static void commandsQueueAddTail(MV_SATA_CHANNEL *pSataChannel,
								 MV_QUEUED_COMMAND_ENTRY *pCommandEntry);

static void commandsQueueRemove(MV_SATA_CHANNEL *pSataChannel,
								MV_QUEUED_COMMAND_ENTRY *pCommandEntry);

static void addCommand(MV_SATA_CHANNEL *pSataChannel,
					   MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
					   MV_QUEUE_COMMAND_INFO *pCommandInfo);

static void removeCommand(MV_SATA_CHANNEL *pSataChannel,
						  MV_QUEUED_COMMAND_ENTRY *pCommandEntry);

static void enableSaDevInterrutps(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

void disableSaDevInterrutps(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void activateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void deactivateEdma(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex);

static void EdmaReqQueueInsert(MV_SATA_CHANNEL *pSataChannel,
							   MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
							   MV_UDMA_COMMAND_PARAMS  *pUdmaParams);

static MV_BOOLEAN sendNoneUdmaCommand(MV_SATA_CHANNEL *pSataChannel,
									  MV_QUEUED_COMMAND_ENTRY *pCommandEntry);

static MV_VOID _doAutoFlush(MV_SATA_CHANNEL *pSataChannel);

#ifdef MV_SATA_C2C_COMM

/* Channel 2 Channel */
static MV_BOOLEAN sendVendorUniqueFIS(MV_SATA_ADAPTER *pAdapter,
									  MV_U8 channelIndex,
									  MV_U32 *vendorUniqueBuffer,
									  MV_U8 numOfDWords);

static void activateBMDmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
							  MV_U32 prdTableHi, MV_U32 prdTableLow,
							  MV_UDMA_TYPE dmaType);
#endif

#ifdef MV_SATA_IO_GRANULARITY

static void setIoGranularityCount(MV_SATA_ADAPTER *pAdapter,
								  MV_U8 transId,
								  MV_U8 counter);
static MV_U8 readIoGranularityCount(MV_SATA_ADAPTER *pAdapter,
									MV_U8 transId);
static void iogInterrupt(MV_SATA_ADAPTER *pAdapter,
						 MV_BUS_ADDR_T ioBaseAddr,
						 MV_U32 mainCause);
static void checkIogCompletion(MV_SATA_ADAPTER *pAdapter,
							   MV_U32 iogCause, MV_U8 offset);
static void checkIogBit(MV_SATA_ADAPTER *pAdapter,
						MV_U8 bitOffset,
						MV_U8 value);

static MV_BOOLEAN iogReset(MV_SATA_ADAPTER *pAdapter);
#endif


/* Calculate the base address of the registers for a SATA channel */
MV_U32 edmaRegOffst[MV_SATA_CHANNELS_NUM] = {0x22000, 0x24000, 0x26000, 0x28000,
	0x32000, 0x34000, 0x36000, 0x38000};

#define getEdmaRegOffset(x) edmaRegOffst[(x)]




MV_BOOLEAN waitForBusyAfterHReset(MV_SATA_ADAPTER *pAdapter,
								  MV_U8 channelIndex)
{
	MV_U32 i;
	MV_U8       ATAstatus;
	mvMicroSecondsDelay(pAdapter, MV_HARD_RESET_WAIT_READY);
	for (i = MV_HARD_RESET_WAIT_READY; i < 5000000; i+= 10000)
	{
		ATAstatus = MV_REG_READ_BYTE(pAdapter->adapterIoBaseAddress,
									 getEdmaRegOffset(channelIndex) +
									 MV_ATA_DEVICE_STATUS_REG_OFFSET);
		if ((ATAstatus & MV_ATA_BUSY_STATUS) == 0)
		{
			return MV_TRUE;
		}
		mvMicroSecondsDelay(pAdapter, 10000);
	}
	mvLogMsg(MV_CORE_DRIVER_LOG_ID, MV_DEBUG_ERROR, " %d %d: in Channel Hard Rese"
			 "t wait for busy, ATA STATUS=0x%02x\n", pAdapter->adapterId,
			 channelIndex, ATAstatus);
	return MV_FALSE;
}

static void unmaskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
{
	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
					   getEdmaRegOffset(channelIndex) +
					   MV_EDMA_INTERRUPT_ERROR_CAUSE_REG_OFFSET,
					   0);
	if (pAdapter->sataAdapterGeneration == MV_SATA_GEN_I)
	{
		/* Unmask EDMA self disable (bit 8), device connect and disconnect */
		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
						   getEdmaRegOffset(channelIndex) +
						   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
						   MV_BIT8 | MV_BIT4 | MV_BIT3);
	}
	else
	{
		/* Unmask EDMA self disable (bit 7), device connect and disconnect */
		MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
						   getEdmaRegOffset(channelIndex) +
						   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
						   MV_BIT8 | MV_BIT7 | MV_BIT4 | MV_BIT3);
	}
}

static void maskEdmaInterrupts(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex)
{
	MV_REG_WRITE_DWORD(pAdapter->adapterIoBaseAddress,
					   getEdmaRegOffset(channelIndex) +
					   MV_EDMA_INTERRUPT_ERROR_MASK_REG_OFFSET,
					   0);
}


/* Global Variables */
MV_BOOLEAN mvAutoFlushOnError = MV_FALSE;


/*******************************************************************************
* writeEdmaRequestEntry  - Write a CRQB (COMMAND REQUEST QUEUE BLOCK)
*
* DESCRIPTION:
*       write one CRQB for an EDMA request queue.
*
* INPUT:
*       pReqEntry     - pointer to the CRQB area on the system memory
*                       (HW reqeust Queue).
*       mvSataChannel - pointer to the channel data structure
*       pCommandEntry - pointer to the command entry data structure
*                       (SW request Queue).
*
* RETURN:
*       None
*
* COMMENTS:
*       None.
*
*******************************************************************************/
static void writeEdmaRequestEntry(MV_DMA_REQUEST_QUEUE_ENTRY *pReqEntry,
								  MV_SATA_CHANNEL *mvSataChannel,
								  MV_QUEUED_COMMAND_ENTRY *pCommandEntry,
								  MV_UDMA_COMMAND_PARAMS  *pUdmaParams)
{
	MV_U16           ControlFlags = 0;
	volatile MV_U16  *pCommand = &pReqEntry->command[0];
	MV_U8            ATACommand = 0;

	pReqEntry->prdLowAddr  = MV_CPU_TO_LE32(pUdmaParams->prdLowAddr);
	pReqEntry->prdHighAddr = MV_CPU_TO_LE32(pUdmaParams->prdHighAddr);

	/* Set the direction of the transaction (read/write) */
	if (pUdmaParams->readWrite == MV_UDMA_TYPE_READ)
	{
		ControlFlags |= 0x1; /* Device to system memory */
	}
	ControlFlags |= (pCommandEntry->commandTag << 1);	/* the tag will be used also */

⌨️ 快捷键说明

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