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

📄 core_init.c

📁 6440linuxDriver的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
					case PM_STATE_DEVICE_PLUG_OUT:			SATA_PM_HandleDeviceUnplug(pCore, pPM);			break;					default:			break;	}	return MV_TRUE;}#endif/* please move this to windows driver directory */#ifdef _OS_WINDOWS#define MV_PCI_READ_CONFIG_DWORD(x, y, z) *z = MV_PCI_READ_DWORD(x, y)/* pay attention to the seq. of the arguments */#define MV_PCI_WRITE_CONFIG_DWORD(x, y, z) MV_PCI_WRITE_DWORD(x, z, y)#endif /* _OS_WINDOWS *//*  * Global controller reset  */static MV_BOOLEANResetController(PCore_Driver_Extension pCore){	MV_LPVOID mmio = pCore->Mmio_Base;	MV_U32 tmp;	MV_BOOLEAN ret = MV_TRUE;	MV_U32 reg;		/* Reset controller */	tmp = MV_REG_READ_DWORD(mmio, HBA_CONTROL);	if ((tmp & HOST_RESET) == 0) {#ifdef _OS_BIOS		pCore->host_reseting = 1;#endif//WORKAROUND for WD1500 issue.		if( (pCore->Device_Id==DEVICE_ID_6440)&&(pCore->Revision_Id==0x0) )		{			MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, &reg);			reg &=~MV_PCI_PHY_PWR_ON;			reg |= MV_PCI_PHY_OFF;			MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, reg);			MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, &reg);			reg &=~MV_PCI_PHY_PWR_ON;			reg |= MV_PCI_PHY_OFF;			MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, reg);		}		MV_REG_WRITE_DWORD(mmio, HBA_CONTROL, tmp | HOST_RESET);		MV_REG_READ_DWORD(mmio, HBA_CONTROL); /* flush */	}	/* Reset must complete within 1 second, or the hardware should be considered fried. */	HBA_SleepMillisecond(pCore, 1000);	tmp = MV_REG_READ_DWORD(mmio, HBA_CONTROL);	if (tmp & HOST_RESET) {		MV_ASSERT(MV_FALSE);	//TBD;		ret = MV_FALSE;	}#ifdef _OS_BIOS	pCore->host_reseting = 0;#endif	return ret;}void UpdateWidePortPhyMap(PCore_Driver_Extension pCore){	MV_LPVOID mmio = pCore->Mmio_Base;	PDomain_Port pPort;	MV_U8 i,j;	MV_U32 reg;	for ( i = 0; i<pCore->Phy_Num; i++)	{		if ( 0 == (pCore->Phy[i].PhyStatus & MV_PHY_READY_MASK))			continue;		pCore->Phy[i].WidePortPhyMap |= MV_BIT(i);		pPort = pCore->Phy[i].pDomainPort;		if (pCore->Phy[i].Type&PORT_TYPE_SAS)		{                        /* update WidePortPhyMap */			for (j=i+1; j<pCore->Phy_Num; j++)			{				if (!(pCore->Phy[j].PhyStatus & 				      MV_PHY_READY_MASK))					continue;				if ((pCore->Phy[i].AttDevInfo &				     (PORT_DEV_SMP_TRGT |				      PORT_DEV_SSP_TRGT |				      PORT_DEV_STP_TRGT)) &&				    (U64_COMP_U64_VALUE(pCore->Phy[i].AttDevSASAddr, pCore->Phy[j].AttDevSASAddr)) &&				    (U64_COMP_U64_VALUE(pCore->Phy[i].DevSASAddr, pCore->Phy[j].DevSASAddr)))				{					pCore->Phy[i].WidePortPhyMap |= MV_BIT(j);					pCore->Phy[j].WidePortPhyMap = pCore->Phy[i].WidePortPhyMap;					if (pPort == NULL)						pPort=pCore->Phy[j].pDomainPort;					else						pCore->Phy[j].pDomainPort = pPort;				}			}		}                                /* if it is a new port */		if(pPort==NULL)		{			pPort = GetPortFromPool(pCore);			if (pPort==NULL)				return;			MV_PRINT("phy %d on port %p.\n", i, pPort);			pCore->Phy[i].pDomainPort=pPort;			pPort->pPhy = &pCore->Phy[i];			pPort->Type = pCore->Phy[i].Type;			pPort->Port_State = PORT_STATE_IDLE;			pPort->DiscoveryInstance = 0;			pPort->Core_Extension = pCore;			pPort->Device_Number = 0;			pPort->Expander_Number=0;/* update all wide port group */			for( j=i+1; j<pCore->Phy_Num; j++)			{				if(pCore->Phy[i].WidePortPhyMap&MV_BIT(j))					pCore->Phy[j].pDomainPort=pPort;			}		}		else			pCore->Phy[i].pDomainPort = pPort;		WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_WIDE_PORT);		reg=pCore->Phy[i].WidePortPhyMap;		pPort->MemberPhyMap = pCore->Phy[i].WidePortPhyMap;		WRITE_PORT_CONFIG_DATA(mmio,i,reg);	}}void DetectPortType(PCore_Driver_Extension pCore, MV_U8 i){	MV_LPVOID mmio = pCore->Mmio_Base;	MV_U32 reg;	/* enable auto port detection */	MV_REG_WRITE_DWORD(mmio, VSR_PORT_TYPE_REG, MODE_AUTO_DET_EN);	HBA_SleepMillisecond(pCore, 100);    /* TODO check & save device type*/	reg = MV_REG_READ_DWORD(mmio, VSR_PORT_TYPE_REG);	if (reg & MODE_SAS_SATA & (1 << i))	{		pCore->Phy[i].Type = PORT_TYPE_SAS;	}	else	{		pCore->Phy[i].Type = PORT_TYPE_SATA;	}}void SetPhyTuning( PCore_Driver_Extension pCore, MV_U8 i, PHY_TUNING phy_tuning){	MV_U32 tmp;	MV_LPVOID mmio = pCore->Mmio_Base;	// Amp (amplitude) and Pre-emphasis tuning	WRITE_PORT_VSR_ADDR(mmio,i,1);	tmp=READ_PORT_VSR_DATA(mmio,i);	// Set 0 from bit 14 till bit 8	tmp&=~(0x7F00); 	// Set the bits	tmp|= (phy_tuning.AMP << 11)|(phy_tuning.Pre_Emphasis << 8);	WRITE_PORT_VSR_DATA(mmio,i,tmp);	// Drive EN and Half Pre-emphasis enable	WRITE_PORT_VSR_ADDR(mmio,i,11);	tmp=READ_PORT_VSR_DATA(mmio,i);	// Set 0 from bit 14 till bit 8	tmp&=~(0x23F); 	// Set the bits	tmp|= (phy_tuning.Pre_Half_En << 9)|(phy_tuning.Drive_En);	WRITE_PORT_VSR_DATA(mmio,i,tmp);}void UpdatePhyInfo(PCore_Driver_Extension pCore, MV_U8 i){	MV_LPVOID mmio = pCore->Mmio_Base;	MV_U32 tmp;	MV_ZeroMemory(&pCore->Phy[i], sizeof(Domain_Phy));	DetectPortType(pCore,i);	WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_DEV_INFO);	pCore->Phy[i].DevInfo = 		READ_PORT_CONFIG_DATA(mmio,i);	WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_DEV_ADDR_LO);	pCore->Phy[i].DevSASAddr.parts.low = 		READ_PORT_CONFIG_DATA(mmio,i);	WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_DEV_ADDR_HI);	pCore->Phy[i].DevSASAddr.parts.high = 		READ_PORT_CONFIG_DATA(mmio,i);	pCore->Phy[i].PhyStatus = 		READ_PORT_PHY_CONTROL(mmio,i);	if (pCore->Phy[i].PhyStatus & MV_PHY_READY_MASK)	{		if (pCore->Phy[i].Type&PORT_TYPE_SAS)		{			WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_ATT_DEV_INFO);			pCore->Phy[i].AttDevInfo = READ_PORT_CONFIG_DATA(mmio,i);						WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_ATT_DEV_ADDR_LO);			pCore->Phy[i].AttDevSASAddr.parts.low = READ_PORT_CONFIG_DATA(mmio,i);						WRITE_PORT_CONFIG_ADDR(mmio,i,CONFIG_ATT_DEV_ADDR_HI);			pCore->Phy[i].AttDevSASAddr.parts.high = READ_PORT_CONFIG_DATA(mmio,i);;		}/* workaround for HW phy decoding error on 1.5g disk drive */		WRITE_PORT_VSR_ADDR(mmio,i,0x06);		tmp=READ_PORT_VSR_DATA(mmio,i);		if( ((pCore->Phy[i].PhyStatus&MV_NEG_SPP_PHYS_LINK_RATE_MASK)>>MV_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) == PHY_LINKRATE_1_5)			tmp&=~0x20000000;		else			tmp|=0x20000000;		WRITE_PORT_VSR_DATA(mmio,i,tmp);	}	pCore->Phy[i].IRQStatus = READ_PORT_IRQ_STAT(mmio,i);}/* * It's equivalent to ahci_host_init and ahci_port_start */static MV_VOID InitChip(PCore_Driver_Extension pCore){	MV_LPVOID mmio = pCore->Mmio_Base;	MV_U8 i;	MV_U32 tmp;	AdapterInfo AI;/*	HBA_Info_Page HBA_Info_Param; */	MV_U8 SasAddr[8]={0x50,0x05,0x04,0x30,0x11,0xab,0x00,0x00};	tmp = MV_REG_READ_DWORD(mmio, COMMON_CONFIG);	tmp |= MV_SAS_SATA_RST;	MV_REG_WRITE_DWORD(mmio, COMMON_CONFIG, tmp);	MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_CMD, &tmp);	tmp |= MV_PCI_DEV_EN;	MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_CMD, tmp);#if USE_MSI	mv_enable_msi(pCore);#endif /* USE_MSI *//* commented out for 25 MHz */#if 0	tmp = 0x100f3631; /* PLL for performance */	MV_PCI_WRITE_CONFIG_DWORD(pCore, 0x8c, tmp);#endif /* 0 */	/* write to device control _AND_ device status register? - A.C. */	MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_DEV_CTRL, &tmp);	tmp &= ~MV_PCI_RD_REQ_MASK;	tmp |= MV_PCI_RD_REQ_SIZE;	MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_DEV_CTRL, tmp);	MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, &tmp);	tmp &= ~MV_PCI_PHY_OFF;	tmp |= MV_PCI_PHY_PWR_ON;	MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL, tmp);	MV_PCI_READ_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, &tmp);	tmp &= ~MV_PCI_PHY_OFF;	tmp |= MV_PCI_PHY_PWR_ON;	MV_PCI_WRITE_CONFIG_DWORD(pCore, MV_PCI_REG_PHY_CTRL2, tmp);	/* reset control */	MV_REG_WRITE_DWORD(pCore->Mmio_Base, COMMON_CONTROL, 0);        /* workaround for SATA R-ERR, to ignore phy glitch */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x118);	tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA);	tmp &=~0x200;	tmp |= 0x400;	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp);	/* enable retry 127 times */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x128);	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0x7f7f);	/* extend open frame timeout to max */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x124);	tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA);	tmp &=~0xffff;	tmp |=0x3fff;	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp);	/* workaround for WDTIMEOUT , set to 550 ms */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x13c);//	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0x7ffff);	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0xffffff); /* up with PLL */	/* not to halt for different port op during wideport link change */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x1a4);	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, 0xffefbf7d);	/* workaround for Seagate disk not-found OOB sequence, recv COMINIT before sending out COMWAKE */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, 0x1b8);	tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA);	tmp &=0x0000ffff;	tmp |=0x00fa0000;	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp);	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_ADDR, CMD_PHY_TIMER);	tmp = MV_REG_READ_DWORD(mmio, COMMON_CMD_DATA);	tmp &=0x1fffffff;	tmp |=(MV_U32)2L<<29;	/* 8ms retry */	MV_REG_WRITE_DWORD(mmio, COMMON_CMD_DATA, tmp);	AI.bar[2] = pCore->Base_Address[2];#ifdef DBG_PROGRAM_SAS_ADDRESS	Odin_NVRamWrite( &AI, 		NVRAM_OFF( SasAddr ), 		SasAddr, 		NVRAM_SIZE( SasAddr ) );				    #endif /* DBG_PROGRAM_SAS_ADDRESS */#if defined( SAS_ADDR_IN_NVRAM )	if (Odin_NVRamRead(&AI,			   NVRAM_OFF(SasAddr),			   SasAddr,			   NVRAM_SIZE(SasAddr)) || (U64_COMPARE_U32((*(MV_U64 *) SasAddr), 0) == 0))	{		U64_ASSIGN((*(MV_U64 *) SasAddr), 0x0000ab1130040550ULL);	}#elif defined(SUPPORT_CSMI)	do	{		HBA_Info_Page HBA_Info_Param;		int i;		if( -1 == OdinSPI_Init(&AI))			break;		if (!mvui_init_param(pCore, &HBA_Info_Param))			break;				for (i = 0; i < 8; i++) {			SasAddr[i] = HBA_Info_Param.SAS_Address[0].b[i];		}  		/* Set phy tuning registers if HBA_Info_Param is valid */ 		for (i = 0; i < pCore->Phy_Num; i++) { 			if ((HBA_Info_Param.PHY_Tuning[i].Reserved[0] == 0) &			    (HBA_Info_Param.PHY_Tuning[i].Reserved[1] == 0)) { 				SetPhyTuning(pCore,					     (MV_U8)i,					     HBA_Info_Param.PHY_Tuning[i]); 			} 		}	} while (0);#endif	if(	(U64_COMPARE_U32((*(MV_U64 *) SasAddr), 0) == 0) || (U64_COMP_U64(0xffffffffffffffffULL, (*(MV_U64 *) SasAddr))) )	{		U64_ASSIGN((*(MV_U64 *) SasAddr), 0x0000ab1130040550ULL);	}	for ( i = 0; i<pCore->Phy_Num; i++)	{		DetectPortType(pCore,i);/* Set SAS Addr */		mv_set_SASAddr(pCore, i, SasAddr);/*enable Phy Port XMT*/		tmp = READ_PORT_PHY_CONTROL(mmio, i);		tmp |= MV_PHY_RESET;		WRITE_PORT_PHY_CONTROL(mmio, i, tmp);		HBA_SleepMillisecond(pCore, 100);/*reset irq */		tmp=READ_PORT_IRQ_STAT(mmio,i);		tmp&=~SIG_FIS_RCVD_MASK;		WRITE_PORT_IRQ_STAT(mmio,i,tmp);/*enable phy change interrupt and broadcast change*/		#ifdef SUPPORT_PM		tmp = PHY_RDY_CHNG_MASK | BRDCST_CHNG_RCVD_MASK | UNASSOC_FIS_RCVD_MASK;#else		tmp = PHY_RDY_CHNG_MASK | BRDCST_CHNG_RCVD_MASK;#endif		WRITE_PORT_IRQ_MASK(mmio,i,tmp);		UpdatePhyInfo(pCore, i);	}		/* this function needs a complete rewrite for God's sake - A.C. */	UpdateWidePortPhyMap(pCore);        /* reset CMD queue */	tmp = MV_REG_READ_DWORD(mmio, COMMON_CONTROL);	tmp |= RESET_CMD_ISSUE;	MV_REG_WRITE_DWORD(mmio, COMMON_CONTROL, tmp);#ifndef SOFTWARE_XOR        /* reset XOR CMD queue */	tmp = XOR_RESET;	MV_REG_WRITE_DWORD(mmio, XOR_CONTROL, tmp);#endif        /* little endian for open address and command table, etc. */	/* A.C.	 * it seems that ( from the spec ) turning on big-endian won't 	 * do us any good on big-endian machines, need further confirmation	 */	tmp = MV_REG_READ_DWORD(mmio, COMMON_CONFIG);	MV_DPRINT(("COMMON_CONFIG (default) = 0x%x\n", tmp));	tmp |= MV_CMD_TBL_BE;	tmp |= MV_DATA_BE;	tmp &= ~MV_OPEN_ADDR_BE;	tmp |= MV_RSPNS_FRAME_BE;	MV_REG_WRITE_DWORD(mmio, COMMON_CONFIG, tmp);	tmp = MV_REG_READ_DWORD(mmio, COMMON_CONFIG);	MV_DPRINT(("COMMON_CONFIG (written) = 0x%x\n", tmp));/* assign command list address */	MV_REG_WRITE_DWORD(mmio, COMMON_LST_ADDR, pCore->Cmd_List_DMA.parts.low);	MV_REG_WRITE_DWORD(mmio, COMMON_LST_ADDR_HI, pCore->Cmd_List_DMA.parts.high);/* assign FIS address */	MV_REG_WRITE_DWORD(mmio, COMMON_FIS_ADDR, pCore->RX_FIS_DMA.parts.low);	MV_REG_WRITE_DWORD(mmio, COMMON_FIS_ADDR_HI, pCore->RX_FIS_DMA.parts.high);/* assign delivery queue address */	tmp = 0;	MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_CONFIG, tmp);	tmp = DELV_QUEUE_SIZE_MASK & pCore->Slot_Count_Supported;	tmp |= DELV_QUEUE_ENABLE;	MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_CONFIG, tmp);	MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_ADDR, pCore->DELV_Q_DMA.parts.low);	MV_REG_WRITE_DWORD(mmio, COMMON_DELV_Q_ADDR_HI, pCore->DELV_Q_DMA.parts.high);		// write in a default value for completion queue pointer in memory	tmp = 0xFFF;	MV_CopyMemory( pCore->CMPL_Q, &tmp, 4 );        /* assign completion queue address */	tmp = 0;	MV_REG_WRITE_DWORD(mmio, COMMON_CMPL_Q_CONFIG, tmp);	tmp =  CMPL_QUEUE_SIZ

⌨️ 快捷键说明

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