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

📄 ks8695end.c

📁 这是micrel公司宽带路由ARM9芯片的VXWORKS BSP 源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}

/*
 * SetDefaults
 *	This function is used to set initial defaults before Parse routine.
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	NONE.
 */
LOCAL void SetDefaults(PEND_DEVICE pDrvCtrl)
{
    DRV_LOG(DRV_DEBUG_LOAD, "SetDefaults\n", 1, 2, 3, 4, 5, 6);

	/* Transmit Descriptor Count */
	DI.nTxDescTotal = TXDESC_DEFAULT;		/* 128 | 32 | 32(d) */

	/* Receive Descriptor Count */
	DI.nRxDescTotal = RXDESC_DEFAULT;		/* 128 | 32 | 32(d) */

	/* Transmit Checksum Offload Enable configuration */
	DI.bTxChecksum = TXCHECKSUM_DEFAULT;	/* enabled */

	/* Receive Checksum Offload Enable */
	DI.bRxChecksum = RXCHECKSUM_DEFAULT;	/* enabled */

	/* Flow Control */
	DI.bRxFlowCtrl = FLOWCONTROL_DEFAULT;	/* enabled */

	/* currently Tx control flow shares the setting of Rx control flow */
	DI.bTxFlowCtrl = DI.bRxFlowCtrl;

	/* Programmable Burst Length */
	DI.byTxPBL = PBL_DEFAULT;				/* Tx PBL size */
	DI.byRxPBL = PBL_DEFAULT;				/* Rx PBL size */

	/* Perform PHY PowerDown Reset instead of soft reset, the Option function can 
	   be overwritten by user later */
	DI.bPowerDownReset = TRUE;

#ifdef PACKET_DUMP
	/* for debug only */
	DI.uDebugDumpTxPkt = 0xff;
	DI.uDebugDumpRxPkt = 0xff;

#endif

	pDrvCtrl->nWatchdogDelay = sysClkRateGet() * 5;		/* every 5 secs */
	pDrvCtrl->offset = 2;	/* 2 bytes to make IP header dword aligned */
}

/*
 * CheckConfigurations
 *	This function checks all command line paramters for valid user
 *  input. If an invalid value is given, or if no user specified
 *  value exists, a default value is used.
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	NONE.
 */
LOCAL void CheckConfigurations(PEND_DEVICE pDrvCtrl)
{
	int i;

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

	/* Tx coalescing, currently can only be used if buffer unavailable bit is set */
	DI.nTransmitCoalescing = (DI.nTxDescTotal >> 3);

	/* User speed and/or duplex options */
	DI.usCType[0] = SW_PHY_DEFAULT;

	if (DMA_LAN == DI.usDMAId) {
		/*TEMP, currently assume all other ports share same configuration with
		  first one, will add more options for LAN ports later */
		for (i = 1; i < SW_MAX_LAN_PORTS; i++) {
			DI.usCType[i] = DI.usCType[0];
		}

		/* initialize some variables which do not have user configurable options */
		for (i = 0; i <= SW_MAX_LAN_PORTS; i++) {
			DPI[i].byCrossTalkMask = 0x1f;
			DPI[i].bySpanningTree = SW_SPANNINGTREE_ALL;
			DPI[i].byDisableSpanningTreeLearn = FALSE;
		}

		/* set default as direct mode for port 5, so no lookup table is checking */
		DI.bRxDirectMode = FALSE;
		DI.bTxRreTagMode = FALSE;

		DI.bPort5FlowCtrl = DI.bRxFlowCtrl;
		DI.bPortsFlowCtrl = DI.bRxFlowCtrl;
	}
}

/*
 * gpioConfigure
 *	This function is use to configure GPIO pins required for extra LEDs
 *	as speed indicators.
 *
 * Argument(s)
 *  pDrvCtrl		pionter to END_DEVICE data structure.
 *
 * Return(s)
 *	NONE
 */
void gpioConfigure(PEND_DEVICE pDrvCtrl)
{
	UINT32	uReg;

	uReg = KS8695_READ_REG(REG_GPIO_MODE);
	switch (DI.usDMAId) {
#ifdef	KS8695
	case DMA_HPNA:
		return;
#endif

	case DMA_LAN:
		uReg |= 0xf0;	/* GPIO 4-7 for port 1 - 4, configure them as output */
		break;

	default:
	case DMA_WAN:
		uReg |= 0x08;	/* GPIO 3 for WAN port */
		break;
	}
	KS8695_WRITE_REG(REG_GPIO_MODE, uReg);
}

/*
 * gpioSet
 *	This function is use to set/reset given GPIO pin corresponding to the port.
 *
 * Argument(s)
 *  pDrvCtrl	pionter to END_DEVICE data structure.
 *  uPort		port for the tag to insert
 *  bSet		enable/disable LED
 *
 * Return(s)
 *  NONE
 */
void gpioSet(PEND_DEVICE pDrvCtrl, UINT uPort, UINT bSet)
{
	UINT32	uReg;

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

	uReg = KS8695_READ_REG(REG_GPIO_DATA);
	switch (DI.usDMAId) {
#ifdef	KS8695
	case DMA_HPNA:
		return;
#endif

	case DMA_LAN:
		if (bSet)
			uReg &= ~(1 << (uPort + 4));	/* low for LED on */
		else
			uReg |= (1 << (uPort + 4));	/* high for LED off */
		break;

	default:
	case DMA_WAN:
		if (bSet)
			uReg &= ~0x08;	/* low for LED on */
		else
			uReg |= 0x08;	/* high for LED off */
		break;
	}
	KS8695_WRITE_REG(REG_GPIO_DATA, uReg);
}

/*
 * swGetPhyStatus
 *	This function is used to get the status of auto negotiation.
 *
 * Argument(s)
 *	pDrvCtrl	pointer to END_DEVICE structure.
 *  uPort		port to query
 *
 * Return(s)
 *	TRUE	if connected
 *	FALSE	otherwise
 */
int swGetPhyStatus(PEND_DEVICE pDrvCtrl, UINT uPort)
{
	UINT	uReg, uOff, uShift = 0;

    DRV_LOG(DRV_DEBUG_LOG_PHY, "swGetPhyStatus\n", 1, 2, 3, 4, 5, 6);

	switch (DI.usDMAId) {
#ifdef	KS8695
	case DMA_HPNA:
		/* temp */
		uReg = KS8695_READ_REG(KS8695_HPNA_CONTROL);
		DI.usLinkSpeed[uPort] = (uReg & 0x00000002) ? SPEED_100 : SPEED_10;
		DI.bHalfDuplex[uPort] = (uReg & 0x00000001) ? FULL_DUPLEX : HALF_DUPLEX;
		/* note that there is no register bit corresponding to HPNA's link status
		   therefore don't report it */
		DI.bLinkActive[uPort] = TRUE;
		return TRUE;
#endif

	case DMA_WAN:
		uOff = REG_WAN_CONTROL;
		uShift = 16;
		break;

	default:
	case DMA_LAN:
		switch (uPort) {
		case SW_PORT_4:
			uOff = REG_SWITCH_AUTO1;
			break;
			break;

		case SW_PORT_3:
			uOff = REG_SWITCH_AUTO1;
			break;
			uShift = 16;
			break;

		case SW_PORT_2:
			uOff = REG_SWITCH_AUTO0;
			break;

		case SW_PORT_1:
		default:
			uOff = REG_SWITCH_AUTO0;
			uShift = 16;
			break;
		}
	}

	uReg = KS8695_READ_REG(uOff);
	/* if not linked yet */
	if (!(uReg & ((UINT)SW_AUTONEGO_STAT_LINK << uShift))) {
		DI.bLinkActive[uPort] = FALSE;
		DI.usLinkSpeed[uPort] = SPEED_UNKNOWN;
		DI.bHalfDuplex[uPort] = 0;
		gpioSet(pDrvCtrl, uPort, FALSE);
		return FALSE;
	}
	DI.bLinkActive[uPort] = TRUE;
	if (SW_PHY_AUTO == DI.usCType[uPort]) {
		/* if auto nego complete */
		if ((UINT)SW_AUTONEGO_COMPLETE << uShift) {
			/* clear auto nego restart bit */
			uReg &= ~((UINT)SW_AUTONEGO_RESTART << uShift);
			KS8695_WRITE_REG(uOff, uReg);
			SW_WRITE_DELAY();

			DI.usLinkSpeed[uPort] = (uReg & ((UINT)SW_AUTONEGO_STAT_SPEED << uShift)) ? SPEED_100 : SPEED_10;
			DI.bHalfDuplex[uPort] = (uReg & ((UINT)SW_AUTONEGO_STAT_DUPLEX << uShift)) ? FULL_DUPLEX : HALF_DUPLEX;
			DI.bAutoNegoInProgress[uPort] = FALSE;
			
			gpioSet(pDrvCtrl, uPort, SPEED_100 == DI.usLinkSpeed[uPort]);
			/*RLQ, need to verify real duplex mode instead report it correct here */
			/* duplex bit may not right if partner doesn't support all mode, do further detection */
			if ((uReg & (SW_AUTONEGO_PART_100FD | SW_AUTONEGO_PART_100HD | SW_AUTONEGO_PART_10FD | SW_AUTONEGO_PART_10HD) << uShift)
				!= (SW_AUTONEGO_PART_100FD | SW_AUTONEGO_PART_100HD | SW_AUTONEGO_PART_10FD | SW_AUTONEGO_PART_10HD)) {
				if (SPEED_100 == DI.usLinkSpeed[uPort]) {
					if ((uReg & (SW_AUTONEGO_PART_100FD << uShift))) {
						DI.bHalfDuplexDetected[uPort] = FULL_DUPLEX;
#if !defined(KS8695) && !defined(KS8695X)
						forceFlowControl(pDrvCtrl, uPort, TRUE);
						backPressureEnable(pDrvCtrl, uPort, FALSE);
#endif
					} else {
						DI.bHalfDuplexDetected[uPort] = HALF_DUPLEX;
#if !defined(KS8695) && !defined(KS8695X)
						forceFlowControl(pDrvCtrl, uPort, FALSE);
						backPressureEnable(pDrvCtrl, uPort, TRUE);
#endif
					}
				}
				else {
					if ((uReg & (SW_AUTONEGO_PART_10FD << uShift))) {
						DI.bHalfDuplexDetected[uPort] = FULL_DUPLEX;
#if !defined(KS8695) && !defined(KS8695X)
						forceFlowControl(pDrvCtrl, uPort, TRUE);
						backPressureEnable(pDrvCtrl, uPort, FALSE);
#endif
					}
					else {
						DI.bHalfDuplexDetected[uPort] = HALF_DUPLEX;
#if !defined(KS8695) && !defined(KS8695X)
						forceFlowControl(pDrvCtrl, uPort, FALSE);
						backPressureEnable(pDrvCtrl, uPort, TRUE);
#endif
					}
				}
			}

			/* software workaround for flow control, need to know partner's flow control */
			if (DMA_WAN == DI.usDMAId) {	/* currently do it to WAN only, there is no problem to LAN, will do HPNA later */
				uint8_t	bFlowCtrl;

				/* we need to check partner's control flow setting for the matching, if not, changes ours */
				bFlowCtrl = ((SW_AUTONEGO_PART_PAUSE << uShift) & uReg) ? TRUE : FALSE;
				if (bFlowCtrl != DI.bRxFlowCtrl) {	/* Tx same as Rx, so test Rx should be enough */
					/* need to change ours accordingly, which will overwrite current one */
					macConfigureFlow(pDrvCtrl, bFlowCtrl);
				}
			}
		    DRV_LOG(DRV_DEBUG_LOG_PHY, "Auto Nego completed\n", 1, 2, 3, 4, 5, 6);
		}
		else {
			/* auto nego in progress */
		    DRV_LOG(DRV_DEBUG_LOG_PHY, "Auto Nego in progress...\n", 1, 2, 3, 4, 5, 6);
			/* wait for next timer */
			DI.bLinkActive[uPort] = FALSE;
			DI.usLinkSpeed[uPort] = SPEED_UNKNOWN;
			DI.bHalfDuplex[uPort] = 0;
		}
	}
	else {
		/* manually connection */
		if (SW_PHY_10BASE_T_FD == DI.usCType[uPort] || SW_PHY_100BASE_TX_FD == DI.usCType[uPort]) {
			DI.bHalfDuplex[uPort] = FULL_DUPLEX;
#if !defined(KS8695) && !defined(KS8695X)
			forceFlowControl(pDrvCtrl, uPort, TRUE);
			backPressureEnable(pDrvCtrl, uPort, FALSE);
#endif
		}
		else {
			DI.bHalfDuplex[uPort] = HALF_DUPLEX;
#if !defined(KS8695) && !defined(KS8695X)
			forceFlowControl(pDrvCtrl, uPort, FALSE);
			backPressureEnable(pDrvCtrl, uPort, TRUE);
#endif
		}
		if (SW_PHY_100BASE_TX_FD == DI.usCType[uPort] || SW_PHY_100BASE_TX == DI.usCType[uPort]) {
			DI.usLinkSpeed[uPort] = SPEED_100;
			gpioSet(pDrvCtrl, uPort, TRUE);
		}
		else {
			DI.usLinkSpeed[uPort] = SPEED_10;
			gpioSet(pDrvCtrl, uPort, FALSE);
		}

		/* software workaround for flow control, need to know partner's flow control */
		if (DMA_WAN == DI.usDMAId) {	/* currently do it to WAN only, there is no problem to LAN, will do HPNA later */
			macConfigureFlow(pDrvCtrl, FULL_DUPLEX == DI.bHalfDuplex[uPort] ? TRUE : FALSE);
		}
	}
	return TRUE;
}

/*
 * swDetectPhyConnection
 *	This function is used to start auto negotiation
 *
 * Argument(s)
 *  pDrvCtrl	pointer to END_DEVICE struct
 *  uPort		port to start
 *
 * Return(s)
 *	NONE.
 */
LOCAL void swDetectPhyConnection(PEND_DEVICE pDrvCtrl, UINT uPort)
{
	if (LINK_SELECTION_FORCED != DI.byDisableAutoNego[uPort] && !DI.bAutoNegoInProgress[uPort] && DI.bLinkChanged[uPort]) {
		swAutoNegoStart(pDrvCtrl, uPort);
		DI.bLinkChanged[uPort] = FALSE;
		DI.bLinkActive[uPort] = FALSE;
	}
	swGetPhyStatus(pDrvCtrl, uPort);
}

/*
 * swPhyReset
 *	This function is used to reset phy chipset (powerdown or soft reset).
 *
 * Argument(s)
 *	pDrvCtrl	pointer to END_DEVICE structure.
 *  uPort		port to start
 *
 * Return(s)
 *	NONE
 */
void swPhyReset(PEND_DEVICE pDrvCtrl, UINT uPort)
{
	UINT	uReg, uShift = 0;
	UINT	uPowerReg;
	UINT	uReg1;

    DRV_LOG(DRV_DEBUG_LOG_PHY, "swPhyReset\n", 1, 2, 3, 4, 5, 6);

	/* IEEE spec. of auto nego bit */
	uReg1 = BIT(7);
	switch (DI.usDMAId) {
#ifdef	KS8695
	case DMA_HPNA:
		return;
#endif

	case DMA_WAN:
		uPowerReg = REG_WAN_POWERMAGR;
		break;

	default:
	case DMA_LAN:
		switch (uPort) {
		case SW_PORT_4:
			uPowerReg = REG_LAN34_POWERMAGR;
			break;

		case SW_PORT_3:
			uPowerReg = REG_LAN34_POWERMAGR;
			uShift = 16;
			break;

		case SW_PORT_2:
			uPowerReg = REG_LAN12_POWERMAGR;
			break;

		case SW_PORT_1:
		default:
			uPowerReg = REG_LAN12_POWERMAGR;
			uShift = 16;
			break;
		}
	}

	if (DI.bPowerDownReset) {
		uReg = KS8695_READ_REG(uPowerReg);
		KS8695_WRITE_REG(uPowerReg, uReg | ((UINT)POWER_POWERDOWN << uShift));
#ifndef	NO_TASK_DELAY
		taskDelay(5);
#else
		delayEx(500000);
#endif
		uReg &= ~((UINT)POWER_POWERDOWN << uShift);
		/* turn off IEEE auto nego */
		uReg &= ~(uReg1 << uShift);
		KS8695_WRITE_REG(uPowerReg, uReg);
		/* need 20 cpu clock delay for switch related registers */
		SW_WRITE_DELAY();
	}
	else {
		uReg = KS8695_READ_REG(uPowerReg);
		/* turn off IEEE auto nego */
		uReg &= ~(uReg1 << uShift);
		KS8695_WRITE_REG(uPowerReg, uReg);
		/* need 20 cpu clock delay for switch related registers */
		SW_WRITE_DELAY();
	}
}

/*
 * macReset
 *	This function will execute a soft reset the chipset.
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	OK		if success
 *	ERROR	otherwise
 */
int macReset(PEND_DEVICE pDrvCtrl)
{
	int nTimeOut = 200;
	UINT32 uReg;

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

	/* disable IER if any */
	uReg = KS8695_READ_REG(REG_INT_ENABLE);
	switch (DI.usDMAId) {
#ifdef	KS8695
	case DMA_HPNA:
		uReg &= ~INT_HPNA_MASK;
		break;
#endif

	case DMA_LAN:
		uReg &= ~INT_LAN_MASK;
		break;

	default:
	case DMA_WAN:

⌨️ 快捷键说明

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