mv_eth.c

来自「适合KS8695X」· C语言 代码 · 共 1,878 行 · 第 1/5 页

C
1,878
字号
					    &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 */
			break;
		}
	} while (release_result == ETH_OK);


	return 0;		/* success */
      error:
	return 1;		/* Failed - higher layers will free the skb */
}

/**********************************************************************
 * mv64360_eth_receive
 *
 * This function is forward packets that are received from the port's
 * queues toward kernel core or FastRoute them to another interface.
 *
 * Input : dev - a pointer to the required interface
 *         max - maximum number to receive (0 means unlimted)
 *
 * Output : number of served packets
 **********************************************************************/

int mv64360_eth_receive (struct eth_device *dev)
{
	ETH_PORT_INFO *ethernet_private;
	struct mv64360_eth_priv *port_private;
	unsigned int port_num;
	PKT_INFO pkt_info;
	struct net_device_stats *stats;


	ethernet_private = (ETH_PORT_INFO *) dev->priv;
	port_private =
		(struct mv64360_eth_priv *) ethernet_private->port_private;
	port_num = port_private->port_num;
	stats = port_private->stats;

	while ((eth_port_receive (ethernet_private, ETH_Q0, &pkt_info) ==
		ETH_OK)) {

#ifdef DEBUG_MV_ETH
		if (pkt_info.byte_cnt != 0) {
			printf ("%s: Received %d byte Packet @ 0x%x\n",
				__FUNCTION__, pkt_info.byte_cnt,
				pkt_info.buf_ptr);
		}
#endif
		/* Update statistics. Note byte count includes 4 byte CRC count */
		stats->rx_packets++;
		stats->rx_bytes += pkt_info.byte_cnt;

		/*
		 * In case received a packet without first / last bits on OR the error
		 * summary bit is on, the packets needs to be dropeed.
		 */
		if (((pkt_info.
		      cmd_sts & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
		     (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
		    || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
			stats->rx_dropped++;

			printf ("Received packet spread on multiple descriptors\n");

			/* Is this caused by an error ? */
			if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY) {
				stats->rx_errors++;
			}

			/* free these descriptors again without forwarding them to the higher layers */
			pkt_info.buf_ptr &= ~0x7;	/* realign buffer again */
			pkt_info.byte_cnt = 0x0000;	/* Reset Byte count */

			if (eth_rx_return_buff
			    (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) {
				printf ("Error while returning the RX Desc to Ring\n");
			} else {
				DP (printf ("RX Desc returned to Ring\n"));
			}
			/* /free these descriptors again */
		} else {

/* !!! call higher layer processing */
#ifdef DEBUG_MV_ETH
			printf ("\nNow send it to upper layer protocols (NetReceive) ...\n");
#endif
			/* let the upper layer handle the packet */
			NetReceive ((uchar *) pkt_info.buf_ptr,
				    (int) pkt_info.byte_cnt);

/* **************************************************************** */
/* free descriptor  */
			pkt_info.buf_ptr &= ~0x7;	/* realign buffer again */
			pkt_info.byte_cnt = 0x0000;	/* Reset Byte count */
			DP (printf
			    ("RX: pkt_info.buf_ptr =	%x\n",
			     pkt_info.buf_ptr));
			if (eth_rx_return_buff
			    (ethernet_private, ETH_Q0, &pkt_info) != ETH_OK) {
				printf ("Error while returning the RX Desc to Ring\n");
			} else {
				DP (printf ("RX Desc returned to Ring\n"));
			}

/* **************************************************************** */

		}
	}
	mv64360_eth_get_stats (dev);	/* update statistics */
	return 1;
}

/**********************************************************************
 * mv64360_eth_get_stats
 *
 * Returns a pointer to the interface statistics.
 *
 * Input : dev - a pointer to the required interface
 *
 * Output : a pointer to the interface's statistics
 **********************************************************************/

static struct net_device_stats *mv64360_eth_get_stats (struct eth_device *dev)
{
	ETH_PORT_INFO *ethernet_private;
	struct mv64360_eth_priv *port_private;
	unsigned int port_num;

	ethernet_private = (ETH_PORT_INFO *) dev->priv;
	port_private =
		(struct mv64360_eth_priv *) ethernet_private->port_private;
	port_num = port_private->port_num;

	mv64360_eth_update_stat (dev);

	return port_private->stats;
}


/**********************************************************************
 * mv64360_eth_update_stat
 *
 * Update the statistics structure in the private data structure
 *
 * Input : pointer to ethernet interface network device structure
 * Output : N/A
 **********************************************************************/

static void mv64360_eth_update_stat (struct eth_device *dev)
{
	ETH_PORT_INFO *ethernet_private;
	struct mv64360_eth_priv *port_private;
	struct net_device_stats *stats;
	unsigned int port_num;
	volatile unsigned int dummy;

	ethernet_private = (ETH_PORT_INFO *) dev->priv;
	port_private =
		(struct mv64360_eth_priv *) ethernet_private->port_private;
	port_num = port_private->port_num;
	stats = port_private->stats;

	/* These are false updates */
	stats->rx_packets += (unsigned long)
		eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_GOOD_FRAMES_RECEIVED);
	stats->tx_packets += (unsigned long)
		eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_GOOD_FRAMES_SENT);
	stats->rx_bytes += (unsigned long)
		eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_GOOD_OCTETS_RECEIVED_LOW);
	/*
	 * Ideally this should be as follows -
	 *
	 *   stats->rx_bytes   += stats->rx_bytes +
	 * ((unsigned long) ethReadMibCounter (ethernet_private->port_num ,
	 * ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32);
	 *
	 * But the unsigned long in PowerPC and MIPS are 32bit. So the next read
	 * is just a dummy read for proper work of the GigE port
	 */
	dummy = eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH);
	stats->tx_bytes += (unsigned long)
		eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_GOOD_OCTETS_SENT_LOW);
	dummy = eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_GOOD_OCTETS_SENT_HIGH);
	stats->rx_errors += (unsigned long)
		eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_MAC_RECEIVE_ERROR);

	/* Rx dropped is for received packet with CRC error */
	stats->rx_dropped +=
		(unsigned long) eth_read_mib_counter (ethernet_private->
						      port_num,
						      ETH_MIB_BAD_CRC_EVENT);
	stats->multicast += (unsigned long)
		eth_read_mib_counter (ethernet_private->port_num,
				      ETH_MIB_MULTICAST_FRAMES_RECEIVED);
	stats->collisions +=
		(unsigned long) eth_read_mib_counter (ethernet_private->
						      port_num,
						      ETH_MIB_COLLISION) +
		(unsigned long) eth_read_mib_counter (ethernet_private->
						      port_num,
						      ETH_MIB_LATE_COLLISION);
	/* detailed rx errors */
	stats->rx_length_errors +=
		(unsigned long) eth_read_mib_counter (ethernet_private->
						      port_num,
						      ETH_MIB_UNDERSIZE_RECEIVED)
		+
		(unsigned long) eth_read_mib_counter (ethernet_private->
						      port_num,
						      ETH_MIB_OVERSIZE_RECEIVED);
	/* detailed tx errors */
}

#ifndef  UPDATE_STATS_BY_SOFTWARE
/**********************************************************************
 * mv64360_eth_print_stat
 *
 * Update the statistics structure in the private data structure
 *
 * Input : pointer to ethernet interface network device structure
 * Output : N/A
 **********************************************************************/

static void mv64360_eth_print_stat (struct eth_device *dev)
{
	ETH_PORT_INFO *ethernet_private;
	struct mv64360_eth_priv *port_private;
	struct net_device_stats *stats;
	unsigned int port_num;

	ethernet_private = (ETH_PORT_INFO *) dev->priv;
	port_private =
		(struct mv64360_eth_priv *) ethernet_private->port_private;
	port_num = port_private->port_num;
	stats = port_private->stats;

	/* These are false updates */
	printf ("\n### Network statistics: ###\n");
	printf ("--------------------------\n");
	printf (" Packets received:		%ld\n", stats->rx_packets);
	printf (" Packets send:			%ld\n", stats->tx_packets);
	printf (" Received bytes:		%ld\n", stats->rx_bytes);
	printf (" Send bytes:			%ld\n", stats->tx_bytes);
	if (stats->rx_errors != 0)
		printf (" Rx Errors:			%ld\n",
			stats->rx_errors);
	if (stats->rx_dropped != 0)
		printf (" Rx dropped (CRC Errors):	%ld\n",
			stats->rx_dropped);
	if (stats->multicast != 0)
		printf (" Rx mulicast frames:		%ld\n",
			stats->multicast);
	if (stats->collisions != 0)
		printf (" No. of collisions:		%ld\n",
			stats->collisions);
	if (stats->rx_length_errors != 0)
		printf (" Rx length errors:		%ld\n",
			stats->rx_length_errors);
}
#endif

/**************************************************************************
 *network_start - Network Kick Off Routine UBoot
 *Inputs :
 *Outputs :
 **************************************************************************/

bool db64360_eth_start (struct eth_device *dev)
{
	return (mv64360_eth_open (dev));	/* calls real open */
}

/*************************************************************************
**************************************************************************
**************************************************************************
*  The second part is the low level driver of the gigE ethernet ports.   *
**************************************************************************
**************************************************************************
*************************************************************************/
/*
 * based on Linux code
 * arch/ppc/galileo/EVB64360/mv64360_eth.c - Driver for MV64360X ethernet ports
 * Copyright (C) 2002 rabeeh@galileo.co.il

 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

/********************************************************************************
 * Marvell's Gigabit Ethernet controller low level driver
 *
 * DESCRIPTION:
 *       This file introduce low level API to Marvell's Gigabit Ethernet
 *		controller. This Gigabit Ethernet Controller driver API controls
 *		1) Operations (i.e. port init, start, reset etc').
 *		2) Data flow (i.e. port send, receive etc').
 *		Each Gigabit Ethernet port is controlled via ETH_PORT_INFO
 *		struct.
 *		This struct includes user configuration information as well as
 *		driver internal data needed for its operations.
 *
 *		Supported Features:
 *		- This low level driver is OS independent. Allocating memory for
 *		  the descriptor rings and buffers are not within the scope of
 *		  this driver.
 *		- The user is free from Rx/Tx queue managing.
 *		- This low level driver introduce functionality API that enable
 *		  the to operate Marvell's Gigabit Ethernet Controller in a
 *		  convenient way.
 *		- Simple Gigabit Ethernet port operation API.
 *		- Simple Gigabit Ethernet port data flow API.
 *		- Data flow and operation API support per queue functionality.
 *		- Support cached descriptors for better performance.
 *		- Enable access to all four DRAM banks and internal SRAM memory
 *		  spaces.
 *		- PHY access and control API.
 *		- Port control register configuration API.
 *		- Full control over Unicast and Multicast MAC configurations.
 *
 *		Operation flow:
 *
 *		Initialization phase
 *		This phase complete the initialization of the ETH_PORT_INFO
 *		struct.
 *		User information regarding port configuration has to be set
 *		prior to calling the port initialization routine. For example,
 *		the user has to assign the port_phy_addr field which is board
 *		depended parameter.
 *		In this phase any port Tx/Rx activity is halted, MIB counters
 *		are cleared, PHY address is set according to user parameter and
 *		access to DRAM and internal SRAM memory spaces.
 *
 *		Driver ring initialization
 *		Allocating memory for the descriptor rings and buffers is not
 *		within the scope of this driver. Thus, the user is required to
 *		allocate memory for the descriptors ring and buffers. Those

⌨️ 快捷键说明

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