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

📄 ks8695end.c

📁 这是micrel公司宽带路由ARM9芯片的VXWORKS BSP 源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		uReg &= ~INT_WAN_MASK;
		break;
	}
	KS8695_WRITE_REG(REG_INT_ENABLE, uReg);

	/* reset corresponding register and wait for completion */
	KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, DMA_SOFTRESET);
	do
	{
#ifndef	NO_TASK_DELAY
		taskDelay(1);
#else
		delayEx(100000);
#endif
		uReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
		if (!(uReg & DMA_SOFTRESET))
			break;
	} while (--nTimeOut);

	if (nTimeOut < 1) {
	    DRV_LOG(DRV_DEBUG_LOAD, "macReset: timeout error\n", 1, 2, 3, 4, 5, 6);
		return ERROR;
	}

	/* clear statistic counters */
	swResetSNMPInfo(pDrvCtrl);

	return OK;
}

/*
 * macConfigure
 *	This function is used to set MAC control register based on configurable
 *  option settings.
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	NONE
 */
void macConfigure(PEND_DEVICE pDrvCtrl)
{
	UINT uRxReg, uTxReg;

    DRV_LOG(DRV_DEBUG_LOAD, "macConfigure: timeout error\n", 1, 2, 3, 4, 5, 6);

	/* read TX mode register */
	uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);

	/* clear PBL bits first */
	uTxReg &= ~DMA_PBLTMASK;				/* 29:24 */
	if (DI.byTxPBL)
		uTxReg |= ((UINT32)DI.byTxPBL << DMA_PBLTSHIFT);

	if (DI.bTxChecksum) {
		uTxReg |= (DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
	}
	else {
		uTxReg &= ~(DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
	}

	if (DI.bTxFlowCtrl)
	{
		uTxReg |= DMA_FLOWCTRL;
	}
	else {
		uTxReg &= ~DMA_FLOWCTRL;
	}
	uTxReg |= (DMA_PADDING | DMA_CRC);
	/* write TX mode register */
	KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);

	/* read RX mode register */
	uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
	/* clear PBL bits first */
	uRxReg &= ~DMA_PBLTMASK;				/* 29:24 */
	if (DI.byRxPBL)
		uRxReg |= ((UINT32)DI.byRxPBL << DMA_PBLTSHIFT);
	/* checksum */
	if (DI.bRxChecksum) {
		uRxReg |= (DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
	}
	else {
		uRxReg &= ~(DMA_IPCHECKSUM | DMA_TCPCHECKSUM | DMA_UDPCHECKSUM);
	}
	/* flow control */
	if (DI.bRxFlowCtrl)
	{
		uRxReg |= DMA_FLOWCTRL;
	}
	else {
		uRxReg &= ~DMA_FLOWCTRL;
	}
	/* set unicast only, and let ks8695_set_multi function to set the rest */
	uRxReg |= DMA_UNICAST;

	/* write RX mode register */
	KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);
}

/*
 * macSetStationAddress
 *	This function sets MAC address to given type (WAN, LAN or HPHA)
 *
 * Argument(s)
 *  pDrvCtrl		pointer to END_DEVICE struct
 *  pMacAddress	pointer to a byte array to hold MAC address (at least 6 bytes long)
 *
 * Return(s)
 *	NONE.
 */
void macSetStationAddress(PEND_DEVICE pDrvCtrl, uint8_t *pMacAddress)
{
	UINT32 uLow, uHigh;

    DRV_LOG(DRV_DEBUG_LOAD, "macSetStationAddress\n", 1, 2, 3, 4, 5, 6);

	uLow = ((UINT32)pMacAddress[2] << 24);
	uLow += ((UINT32)pMacAddress[3] << 16);
	uLow += ((UINT32)pMacAddress[4] << 8);
	uLow += pMacAddress[5];
	uHigh = ((UINT32)pMacAddress[0] << 8) + pMacAddress[1];
	KS8695_WRITE_REG(REG_STATION_LOW + DI.nOffset, uLow);
	KS8695_WRITE_REG(REG_STATION_HIGH + DI.nOffset, uHigh);
}

/*
 * swConfigurePort
 *	This function is used to configure a give port for LAN.
 *
 * Argument(s)
 *  pDrvCtrl		pointer to END_DEVICE struct
 *  uPort		port to start
 *
 * Return(s)
 *	NONE.
 */
void swConfigurePort(PEND_DEVICE pDrvCtrl, UINT uPort)
{
	UINT	uReg, uOff;
	BOOLEAN	bPort5 = FALSE;

	if (uPort >= SW_MAX_LAN_PORTS) {
		if (SW_MAX_LAN_PORTS == uPort) {
			/* port 5 */
			bPort5 = TRUE;
		}
		else {
			/* out of range */
		    DRV_LOG(DRV_DEBUG_ERROR, "swConfigurePort: port out of range\n", 1, 2, 3, 4, 5, 6);
			return;
		}
	}

#if defined(KS8695) || defined(KS8695X)
	uOff = KS8695_SWITCH_PORT1 + uPort * 4;
#else
	if (bPort5)
		uOff = KS8695_SEP5C1;
	else
		uOff = KS8695_SEP1C1 + uPort * 0x0c;
#endif

	uReg = 0;
	uReg |= (UINT)DPI[uPort].usTag << 16;

	if (!bPort5) {
		/* connection media type */
		/*uReg &= ~(SW_PORT_DISABLE_AUTONEG | SW_PORT_100BASE | SW_PORT_FULLDUPLEX);*/
		if (SW_PHY_AUTO != DI.usCType[uPort]) {
			uReg |= SW_PORT_DISABLE_AUTONEG;
			if (SW_PHY_100BASE_TX == DI.usCType[uPort] || 
				SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
				uReg |= SW_PORT_100BASE;
			}
			if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] || 
				SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
				uReg |= SW_PORT_FULLDUPLEX;
			}
		}
	}
	else {
		/* Rx direct mode */
		if (DI.bRxDirectMode) {
			uReg |= SW_PORT_RX_DIRECT_MODE;
		}
		/* Tx Pre-tag mode */
		if (DI.bTxRreTagMode) {
			uReg |= SW_PORT_TX_PRETAG_MODE;
		}
	}

	/* cross talk bit mask */
	uReg |= ((UINT)(DPI[uPort].byCrossTalkMask & 0x1f)) << 8;

	/* spanning tree */
	if (SW_SPANNINGTREE_ALL == DPI[uPort].bySpanningTree) {
		uReg |= SW_PORT_TX_SPANNINGTREE | SW_PORT_RX_SPANNINGTREE;
	}
	else {
		if (SW_SPANNINGTREE_TX == DPI[uPort].bySpanningTree) {
			uReg |= SW_PORT_TX_SPANNINGTREE;
		}
		if (SW_SPANNINGTREE_RX == DPI[uPort].bySpanningTree) {
			uReg |= SW_PORT_RX_SPANNINGTREE;
		}
	}
	if (DPI[uPort].byDisableSpanningTreeLearn) {
		uReg |= SW_PORT_NO_SPANNINGTREE;
	}
	/* ingress broadcast storm protection */
	if (DPI[uPort].byStormProtection) {
		uReg |= SW_PORT_STORM_PROCTION;
	}
	/* ingress priority */
	if (DPI[uPort].byIngressPriority) {
		uReg |= SW_PORT_HI_PRIORITY;
	}
	if (DPI[uPort].byIngressPriorityTOS) {
		uReg |= SW_PORT_TOS_ENABLE;
	}
	if (DPI[uPort].byIngressPriority802_1P) {
		uReg |= SW_PORT_8021Q_ENABLE;
	}
	/* egress priority */
	if (DPI[uPort].byEgressPriority) {
		uReg |= SW_PORT_PRIOTIRY_ENABLE;
	}
	KS8695_WRITE_REG(uOff, uReg);
	/* need 20 cpu clock delay for switch related registers */
	SW_WRITE_DELAY();
}

#ifdef	USE_READSNMPREG
/*
 * swReadSNMPReg
 *	This function is used to read SNMP registers
 *
 * Argument(s)
 *	pDrvCtrl	pointer to END_DEVICE structure.
 *	uIndex		index of SNMP register to read
 *
 * Return(s)
 *	value read
 */
LOCAL UINT32 swReadSNMPReg(PEND_DEVICE pDrvCtrl, UINT uIndex)
{
#if defined(KS8695) || defined(KS8695X)
	UINT	uValue, uTimeout = 0;

	if (uIndex >= 512)
		uIndex = 511;

	KS8695_WRITE_REG(KS8695_MANAGE_COUNTER, uIndex);
	SW_WRITE_DELAY();
	do {
		uValue = KS8695_READ_REG(KS8695_MANAGE_DATA);
		if (uValue & SW_SNMP_DATA_VALID) {
			if (uValue & SW_SNMP_DATA_OVERFLOW) {
				KS8695_WRITE_REG(KS8695_MANAGE_DATA, SW_SNMP_DATA_OVERFLOW);
			}
			/* clear status bits */
			uValue &= 0x3fffffff;
			return uValue;
		}
		SW_WRITE_DELAY();
	} 
	while (uTimeout++ < 1000);

	if (uValue & SW_SNMP_DATA_OVERFLOW) {
		KS8695_WRITE_REG(KS8695_MANAGE_DATA, SW_SNMP_DATA_OVERFLOW);
	}
#else
	UINT32	reg, value, timeout = 0;

	reg = KS8695_SEIAC_READ | KS8695_SEIAC_TAB_MIB | (KS8695_SEIAC_INDEX_MASK & uIndex);
	do {
		KS8695_WRITE_REG(KS8695_SEIAC, reg);
		SW_WRITE_DELAY();

		value = KS8695_READ_REG(KS8695_SEIADL);
		if (value & SW_SNMP_DATA_VALID) {
			if (value & SW_SNMP_DATA_OVERFLOW) {
				reg = KS8695_SEIAC_WRITE | KS8695_SEIAC_TAB_MIB | (KS8695_SEIAC_INDEX_MASK & uIndex);
				KS8695_WRITE_REG(KS8695_SEIAC, reg);
				SW_WRITE_DELAY();
			}
			/* clear status bits */
			value &= 0x3fffffff;
			return value;
		}
	}
	while (timeout++ < 1000);

#endif
    logMsg("swReadSNMPReg: timeout error\n", 1, 2, 3, 4, 5, 6);
	return 0;
}
#endif /*USE_READSNMPREG*/


/*
 * swConfigure
 *	This function is used to config switch engine. It is assume that
 *	the BIST is performed already (by boot loader).
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	NONE
 */
void swConfigure(PEND_DEVICE pDrvCtrl)
{
	UINT uReg, i;

    DRV_LOG(DRV_DEBUG_LOAD, "swConfigure\n", 1, 2, 3, 4, 5, 6);

	if (DMA_LAN == DI.usDMAId) {
		/* read switch control 0 register */
		uReg = KS8695_READ_REG(REG_SWITCH_CTRL0);
		/* flow control for LAN ports */
		if (DI.bPort5FlowCtrl)
		{
			/* flow control for port 5 */
			uReg |= SW_CTRL0_ENABLE_PORT5;
		}
		else {
			uReg &= ~SW_CTRL0_ENABLE_PORT5;
		}
#if defined(KS8695) || defined(KS8695X)
		if (DI.bPortsFlowCtrl)
		{
			/* four flow control for each LAN port */
			uReg |= SW_CTRL0_ENABLE_PORTS;
		}
		else {
			uReg &= ~SW_CTRL0_ENABLE_PORTS;
		}
#else
#if	0
		/* RLQ, need to verify */
		for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
			forceFlowControl(pDrvCtrl, i, DI.bPortsFlowCtrl);
			//if (!DI.bPortsFlowCtrl)
			//	backPressureEnable(pDrvCtrl, i, DI.bPortsFlowCtrl);
			backPressureEnable(pDrvCtrl, i, TRUE);
		}
#endif
#endif

		/*RLQ, 11/20/2002, requested by Hock, backpressure will fix packet 
		 * drop problem in half duplex mode
		 */
		uReg |= 0x00000020;		/* bit 5 */

		/* set flow control fairness mode based on LAN flow control settings, should use */

#if !defined(KS8695) && !defined(KS8695X)
		/*RLQ, EXPE, 11/14/2003 */
		uReg |= KS8695_SEC0_PASS_ALL_FRAMES;
#else
		uReg |= KS8695_SWITCH_CTRL0_PASS_ALL_FRAMES;

#endif
		/* read switch control 0 register */
		KS8695_WRITE_REG(REG_SWITCH_CTRL0, uReg);
		/* need 20 cpu clock delay for switch related registers */
		SW_WRITE_DELAY();
		
		/* configure LAN port 1-4 and Port 5 */
		for (i = 0; i <= SW_MAX_LAN_PORTS; i++) 
			swConfigurePort(pDrvCtrl, i);
	}
	else {
	    DRV_LOG(DRV_DEBUG_ERROR, "swConfigure: not supported type\n", 1, 2, 3, 4, 5, 6);
	}
}

/*
 * macConfigureFlow
 *	This function is used to set mac flow control as a workaround for WAN port.
 *  option settings.
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *	bFlowCtrl	flow control to set
 *
 * Return(s)
 *	NONE
 */
void macConfigureFlow(PEND_DEVICE pDrvCtrl, uint8_t bFlowCtrl)
{
	UINT uRxReg, uTxReg;
	BOOLEAN bTxStarted, bRxStarted;

    DRV_LOG(DRV_DEBUG_LOAD, "macConfigureFlow\n", 1, 2, 3, 4, 5, 6);

	/* need to stop mac engines if started */
	bTxStarted = DI.bTxStarted;
	bRxStarted = DI.bRxStarted;
	if (bRxStarted)
		macStartRx(pDrvCtrl, FALSE);
	if (bTxStarted)
		macStartTx(pDrvCtrl, FALSE);

	/* read TX mode register */
	uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);
	if (bFlowCtrl)
	{
		uTxReg |= DMA_FLOWCTRL;
	}
	else {
		uTxReg &= ~DMA_FLOWCTRL;
	}
	/* write TX mode register */
	KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);

	/* read RX mode register */
	uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
	if (bFlowCtrl)
	{
		uRxReg |= DMA_FLOWCTRL;
	}
	else {
		uRxReg &= ~DMA_FLOWCTRL;
	}
	/* write RX mode register */
	KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uRxReg);

	if (bRxStarted)
		macStartRx(pDrvCtrl, TRUE);
	if (bTxStarted)
		macStartTx(pDrvCtrl, TRUE);
}

/*
 * macSetLoopback
 *	This function is used to set MAC lookback mode (for debugging purpose)
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	NONE
 */
void macSetLoopback(PEND_DEVICE pDrvCtrl, BOOLEAN bLoopback)
{
	UINT uTxReg;
	BOOLEAN bTxStarted, bRxStarted;

	bTxStarted = DI.bTxStarted;
	bRxStarted = DI.bRxStarted;

	if (bRxStarted)
		macStartRx(pDrvCtrl, FALSE);
	if (bTxStarted)
		macStartTx(pDrvCtrl, FALSE);

	/* read TX mode register */
	uTxReg = KS8695_READ_REG(REG_TXCTRL + DI.nOffset);

	if (bLoopback)
	{
		uTxReg |= DMA_LOOPBACK;
	}
	else {
		uTxReg &= ~DMA_LOOPBACK;
	}

	/* write TX mode register */
	KS8695_WRITE_REG(REG_TXCTRL + DI.nOffset, uTxReg);

	if (bRxStarted)
		macStartRx(pDrvCtrl, TRUE);
	if (bTxStarted)
		macStartTx(pDrvCtrl, TRUE);
}

/*
 *  macStartRx
 *      This routine will start/stop RX machine.
 *
 *  Inputs:
 *      pDrvCtrl	pointer to END_DEVICE data structure.
 *		bStart		TRUE if start Rx machine, FALSE if stop it
 *

⌨️ 快捷键说明

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