📄 mv_eth.c
字号:
/* * (C) Copyright 2003 * Ingo Assmus <ingo.assmus@keymile.com> * * based on - Driver for MV64460X ethernet ports * Copyright (C) 2002 rabeeh@galileo.co.il * * See file CREDITS for list of people who contributed to this * project. * * 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 *//* * mv_eth.c - header file for the polled mode GT ethernet driver */#include <common.h>#include <net.h>#include <malloc.h>#include "mv_eth.h"/* enable Debug outputs */#undef DEBUG_MV_ETH#ifdef DEBUG_MV_ETH#define DEBUG#define DP(x) x#else#define DP(x)#endif#undef MV64460_CHECKSUM_OFFLOAD/****************************************************************************************************************************************************************************************************************************** The first part is the high level driver of the gigE ethernet ports. ******************************************************************************************************************************************************************************************************************************//* Definition for configuring driver *//* #define UPDATE_STATS_BY_SOFTWARE */#undef MV64460_RX_QUEUE_FILL_ON_TASK/* Constants */#define MAGIC_ETH_RUNNING 8031971#define MV64460_INTERNAL_SRAM_SIZE _256K#define EXTRA_BYTES 32#define WRAP ETH_HLEN + 2 + 4 + 16#define BUFFER_MTU dev->mtu + WRAP#define INT_CAUSE_UNMASK_ALL 0x0007ffff#define INT_CAUSE_UNMASK_ALL_EXT 0x0011ffff#ifdef MV64460_RX_FILL_ON_TASK#define INT_CAUSE_MASK_ALL 0x00000000#define INT_CAUSE_CHECK_BITS INT_CAUSE_UNMASK_ALL#define INT_CAUSE_CHECK_BITS_EXT INT_CAUSE_UNMASK_ALL_EXT#endif/* Read/Write to/from MV64460 internal registers */#define MV_REG_READ(offset) my_le32_to_cpu(* (volatile unsigned int *) (INTERNAL_REG_BASE_ADDR + offset))#define MV_REG_WRITE(offset,data) *(volatile unsigned int *) (INTERNAL_REG_BASE_ADDR + offset) = my_cpu_to_le32 (data)#define MV_SET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)((INTERNAL_REG_BASE_ADDR) + (regOffset)))) |= ((unsigned int)my_cpu_to_le32(bits)))#define MV_RESET_REG_BITS(regOffset,bits) ((*((volatile unsigned int*)((INTERNAL_REG_BASE_ADDR) + (regOffset)))) &= ~((unsigned int)my_cpu_to_le32(bits)))/* Static function declarations */static int mv64460_eth_real_open (struct eth_device *eth);static int mv64460_eth_real_stop (struct eth_device *eth);static struct net_device_stats *mv64460_eth_get_stats (struct eth_device *dev);static void eth_port_init_mac_tables (ETH_PORT eth_port_num);static void mv64460_eth_update_stat (struct eth_device *dev);bool db64460_eth_start (struct eth_device *eth);unsigned int eth_read_mib_counter (ETH_PORT eth_port_num, unsigned int mib_offset);int mv64460_eth_receive (struct eth_device *dev);int mv64460_eth_xmit (struct eth_device *, volatile void *packet, int length);#ifndef UPDATE_STATS_BY_SOFTWAREstatic void mv64460_eth_print_stat (struct eth_device *dev);#endif/* Processes a received packet */extern void NetReceive (volatile uchar *, int);extern unsigned int INTERNAL_REG_BASE_ADDR;/************************************************* *Helper functions - used inside the driver only * *************************************************/#ifdef DEBUG_MV_ETHvoid print_globals (struct eth_device *dev){ printf ("Ethernet PRINT_Globals-Debug function\n"); printf ("Base Address for ETH_PORT_INFO: %08x\n", (unsigned int) dev->priv); printf ("Base Address for mv64460_eth_priv: %08x\n", (unsigned int) &(((ETH_PORT_INFO *) dev->priv)-> port_private)); printf ("GT Internal Base Address: %08x\n", INTERNAL_REG_BASE_ADDR); printf ("Base Address for TX-DESCs: %08x Number of allocated Buffers %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_tx_desc_area_base[0], MV64460_TX_QUEUE_SIZE); printf ("Base Address for RX-DESCs: %08x Number of allocated Buffers %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)->p_rx_desc_area_base[0], MV64460_RX_QUEUE_SIZE); printf ("Base Address for RX-Buffer: %08x allocated Bytes %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> p_rx_buffer_base[0], (MV64460_RX_QUEUE_SIZE * MV64460_RX_BUFFER_SIZE) + 32); printf ("Base Address for TX-Buffer: %08x allocated Bytes %d\n", (unsigned int) ((ETH_PORT_INFO *) dev->priv)-> p_tx_buffer_base[0], (MV64460_TX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE) + 32);}#endif#define my_cpu_to_le32(x) my_le32_to_cpu((x))unsigned long my_le32_to_cpu (unsigned long x){ return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) << 8) | ((x & 0x00ff0000U) >> 8) | ((x & 0xff000000U) >> 24));}/********************************************************************** * mv64460_eth_print_phy_status * * Prints gigabit ethenret phy status * * Input : pointer to ethernet interface network device structure * Output : N/A **********************************************************************/static void mv64460_eth_print_phy_status (struct eth_device *dev){ struct mv64460_eth_priv *port_private; unsigned int port_num; ETH_PORT_INFO *ethernet_private = (ETH_PORT_INFO *) dev->priv; unsigned int port_status, phy_reg_data; port_private = (struct mv64460_eth_priv *) ethernet_private->port_private; port_num = port_private->port_num; /* Check Link status on phy */ eth_port_read_smi_reg (port_num, 1, &phy_reg_data); if (!(phy_reg_data & 0x20)) { printf ("Ethernet port changed link status to DOWN\n"); } else { port_status = MV_REG_READ (MV64460_ETH_PORT_STATUS_REG (port_num)); printf ("Ethernet status port %d: Link up", port_num); printf (", %s", (port_status & BIT2) ? "Full Duplex" : "Half Duplex"); if (port_status & BIT4) printf (", Speed 1 Gbps"); else printf (", %s", (port_status & BIT5) ? "Speed 100 Mbps" : "Speed 10 Mbps"); printf ("\n"); }}/********************************************************************** * u-boot entry functions for mv64460_eth * **********************************************************************/int db64460_eth_probe (struct eth_device *dev){ return ((int) db64460_eth_start (dev));}int db64460_eth_poll (struct eth_device *dev){ return mv64460_eth_receive (dev);}int db64460_eth_transmit (struct eth_device *dev, volatile void *packet, int length){ mv64460_eth_xmit (dev, packet, length); return 0;}void db64460_eth_disable (struct eth_device *dev){ mv64460_eth_stop (dev);}void mv6446x_eth_initialize (bd_t * bis){ struct eth_device *dev; ETH_PORT_INFO *ethernet_private; struct mv64460_eth_priv *port_private; int devnum, x, temp; char *s, *e, buf[64]; for (devnum = 0; devnum < MV_ETH_DEVS; devnum++) { dev = calloc (sizeof (*dev), 1); if (!dev) { printf ("%s: mv_enet%d allocation failure, %s\n", __FUNCTION__, devnum, "eth_device structure"); return; } /* must be less than NAMESIZE (16) */ sprintf (dev->name, "mv_enet%d", devnum);#ifdef DEBUG printf ("Initializing %s\n", dev->name);#endif /* Extract the MAC address from the environment */ switch (devnum) { case 0: s = "ethaddr"; break; case 1: s = "eth1addr"; break; case 2: s = "eth2addr"; break; default: /* this should never happen */ printf ("%s: Invalid device number %d\n", __FUNCTION__, devnum); return; } temp = getenv_r (s, buf, sizeof (buf)); s = (temp > 0) ? buf : NULL;#ifdef DEBUG printf ("Setting MAC %d to %s\n", devnum, s);#endif for (x = 0; x < 6; ++x) { dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } /* ronen - set the MAC addr in the HW */ eth_port_uc_addr_set (devnum, dev->enetaddr, 0); dev->init = (void *) db64460_eth_probe; dev->halt = (void *) ethernet_phy_reset; dev->send = (void *) db64460_eth_transmit; dev->recv = (void *) db64460_eth_poll; dev->priv = (void *) ethernet_private = calloc (sizeof (*ethernet_private), 1); if (!ethernet_private) { printf ("%s: %s allocation failure, %s\n", __FUNCTION__, dev->name, "Private Device Structure"); free (dev); return; } /* start with an zeroed ETH_PORT_INFO */ memset (ethernet_private, 0, sizeof (ETH_PORT_INFO)); memcpy (ethernet_private->port_mac_addr, dev->enetaddr, 6); /* set pointer to memory for stats data structure etc... */ ethernet_private->port_private = (void *) port_private = calloc (sizeof (*ethernet_private), 1); if (!port_private) { printf ("%s: %s allocation failure, %s\n", __FUNCTION__, dev->name, "Port Private Device Structure"); free (ethernet_private); free (dev); return; } port_private->stats = calloc (sizeof (struct net_device_stats), 1); if (!port_private->stats) { printf ("%s: %s allocation failure, %s\n", __FUNCTION__, dev->name, "Net stat Structure"); free (port_private); free (ethernet_private); free (dev); return; } memset (ethernet_private->port_private, 0, sizeof (struct mv64460_eth_priv)); switch (devnum) { case 0: ethernet_private->port_num = ETH_0; break; case 1: ethernet_private->port_num = ETH_1; break; case 2: ethernet_private->port_num = ETH_2; break; default: printf ("Invalid device number %d\n", devnum); break; }; port_private->port_num = devnum; /* * Read MIB counter on the GT in order to reset them, * then zero all the stats fields in memory */ mv64460_eth_update_stat (dev); memset (port_private->stats, 0, sizeof (struct net_device_stats)); /* Extract the MAC address from the environment */ switch (devnum) { case 0: s = "ethaddr"; break; case 1: s = "eth1addr"; break; case 2: s = "eth2addr"; break; default: /* this should never happen */ printf ("%s: Invalid device number %d\n", __FUNCTION__, devnum); return; } temp = getenv_r (s, buf, sizeof (buf)); s = (temp > 0) ? buf : NULL;#ifdef DEBUG printf ("Setting MAC %d to %s\n", devnum, s);#endif for (x = 0; x < 6; ++x) { dev->enetaddr[x] = s ? simple_strtoul (s, &e, 16) : 0; if (s) s = (*e) ? e + 1 : e; } DP (printf ("Allocating descriptor and buffer rings\n")); ethernet_private->p_rx_desc_area_base[0] = (ETH_RX_DESC *) memalign (16, RX_DESC_ALIGNED_SIZE * MV64460_RX_QUEUE_SIZE + 1); ethernet_private->p_tx_desc_area_base[0] = (ETH_TX_DESC *) memalign (16, TX_DESC_ALIGNED_SIZE * MV64460_TX_QUEUE_SIZE + 1); ethernet_private->p_rx_buffer_base[0] = (char *) memalign (16, MV64460_RX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE + 1); ethernet_private->p_tx_buffer_base[0] = (char *) memalign (16, MV64460_RX_QUEUE_SIZE * MV64460_TX_BUFFER_SIZE + 1);#ifdef DEBUG_MV_ETH /* DEBUG OUTPUT prints adresses of globals */ print_globals (dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -