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 + -
显示快捷键?