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

📄 mv_eth.c

📁 omap osk环境下的bootloader,包含完整的uboot源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif		eth_register (dev);	}	DP (printf ("%s: exit\n", __FUNCTION__));}/********************************************************************** * mv64460_eth_open * * This function is called when openning the network device. The function * should initialize all the hardware, initialize cyclic Rx/Tx * descriptors chain and buffers and allocate an IRQ to the network * device. * * Input : a pointer to the network device structure * / / ronen - changed the output to match  net/eth.c needs * Output : nonzero of success , zero if fails. * under construction **********************************************************************/int mv64460_eth_open (struct eth_device *dev){	return (mv64460_eth_real_open (dev));}/* Helper function for mv64460_eth_open */static int mv64460_eth_real_open (struct eth_device *dev){	unsigned int queue;	ETH_PORT_INFO *ethernet_private;	struct mv64460_eth_priv *port_private;	unsigned int port_num;	u32 port_status, phy_reg_data;	ethernet_private = (ETH_PORT_INFO *) dev->priv;	/* ronen - when we update the MAC env params we only update dev->enetaddr	   see ./net/eth.c eth_set_enetaddr() */	memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6);	port_private =		(struct mv64460_eth_priv *) ethernet_private->port_private;	port_num = port_private->port_num;	/* Stop RX Queues */	MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num),		      0x0000ff00);	/* Clear the ethernet port interrupts */	MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0);	MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0);	/* Unmask RX buffer and TX end interrupt */	MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num),		      INT_CAUSE_UNMASK_ALL);	/* Unmask phy and link status changes interrupts */	MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num),		      INT_CAUSE_UNMASK_ALL_EXT);	/* Set phy address of the port */	ethernet_private->port_phy_addr = 0x8 + port_num;	/* Activate the DMA channels etc */	eth_port_init (ethernet_private);	/* "Allocate" setup TX rings */	for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) {		unsigned int size;		port_private->tx_ring_size[queue] = MV64460_TX_QUEUE_SIZE;		size = (port_private->tx_ring_size[queue] * TX_DESC_ALIGNED_SIZE);	/*size = no of DESCs times DESC-size */		ethernet_private->tx_desc_area_size[queue] = size;		/* first clear desc area completely */		memset ((void *) ethernet_private->p_tx_desc_area_base[queue],			0, ethernet_private->tx_desc_area_size[queue]);		/* initialize tx desc ring with low level driver */		if (ether_init_tx_desc_ring		    (ethernet_private, ETH_Q0,		     port_private->tx_ring_size[queue],		     MV64460_TX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ ,		     (unsigned int) ethernet_private->		     p_tx_desc_area_base[queue],		     (unsigned int) ethernet_private->		     p_tx_buffer_base[queue]) == false)			printf ("### Error initializing TX Ring\n");	}	/* "Allocate" setup RX rings */	for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) {		unsigned int size;		/* Meantime RX Ring are fixed - but must be configurable by user */		port_private->rx_ring_size[queue] = MV64460_RX_QUEUE_SIZE;		size = (port_private->rx_ring_size[queue] *			RX_DESC_ALIGNED_SIZE);		ethernet_private->rx_desc_area_size[queue] = size;		/* first clear desc area completely */		memset ((void *) ethernet_private->p_rx_desc_area_base[queue],			0, ethernet_private->rx_desc_area_size[queue]);		if ((ether_init_rx_desc_ring		     (ethernet_private, ETH_Q0,		      port_private->rx_ring_size[queue],		      MV64460_RX_BUFFER_SIZE /* Each Buffer is 1600 Byte */ ,		      (unsigned int) ethernet_private->		      p_rx_desc_area_base[queue],		      (unsigned int) ethernet_private->		      p_rx_buffer_base[queue])) == false)			printf ("### Error initializing RX Ring\n");	}	eth_port_start (ethernet_private);	/* Set maximum receive buffer to 9700 bytes */	MV_REG_WRITE (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num),		      (0x5 << 17) |		      (MV_REG_READ		       (MV64460_ETH_PORT_SERIAL_CONTROL_REG (port_num))		       & 0xfff1ffff));	/*	 * Set ethernet MTU for leaky bucket mechanism to 0 - this will	 * disable the leaky bucket mechanism .	 */	MV_REG_WRITE (MV64460_ETH_MAXIMUM_TRANSMIT_UNIT (port_num), 0);	port_status = MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num));	/* Check Link status on phy */	eth_port_read_smi_reg (port_num, 1, &phy_reg_data);	if (!(phy_reg_data & 0x20)) {		/* Reset PHY */		if ((ethernet_phy_reset (port_num)) != true) {			printf ("$$ Warnning: No link on port %d \n",				port_num);			return 0;		} else {			eth_port_read_smi_reg (port_num, 1, &phy_reg_data);			if (!(phy_reg_data & 0x20)) {				printf ("### Error: Phy is not active\n");				return 0;			}		}	} else {		mv64460_eth_print_phy_status (dev);	}	port_private->eth_running = MAGIC_ETH_RUNNING;	return 1;}static int mv64460_eth_free_tx_rings (struct eth_device *dev){	unsigned int queue;	ETH_PORT_INFO *ethernet_private;	struct mv64460_eth_priv *port_private;	unsigned int port_num;	volatile ETH_TX_DESC *p_tx_curr_desc;	ethernet_private = (ETH_PORT_INFO *) dev->priv;	port_private =		(struct mv64460_eth_priv *) ethernet_private->port_private;	port_num = port_private->port_num;	/* Stop Tx Queues */	MV_REG_WRITE (MV64460_ETH_TRANSMIT_QUEUE_COMMAND_REG (port_num),		      0x0000ff00);	/* Free TX rings */	DP (printf ("Clearing previously allocated TX queues... "));	for (queue = 0; queue < MV64460_TX_QUEUE_NUM; queue++) {		/* Free on TX rings */		for (p_tx_curr_desc =		     ethernet_private->p_tx_desc_area_base[queue];		     ((unsigned int) p_tx_curr_desc <= (unsigned int)		      ethernet_private->p_tx_desc_area_base[queue] +		      ethernet_private->tx_desc_area_size[queue]);		     p_tx_curr_desc =		     (ETH_TX_DESC *) ((unsigned int) p_tx_curr_desc +				      TX_DESC_ALIGNED_SIZE)) {			/* this is inside for loop */			if (p_tx_curr_desc->return_info != 0) {				p_tx_curr_desc->return_info = 0;				DP (printf ("freed\n"));			}		}		DP (printf ("Done\n"));	}	return 0;}static int mv64460_eth_free_rx_rings (struct eth_device *dev){	unsigned int queue;	ETH_PORT_INFO *ethernet_private;	struct mv64460_eth_priv *port_private;	unsigned int port_num;	volatile ETH_RX_DESC *p_rx_curr_desc;	ethernet_private = (ETH_PORT_INFO *) dev->priv;	port_private =		(struct mv64460_eth_priv *) ethernet_private->port_private;	port_num = port_private->port_num;	/* Stop RX Queues */	MV_REG_WRITE (MV64460_ETH_RECEIVE_QUEUE_COMMAND_REG (port_num),		      0x0000ff00);	/* Free RX rings */	DP (printf ("Clearing previously allocated RX queues... "));	for (queue = 0; queue < MV64460_RX_QUEUE_NUM; queue++) {		/* Free preallocated skb's on RX rings */		for (p_rx_curr_desc =		     ethernet_private->p_rx_desc_area_base[queue];		     (((unsigned int) p_rx_curr_desc <		       ((unsigned int) ethernet_private->			p_rx_desc_area_base[queue] +			ethernet_private->rx_desc_area_size[queue])));		     p_rx_curr_desc =		     (ETH_RX_DESC *) ((unsigned int) p_rx_curr_desc +				      RX_DESC_ALIGNED_SIZE)) {			if (p_rx_curr_desc->return_info != 0) {				p_rx_curr_desc->return_info = 0;				DP (printf ("freed\n"));			}		}		DP (printf ("Done\n"));	}	return 0;}/********************************************************************** * mv64460_eth_stop * * This function is used when closing the network device. * It updates the hardware, * release all memory that holds buffers and descriptors and release the IRQ. * Input : a pointer to the device structure * Output : zero if success , nonzero if fails *********************************************************************/int mv64460_eth_stop (struct eth_device *dev){	ETH_PORT_INFO *ethernet_private;	struct mv64460_eth_priv *port_private;	unsigned int port_num;	ethernet_private = (ETH_PORT_INFO *) dev->priv;	port_private =		(struct mv64460_eth_priv *) ethernet_private->port_private;	port_num = port_private->port_num;	/* Disable all gigE address decoder */	MV_REG_WRITE (MV64460_ETH_BASE_ADDR_ENABLE_REG, 0x3f);	DP (printf ("%s Ethernet stop called ... \n", __FUNCTION__));	mv64460_eth_real_stop (dev);	return 0;};/* Helper function for mv64460_eth_stop */static int mv64460_eth_real_stop (struct eth_device *dev){	ETH_PORT_INFO *ethernet_private;	struct mv64460_eth_priv *port_private;	unsigned int port_num;	ethernet_private = (ETH_PORT_INFO *) dev->priv;	port_private =		(struct mv64460_eth_priv *) ethernet_private->port_private;	port_num = port_private->port_num;	mv64460_eth_free_tx_rings (dev);	mv64460_eth_free_rx_rings (dev);	eth_port_reset (ethernet_private->port_num);	/* Disable ethernet port interrupts */	MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_REG (port_num), 0);	MV_REG_WRITE (MV64460_ETH_INTERRUPT_CAUSE_EXTEND_REG (port_num), 0);	/* Mask RX buffer and TX end interrupt */	MV_REG_WRITE (MV64460_ETH_INTERRUPT_MASK_REG (port_num), 0);	/* Mask phy and link status changes interrupts */	MV_REG_WRITE (MV64460_ETH_INTERRUPT_EXTEND_MASK_REG (port_num), 0);	MV_RESET_REG_BITS (MV64460_CPU_INTERRUPT0_MASK_HIGH,			   BIT0 << port_num);	/* Print Network statistics */#ifndef  UPDATE_STATS_BY_SOFTWARE	/*	 * Print statistics (only if ethernet is running),	 * then zero all the stats fields in memory	 */	if (port_private->eth_running == MAGIC_ETH_RUNNING) {		port_private->eth_running = 0;		mv64460_eth_print_stat (dev);	}	memset (port_private->stats, 0, sizeof (struct net_device_stats));#endif	DP (printf ("\nEthernet stopped ... \n"));	return 0;}/********************************************************************** * mv64460_eth_start_xmit * * This function is queues a packet in the Tx descriptor for * required port. * * Input : skb - a pointer to socket buffer *         dev - a pointer to the required port * * Output : zero upon success **********************************************************************/int mv64460_eth_xmit (struct eth_device *dev, volatile void *dataPtr,		      int dataSize){	ETH_PORT_INFO *ethernet_private;	struct mv64460_eth_priv *port_private;	unsigned int port_num;	PKT_INFO pkt_info;	ETH_FUNC_RET_STATUS status;	struct net_device_stats *stats;	ETH_FUNC_RET_STATUS release_result;	ethernet_private = (ETH_PORT_INFO *) dev->priv;	port_private =		(struct mv64460_eth_priv *) ethernet_private->port_private;	port_num = port_private->port_num;	stats = port_private->stats;	/* Update packet info data structure */	pkt_info.cmd_sts = ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;	/* DMA owned, first last */	pkt_info.byte_cnt = dataSize;	pkt_info.buf_ptr = (unsigned int) dataPtr;	status = eth_port_send (ethernet_private, ETH_Q0, &pkt_info);	if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL)) {		printf ("Error on transmitting packet ..");		if (status == ETH_QUEUE_FULL)			printf ("ETH Queue is full. \n");		if (status == ETH_QUEUE_LAST_RESOURCE)			printf ("ETH Queue: using last available resource. \n");		goto error;	}	/* Update statistics and start of transmittion time */	stats->tx_bytes += dataSize;	stats->tx_packets++;	/* Check if packet(s) is(are) transmitted correctly (release everything) */	do {		release_result =			eth_tx_return_desc (ethernet_private, ETH_Q0,					    &pkt_info);		switch (release_result) {		case ETH_OK:			DP (printf ("descriptor released\n"));			if (pkt_info.cmd_sts & BIT0) {				printf ("Error in TX\n");				stats->tx_errors++;			}			break;		case ETH_RETRY:			DP (printf ("transmission still in process\n"));			break;		case ETH_ERROR:			printf ("routine can not access Tx desc ring\n");			break;		case ETH_END_OF_JOB:			DP (printf ("the routine has nothing to release\n"));			break;		default:	/* should not happen */

⌨️ 快捷键说明

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