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

📄 ks8695end.c

📁 这是micrel公司宽带路由ARM9芯片的VXWORKS BSP 源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 *
 * Argument(s)
 *	count		loop count to delay
 *
 * Return(s)
 *	NONE.
 */
LOCAL void delayEx(UINT32 count) 
{
	int	i;

	while (count--) {
		i++;
	}
}
#endif

#if 0
/*
 * delayTicks
 *	This function is use to delay given ticks.
 *
 * Argument(s)
 *	ticks		ticks to delay
 *
 * Return(s)
 *	NONE.
 */
LOCAL void delayTicks(UINT ticks) 
{
    ULONG	currentTicks;

	if (ticks) {
		currentTicks = tickGet();
		while (tickGet() < (currentTicks + ticks));
	}
}

/*
 * delayOneSec
 *	This function is use to delay a second.
 *
 * Argument(s)
 *	NONE
 *
 * Return(s)
 *	NONE.
 */
LOCAL void delayOneSec(void)
{
	delayTicks(sysClkRateGet());
}
#endif

#ifdef DRV_DEBUG
/*
 * logValue
 *	This function is use to print register value using logging mechanims.
 *
 * Argument(s)
 *	prompt		pointer to the prompt string
 *	value		register value to prompt for debug
 *	hex			hex or decimal value
 *	flag		log bit flag
 *
 * Return(s)
 *	NONE.
 */
LOCAL void logValue(char *prompt, UINT32 value, int hex, UINT32 flag)
{
	char buf[128];

	if (hex)
		sprintf(buf, "%s=0x%08x\n", prompt, value);
	else
		sprintf(buf, "%s=%d\n", prompt, value);

	DRV_LOG(flag, buf, 1, 2, 3, 4, 5, 6);
}
#endif

/*
 * printStr
 *	This function is use to delay a second.
 *
 * Argument(s)
 *	str		pointer to a string to print out in sync manner (for debug)
 *
 * Return(s)
 *	NONE.
 */
LOCAL void printStr(char *str)
{
	int i, len;

	len = strlen(str);
	if (len) {
		KS8695_WRITE_REG(REG_GPIO_DATA, 0x0000ffdf);
		for (i = 0; i < len; i++) {
			KS8695_WRITE_REG(REG_UART_TX_HOLDING, *(str + i));
		}
		KS8695_WRITE_REG(REG_UART_TX_HOLDING,0x0a);
		KS8695_WRITE_REG(REG_UART_TX_HOLDING,0x0d);
	}
}

/*
 * ks8695_set_multi
 *	This function is used to set Multicast and Promiscuous mode. It is 
 *	called whenever the multicast address list or the network interface
 *	flags are updated. This routine is resposible for configuring the 
 *	hardware for proper multicast, promiscuous mode, and all-multi behavior.
 *
 * Argument(s)
 *  pDrvCtrl		pointer to END_DEVICE struct
 *
 * Return(s)
 *	NONE.
 */
LOCAL void ks8695_set_multi(PEND_DEVICE pDrvCtrl)
{
	uint32_t uReg;
	BOOLEAN	bRxStarted;

	DRV_LOG(DRV_DEBUG_IOCTL, "ks8695_set_multi\n",	1, 2, 3, 4, 5, 6);

	bRxStarted = DI.bRxStarted;
#if 0
	if (bRxStarted) {
		macStartRx(pDrvCtrl, FALSE);
	}
#endif

	/* read RX mode register in order to set hardware filter mode */
	uReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
	uReg |= DMA_UNICAST | DMA_BROADCAST;
	uReg &= ~(DMA_PROMISCUOUS | DMA_MULTICAST);

    /* Set promiscuous mode if it's asked for. */
	if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) {
		DRV_LOG(DRV_DEBUG_IOCTL, "Promiscuous mode on!\n",	1, 2, 3, 4, 5, 6);
		uReg |= DMA_PROMISCUOUS;
	}
	if (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_ALLMULTI | IFF_MULTICAST)) {
		DRV_LOG(DRV_DEBUG_IOCTL, "Multicast mode on!\n",	1, 2, 3, 4, 5, 6);
		uReg |= DMA_MULTICAST;
	}
	KS8695_WRITE_REG(REG_RXCTRL + DI.nOffset, uReg);

	if (bRxStarted) {
#if 0
		macStartRx(pDrvCtrl, TRUE);
#endif
	}

	ks8695_relink(pDrvCtrl);
}

/*
 * ResetDma
 *	This function is use to reset DMA in case Tx DMA was sucked due to 
 *	heavy traffic condition.
 *
 * Argument(s)
 *  pDrvCtrl		pointer to END_DEVICE struct
 *
 * Return(s)
 *	0				if success
 *	negative value	if failed
 */
LOCAL __inline void ResetDma(PEND_DEVICE pDrvCtrl)
{
	UINT uRxReg;

	if (KS8695_FLAGS_ISSET(&pDrvCtrl->end, IFF_RUNNING)) {
	    logMsg("ResetDma, not running!\n", 1, 2, 3, 4, 5, 6);
		return;
	}
    logMsg("ResetDma: not implented yet\n", 1, 2, 3, 4, 5, 6);
	return;

    END_FLAGS_CLR(&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));

	macStopAll(pDrvCtrl);

	CleanRxRing(pDrvCtrl);
	InitRxRing(pDrvCtrl);
	CleanTxRing(pDrvCtrl);
	InitTxRing(pDrvCtrl);
	ReceiveBufferFill(pDrvCtrl);

	ks8695_ChipInit(pDrvCtrl, FALSE);

	KS8695_WRITE_REG(REG_INT_STATUS, DI.uIntMask);
	/* read RX mode register */
	uRxReg = KS8695_READ_REG(REG_RXCTRL + DI.nOffset);
	if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC) {
		uRxReg |= DMA_PROMISCUOUS;
	}
	if (END_FLAGS_GET(&pDrvCtrl->end) & (IFF_ALLMULTI | IFF_MULTICAST)) {
		uRxReg |= DMA_MULTICAST;
	}
	uRxReg |= DMA_BROADCAST;

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

	KS8695_WRITE_REG(REG_RXBASE + DI.nOffset, DI.RxDescDMA);
	KS8695_WRITE_REG(REG_TXBASE + DI.nOffset, DI.TxDescDMA);
	macEnableInterrupt(pDrvCtrl, TRUE);

	macStartRx(pDrvCtrl, TRUE);
	macStartTx(pDrvCtrl, TRUE);

	DI.bTxNoResource = FALSE;
    END_FLAGS_SET(&pDrvCtrl->end, (IFF_UP | IFF_RUNNING));
}

/*
 * hook_irqs
 *	This function is used to hook irqs associated to given DMA type
 *
 * Argument(s)
 *	pDrvCtrl	pointer to END_DEVICE structure.
 *	req			request or free interrupts
 *
 * Return(s)
 *	OK		if success
 *	ERROR	if failed
 */
LOCAL int hook_irqs(PEND_DEVICE pDrvCtrl, int req)
{
    STATUS result;
	int	i;

	switch (DI.usDMAId) {
	default:
		break;

	case DMA_WAN:
		if (DI.uLinkIntMask & INT_WAN_LINK) {
			if (req) {
				result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(31), ks8695IntLink, (int)pDrvCtrl);			    
				if (ERROR == result) {
				    DRV_LOG(DRV_DEBUG_ERROR, "intConnect failed\n", 1, 2, 3, 4, 5, 6);
					intEnable(INT_LVL_WMLCS);
					return result;
				}
			}
			else {
				intDisable(INT_LVL_WMLCS);
			}
		}
		break;
	}

	/* each DMA has 6 interrupt bits associated, except WAN which has one extra, INT_WAN_LINK */
	for (i = 0; i < 6; i++) {
		if (DI.uIntMask & (1L << (DI.uIntShift + i))) { 
			if (req) {
				switch ((1 << i))
				{
					default:
					case INT_TX_BIT:
						result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxComp, (int)pDrvCtrl);
						break;
					case INT_RX_BIT:
						result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxAvail, (int)pDrvCtrl);
						break;
					case INT_TX_UNAVAIL_BIT:
						result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxUnavail, (int)pDrvCtrl);
						break;
					case INT_RX_UNAVAIL_BIT:
						result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxUnavail, (int)pDrvCtrl);
						break;
					case INT_TX_STOPPED_BIT:
						result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntTxStop, (int)pDrvCtrl);
						break;
					case INT_RX_STOPPED_BIT:
						result = intConnect((VOIDFUNCPTR *)INUM_TO_IVEC(i + DI.uIntShift), ks8695IntRxStop, (int)pDrvCtrl);
						break;
				}
				if (ERROR == result) {
				    DRV_LOG(DRV_DEBUG_ERROR, "intConnect failed\n", 1, 2, 3, 4, 5, 6);
					/* disconnect any one connected previously before failing it */
					while (--i >= 0) {
						intDisable(i + DI.uIntShift);
					}
					return result;
				}
				intEnable(i + DI.uIntShift);
			}
			else {
				intDisable(i + DI.uIntShift);
			}
		}
	}

	return OK;
}

/*
 * ks8695_dump_packet
 *	This function is use to dump given packet for debugging.
 *
 * Argument(s)
 *	pDrvCtrl	pointer to END_DEVICE structure.
 *	data		pointer to the beginning of the packet to dump
 *	len			length of the packet
 *	flag		debug flag
 *
 * Return(s)
 *	NONE.
 */
__inline void ks8695_dump_packet(PEND_DEVICE pDrvCtrl, unsigned char *data, int len, UINT flag)
{
	/* we may need to have locking mechamism to use this function, since Rx call it within INT context
	   and Tx call it in normal context */
	if (flag && len >= 18) {
		if (flag & DEBUG_PACKET_LEN) {
			printf("Pkt Len=%d\n", len);
		}
		if (flag & DEBUG_PACKET_HEADER) {
			printf("DA=%02x:%02x:%02x:%02x:%02x:%02x\n", 
				*data, *(data + 1), *(data + 2), *(data + 3), *(data + 4), *(data + 5));
			printf("SA=%02x:%02x:%02x:%02x:%02x:%02x\n", 
				*(data + 6), *(data + 7), *(data + 8), *(data + 9), *(data + 10), *(data + 11));
			printf("Type=%04x (%d)\n", ntohs(*(unsigned short *)(data + 12)), ntohs(*(unsigned short *)(data + 12)));
		}
		if (flag & DEBUG_PACKET_CONTENT) {
			int	j = 0, k;

			/* skip DA/SA/TYPE */
            /*
			data += ENET_HEADER_SIZE;
			len -= ENET_HEADER_SIZE;
            */
			do {
				printf("\n %04d   ", j);
				for (k = 0; (k < 16 && len); k++, data++, len--) {
					printf("%02x  ", *data);
				}
				j += 16;
			} while (len > 0);
			/* last dump crc field */
			/*printf("\nCRC=%04x\n", ntohl(*(unsigned int *)data));*/
			printf("\n");
		}
	}
}

#ifdef USE_DUMP_REG
/*
 * ks8695_dump_reg
 *	This function is use to dump registers of given range!
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *	offset			register offset to dump
 *	length			length of registers to dump
 *
 * Return(s)
 *	NONE.
 */
LOCAL void ks8695_dump_reg(PEND_DEVICE pDrvCtrl, UINT32 offset, UINT32 length)
{
	int	i;
	UINT32	val;

	printf("-reg-  --value(hex)--  --value(dec)---\n");
	for (i = offset; i <= (offset + length); i += 4) {
		val = KS8695_READ_REG(i);
		printf("0x%04x   0x%08x       %12d\n", i, val, val);
	}
}

/*
 * ks8695_dump_reg_set
 *	This function is use to dump registers of given range!
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *	set				bit for which set to dump
 *
 * Return(s)
 *	NONE.
 */
LOCAL void ks8695_dump_reg_set(PEND_DEVICE pDrvCtrl, UINT32 set)
{
	if (set & SET_DMA_DUMP) {
		ks8695_dump_reg(pDrvCtrl, DI.nOffset + REG_TXCTRL, REG_STATION_HIGH);
	}
	if (set & SET_DMA_STATION_DUMP) {
		ks8695_dump_reg(pDrvCtrl, DI.nOffset + REG_MAC0_LOW, (REG_MAC15_HIGH - REG_MAC0_LOW));
	}
	if (set & SET_UART_DUMP) {
		ks8695_dump_reg(pDrvCtrl, REG_UART_RX_BUFFER, (REG_UART_STATUS - REG_UART_RX_BUFFER));
	}
	if (set & SET_INT_DUMP) {
		/*ks8695_dump_reg(pDrvCtrl, REG_INT_CONTL, (REG_IRQ_PEND_PRIORITY - REG_INT_CONTL));*/
		ks8695_dump_reg(pDrvCtrl, REG_INT_CONTL, (REG_INT_LAN_PRIORITY - REG_INT_CONTL));
	}

	if (set & SET_TIMER_DUMP) {
		ks8695_dump_reg(pDrvCtrl, REG_TIMER_CTRL, (REG_TIMER0_PCOUNT -REG_TIMER_CTRL));
	}
	if (set & SET_GPIO_DUMP) {
		ks8695_dump_reg(pDrvCtrl, REG_GPIO_MODE, (REG_GPIO_DATA - REG_GPIO_MODE));
	}
	if (set & SET_SWITCH_DUMP) {
		ks8695_dump_reg(pDrvCtrl, REG_SWITCH_CTRL0, (REG_LAN34_POWERMAGR - REG_SWITCH_CTRL0));
	}
	if (set & SET_MISC_DUMP) {
		ks8695_dump_reg(pDrvCtrl, REG_DEVICE_ID, (REG_WAN_PHY_STATUS - REG_DEVICE_ID));
	}
	if (set & SET_SNMP_DUMP) {
#ifdef	USE_READSNMPREG
		UINT32 val, i;

		for (i = 0; i <= REG_SNMP_MAX ; i++) {
			val = swReadSNMPReg(pDrvCtrl, i);
			printf("0x%04x = %10d\n", i, val);
		}
#endif	/*USE_READSNMPREG*/
	}
}
#endif

/*
 * ks8695_relink
 *	This function is use to setup link in case some dynamic configuration
 *	is applied via ifconfig! if driver is opened!
 *
 * Argument(s)
 *	pDrvCtrl		pointer to END_DEVICE structure.
 *
 * Return(s)
 *	NONE.
 */
LOCAL void ks8695_relink(PEND_DEVICE pDrvCtrl)
{
	/* reset the flag even if auto nego is in progress
	   to make sure we don't miss it!!! */
	if (DMA_LAN != DI.usDMAId) {
		swDetectPhyConnection(pDrvCtrl, 0);
	}
	else {
		int	i;

		for (i = 0; i < SW_MAX_LAN_PORTS; i++) {
			swDetectPhyConnection(pDrvCtrl, i);
		}
	}
}

/*
 * SoftwareInit
 *	This function initializes the pDrvCtrl private data structure.
 *
 * Argument(s)
 *  pDrvCtrl	pointer to END_DEVICE structure
 *
 * Return(s)
 *	OK		if success
 *	ERROR	if failed
 */
LOCAL int SoftwareInit(PEND_DEVICE pDrvCtrl)
{
	/* Initial Receive Buffer Length */
	if ((ETHERMTU + ENET_HEADER_SIZE + ETH_CRC_LENGTH + 2) <= KS8695_MIN_FBUF - 4 - pDrvCtrl->offset) {
		DI.uRxBufferLen = KS8695_MIN_FBUF;	/* 0x600 */
	}
	else if ((ETHERMTU + ENET_HEADER_SIZE + ETH_CRC_LENGTH + 2) <= BUFFER_1568 - 4 - pDrvCtrl->offset) {
		DI.uRxBufferLen = BUFFER_1568;	/* 0x620 */
	}
	else {
		DI.uRxBufferLen = BUFFER_2048;	/* 0x800 */
	}

	/* please update link status within watchdog routine */
	DI.bLinkChanged[0] = TRUE;
	if (DMA_LAN == DI.usDMAId) {	/* if LAN driver, 3 more ports */
		DI.bLinkChanged[1] = TRUE;
		DI.bLinkChanged[2] = TRUE;
		DI.bLinkChanged[3] = TRUE;
	}

	return OK;

⌨️ 快捷键说明

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