diff options
author | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-04-21 16:42:05 +0000 |
---|---|---|
committer | juhosg <juhosg@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2012-04-21 16:42:05 +0000 |
commit | d71e7bf38e5008e69b189970ff305f4c7fdc6c76 (patch) | |
tree | dd7e89527ff26840b7258151363f1130b95273c6 /target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch | |
parent | 7665f62dad0e34b18bb227aa478b3ba4abcd3af3 (diff) |
cns3xxx: remove 2.6.31 support
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@31418 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch')
-rw-r--r-- | target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch | 11802 |
1 files changed, 0 insertions, 11802 deletions
diff --git a/target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch b/target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch deleted file mode 100644 index 945edec6be..0000000000 --- a/target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch +++ /dev/null @@ -1,11802 +0,0 @@ ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_config.h -@@ -0,0 +1,136 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+#include <linux/version.h> -+ -+#ifndef CNS3XXX_CONFIG_H -+#define CNS3XXX_CONFIG_H -+ -+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27) -+#define LINUX2627 1 -+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) -+#define LINUX2631 1 -+#endif -+ -+ -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+#define CNS3XXX_VLAN_8021Q -+#endif -+ -+#ifdef CNS3XXX_VLAN_8021Q -+//#define CNS3XXX_NIC_MODE_8021Q // use NIC mode to support 8021Q -+ -+#endif -+ -+#define CONFIG_CNS3XXX_JUMBO_FRAME -+ -+#ifdef CONFIG_CNS3XXX_JUMBO_FRAME -+#define MAX_PACKET_LEN 9600 -+#else -+#define MAX_PACKET_LEN 1536 -+#endif -+ -+//#define CONFIG_SWITCH_BIG_ENDIAN -+ -+//#define CONFIG_FPGA_FORCE -+ -+//#define CNS3XXX_GIGA_MODE -+ -+#define CNS3XXX_SET_ARL_TABLE -+#define CNS3XXX_AGE_ENABLE -+#define CNS3XXX_LEARN_ENABLE -+#define CNS3XXX_CPU_PORT_FC -+#define CNS3XXX_CPU_MIB_COUNTER -+#define CNS3XXX_MAC0_MIB_COUNTER -+#define CNS3XXX_MAC1_MIB_COUNTER -+//#define CNS3XXX_MAC2_MIB_COUNTER -+//#define QOS_TEST -+//#define ACCEPT_CRC_BAD_PKT -+//#define CONFIG_FAST_BRIDGE -+//#define CONFIG_HOLP_TEST -+ -+ -+#define CONFIG_CNS3XXX_NAPI -+#ifdef CONFIG_CNS3XXX_NAPI -+#define CNS3XXX_NAPI_WEIGHT 64 -+#endif -+//#define CONFIG_NIC_MODE -+//#define CNS3XXX_TX_HW_CHECKSUM -+//#define CNS3XXX_RX_HW_CHECKSUM -+//#define CNS3XXX_STATUS_ISR -+//#define CNS3XXX_TEST_ONE_LEG_VLAN -+//#define CNS3XXX_TX_DSCP_PROC -+ -+ -+#define CNS3XXX_FSQF_RING0_ISR -+//#define CNS3XXX_TSTC_RING0_ISR -+//#define CNS3XXX_TSTC_RING1_ISR -+ -+//#define CNS3XXX_COMPARE_PACKET -+//#define CONFIG_FPGA_10 -+//#define CNS3XXX_CONFIG_SIM_MODE -+ -+#define CNS3XXX_8021Q_HW_TX -+ -+ -+#ifndef CONFIG_CNS3XXX_SPPE -+#define IVL // if no define, use SVL -+#endif -+//#define CNS3XXX_4N // if don't define it, use 4N+2 -+ -+//#define NCNB_TEST -+//#define CNS3XXX_TEST_D_CACHE -+#define CNS3XXX_FREE_TX_IN_RX_PATH -+ -+ -+//#define DEBUG_RX -+//#define DEBUG_TX -+//#define DEBUG_PRIO_IPDSCR -+#define DEBUG_RX_PROC -+#define DEBUG_TX_PROC -+//#define DEBUG_PHY_PROC -+#define CNS3XXX_PVID_PROC -+#define CNS3XXX_SARL_PROC -+ -+ -+//#define DOUBLE_RING_TEST -+ -+//#define CNS3XXX_DOUBLE_RX_RING -+//#define CNS3XXX_DOUBLE_TX_RING -+#define CNS3XXX_USE_MASK -+ -+#define CNS3XXX_CONFIG_CHANGE_TX_RING -+ -+#ifdef CNS3XXX_DOUBLE_RX_RING -+#define CNS3XXX_FSQF_RING1_ISR -+#endif -+ -+//#define CNS3XXX_DELAYED_INTERRUPT -+ -+#ifdef CNS3XXX_DELAYED_INTERRUPT -+#define MAX_PEND_INT_CNT 0x06 -+#define MAX_PEND_TIME 0x20 -+#endif -+ -+//#define CNS3XXX_ENABLE_RINT1 -+#endif ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_ethtool.c -@@ -0,0 +1,436 @@ -+/******************************************************************************* -+ * -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+//#include <linux/module.h> -+#include <linux/types.h> -+#include <linux/ethtool.h> -+#include <linux/netdevice.h> -+#include "cns3xxx_symbol.h" -+#include "cns3xxx.h" -+#include "cns3xxx_tool.h" -+ -+// ethtool support reference e100.c and e1000_ethtool.c . -+static void cns3xxx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info) -+{ -+ strcpy(info->driver, "cns3xxx"); -+ strcpy(info->version, DRV_VERSION); -+ strcpy(info->fw_version, "N/A"); -+ strcpy(info->bus_info, "N/A"); -+} -+ -+static void cns3xxx_get_ringparam(struct net_device *netdev, -+ struct ethtool_ringparam *ring) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ ring->rx_max_pending = priv->rx_ring->max_ring_size; -+ ring->tx_max_pending = priv->tx_ring->max_ring_size; -+ ring->rx_pending = priv->rx_ring->ring_size; -+ ring->tx_pending = priv->tx_ring->ring_size; -+#if 0 -+ struct nic *nic = netdev_priv(netdev); -+ struct param_range *rfds = &nic->params.rfds; -+ struct param_range *cbs = &nic->params.cbs; -+ -+ ring->rx_max_pending = rfds->max; -+ ring->tx_max_pending = cbs->max; -+ ring->rx_mini_max_pending = 0; -+ ring->rx_jumbo_max_pending = 0; -+ ring->rx_pending = rfds->count; -+ ring->tx_pending = cbs->count; -+ ring->rx_mini_pending = 0; -+ ring->rx_jumbo_pending = 0; -+#endif -+} -+ -+ -+ -+static int cns3xxx_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) -+{ -+ int cns3xxx_up(void); -+ int cns3xxx_down(void); -+ int cns3xxx_close(struct net_device *dev); -+ int cns3xxx_open(struct net_device *dev); -+ extern struct net_device *net_dev_array[]; -+ -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ int i=0; -+ -+#if 0 -+ struct nic *nic = netdev_priv(netdev); -+ struct param_range *rfds = &nic->params.rfds; -+ struct param_range *cbs = &nic->params.cbs; -+ -+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) -+ return -EINVAL; -+ -+ if(netif_running(netdev)) -+ e100_down(nic); -+ rfds->count = max(ring->rx_pending, rfds->min); -+ rfds->count = min(rfds->count, rfds->max); -+ cbs->count = max(ring->tx_pending, cbs->min); -+ cbs->count = min(cbs->count, cbs->max); -+ DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n", -+ rfds->count, cbs->count); -+ if(netif_running(netdev)) -+ e100_up(nic); -+ -+#endif -+ //ring->rx_max_pending = RX_DESC_SIZE; -+ //ring->tx_max_pending = TX_DESC_SIZE; -+ -+#if 0 -+ printk("ring->rx_max_pending: %d\n", ring->rx_max_pending); -+ printk("ring->tx_max_pending: %d\n", ring->tx_max_pending); -+ printk("ring->rx_pending: %d\n", ring->rx_pending); -+ printk("ring->tx_pending: %d\n", ring->tx_pending); -+#endif -+ -+ for (i=0 ; i < NETDEV_SIZE ; ++i) { -+ if(net_dev_array[i] && netif_running(net_dev_array[i])) { -+ //printk("close net_dev_array[%d]: %s\n", i, net_dev_array[i]); -+ cns3xxx_close(net_dev_array[i]); -+ } -+ } -+ -+ //cns3xxx_down(); -+ -+ priv->rx_ring->ring_size = min(ring->rx_pending, priv->rx_ring->max_ring_size); -+ priv->tx_ring->ring_size = min(ring->rx_pending, priv->tx_ring->max_ring_size); -+ -+ for (i=0 ; i < NETDEV_SIZE ; ++i) { -+ if(net_dev_array[i] && netif_running(net_dev_array[i])) { -+ //printk("open net_dev_array[%d]: %s\n", i, net_dev_array[i]); -+ cns3xxx_open(net_dev_array[i]); -+ } -+ } -+ //cns3xxx_up(); -+ -+ return 0; -+} -+ -+static uint32_t cns3xxx_get_tx_csum(struct net_device *netdev) -+{ -+ //return (netdev->features & NETIF_F_HW_CSUM) != 0; -+ return (netdev->features & NETIF_F_IP_CSUM) != 0; -+} -+ -+static int cns3xxx_set_tx_csum(struct net_device *netdev, uint32_t data) -+{ -+ if (data) -+ netdev->features |= NETIF_F_IP_CSUM; -+ else -+ netdev->features &= ~NETIF_F_IP_CSUM; -+ return 0; -+} -+ -+static uint32_t cns3xxx_get_rx_csum(struct net_device *netdev) -+{ -+ //struct e1000_adapter *adapter = netdev_priv(netdev); -+ //return adapter->rx_csum; -+ return 1; -+} -+ -+static int cns3xxx_set_rx_csum(struct net_device *netdev, uint32_t data) -+{ -+ return 0; -+} -+ -+u32 cns3xxx_get_sg(struct net_device *dev) -+{ -+#ifdef NETIF_F_SG -+ return (dev->features & NETIF_F_SG) != 0; -+#else -+ return 0; -+#endif -+} -+ -+int cns3xxx_set_sg(struct net_device *dev, u32 data) -+{ -+#ifdef NETIF_F_SG -+ if (data) -+ dev->features |= NETIF_F_SG; -+ else -+ dev->features &= ~NETIF_F_SG; -+#endif -+ -+ return 0; -+} -+ -+static void cns3xxx_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -+{ -+ u32 mac_port_config = 0; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ switch (priv->net_device_priv->which_port) -+ { -+ case MAC_PORT0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case MAC_PORT1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case MAC_PORT2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ -+ pause->autoneg = ( ((mac_port_config >> 7) & 1) ? AUTONEG_ENABLE : AUTONEG_DISABLE); -+ pause->tx_pause = (mac_port_config >> 6) & 1; -+ pause->rx_pause = (mac_port_config >> 5) & 1; -+} -+ -+static int cns3xxx_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause) -+{ -+ u32 mac_port_config = 0; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ switch (priv->net_device_priv->which_port) -+ { -+ case MAC_PORT0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case MAC_PORT1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case MAC_PORT2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ -+ mac_port_config &= ~(0x1 << 7); // clean AN -+ mac_port_config &= ~(0x1 << 11); // clean rx flow control -+ mac_port_config &= ~(0x1 << 12); // clean tx flow control -+ -+ mac_port_config |= ( (pause->autoneg << 7) | (pause->rx_pause << 11) | (pause->tx_pause << 12) ); -+ -+ -+ switch (priv->net_device_priv->which_port) -+ { -+ case MAC_PORT0: -+ { -+ MAC0_CFG_REG = mac_port_config; -+ break; -+ } -+ case MAC_PORT1: -+ { -+ MAC1_CFG_REG = mac_port_config; -+ break; -+ } -+ case MAC_PORT2: -+ { -+ MAC2_CFG_REG = mac_port_config; -+ break; -+ } -+ } -+ return 0; -+} -+ -+u32 cns3xxx_get_link(struct net_device *netdev) -+{ -+ u32 mac_port_config = 0; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ switch (priv->net_device_priv->which_port) -+ { -+ case MAC_PORT0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case MAC_PORT1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case MAC_PORT2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ return (mac_port_config & 1 ) ? 1 : 0; -+ //return netif_carrier_ok(dev) ? 1 : 0; -+} -+ -+ -+static int cns3xxx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -+{ -+ u8 value; -+ u32 mac_port_config = 0; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ -+ if (priv->net_device_priv->nic_setting == 0) { // connect to switch chip -+ -+ GET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config) -+ -+ ecmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full| SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_Pause); -+ -+ ecmd->duplex = ((mac_port_config >> 4) & 0x1) ? DUPLEX_FULL : DUPLEX_HALF ; -+ -+ value = ((mac_port_config >> 2) & 0x3); -+ switch (value) -+ { -+ case 0: -+ ecmd->speed = SPEED_10; -+ break; -+ case 1: -+ ecmd->speed = SPEED_100; -+ break; -+ case 2: -+ ecmd->speed = SPEED_1000; -+ break; -+ } -+ -+ ecmd->autoneg = ((mac_port_config >> 7) & 1) ? AUTONEG_ENABLE : AUTONEG_DISABLE; -+ -+ -+ -+ } else { // connect to PHY chip -+ -+ } -+ -+ return 0; -+} -+ -+// set speed and duplex -+int cns3xxx_set_spd_dplx(struct net_device *netdev, u16 spddplx) -+{ -+ u32 mac_port_config = 0; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ GET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config) -+ -+ //printk("mac_port_config: %x\n", mac_port_config); -+ -+ mac_port_config &= ~(0x3 << 8); // clear speed -+ mac_port_config &= ~(0x1 << 10); // clear duplex -+ mac_port_config &= ~(0x1 << 7); // disable AN -+ -+ switch (spddplx) { -+ case AUTONEG_ENABLE: -+ mac_port_config |= (0x1 << 7); // enable AN -+ break; -+ case SPEED_10 + DUPLEX_HALF: -+ printk("10, halt\n"); -+ mac_port_config |= (0 << 8); // set speed -+ mac_port_config |= (0 << 10); // set duplex -+ //printk("xxx mac_port_config: %x\n", mac_port_config); -+ break; -+ case SPEED_10 + DUPLEX_FULL: -+ mac_port_config |= (0 << 8); // set speed -+ mac_port_config |= (1 << 10); // set duplex -+ break; -+ case SPEED_100 + DUPLEX_HALF: -+ mac_port_config |= (1 << 8); // set speed -+ mac_port_config |= (0 << 10); // set duplex -+ break; -+ case SPEED_100 + DUPLEX_FULL: -+ mac_port_config |= (1 << 8); // set speed -+ mac_port_config |= (1 << 10); // set duplex -+ break; -+ case SPEED_1000 + DUPLEX_HALF: -+ mac_port_config |= (2 << 8); // set speed -+ mac_port_config |= (0 << 10); // set duplex -+ break; -+ case SPEED_1000 + DUPLEX_FULL: -+ mac_port_config |= (2 << 8); // set speed -+ mac_port_config |= (1 << 10); // set duplex -+ break; -+ default: -+ //printk("Unsupported Speed/Duplex configuration\n"); -+ return -EINVAL; -+ } -+ -+ SET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config) -+ -+ return 0; -+} -+ -+static int cns3xxx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -+{ -+ u8 value = 0; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ if (priv->net_device_priv->nic_setting == 0) { // connect to switch chip -+ if (ecmd->autoneg == AUTONEG_ENABLE) { -+ printk("autoneg\n"); -+ if ((value=cns3xxx_set_spd_dplx(netdev, AUTONEG_ENABLE)) != 0) { -+ return -EINVAL; -+ } -+ } else { -+ printk("no autoneg\n"); -+ if ((value=cns3xxx_set_spd_dplx(netdev, ecmd->speed + ecmd->duplex)) != 0) { -+ return -EINVAL; -+ } -+ -+ -+ } -+ -+ } else { // connect to PHY chip -+ -+ } -+ -+ // down then up -+ return 0; -+} -+ -+static const struct ethtool_ops cns3xxx_ethtool_ops = { -+ .get_drvinfo = cns3xxx_get_drvinfo, -+ .get_ringparam = cns3xxx_get_ringparam, -+ .set_ringparam = cns3xxx_set_ringparam, -+ .get_rx_csum = cns3xxx_get_rx_csum, -+ .set_rx_csum = cns3xxx_set_rx_csum, -+ .get_tx_csum = cns3xxx_get_tx_csum, -+ .set_tx_csum = cns3xxx_set_tx_csum, -+ .get_sg = cns3xxx_get_sg, -+ .set_sg = cns3xxx_set_sg, -+ .get_pauseparam = cns3xxx_get_pauseparam, -+ .set_pauseparam = cns3xxx_set_pauseparam, -+ .get_link = cns3xxx_get_link, -+ .get_settings = cns3xxx_get_settings, -+ .set_settings = cns3xxx_set_settings, -+}; -+ -+void cns3xxx_set_ethtool_ops(struct net_device *netdev) -+{ -+ SET_ETHTOOL_OPS(netdev, &cns3xxx_ethtool_ops); -+} ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx.h -@@ -0,0 +1,452 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+#ifndef CNS3XXX_H -+#define CNS3XXX_H -+ -+#include "cns3xxx_symbol.h" -+#include "cns3xxx_config.h" -+#include <linux/cns3xxx/switch_api.h> -+ -+#include <linux/module.h> -+#include <linux/init.h> -+#include <linux/kernel.h> -+#include <linux/bootmem.h> -+#include <linux/sched.h> -+#include <linux/types.h> -+#include <linux/fcntl.h> -+#include <linux/interrupt.h> -+#include <linux/ptrace.h> -+#include <linux/ioport.h> -+#include <linux/in.h> -+#include <linux/slab.h> -+#include <linux/init.h> -+#include <linux/proc_fs.h> -+#include <linux/reboot.h> -+#include <asm/bitops.h> -+#include <asm/irq.h> -+#include <asm/io.h> -+//#include <asm/hardware.h> -+#include <linux/pci.h> -+#include <linux/errno.h> -+#include <linux/delay.h> -+#include <linux/netdevice.h> -+#include <linux/etherdevice.h> -+#include <linux/skbuff.h> -+#include <linux/ip.h> -+#include <linux/if_ether.h> -+#include <linux/icmp.h> -+#include <linux/udp.h> -+#include <linux/tcp.h> -+#include <linux/if_arp.h> -+#include <net/arp.h> -+ -+ -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+#include <linux/if_vlan.h> -+#endif -+ -+//#define VERSION "1.0" -+ -+ -+typedef struct -+{ -+ int32_t sdp; // segment data pointer -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ u32 cown:1; -+ u32 eor:1; -+ u32 fsd:1; -+ u32 lsd:1; -+ u32 interrupt:1; -+ u32 fr:1; -+ u32 fp:1; // force priority -+ u32 pri:3; -+ u32 rsv_1:3; // reserve -+ u32 ico:1; -+ u32 uco:1; -+ u32 tco:1; -+ u32 sdl:16; // segment data length -+ -+#else -+ u32 sdl:16; // segment data length -+ u32 tco:1; -+ u32 uco:1; -+ u32 ico:1; -+ u32 rsv_1:3; // reserve -+ u32 pri:3; -+ u32 fp:1; // force priority -+ u32 fr:1; -+ u32 interrupt:1; -+ u32 lsd:1; -+ u32 fsd:1; -+ u32 eor:1; -+ u32 cown:1; -+#endif -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ u32 rsv_3:5; -+ u32 fewan:1; -+ u32 ewan:1; -+ u32 mark:3; -+ u32 pmap:5; -+ u32 rsv_2:9; -+ u32 dels:1; -+ u32 inss:1; -+ u32 sid:4; -+ u32 stv:1; -+ u32 ctv:1; -+#else -+ u32 ctv:1; -+ u32 stv:1; -+ u32 sid:4; -+ u32 inss:1; -+ u32 dels:1; -+ u32 rsv_2:9; -+ u32 pmap:5; -+ u32 mark:3; -+ u32 ewan:1; -+ u32 fewan:1; -+ u32 rsv_3:5; -+#endif -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ u32 s_pri:3; -+ u32 s_dei:1; -+ u32 s_vid:12; -+ u32 c_pri:3; -+ u32 c_cfs:1; -+ u32 c_vid:12; -+#else -+ u32 c_vid:12; -+ u32 c_cfs:1; -+ u32 c_pri:3; -+ u32 s_vid:12; -+ u32 s_dei:1; -+ u32 s_pri:3; -+#endif -+ -+ u8 alignment[16]; // for alignment 32 byte -+ -+} __attribute__((packed)) TXDesc; -+ -+typedef struct -+{ -+ u32 sdp; -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ u32 cown:1; -+ u32 eor:1; -+ u32 fsd:1; -+ u32 lsd:1; -+ u32 hr :6; -+ u32 prot:4; -+ u32 ipf:1; -+ u32 l4f:1; -+ u32 sdl:16; -+#else -+ u32 sdl:16; -+ u32 l4f:1; -+ u32 ipf:1; -+ u32 prot:4; -+ u32 hr :6; -+ u32 lsd:1; -+ u32 fsd:1; -+ u32 eor:1; -+ u32 cown:1; -+#endif -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ u32 rsv_3:11; -+ u32 ip_offset:5; -+ u32 rsv_2:1; -+ u32 tc:2; -+ u32 un_eth:1; -+ u32 crc_err:1; -+ u32 sp:3; -+ u32 rsv_1:2; -+ u32 e_wan:1; -+ u32 exdv:1; -+ u32 iwan:1; -+ u32 unv:1; -+ u32 stv:1; -+ u32 ctv:1; -+#else -+ u32 ctv:1; -+ u32 stv:1; -+ u32 unv:1; -+ u32 iwan:1; -+ u32 exdv:1; -+ u32 e_wan:1; -+ u32 rsv_1:2; -+ u32 sp:3; -+ u32 crc_err:1; -+ u32 un_eth:1; -+ u32 tc:2; -+ u32 rsv_2:1; -+ u32 ip_offset:5; -+ u32 rsv_3:11; -+#endif -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ u32 s_pri:3; -+ u32 s_dei:1; -+ u32 s_vid:12; -+ u32 c_pri:3; -+ u32 c_cfs:1; -+ u32 c_vid:12; -+#else -+ u32 c_vid:12; -+ u32 c_cfs:1; -+ u32 c_pri:3; -+ u32 s_vid:12; -+ u32 s_dei:1; -+ u32 s_pri:3; -+#endif -+ -+ u8 alignment[16]; // for alignment 32 byte -+ -+} __attribute__((packed)) RXDesc; -+ -+typedef struct { -+ TXDesc *tx_desc; -+ struct sk_buff *skb; // for free skb -+ u32 pri; -+ unsigned long j; -+ unsigned long tx_index; -+}TXBuffer; -+ -+typedef struct { -+ RXDesc *rx_desc; -+ struct sk_buff *skb; // rx path need to fill some skb field, ex: length ... -+#ifdef NCNB_TEST -+ u32 ncnb_index; -+#endif -+}RXBuffer; -+ -+ -+typedef struct { -+ TXBuffer *head; -+ TXDesc *tx_desc_head_vir_addr; -+ dma_addr_t tx_desc_head_phy_addr; -+ u32 cur_index; // for put send packet -+ spinlock_t tx_lock; -+ u32 non_free_tx_skb; -+ u32 free_tx_skb_index; -+ u32 ring_size; -+ u32 max_ring_size; -+}TXRing; -+ -+ -+typedef struct { -+ RXBuffer *head; -+ RXDesc *rx_desc_head_vir_addr; -+ dma_addr_t rx_desc_head_phy_addr; -+ u32 cur_index; -+ u32 ring_size; -+ u32 max_ring_size; -+}RXRing; -+ -+#if 0 -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ TXRing *tx_ring; -+ RXRing *rx_ring; -+}CNS3XXXRingStatus; -+#endif -+ -+ -+#define RX_RING0(priv) (priv->rx_ring[0]) -+#define TX_RING0(priv) (priv->tx_ring[0]) -+ -+ -+static inline u32 get_rx_ring_size(const RXRing *ring) -+{ -+ //printk("rx ring->ring_size: %d\n", ring->ring_size); -+ return ring->ring_size; -+} -+ -+static inline u32 get_tx_ring_size(TXRing *ring) -+{ -+ //printk("tx ring->ring_size: %d\n", ring->ring_size); -+ return ring->ring_size; -+} -+ -+static inline RXBuffer *get_rx_ring_head(const RXRing *rx_ring) -+{ -+ return rx_ring->head; -+} -+ -+static inline TXBuffer *get_tx_ring_head(TXRing *tx_ring) -+{ -+ return tx_ring->head; -+} -+ -+static inline RXBuffer *get_cur_rx_buffer(RXRing *rx_ring) -+{ -+ return rx_ring->head + rx_ring->cur_index; -+} -+ -+static inline TXBuffer *get_cur_tx_buffer(TXRing *tx_ring) -+{ -+ return tx_ring->head + tx_ring->cur_index; -+} -+ -+static inline u32 get_rx_head_phy_addr(RXRing *rx_ring) -+{ -+ return rx_ring->rx_desc_head_phy_addr; -+} -+ -+static inline u32 get_tx_ring_head_phy_addr(TXRing *tx_ring) -+{ -+ return tx_ring->tx_desc_head_phy_addr; -+} -+ -+ -+static inline u32 get_rx_cur_index(RXRing *rx_ring) -+{ -+ return rx_ring->cur_index; -+} -+ -+static inline u32 get_tx_cur_index(TXRing *tx_ring) -+{ -+ return tx_ring->cur_index; -+} -+ -+static inline u32 get_tx_cur_phy_addr(u8 ring_num) -+{ -+ if (ring_num == 0) -+ return TS_DESC_PTR0_REG; -+ if (ring_num == 1) -+ return TS_DESC_PTR1_REG; -+ return 0; // fail -+} -+ -+static inline void rx_index_next(RXRing *ring) -+{ -+ ring->cur_index = ((ring->cur_index + 1) % ring->ring_size); -+} -+static inline void tx_index_next(TXRing *ring) -+{ -+ ring->cur_index = ((ring->cur_index + 1) % ring->ring_size); -+} -+ -+ -+ -+struct CNS3XXXPrivate_; -+ -+typedef int (*RXFuncPtr)(struct sk_buff *skb, RXDesc*tx_desc_ptr, const struct CNS3XXXPrivate_* ); -+typedef int (*TXFuncPtr)(TXDesc*tx_desc_ptr, const struct CNS3XXXPrivate_*, struct sk_buff *); -+typedef void (*OpenPtr)(void); -+typedef void (*ClosePtr)(void); -+ -+ -+// for ethtool set operate -+typedef struct{ -+ -+}NICSetting; -+ -+typedef struct{ -+ int pmap; // for port base, force route -+ int is_wan; // mean the net device is WAN side. -+ //u16 gid; -+ u16 s_tag; -+ //u8 mac_type; // VLAN base, or port base; -+ u16 vlan_tag; -+ -+ // do port base mode and vlan base mode work -+ RXFuncPtr rx_func; -+ TXFuncPtr tx_func; -+ OpenPtr open; -+ ClosePtr close; -+ u8 which_port; -+ //NICSetting *nic_setting; -+ u8 *mac; // point to a mac address array -+ VLANTableEntry *vlan_table_entry; -+ ARLTableEntry *arl_table_entry; -+ NICSetting *nic_setting; -+ const char *name; // 16 bytes, reference include/linux/netdevice.h IFNAMSIZ -+}NetDevicePriv; -+ -+typedef struct -+{ -+ u8 num_rx_queues; -+ u8 num_tx_queues; -+ TXRing *tx_ring; -+ RXRing *rx_ring; -+}RingInfo; -+ -+ -+/* store this information for the driver.. */ -+typedef struct CNS3XXXPrivate_ -+{ -+ u8 num_rx_queues; -+ u8 num_tx_queues; -+ TXRing *tx_ring; -+ RXRing *rx_ring; -+ struct net_device_stats stats; -+ spinlock_t lock; -+ int pmap; -+ int is_wan; // mean the net device is WAN side. -+ u16 gid; -+ u8 mac_type; // VLAN base, or port base; -+ u16 vlan_tag; -+ struct napi_struct napi; -+ struct work_struct reset_task; -+ -+ u8 which_port; -+ //NICSetting *nic_setting; -+ char name[IFNAMSIZ]; // 16 bytes, reference include/linux/netdevice.h IFNAMSIZ -+ -+ -+ NetDevicePriv *net_device_priv; -+ u8 ring_index; -+ -+ u32 rx_s_vid[4096]; // record receive s vid (0x9100 ...) -+ u32 rx_c_vid[4096]; // record receive c vid (0x8100 ...) -+#ifdef CONFIG_CNS3XXX_NAPI -+ volatile unsigned long is_qf; // determine rx ring queue full state -+#endif -+ -+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) -+ struct vlan_group *vlgrp; -+#endif -+}CNS3XXXPrivate; -+ -+ -+ -+ -+int rx_port_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv); -+ -+int rx_vlan_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv); -+ -+int tx_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb); -+ -+ -+int tx_vlan_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb); -+#if defined (CONFIG_CNS3XXX_SPPE) -+int fp_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb); -+#endif -+#endif -+ ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_main.c -@@ -0,0 +1,3949 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+#include <linux/module.h> -+#include <mach/board.h> -+#include <linux/platform_device.h> -+#include "cns3xxx.h" -+#include "cns3xxx_tool.h" -+#include "cns3xxx_config.h" -+ -+#if defined (CONFIG_CNS3XXX_SPPE) -+#include <linux/cns3xxx/sppe.h> -+#define PACKET_REASON_TO_CPU (0x2C) -+#endif -+ -+#define RX_SDP_ALIGN 64 -+ -+#ifdef CONFIG_FPGA -+#include "fpga.h" -+#endif -+ -+#ifdef CONFIG_VB -+#include "vb.h" -+#endif -+ -+#define CPU_CACHE_BYTES 64 -+#define CPU_CACHE_ALIGN(X) (((X) + (CPU_CACHE_BYTES-1)) & ~(CPU_CACHE_BYTES-1)) -+ -+ -+#define QUEUE_WEIGHT_SET(port, ctl) \ -+{ \ -+ MAC##port##_PRI_CTRL_REG &= ~(0x3ffff); \ -+ MAC##port##_PRI_CTRL_REG |= (ctl.sch_mode << 16); \ -+ MAC##port##_PRI_CTRL_REG |= (ctl.q0_w); \ -+ MAC##port##_PRI_CTRL_REG |= (ctl.q1_w << 4); \ -+ MAC##port##_PRI_CTRL_REG |= (ctl.q2_w << 8); \ -+ MAC##port##_PRI_CTRL_REG |= (ctl.q3_w << 12); \ -+} -+ -+#define QUEUE_WEIGHT_GET(port, ctl) \ -+{ \ -+ ctl.sch_mode = ((MAC##port##_PRI_CTRL_REG >> 16 ) & 0x3); \ -+ ctl.q0_w = ((MAC##port##_PRI_CTRL_REG >> 0 ) & 0x7); \ -+ ctl.q1_w = ((MAC##port##_PRI_CTRL_REG >> 4 ) & 0x7); \ -+ ctl.q2_w = ((MAC##port##_PRI_CTRL_REG >> 8 ) & 0x7); \ -+ ctl.q3_w = ((MAC##port##_PRI_CTRL_REG >> 12 ) & 0x7); \ -+} -+ -+int cns3xxx_send_packet(struct sk_buff *skb, struct net_device *netdev); -+static int install_isr_rc = 0; -+static int rc_setup_rx_tx = 0; // rc means reference counting. -+static struct net_device *intr_netdev; -+struct net_device *net_dev_array[NETDEV_SIZE]; -+spinlock_t tx_lock; -+spinlock_t rx_lock; -+u8 fast_bridge_en=1; -+u8 show_rx_proc=0; -+u8 show_tx_proc=0; -+ -+int init_port=7; // bit map 7 means port 0, 1 and 2, default is 7. -+//module_param(init_port, u8, S_IRUGO); -+module_param(init_port, int, 0); -+ -+u8 ring_index=0; // 0 or 1 -+ -+#ifdef CNS3XXX_DELAYED_INTERRUPT -+static u32 max_pend_int_cnt=MAX_PEND_INT_CNT, max_pend_time=MAX_PEND_TIME; -+#endif -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+struct net_device *napi_dev; -+ #ifdef CNS3XXX_DOUBLE_RX_RING -+ struct net_device *r1_napi_dev; // ring1 napi dev -+ #endif -+#endif -+ -+const u32 MAX_RX_DESC_SIZE = 512; -+const u32 MAX_TX_DESC_SIZE = 512; -+const u32 RX_DESC_SIZE = 128; -+//const u32 RX_DESC_SIZE = 5; -+const u32 TX_DESC_SIZE = 120; -+ -+//RXRing *rx_ring; -+//TXRing *tx_ring; -+ -+// only for debug (proc) -+RingInfo g_ring_info; -+ -+int MSG_LEVEL = NORMAL_MSG; -+ -+#ifdef CNS3XXX_STATUS_ISR -+const char *cns3xxx_gsw_status_tbl[] = { -+ "\nMAC0_Q_FULL\n", -+ "\nMAC1_Q_FULL\n", -+ "\nCPU_Q_FULL\n", -+ "\nHNAT_Q_FULL\n", -+ "\nMAC2_Q_FULL\n", -+ "\nMAC0_Q_EXT_FULL\n", -+ "\nGLOBAL_Q_FULL\n", -+ "\nBUFFER_FULL\n", -+ "\nMIB_COUNTER_TH\n", -+ "\n", // 9 -+ "\nMAC0_INTRUDER\n", -+ "\nMAC1_INTRUDER\n", -+ "\nCPU_INTRUDER\n", -+ "\nMAC2_INTRUDER\n", -+ "\nMAC0_STATUS_CHG\n", -+ "\nMAC1_STATUS_CHG\n", -+ "\nMAC2_STATUS_CHG\n", -+ "\nMAC0_NO_LINK_DROP\n", -+ "\nMAC1_NO_LINK_DROP\n", -+ "\nMAC2_NO_LINK_DROP\n", -+ "\nMAC0_RX_ERROR_DROP\n", -+ "\nMAC1_RX_ERROR_DROP\n", -+ "\nMAC2_RX_ERROR_DROP\n", -+ "\nMAC0_NO_DESTINATION_DROP\n", -+ "\nMAC1_NO_DESTINATION_DROP\n", -+ "\nMAC2_NO_DESTINATION_DROP\n", -+ "\nMAC0_RMC_PAUSE_DROP\n", -+ "\nMAC1_RMC_PAUSE_DROP\n", -+ "\nMAC2_RMC_PAUSE_DROP\n", -+ "\nMAC0_LOCAL_DROP\n", -+ "\nMAC1_LOCAL_DROP\n", -+ "\nMAC2_LOCAL_DROP\n", -+}; -+#endif -+ -+#define MIN_PACKET_LEN 14 -+ -+void cns3xxx_write_pri_mask(u8 pri_mask); -+ -+static int cns3xxx_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr); -+ -+static struct notifier_block cns3xxx_notifier_reboot = { -+ .notifier_call = cns3xxx_notify_reboot, -+ .next = NULL, -+ .priority = 0 -+}; -+ -+#if defined(CNS3XXX_VLAN_8021Q) -+void cns3xxx_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid); -+void cns3xxx_vlan_rx_register(struct net_device *dev, struct vlan_group *grp); -+#endif -+ -+void take_off_vlan_header(struct sk_buff *skb) -+{ -+ // take off VLAN header -+ memmove(skb->data + 4, skb->data, 12); -+#if 0 -+ //skb_ptr->data += 4; -+ skb_reserve(skb, 4); -+#else -+ skb->data += 4; -+#endif -+ skb->len -= 4; // minus 4 byte vlan tag -+} -+ -+int rx_port_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv) -+{ -+ if (skb->data[12] == 0x81 && skb->data[13] == 0x00) // VLAN header -+ { -+ take_off_vlan_header(skb); -+ print_packet(skb->data, skb->len); -+ } -+ return 0; -+} -+ -+int rx_vlan_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv) -+{ -+ return 0; -+} -+ -+int tx_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb) -+{ -+#if defined(CNS3XXX_VLAN_8021Q) && defined (CNS3XXX_8021Q_HW_TX) -+ if (skb && priv->vlgrp != NULL && vlan_tx_tag_present(skb)) -+ { -+ tx_desc_ptr->c_vid = cpu_to_le16(vlan_tx_tag_get(skb)); -+ tx_desc_ptr->ctv=1; -+ tx_desc_ptr->fr = 0; -+ -+ } -+ else -+#endif -+ { -+ tx_desc_ptr->ctv = 0; -+ tx_desc_ptr->pmap = priv->net_device_priv->pmap; -+ tx_desc_ptr->fr = 1; -+ } -+ -+ return 0; -+} -+ -+ -+int tx_vlan_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb) -+{ -+#if defined(CNS3XXX_VLAN_8021Q) -+ -+ if (skb && priv->vlgrp != NULL && vlan_tx_tag_present(skb)) { -+ tx_desc_ptr->c_vid = cpu_to_le16(vlan_tx_tag_get(skb)); -+ } -+#else -+ tx_desc_ptr->c_vid = priv->net_device_priv->vlan_tag; -+ -+#endif -+ tx_desc_ptr->ctv=1; -+ tx_desc_ptr->fr = 0; -+ -+ return 0; -+} -+ -+#if defined (CONFIG_CNS3XXX_SPPE) -+int fp_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb) -+{ -+#if 1 -+ tx_desc_ptr->fr = 1; -+ tx_desc_ptr->pmap = 0x8; -+#else -+ tx_desc_ptr->fr = 0; -+ tx_desc_ptr->ctv = 1; -+ tx_desc_ptr->c_vid = 80; -+#endif -+ return 0; -+} -+#endif -+ -+static inline struct sk_buff *cns3xxx_alloc_skb(void) -+{ -+ struct sk_buff *skb; -+ u32 align_64; -+ -+ skb = dev_alloc_skb(MAX_PACKET_LEN + 2 + RX_SDP_ALIGN); -+ -+ if (unlikely(!skb)) { -+ return NULL; -+ } -+ pci_dma_sync_single_for_device(NULL, virt_to_phys(skb->data), MAX_PACKET_LEN+2+RX_SDP_ALIGN, PCI_DMA_FROMDEVICE); -+ -+ align_64=CPU_CACHE_ALIGN((u32)skb->data); -+ skb_reserve(skb, align_64-(u32)skb->data); /* 16 bytes alignment */ -+ -+#ifndef CNS3XXX_4N -+ skb_reserve(skb, NET_IP_ALIGN); /* 16 bytes alignment */ -+#endif -+ -+ -+ -+ return skb; -+} -+ -+static int free_rx_skb(RXRing *rx_ring) -+{ -+ int i=0; -+ RXBuffer *rx_buffer = rx_ring->head; -+ //RXDesc *rx_desc = rx_ring.rx_desc_head_vir_addr; -+ -+ for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) { -+ if (rx_buffer->rx_desc->cown==0 && rx_buffer->skb) { -+ dev_kfree_skb(rx_buffer->skb); -+ rx_buffer->skb=0; -+ } -+ } -+ return 0; -+} -+ -+int cns3xxx_setup_all_rx_resources(RXRing *rx_ring, u8 ring_num) -+{ -+ int i=0; -+ RXBuffer *rx_buffer = 0; -+ RXDesc *rx_desc = 0; -+ -+#ifdef NCNB_TEST -+ ncnb_buf = dma_alloc_coherent(NULL, 2*1024* get_rx_ring_size(rx_ring), &ncnb_buf_phy, GFP_KERNEL); -+ printk("NCB_BUF: %08X PHY: %08X \n", ncnb_buf, ncnb_buf_phy); -+ -+#endif -+ -+ // alloc RXDesc array -+ rx_ring->rx_desc_head_vir_addr = dma_alloc_coherent(NULL, sizeof(RXDesc) * (get_rx_ring_size(rx_ring)), &rx_ring->rx_desc_head_phy_addr, GFP_KERNEL); -+ if (!rx_ring->rx_desc_head_vir_addr) { -+ return -ENOMEM; -+ } -+ -+ memset(rx_ring->rx_desc_head_vir_addr, 0, sizeof(RXDesc) * get_rx_ring_size(rx_ring)); -+ -+ // alloc RXBuffer array -+ rx_ring->head = kmalloc(sizeof(RXBuffer) * get_rx_ring_size(rx_ring), GFP_KERNEL); -+ -+ if (!rx_ring->head) { -+ return -ENOMEM; -+ } -+ -+ rx_buffer = rx_ring->head; -+ for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) { -+ rx_buffer->skb=0; -+ ++rx_buffer; -+ } -+ -+ rx_buffer = rx_ring->head; -+ rx_desc = rx_ring->rx_desc_head_vir_addr; -+ for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i, ++rx_buffer, ++rx_desc) { -+ rx_buffer->rx_desc = rx_desc; -+ rx_buffer->skb = cns3xxx_alloc_skb(); -+ -+ if (!rx_buffer->skb) { -+ -+ free_rx_skb(rx_ring); -+ kfree(rx_ring->head); -+ dma_free_coherent(NULL, sizeof(RXDesc) * get_rx_ring_size(rx_ring), rx_ring->rx_desc_head_vir_addr, rx_ring->rx_desc_head_phy_addr); -+ return -ENOMEM; -+ } -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ { -+ RXDesc tmp_rx_desc; -+ -+ memset(&tmp_rx_desc, 0, sizeof(RXDesc)); -+ tmp_rx_desc.sdp = (u32)virt_to_phys(rx_buffer->skb->data); -+ tmp_rx_desc.sdl = MAX_PACKET_LEN; -+ if (i == (get_rx_ring_size(rx_ring)-1) ){ -+ tmp_rx_desc.eor = 1; -+ } -+ tmp_rx_desc.fsd = 1; -+ tmp_rx_desc.lsd = 1; -+ swap_rx_desc(&tmp_rx_desc, rx_buffer->rx_desc); -+ } -+ -+#else -+ rx_buffer->rx_desc->sdp = (u32)virt_to_phys(rx_buffer->skb->data); -+ rx_buffer->rx_desc->sdl = MAX_PACKET_LEN; -+ if (i == (get_rx_ring_size(rx_ring)-1) ){ -+ rx_buffer->rx_desc->eor = 1; -+ } -+ rx_buffer->rx_desc->fsd = 1; -+ rx_buffer->rx_desc->lsd = 1; -+#endif -+ -+ } -+ rx_ring->cur_index = 0 ; -+ -+ if (ring_num == 0){ -+ FS_DESC_PTR0_REG = rx_ring->rx_desc_head_phy_addr; -+ FS_DESC_BASE_ADDR0_REG = rx_ring->rx_desc_head_phy_addr; -+ -+ } else if (ring_num == 1){ -+ FS_DESC_PTR1_REG = rx_ring->rx_desc_head_phy_addr; -+ FS_DESC_BASE_ADDR1_REG = rx_ring->rx_desc_head_phy_addr; -+ } -+ -+ return CAVM_OK; -+} -+ -+static int cns3xxx_setup_all_tx_resources(TXRing *tx_ring, u8 ring_num) -+{ -+ int i=0; -+ TXBuffer *tx_buffer = 0; -+ TXDesc *tx_desc = 0; -+ -+ -+ spin_lock_init(&(tx_ring->tx_lock)); -+ -+ tx_ring->tx_desc_head_vir_addr = dma_alloc_coherent(NULL, sizeof(TXDesc) * get_tx_ring_size(tx_ring), &tx_ring->tx_desc_head_phy_addr, GFP_KERNEL); -+ if (!tx_ring->tx_desc_head_vir_addr) { -+ return -ENOMEM; -+ } -+ -+ memset(tx_ring->tx_desc_head_vir_addr, 0, sizeof(TXDesc) * get_tx_ring_size(tx_ring)); -+ tx_ring->head = kmalloc(sizeof(TXBuffer) * get_tx_ring_size(tx_ring), GFP_KERNEL); -+ -+ tx_buffer = tx_ring->head; -+ tx_desc = tx_ring->tx_desc_head_vir_addr; -+ for (i=0 ; i < get_tx_ring_size(tx_ring) ; ++i, ++tx_buffer, ++tx_desc) { -+ tx_buffer->tx_desc = tx_desc; -+ -+ tx_buffer->tx_desc->cown = 1; -+ tx_buffer->skb = 0; -+ if (i == (get_tx_ring_size(tx_ring)-1) ){ -+ tx_buffer->tx_desc->eor = 1; -+ } -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ swap_tx_desc(tx_buffer->tx_desc, tx_buffer->tx_desc); -+#endif -+ -+ } -+ -+ tx_ring->cur_index = 0 ; -+ -+ if (ring_num == 0){ -+ TS_DESC_PTR0_REG = tx_ring->tx_desc_head_phy_addr; -+ TS_DESC_BASE_ADDR0_REG = tx_ring->tx_desc_head_phy_addr; -+ } else if (ring_num == 1){ -+ TS_DESC_PTR1_REG = tx_ring->tx_desc_head_phy_addr; -+ TS_DESC_BASE_ADDR1_REG = tx_ring->tx_desc_head_phy_addr; -+ } -+ return CAVM_OK; -+} -+ -+int cns3xxx_free_all_rx_resources(RXRing *rx_ring) -+{ -+ free_rx_skb(rx_ring); -+ kfree(rx_ring->head); -+ dma_free_coherent(NULL, sizeof(RXDesc) * get_rx_ring_size(rx_ring), rx_ring->rx_desc_head_vir_addr, rx_ring->rx_desc_head_phy_addr); -+ return 0; -+} -+ -+static int free_tx_skb(TXRing *tx_ring) -+{ -+ int i=0; -+ TXBuffer *tx_buffer = tx_ring->head; -+ -+ for (i=0 ; i < get_tx_ring_size(tx_ring) ; ++i) { -+ if (tx_buffer->skb) { -+ dev_kfree_skb(tx_buffer->skb); -+ tx_buffer->skb = 0; -+ } -+ } -+ return 0; -+} -+ -+int cns3xxx_free_all_tx_resources(TXRing *tx_ring) -+{ -+ free_tx_skb(tx_ring); -+ kfree(tx_ring->head); -+ dma_free_coherent(NULL, sizeof(TXDesc) * get_tx_ring_size(tx_ring), tx_ring->tx_desc_head_vir_addr, tx_ring->tx_desc_head_phy_addr); -+ return 0; -+} -+ -+static int cns3xxx_free_rx_tx_res(CNS3XXXPrivate *priv) -+{ -+ int i=0; -+ -+ --rc_setup_rx_tx; -+ if (rc_setup_rx_tx == 0) { -+ enable_port(3, 0); // disable cpu port -+ -+ // stop RX/TX ring0 dma -+ enable_rx_dma(0, 0); -+ enable_tx_dma(0, 0); -+ -+ for (i=0 ; i < priv->num_rx_queues ; ++i) { -+ cns3xxx_free_all_rx_resources(priv->rx_ring+i); -+ memset(priv->rx_ring + i, 0, sizeof(RXRing)); -+ } -+ -+ for (i=0 ; i < priv->num_tx_queues ; ++i) { -+ cns3xxx_free_all_tx_resources(priv->tx_ring+i); -+ memset(priv->tx_ring + i, 0, sizeof(TXRing)); -+ } -+ -+ } -+ return 0; -+} -+ -+ -+static int cns3xxx_setup_rx_tx_res(CNS3XXXPrivate *priv) -+{ -+ int i=0; -+ -+ if (rc_setup_rx_tx == 0) { -+ clear_fs_dma_state(1); -+ FS_DESC_PTR0_REG = 0; -+ FS_DESC_BASE_ADDR0_REG = 0; -+ FS_DESC_PTR1_REG = 0; -+ FS_DESC_BASE_ADDR1_REG = 0; -+ TS_DESC_PTR0_REG = 0; -+ TS_DESC_BASE_ADDR0_REG = 0; -+ TS_DESC_PTR1_REG = 0; -+ TS_DESC_BASE_ADDR1_REG = 0; -+ -+ for (i=0 ; i < priv->num_tx_queues ; ++i) { -+ spin_lock_init(&((priv->tx_ring+i)->tx_lock)); -+ (priv->tx_ring+i)->max_ring_size = MAX_TX_DESC_SIZE; -+ (priv->tx_ring+i)->ring_size = TX_DESC_SIZE; -+ if (cns3xxx_setup_all_tx_resources(priv->tx_ring+i, i) != CAVM_OK) -+ return CAVM_ERR; -+ } -+ -+ for (i=0 ; i < priv->num_rx_queues ; ++i) { -+ (priv->rx_ring+i)->max_ring_size = MAX_RX_DESC_SIZE; -+ (priv->rx_ring+i)->ring_size = RX_DESC_SIZE; -+ if (cns3xxx_setup_all_rx_resources(priv->rx_ring+i, i) != CAVM_OK) -+ return CAVM_ERR; -+ -+ } -+ clear_fs_dma_state(0); -+ } -+ ++rc_setup_rx_tx; -+ return CAVM_OK; -+} -+ -+int free_tx_desc_skb(TXRing *tx_ring, u8 ring_num) -+{ -+#if 1 -+ int i=0; -+ //u32 tssd_current=0; -+ TXBuffer *tx_buffer = 0; -+ u32 tx_ring_size = get_tx_ring_size(tx_ring); -+ // check curent hw index previous tx descriptor -+ u32 cur_index = cns3xxx_get_tx_hw_index(ring_num) - 1; -+ -+ tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index); -+ -+ -+ //while (1) -+ for (i=0 ; i < tx_ring_size ; ++i) { -+ if (tx_buffer->tx_desc->cown == 1 && tx_buffer->skb) { -+ dev_kfree_skb_any(tx_buffer->skb); -+ tx_buffer->skb=0; -+ //tx_buffer->tx_desc->cown == 1; -+ } else { -+ break; -+ } -+ // --tx_desc_pair_ptr -+ --cur_index; -+ tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index); -+ -+ } -+#endif -+ return 0; -+} -+ -+void do_arl_lookup(void) -+{ -+} -+ -+inline void assign_netdev(RXBuffer volatile *rx_buffer) -+{ -+ RXDesc * rx_desc=0; -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ RXDesc tmp_rx_desc; -+ rx_desc = &tmp_rx_desc; -+ swap_rx_desc(rx_buffer->rx_desc, rx_desc); -+#else -+ rx_desc = rx_buffer->rx_desc; -+#endif -+ -+ -+#if defined(CONFIG_CNS3XXX_PORT_BASE) || defined(CNS3XXX_VLAN_8021Q) -+ // sp: -+ // 0 - mac port 0 -+ // 1 - mac port 1 -+ // 4 - mac port 2 -+ -+ switch (rx_desc->sp) -+ { -+ case 0: -+ { -+ rx_buffer->skb->dev = PORT0_NETDEV; -+ break; -+ } -+ case 1: -+ { -+ rx_buffer->skb->dev = PORT1_NETDEV; -+ break; -+ } -+ case 4: -+ { -+ rx_buffer->skb->dev = PORT2_NETDEV; -+ break; -+ } -+ -+ } -+#endif -+ -+#ifdef CONFIG_CNS3XXX_VLAN_BASE -+{ -+ u16 vlan_tag; -+ -+ vlan_tag = rx_desc->c_vid; -+ rx_buffer->skb->dev = net_dev_array[vlan_tag]; -+ -+} -+#endif -+ -+} -+ -+#if defined(CNS3XXX_VLAN_8021Q) -+static int cns3xxx_vlan_rx(CNS3XXXPrivate *priv, struct sk_buff *skb, u16 vlan_tag) -+{ -+ return vlan_hwaccel_receive_skb(skb, priv->vlgrp, vlan_tag); -+} -+#endif -+ -+// old_priv has ring index information, current version only uses the information. -+static int cns3xxx_get_rfd_buff(RXBuffer volatile *rx_buffer, CNS3XXXPrivate *old_priv) -+{ -+ CNS3XXXPrivate *priv=0; -+ //RXDesc volatile *rxdesc_ptr = rx_buffer->rx_desc; -+ struct sk_buff *skb; -+ //unsigned char *data; -+ u32 len; -+ RXDesc *rx_desc; -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ -+ RXDesc tmp_rx_desc; -+ -+ rx_desc = &tmp_rx_desc; -+ swap_rx_desc(rx_buffer->rx_desc, rx_desc); -+ -+#else -+ rx_desc = rx_buffer->rx_desc; -+#endif -+ -+ //rxdesc_ptr = rxring.vir_addr + index; -+ skb = rx_buffer->skb; -+ len = rx_desc->sdl; -+ -+ -+#ifdef DEBUG_RX -+ if (MSG_LEVEL == DUMP_RX_PKT_INFO) { -+ print_packet(skb->data, len); -+ } -+ -+#endif -+ -+ pci_dma_sync_single_for_device(NULL, virt_to_phys(skb->data), len, PCI_DMA_FROMDEVICE); -+#if defined (CONFIG_CNS3XXX_SPPE) -+ if (PACKET_REASON_TO_CPU == rx_buffer->rx_desc->hr) { -+ if (sppe_pci_fp_ready) { -+ SPPE_PARAM param; -+ int pci_dev_index; -+ struct iphdr *iph; -+ -+ skb_put(skb, len); -+ iph = (struct iphdr *)(skb->data + sizeof(struct ethhdr)); -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ param.cmd = SPPE_CMD_ARP; -+ param.op = SPPE_OP_GET; -+ param.data.sppe_arp.ip[0] = iph->daddr; -+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) { -+ goto NOT_IN_PCI_FP; -+ } else { -+ pci_dev_index = param.data.sppe_arp.unused_1; -+ } -+ param.cmd = SPPE_CMD_PCI_FP_DEV; -+ param.op = SPPE_OP_GET; -+ param.data.sppe_pci_fp_dev.dev = NULL; -+ param.data.sppe_pci_fp_dev.index = pci_dev_index; -+ if (SPPE_RESULT_SUCCESS != sppe_pci_fp_hook(¶m)) { -+ goto NOT_IN_PCI_FP; -+ } else { -+ skb->dev = param.data.sppe_pci_fp_dev.dev; -+ } -+ #if 1 -+ dev_queue_xmit(skb); -+ #else -+ skb->dev->hard_start_xmit(skb, skb->dev); -+ #endif -+ -+ return 0; -+ } -+ } -+NOT_IN_PCI_FP: -+#endif -+ -+#ifdef CNS3XXX_NON_NIC_MODE_8021Q -+ if (cns3xxx_is_untag_packet(rx_desc) == 1) -+ take_off_vlan_header(skb); -+#endif -+ -+#ifdef CONFIG_CNS3XXX_PORT_BASE -+ assign_netdev(rx_buffer); -+ -+ if (rx_buffer->skb->dev) // if skb->dev is 0, means VLAN base -+ goto determine_dev_ok; -+ -+#endif /* CONFIG_CNS3XXX_PORT_BASE */ -+ -+ -+#ifdef CONFIG_CNS3XXX_VLAN_BASE -+ -+#ifdef CONFIG_HAVE_VLAN_TAG -+ -+#if defined(CNS3XXX_VLAN_8021Q) -+ // some funcion need netdev like eth_type_trans(), so need to assign it. -+ skb->dev = intr_netdev; -+ // 8021Q module will determine right netdev by vlan tag. -+#else // defined(CNS3XXX_VLAN_8021Q) -+ { -+ assign_netdev(rx_buffer); -+ -+ take_off_vlan_header(skb); -+ if (MSG_LEVEL == 5) -+ print_packet(skb->data, 32); -+ -+ if ( rx_buffer->skb->dev == 0){ -+ goto freepacket; -+ } -+ } -+ -+#endif // CNS3XXX_VLAN_8021Q -+ -+#else /* CONFIG_HAVE_VLAN_TAG */ -+ -+#ifdef CNS3XXX_RX_DESC_VLAN_INFO -+// get VLAN information by RX descriptor field -+ -+#endif -+ -+#endif // CONFIG_HAVE_VLAN_TAG -+ -+#endif // CONFIG_CNS3XXX_VLAN_BASE -+ -+ -+#ifdef CONFIG_CNS3XXX_PORT_BASE -+determine_dev_ok: -+#endif -+ -+ skb_put(skb, len); -+ -+ if (skb->dev) { -+ priv = netdev_priv(skb->dev); -+ } -+ else{ -+ DEBUG_MSG(WARNING_MSG, "skb_ptr->dev==NULL\n"); -+ goto freepacket; -+ } -+ -+#ifdef CNS3XXX_RX_HW_CHECKSUM -+ switch (rx_desc->prot) -+ { -+ case 1 : -+ case 2 : -+ case 5 : -+ case 6 : -+ { -+ if ( rx_desc->l4f == 0) { // tcp/udp checksum is correct -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } else { -+ skb->ip_summed = CHECKSUM_NONE; -+ } -+ break; -+ } -+ default: -+ { -+ skb->ip_summed = CHECKSUM_NONE; -+ break; -+ } -+ } -+#else -+ skb->ip_summed = CHECKSUM_NONE; -+#endif // CNS3XXX_RX_HW_CHECKSUM -+ -+ -+ // this line must, if no, packet will not send to network layer -+#ifdef CONFIG_FAST_BRIDGE -+ if (fast_bridge_en == 0) -+#endif -+ skb->protocol = eth_type_trans(skb, skb->dev); -+ -+ skb->dev->last_rx = jiffies; -+ priv->stats.rx_packets++; -+ priv->stats.rx_bytes += len; -+ -+#ifdef CONFIG_FAST_BRIDGE -+ if (fast_bridge_en == 1) { -+ -+ skb->ip_summed = CHECKSUM_NONE; -+ if ( skb->dev == PORT0_NETDEV) { -+ skb->dev = PORT1_NETDEV; -+ } else if ( skb->dev == PORT1_NETDEV) { -+ skb->dev = PORT0_NETDEV; -+ } -+ //skb->dev->hard_start_xmit(skb, skb->dev); -+ cns3xxx_send_packet(skb, skb->dev); -+ } else { -+#endif // #ifdef CONFIG_FAST_BRIDGE -+ -+ -+//#if defined(CNS3XXX_VLAN_8021Q) -+#if 0 -+ if (priv->vlgrp != NULL) -+ { -+ //cns3xxx_vlan_rx(priv, skb, rx_buffer->rx_desc->c_vid); -+ cns3xxx_vlan_rx(priv, skb, rx_buffer->rx_desc->c_vid); -+ //cns3xxx_vlan_rx(priv, skb, swab16(le32_to_cpu(rx_buffer->rx_desc->c_vid)) ); -+ } -+ else -+#else -+ #ifdef CONFIG_CNS3XXX_NAPI -+ netif_receive_skb(skb); -+ #else -+ netif_rx(skb); -+ #endif -+#endif -+ -+#ifdef CONFIG_FAST_BRIDGE -+ } -+#endif -+ -+ //vlan_hwaccel_receive_skb(skb, priv->vlgrp, 1); -+ -+ return 0; -+ -+freepacket: -+ //DEBUG_MSG(NORMAL_MSG, "freepacket\n"); -+ dev_kfree_skb_any(skb); -+ return 0; -+} -+ -+// index from 1 -+inline u32 get_rx_hw_index(CNS3XXXPrivate *priv) -+{ -+ return ((FS_DESC_PTR0_REG - get_rx_head_phy_addr(&RX_RING0(priv))) / sizeof(RXDesc) ); -+} -+ -+inline int get_rx_hw_index_by_reg(u8 ring_num) -+{ -+ if (ring_num == 0 ) { -+ return ((FS_DESC_PTR0_REG - FS_DESC_BASE_ADDR0_REG) / sizeof(RXDesc) ); -+ } else if (ring_num == 1 ) { -+ return ((FS_DESC_PTR1_REG - FS_DESC_BASE_ADDR1_REG) / sizeof(RXDesc) ); -+ } -+ -+ return CAVM_FAIL; -+} -+ -+void dump_rxring(void) -+{ -+ int j=0; -+ RXBuffer *rx_buffer = 0; -+ -+ rx_buffer = get_rx_ring_head(g_ring_info.rx_ring+0); -+ for (j=0 ; j < get_rx_ring_size(g_ring_info.rx_ring+0); ++j, ++rx_buffer) { -+ printk("[%d] ## rx_buffer->rx_desc->cown: %d\n", j, rx_buffer->rx_desc->cown); -+ } -+} -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+void cns3xxx_receive_packet(CNS3XXXPrivate *priv, int mode, int *work_done, int work_to_do) -+#else -+void cns3xxx_receive_packet(CNS3XXXPrivate *priv, int mode) -+#endif -+{ -+ int fssd_index; -+ //int fssd_current; -+ RXBuffer volatile *rx_buffer = 0; -+ RXDesc volatile *rx_desc=0; -+ struct sk_buff *skb; -+#ifndef CONFIG_CNS3XXX_NAPI -+ int fsqf = 0; // Queue Full Mode =0 -+#endif -+ int i, rxcount = 0; -+ u8 queue_index = priv->ring_index; -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ RXDesc tmp_rx_desc; -+#endif -+ -+ rx_buffer = get_cur_rx_buffer(&(priv->rx_ring[queue_index])); -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ rx_desc = &tmp_rx_desc; -+ swap_rx_desc(rx_buffer->rx_desc, rx_desc); -+#else -+ rx_desc = rx_buffer->rx_desc; -+#endif -+ -+ fssd_index = get_rx_hw_index_by_reg(queue_index); -+ -+ if (fssd_index > get_rx_cur_index(&priv->rx_ring[queue_index]) ) { -+ rxcount = fssd_index - get_rx_cur_index(&priv->rx_ring[queue_index]); -+ } else if (fssd_index < get_rx_cur_index(&priv->rx_ring[queue_index])) { -+ rxcount = (get_rx_ring_size(&priv->rx_ring[queue_index]) - get_rx_cur_index(&priv->rx_ring[queue_index]) ) + fssd_index; -+ } else { // fssd_index == rxring.cur_index -+ if (rx_desc->cown == 0) { // if rx_desc->cown is 1, we can receive the RX descriptor. -+ enable_rx_dma(0, 1); -+ goto receive_packet_exit; -+ } else { -+ // Queue Full -+#ifndef CONFIG_CNS3XXX_NAPI -+ fsqf = 1; -+#endif -+ rxcount = get_rx_ring_size(&priv->rx_ring[queue_index]); -+ } -+ } -+#ifndef CONFIG_CNS3XXX_NAPI -+ if (mode == 1) { -+ fsqf = 1; -+ rxcount = get_rx_ring_size(&priv->rx_ring[queue_index]); -+ } -+#endif -+ -+#ifdef CNS3XXX_FREE_TX_IN_RX_PATH -+ free_tx_desc_skb(priv->tx_ring + 0, 0); -+#ifdef CNS3XXX_DOUBLE_TX_RING -+ free_tx_desc_skb(priv->tx_ring + 1, 1); -+#endif -+#endif -+ -+ for (i = 0; i < rxcount; i++) { -+ -+ if (rx_desc->cown != 0) { // start to get packet -+ // Alloc New skb_buff -+ skb = cns3xxx_alloc_skb(); -+ // Check skb_buff -+ if (skb) { -+ cns3xxx_get_rfd_buff(rx_buffer, priv); -+ rx_buffer->skb = skb; -+#ifndef NCNB_TEST -+ rx_desc->sdp = (u32)virt_to_phys(skb->data); -+#endif -+ rx_desc->sdl = MAX_PACKET_LEN; -+ rx_desc->fsd = 1; -+ rx_desc->lsd = 1; -+ rx_desc->cown = 0; // set cbit to 0 -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ swap_rx_desc(rx_desc, rx_buffer->rx_desc); -+#endif -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+ ++(*work_done); -+ if (*work_done >= work_to_do) { -+ -+ rx_index_next(&priv->rx_ring[queue_index]); // rx_ring.cur_index points to next -+ rx_buffer = get_cur_rx_buffer(&priv->rx_ring[queue_index]); -+ rx_desc = rx_buffer->rx_desc; -+ break; -+ } -+#endif -+ -+ } else { -+ // I will add dev->lp.stats->rx_dropped, it will effect the performance -+ //PDEBUG("%s: Alloc sk_buff fail, reuse the buffer\n", __FUNCTION__); -+ rx_desc->cown = 0; // set cbit to 0 -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ swap_rx_desc(rx_desc, rx_buffer->rx_desc); -+#endif -+ -+ return; -+ } -+ } else { // cown is 0, no packets -+ //*work_done = 0; -+ return; -+ } -+ -+ -+ rx_index_next(&priv->rx_ring[queue_index]); // rx_ring.cur_index points to next -+ rx_buffer = get_cur_rx_buffer(&priv->rx_ring[queue_index]); -+ rx_desc = rx_buffer->rx_desc; -+ -+ } // end for (i = 0; i < rxcount; i++) -+ -+ -+#ifndef CONFIG_CNS3XXX_NAPI -+ if (fsqf) { -+ priv->rx_ring[queue_index].cur_index = fssd_index; -+ mb(); -+ enable_rx_dma(0, 1); -+ } -+#endif -+ -+ -+ //spin_unlock(&rx_lock); -+receive_packet_exit: -+ return; -+} -+ -+irqreturn_t cns3xxx_fsrc_ring0_isr(int irq, void *dev_id) -+{ -+ struct net_device *netdev = dev_id; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ -+ priv->ring_index=0; -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+{ -+ CNS3XXXPrivate *priv = netdev_priv(napi_dev); -+ priv->ring_index=0; -+ -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xb0); -+#else -+ cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID); -+#endif -+ -+ //if (likely(netif_rx_schedule_prep(napi_dev, &priv->napi))) { -+ if (likely(napi_schedule_prep(&priv->napi))) { -+ //__netif_rx_schedule(napi_dev, &priv->napi); -+ __napi_schedule(&priv->napi); -+ } else { -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xf0); -+#else -+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID); -+#endif -+ } -+} -+#else // !CONFIG_CNS3XXX_NAPI -+ -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xb0); -+#else -+ cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID); -+ cns3xxx_disable_irq(FSQF_RING0_INTERRUPT_ID); -+#endif -+ -+ cns3xxx_receive_packet(priv, 0); // Receive Once -+ -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xf0); -+#else -+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID); -+ cns3xxx_enable_irq(FSQF_RING0_INTERRUPT_ID); -+#endif -+ enable_rx_dma(0, 1); -+#endif -+ -+ return IRQ_HANDLED; -+} -+ -+ -+#if defined(CNS3XXX_DOUBLE_RX_RING) -+irqreturn_t cns3xxx_fsrc_ring1_isr(int irq, void *dev_id) -+{ -+ struct net_device *netdev = dev_id; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ priv->ring_index=1; -+ -+ -+#if defined(CONFIG_CNS3XXX_NAPI) && defined(CNS3XXX_DOUBLE_RX_RING) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(r1_napi_dev); -+ priv->ring_index=1; -+ -+ cns3xxx_disable_irq(FSRC_RING1_INTERRUPT_ID); -+ -+ if (likely(napi_schedule_prep(&priv->napi))) { -+ __napi_schedule(&priv->napi); -+ } else { -+ cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID); -+ } -+} -+#else -+ -+ cns3xxx_disable_irq(CNS3XXX_FSRC_RING1_INTERRUPT_ID); -+ cns3xxx_disable_irq(CNS3XXX_FSQF_RING1_INTERRUPT_ID); -+ cns3xxx_receive_packet(priv, 0); // Receive Once -+ enable_rx_dma(1, 1); -+ -+ cns3xxx_enable_irq(CNS3XXX_FSRC_RING1_INTERRUPT_ID); -+ cns3xxx_enable_irq(CNS3XXX_FSQF_RING1_INTERRUPT_ID); -+#endif -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+int cns3xxx_check_enough_tx_descriptor(TXRing *tx_ring, int need_free_tx_desc) -+{ -+#if 1 -+ int i=0; -+ TXDesc *tx_desc=0; -+ u32 cur_index = get_tx_cur_index(tx_ring); -+ TXBuffer *tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index); -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ TXDesc tmp_tx_desc; -+ tx_desc = &tmp_tx_desc; -+ swap_tx_desc(tx_buffer->tx_desc, tx_desc); -+#else -+ tx_desc = tx_buffer->tx_desc; -+#endif -+ -+ -+ for (i=0 ; i < need_free_tx_desc ; ++i) { -+ if ( tx_desc->cown == 0 ) { -+ return 0; // no free TX descriptor -+ } -+ tx_buffer = get_tx_buffer_by_index(tx_ring, ++cur_index); -+ } -+#endif -+ return 1; -+} -+ -+// if return CAVM_ERR, means pad is fail, the packet cannot send by switch. -+ -+int fill_a_skb_to_tx_desc(TXBuffer * tx_buffer, u8 *data, int len, struct sk_buff *skb, const struct CNS3XXXPrivate_ *priv, int sg, int fsd, int lsd) -+{ -+ //TXDesc *tx_desc_ptr = tx_buffer->tx_desc; -+ static int tt=0; -+ -+ TXDesc *tx_desc_ptr = 0; -+#ifdef CONFIG_SWTICH_BIG_ENDIAN -+ TXDesc tmp_tx_desc; -+ tx_desc_ptr = &tmp_tx_desc; -+ swap_tx_desc(tx_buffer->tx_desc, tx_desc_ptr); -+#else -+ tx_desc_ptr = tx_buffer->tx_desc; -+#endif -+ -+ -+ -+ if (tx_buffer->skb) { -+ dev_kfree_skb_any(tx_buffer->skb); -+ tx_buffer->skb = 0 ; -+ } else { -+ //++tx_ring.non_free_tx_skb; -+ } -+ -+ tx_buffer->skb = skb; /* for free skb */ -+ tx_desc_ptr->sdp = virt_to_phys(data); -+ tx_buffer->j = tt; -+ tx_buffer->tx_index = cns3xxx_get_tx_hw_index(0); -+ ++tt; -+ -+#if 0 -+ { -+ static u16 previous_sn_num=10; -+ u16 sn_num=0; -+ u16 e_type=0; -+ -+ memcpy(&e_type, skb->data + 12, 2); -+ e_type = be16_to_cpu(e_type); -+ -+ if (e_type == 0x0800) { -+ memcpy(&sn_num, skb->data + 0x28, 2); -+ sn_num = be16_to_cpu(sn_num); -+ -+ if ( previous_sn_num == sn_num) -+ printk("dup\n"); -+ -+ previous_sn_num = sn_num; -+ } -+ -+ } -+#endif -+ -+ -+#ifdef CNS3XXX_TX_HW_CHECKSUM -+ tx_desc_ptr->ico = 1; -+ tx_desc_ptr->uco = 1; -+ tx_desc_ptr->tco = 1; -+#else -+ tx_desc_ptr->ico = 0; -+ tx_desc_ptr->uco = 0; -+ tx_desc_ptr->tco = 0; -+#endif -+ // Wake interrupt -+#ifdef CNS3XXX_TSTC_RING0_ISR -+ tx_desc_ptr->interrupt = 1; -+#else -+ tx_desc_ptr->interrupt = 0; -+#endif -+ -+ /* fill 0 to MIN_PACKET_LEN size */ -+ // can change MIN_PACKET_LEN to 14 -+ if (sg==0 && len < MIN_PACKET_LEN) { -+ if (skb_padto(skb, MIN_PACKET_LEN)) -+ return CAVM_ERR; -+ -+ //memset(skb->data + len, 0, MIN_PACKET_LEN - len); -+ //skb->len = MIN_PACKET_LEN; -+ tx_desc_ptr->sdl = MIN_PACKET_LEN; -+ } else { -+ tx_desc_ptr->sdl = len; -+ } -+ -+ dma_cache_maint(data, tx_desc_ptr->sdl, PCI_DMA_TODEVICE); -+ -+ /* VLAN base or port base function to set TX descriptor */ -+ /* reference: tx_//port_base(), tx_vlan_base() */ -+ priv->net_device_priv->tx_func(tx_desc_ptr, priv, skb); -+ tx_desc_ptr->fsd = fsd; -+ tx_desc_ptr->lsd = lsd; -+ -+ /* NOT SG packet */ -+ if( fsd == 1 && lsd == 1) -+ tx_desc_ptr->cown = 0; -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+ swap_tx_desc(tx_desc_ptr, tx_buffer->tx_desc); -+#endif -+ -+ return CAVM_OK; -+} -+ -+int cns3xxx_send_packet(struct sk_buff *skb, struct net_device *netdev) -+{ -+ -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ TXBuffer *tx_buffer = 0; -+ unsigned long flags; -+ int nr_frags =skb_shinfo(skb)->nr_frags; -+ -+ TXDesc *tx_desc[10]; // FIXME: ensure to maximum sg size -+ int tx_desc_count=0; -+ int i=0; -+ -+#ifdef DEBUG_TX -+ if (MSG_LEVEL == DUMP_TX_PKT_INFO) { -+ print_packet(tx_buffer->skb->data, tx_buffer->tx_desc->sdl); -+ //dump_tx_desc(tx_buffer->tx_desc); -+ } -+#endif -+ -+ spin_lock_irqsave(&tx_lock, flags); -+ -+ if (cns3xxx_check_enough_tx_descriptor(priv->tx_ring + ring_index, (nr_frags==0 ) ? 1 : nr_frags) == 0) { -+ // no enough tx descriptor -+ spin_unlock_irqrestore(&tx_lock, flags); -+ // re-queue the skb -+ return NETDEV_TX_BUSY; -+ } -+ -+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index); -+ -+ if (nr_frags == 0) { // non scatter/gather I/O -+ -+ fill_a_skb_to_tx_desc(tx_buffer, skb->data, skb->len, skb, priv, 0, 1, 1); -+ -+ tx_index_next(priv->tx_ring + ring_index); -+ -+ } else { // scatter/gather I/O -+ struct skb_frag_struct *frag = 0; -+ -+ -+ fill_a_skb_to_tx_desc(tx_buffer, skb->data, skb->len - skb->data_len, 0, priv, 1, 1, 0); -+ tx_desc[tx_desc_count++] = tx_buffer->tx_desc; -+ tx_index_next(priv->tx_ring + ring_index); -+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index); -+ -+ for (i=0 ; i < nr_frags-1 ; ++i) { -+ frag = &skb_shinfo(skb)->frags[i]; -+ -+ fill_a_skb_to_tx_desc(tx_buffer, page_address(frag->page) + frag->page_offset, frag->size, 0, priv, 1, 0, 0); -+ tx_desc[tx_desc_count++] = tx_buffer->tx_desc; -+ -+ tx_index_next(priv->tx_ring + ring_index); -+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index); -+ } -+ frag = &skb_shinfo(skb)->frags[nr_frags-1]; -+ -+ // last fragment -+ fill_a_skb_to_tx_desc(tx_buffer, page_address(frag->page) + frag->page_offset, frag->size, skb, priv, 1, 0, 1); -+ tx_desc[tx_desc_count++] = tx_buffer->tx_desc; -+ -+ tx_index_next(priv->tx_ring + ring_index); -+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index); -+ } -+ -+ -+ if( nr_frags != 0) { -+ -+ for (i = 0; i < tx_desc_count ; i++ ) -+ tx_desc[i]->cown = 0 ; -+ } -+ -+ mb(); -+ enable_tx_dma(ring_index, 1); -+ -+ priv->stats.tx_packets++; -+ priv->stats.tx_bytes += skb->len; -+ netdev->trans_start = jiffies; -+ -+ spin_unlock_irqrestore(&tx_lock, flags); -+ return NETDEV_TX_OK; -+} -+ -+ -+#ifdef CNS3XXX_FSQF_RING0_ISR -+irqreturn_t cns3xxx_fsqf_ring0_isr(int irq, void *dev_id) -+{ -+#ifndef CONFIG_CNS3XXX_NAPI -+ struct net_device *netdev = dev_id; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+#endif -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+{ -+ CNS3XXXPrivate *priv = netdev_priv(napi_dev); -+ // because in normal state, fsql only invoke once and set_bit is atomic function. -+ // so I don't mask it. -+ set_bit(0, &priv->is_qf); -+} -+#else -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xb0); -+#else -+ cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID); -+ cns3xxx_disable_irq(FSQF_RING0_INTERRUPT_ID); -+#endif -+ -+ -+ cns3xxx_receive_packet(priv, 1); // Receive at Queue Full Mode -+ -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xf0); -+#else -+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID); -+ cns3xxx_enable_irq(FSQF_RING0_INTERRUPT_ID); -+#endif -+ -+ enable_rx_dma(0, 1); -+#endif // CONFIG_CNS3XXX_NAPI -+ -+ return IRQ_HANDLED; -+} -+#endif -+ -+ -+#if defined(CNS3XXX_DOUBLE_RX_RING) -+#ifdef CNS3XXX_FSQF_RING1_ISR -+irqreturn_t cns3xxx_fsqf_ring1_isr(int irq, void *dev_id) -+{ -+ struct net_device *netdev = dev_id; -+ CNS3XXXPrivate *priv = netdev_priv(netdev); -+ //INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSQF_BIT_INDEX); -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+{ -+ CNS3XXXPrivate *priv = netdev_priv(r1_napi_dev); -+ // because in normal state, fsqf only invoke once and set_bit is atomic function. -+ // so don't mask it. -+ set_bit(0, &priv->is_qf); -+} -+#else -+ cns3xxx_disable_irq(FSRC_RING1_INTERRUPT_ID); -+ cns3xxx_disable_irq(FSQF_RING1_INTERRUPT_ID); -+ -+ cns3xxx_receive_packet(priv, 1); // Receive at Queue Full Mode -+ enable_rx_dma(1, 1); -+ -+ cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID); -+ cns3xxx_enable_irq(FSQF_RING1_INTERRUPT_ID); -+#endif -+ return IRQ_HANDLED; -+} -+#endif -+#endif //#if defined(CNS3XXX_DOUBLE_RX_RING) -+ -+ -+#ifdef CNS3XXX_STATUS_ISR -+irqreturn_t cns3xxx_status_isr(int irq, void *dev_id) -+{ -+ u32 int_status = INTR_STAT_REG; -+ u32 i=0; -+ -+ cns3xxx_disable_irq(STATUS_INTERRUPT_ID); -+ for (i = 0; i < 32; i++) { -+ if (int_status & (1 << i)) { -+ PRINT_INFO(cns3xxx_gsw_status_tbl[i]); -+ } -+ } -+ INTR_STAT_REG = 0xffffffff; // write 1 for clear. -+ cns3xxx_enable_irq(STATUS_INTERRUPT_ID); -+ return IRQ_HANDLED; -+} -+#endif -+ -+ -+#ifdef CNS3XXX_TSTC_RING0_ISR -+irqreturn_t cns3xxx_tstc_ring0_isr(int irq, void *dev_id) -+{ -+ return IRQ_HANDLED; -+} -+#endif -+ -+ -+static int cns3xxx_install_isr(struct net_device *dev) -+{ -+ int retval; -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ -+ if (install_isr_rc == 0) { -+ -+ retval = request_irq(FSRC_RING0_INTERRUPT_ID, cns3xxx_fsrc_ring0_isr, IRQF_SHARED, "FSRC_RING0", intr_netdev); -+ -+ if (retval) { -+ return 1; -+ } -+ -+#ifdef CNS3XXX_FSQF_RING0_ISR -+ retval = request_irq(FSQF_RING0_INTERRUPT_ID, cns3xxx_fsqf_ring0_isr, IRQF_SHARED, "FSQF_RING0", intr_netdev); -+ -+ if (retval) { -+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "FSQF_RING0", FSQF_RING0_INTERRUPT_ID, retval); -+ return 2; -+ } -+#endif -+ -+#ifdef CNS3XXX_TSTC_RING0_ISR -+ retval = request_irq(TSTC_RING0_INTERRUPT_ID, cns3xxx_tstc_ring0_isr, IRQF_SHARED, "TSTC_RING0", intr_netdev); -+ -+ if (retval) { -+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "TSTC_RING0", FSQF_RING0_INTERRUPT_ID, retval); -+ return 3; -+ } -+ -+#endif -+ -+ -+ if (priv->num_rx_queues == 2) { -+#if defined(CNS3XXX_DOUBLE_RX_RING) -+ retval = request_irq(FSRC_RING1_INTERRUPT_ID, cns3xxx_fsrc_ring1_isr, IRQF_SHARED, "FSRC_RING1", intr_netdev); -+ -+ if (retval) { -+ return 1; -+ } -+ -+#ifdef CNS3XXX_FSQF_RING1_ISR -+ retval = request_irq(FSQF_RING1_INTERRUPT_ID, cns3xxx_fsqf_ring1_isr, IRQF_SHARED, "FSQF_RING1", intr_netdev); -+ -+ if (retval) { -+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "FSQF_RING1", FSQF_RING1_INTERRUPT_ID, retval); -+ return 2; -+ } -+#endif -+ -+#endif -+ } -+ -+#ifdef CNS3XXX_STATUS_ISR -+ retval = request_irq(STATUS_INTERRUPT_ID, cns3xxx_status_isr, IRQF_SHARED, "GSW_STATUS", intr_netdev); -+ -+ if (retval) { -+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "GSW STATUS INT", STATUS_INTERRUPT_ID, retval); -+ return 3; -+ } -+ INTR_MASK_REG = 0; -+#endif -+ -+ -+ -+ -+ -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+{ -+ CNS3XXXPrivate *sp = netdev_priv(napi_dev); -+ napi_enable(&sp->napi); -+ netif_start_queue(napi_dev); -+ -+#ifdef CNS3XXX_DOUBLE_RX_RING -+ sp = netdev_priv(r1_napi_dev); -+ napi_enable(&sp->napi); -+ netif_start_queue(r1_napi_dev); -+#endif -+} -+#endif -+ // enable cpu port -+ enable_port(3, 1); -+ -+ } // end if (install_isr_rc == 0) -+ -+ ++install_isr_rc; -+ -+ return 0; -+} -+ -+ -+int cns3xxx_open(struct net_device *dev) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ //static int init_state=0; -+ -+ if (cns3xxx_setup_rx_tx_res(priv) != CAVM_OK) { -+ return -1; -+ } -+ -+ netif_start_queue(dev); -+ priv->net_device_priv->open(); -+ -+ cns3xxx_install_isr(dev); -+ -+ enable_rx_dma(0, 1); -+ -+ if (priv->num_rx_queues == 2) -+ enable_rx_dma(1, 1); -+ -+ netif_carrier_on(dev); -+ -+ return 0; -+} -+ -+static int cns3xxx_uninstall_isr(struct net_device *dev) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ --install_isr_rc; -+ if (install_isr_rc == 0) { -+ enable_port(3, 0); -+ free_irq(FSRC_RING0_INTERRUPT_ID, intr_netdev); -+#ifdef CNS3XXX_STATUS_ISR -+ free_irq(STATUS_INTERRUPT_ID, intr_netdev); -+#endif -+ -+#ifdef CNS3XXX_FSQF_RING0_ISR -+ free_irq(FSQF_RING0_INTERRUPT_ID, intr_netdev); -+#endif -+ -+#ifdef CNS3XXX_TSTC_RING0_ISR -+ free_irq(TSTC_RING0_INTERRUPT_ID, intr_netdev); -+#endif -+ -+ if (priv->num_rx_queues == 2) { -+ free_irq(FSRC_RING1_INTERRUPT_ID, intr_netdev); -+ -+#ifdef CNS3XXX_FSQF_RING1_ISR -+ free_irq(FSQF_RING1_INTERRUPT_ID, intr_netdev); -+#endif -+ } -+ -+ -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+{ -+ CNS3XXXPrivate *sp = netdev_priv(napi_dev); -+ -+ napi_disable(&sp->napi); -+ netif_stop_queue(napi_dev); -+#ifdef CNS3XXX_DOUBLE_RX_RING -+ sp = netdev_priv(r1_napi_dev); -+ -+ napi_disable(&sp->napi); -+ netif_stop_queue(r1_napi_dev); -+#endif -+} -+#endif -+ -+ -+ } -+ -+ return 0; -+} -+ -+int cns3xxx_close(struct net_device *dev) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ -+ enable_rx_dma(0, 0); -+ enable_tx_dma(0, 0); -+ -+ if (priv->num_rx_queues == 2) -+ enable_tx_dma(1, 0); -+ -+ if (priv->num_tx_queues == 2) -+ enable_rx_dma(1, 0); -+ -+ netif_stop_queue(dev); -+ -+ priv->net_device_priv->close(); -+ cns3xxx_uninstall_isr(dev); -+ cns3xxx_free_rx_tx_res(priv); -+ netif_carrier_off(dev); -+ return 0; -+} -+ -+ -+ -+//#define MAC_PORT(p) MAC##p##_CFG_REG -+ -+void broadcast_storm_cfg(u8 port, u8 boradcast, u8 multicast, u8 unknown) -+{ -+ switch (port) -+ { -+ case 0: -+ { -+ (boradcast == 1) ? (MAC0_CFG_REG |= (1 << 30)) : (MAC0_CFG_REG &= (~(1 << 30))) ; -+ (multicast == 1) ? (MAC0_CFG_REG |= (1 << 29)) : (MAC0_CFG_REG &= (~(1 << 29))) ; -+ (unknown == 1) ? (MAC0_CFG_REG |= (1 << 28)) : (MAC0_CFG_REG &= (~(1 << 28))) ; -+ break; -+ } -+ case 1: -+ { -+ (boradcast == 1) ? (MAC1_CFG_REG |= (1 << 30)) : (MAC1_CFG_REG &= (~(1 << 30))) ; -+ (multicast == 1) ? (MAC1_CFG_REG |= (1 << 29)) : (MAC1_CFG_REG &= (~(1 << 29))) ; -+ (unknown == 1) ? (MAC1_CFG_REG |= (1 << 28)) : (MAC1_CFG_REG &= (~(1 << 28))) ; -+ break; -+ } -+ case 2: -+ { -+ (boradcast == 1) ? (MAC2_CFG_REG |= (1 << 30)) : (MAC2_CFG_REG &= (~(1 << 30))) ; -+ (multicast == 1) ? (MAC2_CFG_REG |= (1 << 29)) : (MAC2_CFG_REG &= (~(1 << 29))) ; -+ (unknown == 1) ? (MAC2_CFG_REG |= (1 << 28)) : (MAC2_CFG_REG &= (~(1 << 28))) ; -+ break; -+ } -+ } -+} -+ -+void broadcast_storm_rate(u8 rate) -+{ -+ TC_CTRL_REG &= (~(0xf << 24)); -+ TC_CTRL_REG |= (rate << 24); -+} -+ -+// port: 0, 1, 2 ; port0, port1 and port2 -+// config general mac port configuration -+void cns3xxx_general_mac_cfg(u8 port) -+{ -+ u32 cfg=0; -+ -+ switch (port) -+ { -+ case 0: -+ { -+ cfg = MAC0_CFG_REG; -+ break; -+ } -+ case 1: -+ { -+ cfg = MAC1_CFG_REG; -+ break; -+ } -+ case 2: -+ { -+ cfg = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ -+ // txc_check_en: 1 -+ cfg |= (1 << 13); -+ -+ // bp_en: 1 -+ cfg |= (1 << 17); -+ -+#ifdef CNS3XXX_LEARN_ENABLE -+ // learn_dis: 0 -+ cfg &= (~(1 << 19)); -+#else -+ // learn disable -+ cfg |= (1 << 19); -+#endif -+ -+ // blocking_state: 0 -+ cfg &= (~(1 << 20)); -+ -+ // block_mode: 0 -+ cfg &= (~(1 << 21)); -+ -+#ifdef CNS3XXX_AGE_ENABLE -+ // age_en: 1 -+ cfg |= (1 << 22); -+ -+#else -+ // age disable -+ cfg &= (~(1 << 22)); -+#endif -+ -+ // SA_secured: 0 -+ cfg &= (~(1 << 23)); -+ -+ switch (port) -+ { -+ case 0: -+ { -+ MAC0_CFG_REG = cfg; -+ break; -+ } -+ case 1: -+ { -+ MAC1_CFG_REG = cfg; -+ break; -+ } -+ case 2: -+ { -+ MAC2_CFG_REG = cfg; -+ break; -+ } -+ } -+ -+} -+ -+void cns3xxx_configu_cpu_port(void) -+{ -+ // Set CPU port to general configuration -+ -+#ifdef CNS3XXX_LEARN_ENABLE -+ CPU_CFG_REG &= (~(1 << 19)); -+#else -+ // learn_dis: 1 -+ CPU_CFG_REG |= (1 << 19); -+#endif -+ -+#ifdef CNS3XXX_AGE_ENABLE -+ // age_en: 1 -+ CPU_CFG_REG |= (1 << 22); -+#else -+ // age disable -+ CPU_CFG_REG &= (~(1 << 22)); -+#endif -+ -+ // SA_secured: 0 -+ CPU_CFG_REG &= (~(1 << 23)); -+ -+ // go to hnat:1 -+ CPU_CFG_REG |= (1 << 29); -+ -+ //offset 4N +2 -+ CPU_CFG_REG &= (~(1 << 30)); -+#ifdef CNS3XXX_4N -+ CPU_CFG_REG |= (1 << 30); -+#endif -+ -+ // cpu flow control disable -+ CPU_CFG_REG &= (~(1 << 31)); -+#ifdef CNS3XXX_CPU_PORT_FC -+ // cpu flow control enable -+ CPU_CFG_REG |= (1 << 31); -+#endif -+ -+} -+ -+static void __init cns3xxx_gsw_hw_init(void) -+{ -+ //u32 mac_port_config; -+ int i; -+ //u32 cfg_reg = 0; -+ u32 reg_config = 0; -+ -+#ifdef CONFIG_SILICON -+ -+ //GPIOB_PIN_EN_REG |= (1 << 14); //enable GMII2_CRS -+ //GPIOB_PIN_EN_REG |= (1 << 15); //enable GMII2_COL -+ GPIOB_PIN_EN_REG |= (1 << 20); //enable MDC -+ GPIOB_PIN_EN_REG |= (1 << 21); //enable MDIO -+ -+ cns3xxx_gsw_power_enable(); -+ cns3xxx_gsw_software_reset(); -+#endif -+ -+#ifdef CNS3XXX_CONFIG_SIM_MODE -+ SLK_SKEW_CTRL_REG |= (1 << 31); -+#endif -+ -+ -+#if 1 -+ while (((SRAM_TEST_REG >> 20) & 1) == 0); -+#endif -+ -+ clear_fs_dma_state(1); -+ -+ -+ // disable port mac0, mac1, mac2, cpu port -+ enable_port(0, 0); -+ enable_port(1, 0); -+ enable_port(2, 0); -+ enable_port(3, 0); -+ -+ // disable RX0/TX0 RX1/TX1 DMA -+ enable_tx_dma(0, 0); -+ enable_tx_dma(1, 0); -+ enable_rx_dma(0, 0); -+ enable_rx_dma(1, 0); -+ -+ INTR_STAT_REG = 0xffffffff; // write 1 for clear. -+ -+#ifdef CNS3XXX_DELAYED_INTERRUPT -+ DELAY_INTR_CFG_REG = (1 << 16) | (max_pend_int_cnt << 8) | (max_pend_time); -+#endif -+ -+ reg_config = PHY_AUTO_ADDR_REG; -+ reg_config &= ~(3 << 30); -+#ifdef CONFIG_CNS3XXX_JUMBO_FRAME -+ reg_config |= (3 << 30); // maximum frame length: 9600 bytes -+#else -+ reg_config |= (2 << 30); // maximum frame length: 1536 bytes -+#endif -+ -+ PHY_AUTO_ADDR_REG = reg_config; -+ -+ -+ // Set general value for MAC_GLOB_CFG_REG -+ // age_time: 2 ^(1-1) * 300 sec -+ MAC_GLOB_CFG_REG &= (~0xf); -+ MAC_GLOB_CFG_REG |= 1; -+ -+ -+ // bkoff_mode: 111 follow standard -+ MAC_GLOB_CFG_REG &= (~(0x7 << 9)); -+ MAC_GLOB_CFG_REG |= (0x7 << 9); -+ -+ // jam_no: 1010: -+ MAC_GLOB_CFG_REG &= (~(0xf << 12)); -+ MAC_GLOB_CFG_REG |= (0xa << 12); -+ -+ // bp_mode: 10: -+ MAC_GLOB_CFG_REG &= (~(0x3 << 16)); -+ MAC_GLOB_CFG_REG |= (0x2 << 16); -+ -+ // res_mc_flt: 0 -+ MAC_GLOB_CFG_REG &= (~(0x1 << 28)); -+ -+ // col_mode: 11 -+ MAC_GLOB_CFG_REG &= (~(0x3 << 18)); -+ MAC_GLOB_CFG_REG |= (0x3 << 18); -+ -+ // crc_stripping: 1 -+ MAC_GLOB_CFG_REG |= (0x1 << 20); -+ -+ -+ // ACCEPT_CRC_BAD_PKT : 0 -+ MAC_GLOB_CFG_REG &= (~(0x1 << 21)); -+ -+#ifdef ACCEPT_CRC_BAD_PKT -+ MAC_GLOB_CFG_REG |= (0x1 << 21); -+#endif -+ -+ // SVL -+ MAC_GLOB_CFG_REG &= (~(0x1 << 7)); -+ -+#ifdef IVL -+ // IVL: 1 (IVL), 0 (SVL) -+ MAC_GLOB_CFG_REG |= (0x1 << 7); -+#endif -+ -+ -+ // HNAT_en: 0 -+ MAC_GLOB_CFG_REG &= (~(0x1 << 26)); -+ -+ // Firewall_mode: 0 -+ MAC_GLOB_CFG_REG &= (~(0x1 << 27)); -+ -+ -+ -+ cns3xxx_general_mac_cfg(0); -+ cns3xxx_general_mac_cfg(1); -+ cns3xxx_general_mac_cfg(2); -+ cns3xxx_configu_cpu_port(); -+ -+ // write vlan table -+ // set cpu port vlan table -+ cns3xxx_vlan_table_add(&cpu_vlan_table_entry); -+ for (i=0 ; i < sizeof(vlan_table_entry)/sizeof(VLANTableEntry) ; ++i) -+ cns3xxx_vlan_table_add(&vlan_table_entry[i]); -+ -+ cns3xxx_set_pvid(0, PORT0_PVID); -+ cns3xxx_set_pvid(1, PORT1_PVID); -+ cns3xxx_set_pvid(2, PORT2_PVID); -+ cns3xxx_set_pvid(3, CPU_PVID); -+ -+#ifdef CNS3XXX_SET_ARL_TABLE -+ // set arl table -+ cns3xxx_arl_table_flush(); -+#endif -+} -+ -+static int cns3xxx_set_mac_addr(struct net_device *dev, void *p) -+{ -+ //struct sockaddr *sock_addr = addr; -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ -+ struct sockaddr *addr= p; -+ -+ -+ spin_lock_irq(&priv->lock); -+ -+ -+ if (!is_valid_ether_addr(addr->sa_data)) -+ return -EADDRNOTAVAIL; -+ -+ // 1. delete old arl mac entry -+ // 2. add new arl mac entry -+ // 3. copy new mac to netdev field -+ -+ if (priv->net_device_priv->arl_table_entry) { -+ cns3xxx_arl_table_invalid(priv->net_device_priv->arl_table_entry); -+ memcpy(priv->net_device_priv->arl_table_entry->mac, addr->sa_data, dev->addr_len); -+ //print_arl_table_entry(priv->net_device_priv->arl_table_entry); -+ cns3xxx_arl_table_add(priv->net_device_priv->arl_table_entry); -+ } -+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); -+ -+ spin_unlock_irq(&priv->lock); -+ return 0; -+} -+ -+ -+int set_fc_rls(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ FC_GLOB_THRS_REG &= (~(0x1ff << 16)); -+ FC_GLOB_THRS_REG |= (ctl.val << 16); -+ return CAVM_OK; -+} -+ -+int get_fc_rls(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ -+ ctl.val = ((FC_GLOB_THRS_REG >> 16) & 0x1ff); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int set_fc_set(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ FC_GLOB_THRS_REG &= (~0x1ff); -+ FC_GLOB_THRS_REG |= ctl.val; -+ return CAVM_OK; -+} -+ -+int get_fc_set(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ -+ ctl.val = ((FC_GLOB_THRS_REG) & 0x1ff); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+ -+int set_sarl_rls(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ SARL_CTRL_REG &= (~(0x1ff << 12)); -+ SARL_CTRL_REG |= (ctl.val << 12); -+ return CAVM_OK; -+} -+ -+int get_sarl_rls(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ -+ ctl.val = ((SARL_CTRL_REG >> 12) & 0x1ff); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int set_sarl_enable(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ SARL_CTRL_REG &= (~(0x1 << 31)); -+ SARL_CTRL_REG |= (ctl.val << 31); -+ return CAVM_OK; -+} -+ -+int get_sarl_enable(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ ctl.val = ((SARL_CTRL_REG >> 31 ) & 0x1); -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+int set_sarl_set(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ SARL_CTRL_REG &= (~0x1ff); -+ SARL_CTRL_REG |= ctl.val; -+ return CAVM_OK; -+} -+ -+int get_sarl_set(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ -+ ctl.val = ((SARL_CTRL_REG) & 0x1ff); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int set_sarl_oq(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ -+ switch (ctl.gyr) -+ { -+ case 0: // green -+ { -+ SARL_OQ_GTH_REG &= (~(0xff << ctl.tc*8)); -+ SARL_OQ_GTH_REG |= (ctl.val << ctl.tc*8); -+ break; -+ } -+ case 1: // yellow -+ { -+ SARL_OQ_YTH_REG &= (~(0xff << ctl.tc*8)); -+ SARL_OQ_YTH_REG |= (ctl.val << ctl.tc*8); -+ break; -+ } -+ case 2: // red -+ { -+ SARL_OQ_RTH_REG &= (~(0xff << ctl.tc*8)); -+ SARL_OQ_RTH_REG |= (ctl.val << ctl.tc*8); -+ break; -+ } -+ } -+ return CAVM_OK; -+} -+ -+int get_sarl_oq(struct ifreq *ifr) -+{ -+ CNS3XXXSARLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ -+ switch (ctl.gyr) -+ { -+ case 0: // green -+ { -+ ctl.val = ((SARL_OQ_GTH_REG >> ctl.tc*8) & 0xff); -+ break; -+ } -+ case 1: // yellow -+ { -+ ctl.val = ((SARL_OQ_YTH_REG >> ctl.tc*8) & 0xff); -+ break; -+ } -+ case 2: // red -+ { -+ ctl.val = ((SARL_OQ_RTH_REG >> ctl.tc*8) & 0xff); -+ break; -+ } -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int set_queue_weight(struct ifreq *ifr) -+{ -+ CNS3XXXQueueWeightEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQueueWeightEntry)) ) -+ return -EFAULT; -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ QUEUE_WEIGHT_SET(0, ctl) -+ return 0; -+ } -+ case 1: -+ { -+ QUEUE_WEIGHT_SET(1, ctl) -+ return 0; -+ } -+ case 2: -+ { -+ QUEUE_WEIGHT_SET(2, ctl) -+ return 0; -+ } -+ case 3: // cpu port -+ { -+ CPU_PRI_CTRL_REG &= ~(0x3ffff); -+ CPU_PRI_CTRL_REG |= (ctl.sch_mode << 16); -+ CPU_PRI_CTRL_REG |= (ctl.q0_w); -+ CPU_PRI_CTRL_REG |= (ctl.q1_w << 4); -+ CPU_PRI_CTRL_REG |= (ctl.q2_w << 8); -+ CPU_PRI_CTRL_REG |= (ctl.q3_w << 12); -+ return 0; -+ } -+ case 4: // PPE port -+ { -+ HNAT_PRI_CTRL_REG &= ~(0x3ffff); -+ HNAT_PRI_CTRL_REG |= (ctl.sch_mode << 16); -+ HNAT_PRI_CTRL_REG |= (ctl.q0_w); -+ HNAT_PRI_CTRL_REG |= (ctl.q1_w << 4); -+ HNAT_PRI_CTRL_REG |= (ctl.q2_w << 8); -+ HNAT_PRI_CTRL_REG |= (ctl.q3_w << 12); -+ return 0; -+ } -+ default: -+ { -+ return -EFAULT; -+ } -+ } -+} -+ -+int get_queue_weight(struct ifreq *ifr) -+{ -+ CNS3XXXQueueWeightEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQueueWeightEntry)) ) -+ return -EFAULT; -+ -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ QUEUE_WEIGHT_GET(0, ctl) -+ break; -+ } -+ case 1: -+ { -+ QUEUE_WEIGHT_GET(1, ctl) -+ break; -+ } -+ case 2: -+ { -+ QUEUE_WEIGHT_GET(2, ctl) -+ break; -+ } -+ case 3: -+ { -+ ctl.sch_mode = ((CPU_PRI_CTRL_REG >> 16 ) & 0x3); -+ ctl.q0_w = ((CPU_PRI_CTRL_REG >> 0 ) & 0x7); -+ ctl.q1_w = ((CPU_PRI_CTRL_REG >> 4 ) & 0x7); -+ ctl.q2_w = ((CPU_PRI_CTRL_REG >> 8 ) & 0x7); -+ ctl.q3_w = ((CPU_PRI_CTRL_REG >> 12 ) & 0x7); -+ break; -+ } -+ case 4: -+ { -+ ctl.sch_mode = ((HNAT_PRI_CTRL_REG >> 16 ) & 0x3); -+ ctl.q0_w = ((HNAT_PRI_CTRL_REG >> 0 ) & 0x7); -+ ctl.q1_w = ((HNAT_PRI_CTRL_REG >> 4 ) & 0x7); -+ ctl.q2_w = ((HNAT_PRI_CTRL_REG >> 8 ) & 0x7); -+ ctl.q3_w = ((HNAT_PRI_CTRL_REG >> 12 ) & 0x7); -+ break; -+ } -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXQueueWeightEntry)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int set_rate_limit(struct ifreq *ifr) -+{ -+ CNS3XXXRateLimitEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXRateLimitEntry)) ) -+ return -EFAULT; -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ RATE_CTRL_REG &= (~(0x7f << 8)); -+ RATE_CTRL_REG |= ( ctl.band_width << 8); -+ RATE_CTRL_REG &= (~(0x3)); -+ RATE_CTRL_REG |= ctl.base_rate; -+ return 0; -+ } -+ case 1: -+ { -+ RATE_CTRL_REG &= (~(0x7f << 16)); -+ RATE_CTRL_REG |= ( ctl.band_width << 16); -+ RATE_CTRL_REG &= (~(0x3 << 2)); -+ RATE_CTRL_REG |= (ctl.base_rate << 2); -+ return 0; -+ } -+ case 2: -+ { -+ RATE_CTRL_REG &= (~(0x7f << 24)); -+ RATE_CTRL_REG |= ( ctl.band_width << 24); -+ RATE_CTRL_REG &= (~(0x3 << 4)); -+ RATE_CTRL_REG |= (ctl.base_rate << 4); -+ return 0; -+ } -+ case 3: // port 0 extra dma -+ { -+ TC_CTRL_REG &= (~0x7f); -+ TC_CTRL_REG |= ctl.band_width; -+ RATE_CTRL_REG &= (~(0x3 << 6)); -+ RATE_CTRL_REG |= (ctl.base_rate << 6); -+ return 0; -+ } -+ default: -+ { -+ return -EFAULT; -+ } -+ } -+} -+ -+int get_rate_limit(struct ifreq *ifr) -+{ -+ CNS3XXXRateLimitEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXRateLimitEntry)) ) -+ return -EFAULT; -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ ctl.band_width = (RATE_CTRL_REG >> 8) & 0x7f; -+ ctl.base_rate = RATE_CTRL_REG & 0x3; -+ break; -+ } -+ case 1: -+ { -+ ctl.band_width = (RATE_CTRL_REG >> 16) & 0x7f; -+ ctl.base_rate = (RATE_CTRL_REG >> 2) & 0x3; -+ break; -+ } -+ case 2: -+ { -+ ctl.band_width = (RATE_CTRL_REG >> 24) & 0x7f; -+ ctl.base_rate = (RATE_CTRL_REG >> 4) & 0x3; -+ break; -+ } -+ case 3: // port 0 extra dma -+ { -+ ctl.band_width = (TC_CTRL_REG) & 0x7f; -+ ctl.base_rate = (RATE_CTRL_REG >> 6) & 0x3; -+ break; -+ } -+ default: -+ { -+ return -EFAULT; -+ } -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXRateLimitEntry)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int set_fc(struct ifreq *ifr) -+{ -+ CNS3XXXFCEntry ctl; -+ u32 port_offset[]={0x0c, 0x10, 0x18, 0x14}; // 0x14 is cpu port offset -+ u32 val=0; -+ -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXFCEntry)) ) -+ return -EFAULT; -+ -+ val = SWITCH_REG_VALUE(port_offset[ctl.port]); -+ if (ctl.port == 3) { // cpu port, only can set rx fc -+ val &= (~(1 << 31)); -+ if (ctl.fc_en) -+ val |= (1 << 31); -+ } else { -+ val &= (~(1 << 11)); // disable rx fc -+ val &= (~(1 << 12)); // disable tx fc -+ val |= (ctl.fc_en << 11); -+ } -+ -+ SWITCH_REG_VALUE(port_offset[ctl.port]) = val; -+ return CAVM_OK; -+} -+ -+int get_fc(struct ifreq *ifr) -+{ -+ CNS3XXXFCEntry ctl; -+ u32 port_offset[]={0x0c, 0x10, 0x18, 0x14}; // 0x14 is cpu port offset -+ u32 val=0; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXFCEntry)) ) -+ return -EFAULT; -+ -+ val = SWITCH_REG_VALUE(port_offset[ctl.port]); -+ if (ctl.port == 3) { // cpu port, only can set rx fc -+ ctl.fc_en = ((val >> 31) & 1); -+ } else { -+ ctl.fc_en = ((val >> 11) & 3); -+ -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXFCEntry)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int set_ivl(struct ifreq *ifr) -+{ -+ CNS3XXXIVLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXIVLEntry)) ) -+ return -EFAULT; -+ -+ cns3xxx_ivl(ctl.enable); -+ -+ return CAVM_OK; -+} -+ -+int get_ivl(struct ifreq *ifr) -+{ -+ CNS3XXXIVLEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXIVLEntry)) ) -+ return -EFAULT; -+ -+ ctl.enable = ((MAC_GLOB_CFG_REG >> 7) & 0x1); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXIVLEntry)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int set_wan_port(struct ifreq *ifr) -+{ -+ CNS3XXXWANPortEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXWANPortEntry)) ) -+ return -EFAULT; -+ VLAN_CFG &= (~(0x1f << 8)); -+ VLAN_CFG |= (ctl.wan_port << 8); -+ -+ return CAVM_OK; -+} -+int get_wan_port(struct ifreq *ifr) -+{ -+ CNS3XXXWANPortEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXWANPortEntry)) ) -+ return -EFAULT; -+ -+ ctl.wan_port = ((VLAN_CFG >> 8) & 0x1f); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXWANPortEntry)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int set_pvid(struct ifreq *ifr) -+{ -+ CNS3XXXPVIDEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPVIDEntry)) ) -+ return -EFAULT; -+ cns3xxx_set_pvid(ctl.which_port, ctl.pvid); -+ -+ return CAVM_OK; -+} -+ -+int get_pvid(struct ifreq *ifr) -+{ -+ CNS3XXXPVIDEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPVIDEntry)) ) -+ return -EFAULT; -+ -+ ctl.pvid = cns3xxx_get_pvid(ctl.which_port); -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPVIDEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int set_qa(struct ifreq *ifr) -+{ -+ CNS3XXXQAEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQAEntry)) ) -+ return -EFAULT; -+ -+ MAC_GLOB_CFG_EXT_REG &= ~(0x7 << 27); -+ MAC_GLOB_CFG_EXT_REG |= (ctl.qa << 27); -+ -+ return CAVM_OK; -+} -+ -+int get_qa(struct ifreq *ifr) -+{ -+ CNS3XXXQAEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQAEntry)) ) -+ return -EFAULT; -+ -+ ctl.qa = (MAC_GLOB_CFG_EXT_REG >> 27) & 0x7; -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXQAEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int get_packet_max_len(struct ifreq *ifr) -+{ -+ CNS3XXXMaxLenEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXMaxLenEntry)) ) -+ return -EFAULT; -+ -+ ctl.max_len = (PHY_AUTO_ADDR_REG >> 30) & 0x3; -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXMaxLenEntry)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int set_packet_max_len(struct ifreq *ifr) -+{ -+ CNS3XXXMaxLenEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXMaxLenEntry)) ) -+ return -EFAULT; -+ -+ PHY_AUTO_ADDR_REG &= (~(3 << 30)); -+ PHY_AUTO_ADDR_REG |= (ctl.max_len << 30); -+ -+ return CAVM_OK; -+} -+ -+int set_udp_range(struct ifreq *ifr) -+{ -+ CNS3XXXUdpRangeEtypeControl conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXUdpRangeEtypeControl)) ) -+ return -EFAULT; -+ -+ switch (conf.udp_range_num) -+ { -+ case 0: -+ { -+ UDP_RANGE0_REG = 0; -+ UDP_RANGE0_REG |= conf.port_start; -+ UDP_RANGE0_REG |= (conf.port_end << 16); -+ break; -+ } -+ case 1: -+ { -+ UDP_RANGE1_REG = 0; -+ UDP_RANGE1_REG |= conf.port_start; -+ UDP_RANGE1_REG |= (conf.port_end << 16); -+ break; -+ } -+ case 2: -+ { -+ UDP_RANGE2_REG = 0; -+ UDP_RANGE2_REG |= conf.port_start; -+ UDP_RANGE2_REG |= (conf.port_end << 16); -+ break; -+ } -+ case 3: -+ { -+ UDP_RANGE3_REG = 0; -+ UDP_RANGE3_REG |= conf.port_start; -+ UDP_RANGE3_REG |= (conf.port_end << 16); -+ break; -+ } -+ } -+ -+ return CAVM_OK; -+} -+ -+int get_udp_range(struct ifreq *ifr) -+{ -+ CNS3XXXUdpRangeEtypeControl conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXUdpRangeEtypeControl)) ) -+ return -EFAULT; -+ -+ switch (conf.udp_range_num) -+ { -+ case 0: -+ { -+ conf.port_start = (UDP_RANGE0_REG & 0xffff); -+ conf.port_end = ((UDP_RANGE0_REG >> 16 )& 0xffff); -+ break; -+ } -+ case 1: -+ { -+ conf.port_start = (UDP_RANGE1_REG & 0xffff); -+ conf.port_end = ((UDP_RANGE1_REG >> 16 )& 0xffff); -+ break; -+ } -+ case 2: -+ { -+ conf.port_start = (UDP_RANGE2_REG & 0xffff); -+ conf.port_end = ((UDP_RANGE2_REG >> 16 )& 0xffff); -+ break; -+ } -+ case 3: -+ { -+ conf.port_start = (UDP_RANGE3_REG & 0xffff); -+ conf.port_end = ((UDP_RANGE3_REG >> 16 )& 0xffff); -+ break; -+ } -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXEtypeControl)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int get_etype(struct ifreq *ifr) -+{ -+ CNS3XXXEtypeControl conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXEtypeControl)) ) -+ return -EFAULT; -+ switch (conf.etype_num) -+ { -+ case 0: -+ { -+ conf.val = (ETYPE1_ETYPE0_REG & 0xffff); -+ conf.pri = (PRIO_ETYPE_UDP_REG & 0x7); -+ break; -+ } -+ case 1: -+ { -+ conf.val = ((ETYPE1_ETYPE0_REG >> 16 )& 0xffff); -+ conf.pri = ((PRIO_ETYPE_UDP_REG >> 4) & 0x7); -+ break; -+ } -+ case 2: -+ { -+ conf.val = (ETYPE3_ETYPE2_REG & 0xffff); -+ conf.pri = ((PRIO_ETYPE_UDP_REG >> 8) & 0x7); -+ break; -+ } -+ case 3: -+ { -+ conf.val = ((ETYPE3_ETYPE2_REG >> 16 )& 0xffff); -+ conf.pri = ((PRIO_ETYPE_UDP_REG >> 12) & 0x7); -+ break; -+ } -+ } -+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXEtypeControl)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+} -+ -+int set_etype(struct ifreq *ifr) -+{ -+ CNS3XXXEtypeControl conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXEtypeControl)) ) -+ return -EFAULT; -+ switch (conf.etype_num) -+ { -+ case 0: -+ { -+ ETYPE1_ETYPE0_REG &= (~0xffff); -+ ETYPE1_ETYPE0_REG |= conf.val; -+ -+ PRIO_ETYPE_UDP_REG &= (~7); -+ PRIO_ETYPE_UDP_REG |= (conf.pri); -+ break; -+ } -+ case 1: -+ { -+ ETYPE1_ETYPE0_REG &= (~(0xffff << 16)); -+ ETYPE1_ETYPE0_REG |= (conf.val << 16); -+ -+ PRIO_ETYPE_UDP_REG &= (~(7 << 4)); -+ PRIO_ETYPE_UDP_REG |= (conf.pri << 4); -+ break; -+ } -+ case 2: -+ { -+ ETYPE3_ETYPE2_REG &= (~0xffff); -+ ETYPE3_ETYPE2_REG |= conf.val; -+ -+ PRIO_ETYPE_UDP_REG &= (~(7 << 8)); -+ PRIO_ETYPE_UDP_REG |= (conf.pri << 8); -+ break; -+ } -+ case 3: -+ { -+ ETYPE3_ETYPE2_REG &= (~(0xffff << 16)); -+ ETYPE3_ETYPE2_REG |= (conf.val << 16); -+ -+ PRIO_ETYPE_UDP_REG &= (~(7 << 12)); -+ PRIO_ETYPE_UDP_REG |= (conf.pri << 12); -+ break; -+ } -+ } -+ return CAVM_OK; -+} -+ -+int get_pri_ip_dscp(struct ifreq *ifr) -+{ -+ CNS3XXXPriIpDscpControl conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXPriIpDscpControl)) ) -+ return -EFAULT; -+ -+ if ( 0 <= conf.ip_dscp_num && conf.ip_dscp_num <= 7) { -+ conf.pri = ((PRIO_IPDSCP_7_0_REG >> (conf.ip_dscp_num * 4)) & 0x7); -+ } else if ( 8 <= conf.ip_dscp_num && conf.ip_dscp_num <= 15) { -+ conf.pri = ((PRIO_IPDSCP_15_8_REG >> ((conf.ip_dscp_num-8) * 4)) & 0x7); -+ } else if ( 16 <= conf.ip_dscp_num && conf.ip_dscp_num <= 23) { -+ conf.pri = ((PRIO_IPDSCP_23_16_REG >> ((conf.ip_dscp_num-16) * 4)) & 0x7); -+ } else if ( 24 <= conf.ip_dscp_num && conf.ip_dscp_num <= 31) { -+ conf.pri = ((PRIO_IPDSCP_31_24_REG >> ((conf.ip_dscp_num-24) * 4)) & 0x7); -+ } else if ( 32 <= conf.ip_dscp_num && conf.ip_dscp_num <= 39) { -+ conf.pri = ((PRIO_IPDSCP_39_32_REG >> ((conf.ip_dscp_num-32) * 4)) & 0x7); -+ } else if ( 40 <= conf.ip_dscp_num && conf.ip_dscp_num <= 47) { -+ conf.pri = ((PRIO_IPDSCP_47_40_REG >> ((conf.ip_dscp_num-40) * 4)) & 0x7); -+ } else if ( 48 <= conf.ip_dscp_num && conf.ip_dscp_num <= 55) { -+ conf.pri = ((PRIO_IPDSCP_55_48_REG >> ((conf.ip_dscp_num-48) * 4)) & 0x7); -+ } else if ( 56 <= conf.ip_dscp_num && conf.ip_dscp_num <= 63) { -+ conf.pri = ((PRIO_IPDSCP_63_56_REG >> ((conf.ip_dscp_num-56) * 4)) & 0x7); -+ } else { -+ return CAVM_ERR; -+ } -+ -+ -+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXPriIpDscpControl)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+ -+int set_pri_ip_dscp(struct ifreq *ifr) -+{ -+ CNS3XXXPriIpDscpControl conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXPriIpDscpControl)) ) -+ return -EFAULT; -+ -+ if ( 0 <= conf.ip_dscp_num && conf.ip_dscp_num <= 7) { -+ PRIO_IPDSCP_7_0_REG &= (~(0x7 << (conf.ip_dscp_num * 4) ) ); -+ PRIO_IPDSCP_7_0_REG |= (conf.pri << (conf.ip_dscp_num * 4)); -+ } else if ( 8 <= conf.ip_dscp_num && conf.ip_dscp_num <= 15) { -+ PRIO_IPDSCP_15_8_REG &= (~(0x7 << ((conf.ip_dscp_num-8) * 4) ) ); -+ PRIO_IPDSCP_15_8_REG |= (conf.pri << ((conf.ip_dscp_num-8) * 4)); -+ } else if ( 16 <= conf.ip_dscp_num && conf.ip_dscp_num <= 23) { -+ PRIO_IPDSCP_23_16_REG &= (~(0x7 << ((conf.ip_dscp_num-16) * 4) ) ); -+ PRIO_IPDSCP_23_16_REG |= (conf.pri << ((conf.ip_dscp_num-16) * 4)); -+ -+ } else if ( 24 <= conf.ip_dscp_num && conf.ip_dscp_num <= 31) { -+ PRIO_IPDSCP_31_24_REG &= (~(0x7 << ((conf.ip_dscp_num-24) * 4) ) ); -+ PRIO_IPDSCP_31_24_REG |= (conf.pri << ((conf.ip_dscp_num-24) * 4)); -+ -+ } else if ( 32 <= conf.ip_dscp_num && conf.ip_dscp_num <= 39) { -+ PRIO_IPDSCP_39_32_REG &= (~(0x7 << ((conf.ip_dscp_num-32) * 4) ) ); -+ PRIO_IPDSCP_39_32_REG |= (conf.pri << ((conf.ip_dscp_num-32) * 4)); -+ -+ } else if ( 40 <= conf.ip_dscp_num && conf.ip_dscp_num <= 47) { -+ PRIO_IPDSCP_47_40_REG &= (~(0x7 << ((conf.ip_dscp_num-40) * 4) ) ); -+ PRIO_IPDSCP_47_40_REG |= (conf.pri << ((conf.ip_dscp_num-40) * 4)); -+ } else if ( 48 <= conf.ip_dscp_num && conf.ip_dscp_num <= 55) { -+ PRIO_IPDSCP_55_48_REG &= (~(0x7 << ((conf.ip_dscp_num-48) * 4) ) ); -+ PRIO_IPDSCP_55_48_REG |= (conf.pri << ((conf.ip_dscp_num-48) * 4)); -+ } else if ( 56 <= conf.ip_dscp_num && conf.ip_dscp_num <= 63) { -+ PRIO_IPDSCP_63_56_REG &= (~(0x7 << ((conf.ip_dscp_num-56) * 4) ) ); -+ PRIO_IPDSCP_63_56_REG |= (conf.pri << ((conf.ip_dscp_num-56) * 4)); -+ } else { -+ return CAVM_ERR; -+ } -+ return CAVM_OK; -+} -+ -+ -+int bcm53115M_reg_read_ioctl(struct ifreq *ifr) -+{ -+ int bcm53115M_reg_read(int page, int offset, u8 *buf, int len); -+ CNS3XXXBCM53115M conf; -+ int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state); -+ -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXBCM53115M)) ) -+ return -EFAULT; -+ printk("conf.page: %x\n", conf.page); -+ printk("conf.offset: %x\n", conf.offset); -+ printk("conf.data_len: %x\n", conf.data_len); -+ switch (conf.data_len) -+ { -+ case 1: -+ { -+ bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u8_val, 1); -+ printk("conf.u8_val: %x\n", conf.u8_val); -+ break; -+ } -+ case 2: -+ { -+ bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u16_val, 2); -+ printk("conf.u16_val: %x\n", conf.u16_val); -+ break; -+ } -+ case 4: -+ { -+ bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u32_val, 4); -+ printk("conf.u32_val: %x\n", conf.u32_val); -+ break; -+ } -+ default: -+ { -+ printk("[kernel mode]: don't support date length: %d\n", conf.data_len); -+ } -+ } -+ -+ -+ -+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXBCM53115M)) ) -+ return -EFAULT; -+ return CAVM_OK; -+} -+ -+int bcm53115M_reg_write_ioctl(struct ifreq *ifr) -+{ -+ int bcm53115M_reg_write(int page, int offset, u8 *buf, int len); -+ CNS3XXXBCM53115M conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXBCM53115M)) ) -+ return -EFAULT; -+ -+ switch (conf.data_len) -+ { -+ case 1: -+ { -+ bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u8_val, 1); -+ break; -+ } -+ case 2: -+ { -+ bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u16_val, 2); -+ break; -+ } -+ case 4: -+ { -+ bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u32_val, 4); -+ break; -+ } -+ default: -+ { -+ printk("[kernel mode]: don't support date length: %d\n", conf.data_len); -+ } -+ } -+ return CAVM_OK; -+} -+ -+#if 0 -+int get_rxring(struct ifreq *ifr) -+{ -+ CNS3XXXRingStatus conf; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXRingStatus)) ) -+ return -EFAULT; -+ conf.rx_ring=g_ring_info.rx_ring; -+ conf.tx_ring=0; -+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXRingStatus)) ) -+ return -EFAULT; -+} -+#endif -+ -+int dump_mib_counter(struct ifreq *ifr) -+{ -+ CNS3XXXMIBCounter conf; -+ int addr=0,i=0; -+ -+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXMIBCounter)) ) -+ return -EFAULT; -+ -+ for (addr=0x300; addr <= 0x334 ; addr+=4) -+ conf.mib[i++]=SWITCH_REG_VALUE(addr); -+ for (addr=0x400; addr <= 0x434 ; addr+=4) -+ conf.mib[i++]=SWITCH_REG_VALUE(addr); -+ for (addr=0x600; addr <= 0x634 ; addr+=4) -+ conf.mib[i++]=SWITCH_REG_VALUE(addr); -+ // cpu mib counter -+ for (addr=0x500; addr <= 0x528 ; addr+=4) -+ conf.mib[i++]=SWITCH_REG_VALUE(addr); -+ conf.mib_len=i; -+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXMIBCounter)) ) -+ return -EFAULT; -+ return 0; -+} -+ -+// reference e100.c -+int cns3xxx_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -+{ -+ CNS3XXXIoctlCmd ioctl_cmd; -+ -+ //printk("cns3xxx_do_ioctl begin\n"); -+ -+ if (cmd != SIOCDEVPRIVATE) { -+ return -EOPNOTSUPP; -+ } -+ if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(CNS3XXXIoctlCmd))) -+ return -EFAULT; -+ -+ //printk("ioctl_cmd: %d\n", ioctl_cmd); -+ switch (ioctl_cmd) { -+ case CNS3XXX_ARP_REQUEST_SET: -+ { -+ CNS3XXXArpRequestControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXArpRequestControl)) ) -+ return -EFAULT; -+ -+ (ctl.val==0) ? (MAC_GLOB_CFG_REG &= (~(1 << 23)) ): (MAC_GLOB_CFG_REG |= (1 << 23) ); -+ -+ } -+ -+ case CNS3XXX_ARP_REQUEST_GET: -+ { -+ CNS3XXXArpRequestControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXArpRequestControl)) ) -+ return -EFAULT; -+ -+ ctl.val = ((MAC_GLOB_CFG_REG >> 23) & 1); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXArpRequestControl)) ) -+ return -EFAULT; -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_HOL_PREVENT_SET: -+ { -+ CNS3XXXHOLPreventControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXHOLPreventControl)) ) -+ return -EFAULT; -+ (ctl.enable == 1) ? (TC_CTRL_REG |= (1 << 29)) : (TC_CTRL_REG &= (~(1 << 29))) ; -+ -+ return CAVM_OK; -+ } -+ case CNS3XXX_HOL_PREVENT_GET: -+ { -+ CNS3XXXHOLPreventControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXHOLPreventControl)) ) -+ return -EFAULT; -+ -+ ctl.enable = ((TC_CTRL_REG >> 29) & 0x1); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXHOLPreventControl)) ) -+ return -EFAULT; -+ return CAVM_OK; -+ } -+ -+ // for S component or C conponent -+ case CNS3XXX_BRIDGE_SET: -+ { -+ CNS3XXXBridgeControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXBridgeControl)) ) -+ return -EFAULT; -+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 1)) : (VLAN_CFG &= (~(1 << 1))) ; -+ -+ -+ } -+ case CNS3XXX_BRIDGE_GET: -+ { -+ CNS3XXXBridgeControl ctl; -+ -+ ctl.type = ((VLAN_CFG >> 1) & 0x1); -+ printk("[kernel mode] ctl.type: %d\n", ctl.type); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXBridgeControl)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_PORT_NEIGHBOR_SET: -+ { -+ CNS3XXXPortNeighborControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPortNeighborControl)) ) -+ return -EFAULT; -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 4)) : (VLAN_CFG &= (~(1 << 4))) ; -+ return 0; -+ } -+ case 1: -+ { -+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 5)) : (VLAN_CFG &= (~(1 << 5))) ; -+ return 0; -+ } -+ case 2: -+ { -+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 7)) : (VLAN_CFG &= (~(1 << 7))) ; -+ return 0; -+ } -+ case 3: // cpu port -+ { -+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 6)) : (VLAN_CFG &= (~(1 << 6))) ; -+ return 0; -+ } -+ default: -+ return -EFAULT; -+ } -+ -+ } -+ -+ case CNS3XXX_PORT_NEIGHBOR_GET: -+ { -+ CNS3XXXPortNeighborControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPortNeighborControl)) ) -+ return -EFAULT; -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ ctl.type = ((VLAN_CFG >> 4 ) & 0x1); -+ break; -+ } -+ case 1: -+ { -+ ctl.type = ((VLAN_CFG >> 5 ) & 0x1); -+ break; -+ } -+ case 2: -+ { -+ ctl.type = ((VLAN_CFG >> 7 ) & 0x1); -+ break; -+ } -+ case 3: // cpu port -+ { -+ ctl.type = ((VLAN_CFG >> 6 ) & 0x1); -+ break; -+ } -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPortNeighborControl)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_VLAN_TABLE_LOOKUP: -+ { -+ CNS3XXXVLANTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) ) -+ return -EFAULT; -+ if (cns3xxx_vlan_table_lookup(&ctl.entry) == CAVM_NOT_FOUND) { -+ return CAVM_NOT_FOUND; -+ } -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_FOUND; -+ } -+ case CNS3XXX_VLAN_TABLE_READ: -+ { -+ CNS3XXXVLANTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) ) -+ { -+ return -EFAULT; -+ } -+ cns3xxx_vlan_table_read(&ctl.entry); -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry))) -+ return -EFAULT; -+ -+ return 0; -+ } -+ case CNS3XXX_VLAN_TABLE_ADD: -+ { -+ CNS3XXXVLANTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) ) -+ return -EFAULT; -+ cns3xxx_vlan_table_add(&ctl.entry); -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry))) -+ return -EFAULT; -+ -+ return 0; -+ } -+ -+ case CNS3XXX_ARL_TABLE_ADD: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ printk("[kernel mode] CNS3XXX_ARL_TABLE_ADD\n"); -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ cns3xxx_arl_table_add(&ctl.entry); -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return 0; -+ } -+ -+ -+ case CNS3XXX_ARL_TABLE_DEL: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ cns3xxx_arl_table_invalid(&ctl.entry); -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return 0; -+ } -+ case CNS3XXX_VLAN_TABLE_DEL: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ cns3xxx_arl_table_invalid(&ctl.entry); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_FOUND; -+ } -+ -+ case CNS3XXX_ARL_TABLE_SEARCH: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ if (cns3xxx_arl_table_search(&ctl.entry) == CAVM_NOT_FOUND){ -+ printk("[kernel mode] not found\n"); -+ return CAVM_NOT_FOUND; -+ } -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_FOUND; -+ } -+ case CNS3XXX_ARL_IS_TABLE_END: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ if (cns3xxx_is_arl_table_end() == CAVM_ERR) -+ return CAVM_ERR; -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_ARL_TABLE_SEARCH_AGAIN: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ if (cns3xxx_arl_table_search_again(&ctl.entry) == CAVM_NOT_FOUND) -+ return CAVM_NOT_FOUND; -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_FOUND; -+ } -+ -+ case CNS3XXX_ARL_TABLE_FLUSH: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ -+ cns3xxx_arl_table_flush(); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_FOUND; -+ } -+ -+ -+ -+ case CNS3XXX_ARL_TABLE_LOOKUP: -+ { -+ CNS3XXXARLTableEntry ctl; -+ -+ -+ printk("[kernel mode] in CNS3XXX_ARL_TABLE_LOOKUP\n"); -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) ) -+ return -EFAULT; -+ if (cns3xxx_arl_table_lookup(&ctl.entry) == CAVM_NOT_FOUND) -+ return CAVM_NOT_FOUND; -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry))) -+ return -EFAULT; -+ -+ return CAVM_FOUND; -+ } -+ -+ case CNS3XXX_TC_SET: -+ { -+ CNS3XXXTrafficClassControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXTrafficClassControl)) ) -+ return -EFAULT; -+ TC_CTRL_REG &= (~(0x3 << 30)); -+ TC_CTRL_REG |= (ctl.tc << 30); -+ return CAVM_OK; -+ } -+ case CNS3XXX_TC_GET: -+ { -+ CNS3XXXTrafficClassControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXTrafficClassControl)) ) -+ return -EFAULT; -+ -+ ctl.tc = ((TC_CTRL_REG >> 30) & 0x3); -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXTrafficClassControl)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_PRI_CTRL_SET: -+ { -+ CNS3XXXPriCtrlControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPriCtrlControl)) ) -+ return -EFAULT; -+ -+ switch (ctl.which_port) -+ { -+ case 0: -+ { -+ MAC0_PRI_CTRL_REG &= (~(0x7 << 24)); -+ MAC0_PRI_CTRL_REG &= (~(0xf << 18)); -+ -+ MAC0_PRI_CTRL_REG |= (ctl.port_pri << 24); -+ -+ MAC0_PRI_CTRL_REG |= (ctl.ether_pri_en << 18); -+ MAC0_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19); -+ MAC0_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20); -+ MAC0_PRI_CTRL_REG |= (ctl.udp_pri_en << 21); -+ break; -+ } -+ case 1: -+ { -+ MAC1_PRI_CTRL_REG &= (~(0x7 << 24)); -+ MAC1_PRI_CTRL_REG &= (~(0xf << 18)); -+ -+ MAC1_PRI_CTRL_REG |= (ctl.port_pri << 24); -+ -+ MAC1_PRI_CTRL_REG |= (ctl.ether_pri_en << 18); -+ MAC1_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19); -+ MAC1_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20); -+ MAC1_PRI_CTRL_REG |= (ctl.udp_pri_en << 21); -+ break; -+ } -+ case 2: -+ { -+ MAC2_PRI_CTRL_REG &= (~(0x7 << 24)); -+ MAC2_PRI_CTRL_REG &= (~(0xf << 18)); -+ -+ MAC2_PRI_CTRL_REG |= (ctl.port_pri << 24); -+ -+ MAC2_PRI_CTRL_REG |= (ctl.ether_pri_en << 18); -+ MAC2_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19); -+ MAC2_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20); -+ MAC2_PRI_CTRL_REG |= (ctl.udp_pri_en << 21); -+ break; -+ } -+ case 3: // cpu -+ { -+ printk("[kernel mode] CPU_PRI_CTRL_REG: %#x\n", CPU_PRI_CTRL_REG); -+ CPU_PRI_CTRL_REG &= (~(0x7 << 24)); -+ CPU_PRI_CTRL_REG &= (~(0xf << 18)); -+ -+ CPU_PRI_CTRL_REG |= (ctl.port_pri << 24); -+ -+ CPU_PRI_CTRL_REG |= (ctl.ether_pri_en << 18); -+ CPU_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19); -+ CPU_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20); -+ CPU_PRI_CTRL_REG |= (ctl.udp_pri_en << 21); -+ break; -+ } -+ } -+ -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_PRI_CTRL_GET: -+ { -+ CNS3XXXPriCtrlControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPriCtrlControl)) ) -+ return -EFAULT; -+ -+ -+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPriCtrlControl)) ) -+ return -EFAULT; -+ -+ return CAVM_OK; -+ } -+ -+ case CNS3XXX_DMA_RING_CTRL_SET: -+ { -+ CNS3XXXDmaRingCtrlControl ctl; -+ -+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXDmaRingCtrlControl)) ) -+ return -EFAULT; -+ -+ (ctl.ts_double_ring_en == 0) ? DMA_RING_CTRL_REG &= (~(0x1 << 16)) : (DMA_RING_CTRL_REG |= (ctl.ts_double_ring_en << 16)); -+ (ctl.fs_double_ring_en == 0) ? DMA_RING_CTRL_REG &= (~(0x1 << 0)) : (DMA_RING_CTRL_REG |= (ctl.fs_double_ring_en << 0)); -+ (ctl.fs_pkt_allocate == 0) ? DMA_RING_CTRL_REG &= (~(0x1 << 1)) : (DMA_RING_CTRL_REG |= (ctl.fs_pkt_allocate << 1)); -+ } -+ -+ case CNS3XXX_PRI_IP_DSCP_SET: -+ { -+ return set_pri_ip_dscp(ifr); -+ } -+ case CNS3XXX_PRI_IP_DSCP_GET: -+ { -+ return get_pri_ip_dscp(ifr); -+ } -+ -+ case CNS3XXX_ETYPE_SET: -+ { -+ return set_etype(ifr); -+ } -+ case CNS3XXX_ETYPE_GET: -+ { -+ return get_etype(ifr); -+ } -+ -+ case CNS3XXX_UDP_RANGE_SET: -+ { -+ return set_udp_range(ifr); -+ } -+ case CNS3XXX_UDP_RANGE_GET: -+ { -+ return get_udp_range(ifr); -+ } -+ -+ case CNS3XXX_RATE_LIMIT_SET: -+ { -+ return set_rate_limit(ifr); -+ } -+ case CNS3XXX_RATE_LIMIT_GET: -+ { -+ return get_rate_limit(ifr); -+ } -+ case CNS3XXX_QUEUE_WEIGHT_SET: -+ { -+ return set_queue_weight(ifr); -+ } -+ case CNS3XXX_QUEUE_WEIGHT_GET: -+ { -+ return get_queue_weight(ifr); -+ } -+ -+ case CNS3XXX_FC_RLS_SET: -+ { -+ return set_fc_rls(ifr); -+ } -+ case CNS3XXX_FC_RLS_GET: -+ { -+ return get_fc_rls(ifr); -+ } -+ -+ case CNS3XXX_FC_SET_SET: -+ { -+ return set_fc_set(ifr); -+ } -+ case CNS3XXX_FC_SET_GET: -+ { -+ return get_fc_set(ifr); -+ } -+ -+ case CNS3XXX_SARL_RLS_SET: -+ { -+ return set_sarl_rls(ifr); -+ } -+ case CNS3XXX_SARL_RLS_GET: -+ { -+ return get_sarl_rls(ifr); -+ } -+ -+ case CNS3XXX_SARL_SET_SET: -+ { -+ return set_sarl_set(ifr); -+ } -+ case CNS3XXX_SARL_SET_GET: -+ { -+ return get_sarl_set(ifr); -+ } -+ -+ case CNS3XXX_SARL_OQ_SET: -+ { -+ return set_sarl_oq(ifr); -+ } -+ case CNS3XXX_SARL_OQ_GET: -+ { -+ return get_sarl_oq(ifr); -+ } -+ -+ case CNS3XXX_SARL_ENABLE_SET: -+ { -+ return set_sarl_enable(ifr); -+ } -+ case CNS3XXX_SARL_ENABLE_GET: -+ { -+ return get_sarl_enable(ifr); -+ } -+ -+ case CNS3XXX_FC_SET: -+ { -+ return set_fc(ifr); -+ } -+ case CNS3XXX_FC_GET: -+ { -+ return get_fc(ifr); -+ } -+ -+ case CNS3XXX_IVL_SET: -+ { -+ return set_ivl(ifr); -+ } -+ case CNS3XXX_IVL_GET: -+ { -+ return get_ivl(ifr); -+ } -+ -+ case CNS3XXX_WAN_PORT_SET: -+ { -+ return set_wan_port(ifr); -+ } -+ case CNS3XXX_WAN_PORT_GET: -+ { -+ return get_wan_port(ifr); -+ } -+ -+ case CNS3XXX_PVID_SET: -+ { -+ return set_pvid(ifr); -+ } -+ case CNS3XXX_PVID_GET: -+ { -+ return get_pvid(ifr); -+ } -+ -+ case CNS3XXX_QA_GET: -+ { -+ return get_qa(ifr); -+ } -+ case CNS3XXX_QA_SET: -+ { -+ return set_qa(ifr); -+ } -+ -+ case CNS3XXX_PACKET_MAX_LEN_GET: -+ { -+ return get_packet_max_len(ifr); -+ } -+ case CNS3XXX_PACKET_MAX_LEN_SET: -+ { -+ return set_packet_max_len(ifr); -+ } -+ -+ case CNS3XXX_BCM53115M_REG_READ: -+ { -+ return bcm53115M_reg_read_ioctl(ifr); -+ } -+ case CNS3XXX_BCM53115M_REG_WRITE: -+ { -+ return bcm53115M_reg_write_ioctl(ifr); -+ } -+ -+#if 0 -+ case CNS3XXX_RXRING_STATUS: -+ { -+ return get_rxring(ifr); -+ } -+#endif -+ case CNS3XXX_DUMP_MIB_COUNTER: -+ { -+ return dump_mib_counter(ifr); -+ } -+ -+ -+ default: -+ { -+ printk("[kernel mode] don't match any command\n"); -+ break; -+ } -+ -+ } // end switch (ioctl_cmd) -+ return 0; -+} -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+static int cns3xxx_poll(struct napi_struct *napi, int budget) -+{ -+ -+ CNS3XXXPrivate *sp = container_of(napi, CNS3XXXPrivate, napi); -+ int work_done = 0; -+ int work_to_do = budget; // define minima value -+ -+ cns3xxx_receive_packet(sp, 0, &work_done, work_to_do); -+ -+ budget -= work_done; -+ -+ if (work_done) { -+ if (test_bit(0, (unsigned long *)&sp->is_qf) == 1){ -+ clear_bit(0, (unsigned long *)&sp->is_qf); -+ enable_rx_dma(sp->ring_index, 1); -+ return 1; -+ } -+ } else { -+ //netif_rx_complete(napi_dev, &sp->napi); -+ napi_complete(napi); -+#ifdef CNS3XXX_USE_MASK -+ cns3xxx_write_pri_mask(0xf0); -+#else -+ if (sp->ring_index == 0) -+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID); -+ else -+ cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID); -+#endif -+ return 0; -+ } -+ -+ return 1; -+} -+#endif -+ -+static struct net_device_stats *cns3xxx_get_stats(struct net_device *dev) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ -+ return &priv->stats; -+} -+ -+static int cns3xxx_change_mtu(struct net_device *dev, int new_mtu) -+{ -+ if (new_mtu < cns3xxx_min_mtu() || new_mtu > cns3xxx_max_mtu()) -+ return -EINVAL; -+ -+ dev->mtu = new_mtu; -+ -+ return 0; -+} -+ -+static void cns3xxx_timeout(struct net_device *dev) -+{ -+ //star_gsw_enable(dev); -+ netif_wake_queue(dev); -+ dev->trans_start = jiffies; -+} -+ -+#ifdef LINUX2631 -+static const struct net_device_ops cns3xxx_netdev_ops = { -+ .ndo_open = cns3xxx_open, -+ .ndo_stop = cns3xxx_close, -+ .ndo_start_xmit = cns3xxx_send_packet, -+ //.ndo_validate_addr = eth_validate_addr, -+ //.ndo_set_multicast_list = cns3xxx_set_multicast_list, -+ .ndo_set_mac_address = cns3xxx_set_mac_addr, -+ .ndo_change_mtu = cns3xxx_change_mtu, -+ .ndo_do_ioctl = cns3xxx_do_ioctl, -+ .ndo_tx_timeout = cns3xxx_timeout, -+ .ndo_get_stats = cns3xxx_get_stats, -+ -+#if defined(CNS3XXX_VLAN_8021Q) -+ .ndo_vlan_rx_register = cns3xxx_vlan_rx_register, -+ //.ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, -+ .ndo_vlan_rx_kill_vid = cns3xxx_vlan_rx_kill_vid, -+#endif -+ -+#ifdef CONFIG_NET_POLL_CONTROLLER -+ .ndo_poll_controller = cns3xxx_netpoll, -+#endif -+}; -+#endif // LINUX2631 -+ -+static int __init cns3xxx_probe(RingInfo ring_info) -+{ -+ void cns3xxx_set_ethtool_ops(struct net_device *netdev); -+ -+ int netdev_size = sizeof(net_device_prive)/sizeof(NetDevicePriv); -+ int i=0, err=0; -+ struct net_device *netdev=0; -+ CNS3XXXPrivate *priv=0; -+ struct sockaddr sock_addr; -+ -+ for (i=0 ; i < netdev_size ; ++i) { -+ if (init_port & (1 << i)) { -+ -+ netdev = alloc_etherdev(sizeof(CNS3XXXPrivate)); -+ if (!netdev) { -+ err = -ENOMEM; -+ goto err_alloc_etherdev; -+ } -+ if (net_device_prive[i].name) -+ strcpy(netdev->name, net_device_prive[i].name); -+ -+ -+ net_dev_array[net_device_prive[i].vlan_tag] = netdev; -+ if (intr_netdev==0) -+ intr_netdev = netdev; -+ -+ SET_NETDEV_DEV(netdev, NULL); -+ priv = netdev_priv(netdev); -+ spin_lock_init(&priv->lock); -+ memset(priv, 0, sizeof(CNS3XXXPrivate)); -+ -+#if 1 -+ priv->num_rx_queues = ring_info.num_rx_queues; -+ priv->num_tx_queues = ring_info.num_tx_queues; -+ priv->rx_ring = ring_info.rx_ring; -+ priv->tx_ring = ring_info.tx_ring; -+#endif -+ -+ priv->net_device_priv = &net_device_prive[i]; -+ -+ // set netdev MAC address -+ memcpy(sock_addr.sa_data, net_device_prive[i].mac, 6); -+ cns3xxx_set_mac_addr(netdev, &sock_addr); -+ -+#ifdef LINUX2631 -+ netdev->netdev_ops = &cns3xxx_netdev_ops; -+#endif -+ -+ cns3xxx_set_ethtool_ops(netdev); -+#ifdef LINUX2627 -+ //netdev->base_addr = IO_ADDRESS(GSW_BASE_ADDR); -+ netdev->base_addr = 0; -+ netdev->open = cns3xxx_open; -+ netdev->stop = cns3xxx_close; -+ netdev->hard_start_xmit = cns3xxx_send_packet; -+ //netdev->hard_start_xmit = 0; -+ netdev->do_ioctl = cns3xxx_do_ioctl; -+ netdev->change_mtu = cns3xxx_change_mtu; -+ -+ //netdev->get_stats = cns3xxx_get_stats; -+ netdev->watchdog_timeo = 5 * HZ; // ref e1000_main.c -+ netdev->tx_timeout = cns3xxx_timeout; -+ netdev->set_mac_address = cns3xxx_set_mac_addr; -+#endif -+ -+#if defined(CNS3XXX_TX_HW_CHECKSUM) -+ netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG); -+ //netdev->features |= (NETIF_F_HW_CSUM | NETIF_F_SG); -+#endif -+ -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+ //netif_napi_add(netdev, &priv->napi, cns3xxx_poll, CNS3XXX_NAPI_WEIGHT); -+#endif -+ -+#if defined(CNS3XXX_VLAN_8021Q) -+ // do not let 8021Q module insert vlan tag -+ // can use the snippet code to get vlan tage -+ // if (priv->vlgrp && vlan_tx_tag_present(skb)) -+ // vlan_tag = cpu_to_be16(vlan_tx_tag_get(skb)); -+#ifdef CNS3XXX_8021Q_HW_TX -+ // hardware support insert VLAN tag on TX path -+ netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -+#else -+ netdev->features |= NETIF_F_HW_VLAN_RX; // remove NETIF_F_HW_VLAN_TX flag that 8021Q module to insert vlan tag. -+#endif -+ -+ //netdev->vlan_rx_register = cns3xxx_vlan_rx_register; -+ //netdev->vlan_rx_kill_vid = cns3xxx_vlan_rx_kill_vid; -+#endif -+ -+ -+ err = register_netdev(netdev); -+ if (err) { -+ goto err_register_netdev; -+ } -+ -+ netif_carrier_off(netdev); -+ netdev = 0; -+ } -+ } // for (i=0 ; i < netdev_size ; ++i) -+ -+ return 0; -+ -+ -+err_register_netdev: -+ free_netdev(netdev); -+ -+err_alloc_etherdev: -+ return err; -+} -+ -+int cns3xxx_gsw_config_mac_port0(void) -+{ -+ INIT_PORT0_PHY -+ INIT_PORT0_MAC -+ PORT0_LINK_DOWN -+ return 0; -+} -+ -+int cns3xxx_gsw_config_mac_port1(void) -+{ -+ INIT_PORT1_PHY -+ INIT_PORT1_MAC -+ PORT1_LINK_DOWN -+ return 0; -+} -+ -+int cns3xxx_gsw_config_mac_port2(void) -+{ -+ INIT_PORT2_PHY -+ INIT_PORT2_MAC -+ PORT2_LINK_DOWN -+ return 0; -+} -+ -+static int cns3xxx_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr) -+{ -+ // stop the DMA -+ enable_rx_dma(0, 0); -+ enable_tx_dma(0, 0); -+ enable_rx_dma(1, 0); -+ enable_tx_dma(1, 0); -+ -+ // disable Port 0 -+ enable_port(0, 0); -+ enable_port(1, 0); -+ enable_port(2, 0); -+ enable_port(3, 0); -+ return NOTIFY_DONE; -+} -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+static struct net_device *init_napi_dev(struct net_device *ndev, const RingInfo *ring_info) -+{ -+ CNS3XXXPrivate *priv; -+ -+ ndev = alloc_etherdev(sizeof(CNS3XXXPrivate)); -+ if (!ndev) { -+ BUG(); -+ } -+ priv = netdev_priv(ndev); -+ memset(priv, 0, sizeof(CNS3XXXPrivate)); -+ -+ //priv = netdev_priv(napi_dev); -+ priv->num_rx_queues = ring_info->num_rx_queues; -+ priv->num_tx_queues = ring_info->num_tx_queues; -+ priv->rx_ring = ring_info->rx_ring; -+ priv->tx_ring = ring_info->tx_ring; -+ //priv->is_qf=0; // because of memset, so need not the line -+ -+ netif_napi_add(ndev, &priv->napi , cns3xxx_poll, CNS3XXX_NAPI_WEIGHT); -+ dev_hold(ndev); -+ set_bit(__LINK_STATE_START, &ndev->state); -+ -+ return ndev; -+} -+#endif -+ -+ -+void cns3xxx_config_intr(void) -+{ -+ u32 v=0xffffffff; -+ -+ get_interrupt_type(FSRC_RING0_INTERRUPT_ID, &v); -+#if 1 -+ set_interrupt_type(FSRC_RING0_INTERRUPT_ID, RISING_EDGE); -+ get_interrupt_type(FSRC_RING0_INTERRUPT_ID, &v); -+ -+ get_interrupt_type(FSRC_RING1_INTERRUPT_ID, &v); -+ set_interrupt_type(FSRC_RING1_INTERRUPT_ID, RISING_EDGE); -+ get_interrupt_type(FSRC_RING1_INTERRUPT_ID, &v); -+ -+ get_interrupt_type(FSQF_RING0_INTERRUPT_ID, &v); -+ set_interrupt_type(FSQF_RING0_INTERRUPT_ID, RISING_EDGE); -+ get_interrupt_type(FSQF_RING0_INTERRUPT_ID, &v); -+ -+ get_interrupt_type(FSQF_RING1_INTERRUPT_ID, &v); -+ set_interrupt_type(FSQF_RING1_INTERRUPT_ID, RISING_EDGE); -+ get_interrupt_type(FSQF_RING1_INTERRUPT_ID, &v); -+ -+ #ifdef CNS3XXX_USE_MASK -+ get_interrupt_pri(FSRC_RING0_INTERRUPT_ID, &v); -+ set_interrupt_pri(FSRC_RING0_INTERRUPT_ID, 0xc); -+ get_interrupt_pri(FSRC_RING0_INTERRUPT_ID, &v); -+ -+ get_interrupt_pri(FSRC_RING1_INTERRUPT_ID, &v); -+ set_interrupt_pri(FSRC_RING1_INTERRUPT_ID, 0xc); -+ get_interrupt_pri(FSRC_RING1_INTERRUPT_ID, &v); -+ -+ get_interrupt_pri(FSQF_RING1_INTERRUPT_ID, &v); -+ set_interrupt_pri(FSQF_RING1_INTERRUPT_ID, 0xc); -+ get_interrupt_pri(FSQF_RING1_INTERRUPT_ID, &v); -+ -+ #ifndef CONFIG_CNS3XXX_NAPI -+ set_interrupt_pri(FSQF_RING0_INTERRUPT_ID, 0xc); -+ #endif -+ -+ -+ #endif // CNS3XXX_USE_MASK -+#endif -+} -+ -+static int __devinit cns3xxx_init(struct platform_device *pdev) -+{ -+ // when tx_ring/rx_ring alloc memory, -+ // don't free them until cns3xxx_exit_module -+ -+ struct eth_plat_info *plat = pdev->dev.platform_data; -+ init_port = plat->ports; -+ memcpy(cpu_vlan_table_entry.my_mac, plat->cpu_hwaddr, ETH_ALEN); -+#if defined (CONFIG_CNS3XXX_SPPE) -+ memcpy(net_device_prive[3].mac, plat->cpu_hwaddr, ETH_ALEN); -+#endif -+ -+ RingInfo ring_info; -+ int i=0; -+ //spin_lock_init(&star_gsw_send_lock); -+ -+ -+#ifdef CNS3XXX_DOUBLE_RX_RING -+ ring_info.num_rx_queues = 2; -+#else -+ ring_info.num_rx_queues = 1; -+#endif -+ -+#ifdef CNS3XXX_DOUBLE_TX_RING -+ ring_info.num_tx_queues = 2; -+#else -+ ring_info.num_tx_queues = 1; -+#endif -+ -+ ring_info.rx_ring = kcalloc(ring_info.num_rx_queues, sizeof(RXRing), GFP_KERNEL); -+ if (!ring_info.rx_ring) -+ return -ENOMEM; -+ -+ for (i=0 ; i < ring_info.num_rx_queues ; ++i) { -+ memset(ring_info.rx_ring + i, 0, sizeof(RXRing)); -+ } -+ -+ -+ ring_info.tx_ring = kcalloc(ring_info.num_tx_queues, sizeof(TXRing), GFP_KERNEL); -+ -+ -+ if (!ring_info.tx_ring) -+ return -ENOMEM; -+ -+ for (i=0 ; i < ring_info.num_tx_queues ; ++i) { -+ memset(ring_info.tx_ring + i, 0, sizeof(TXRing)); -+ } -+ -+ -+ g_ring_info = ring_info; -+ -+ cns3xxx_gsw_hw_init(); -+ -+#ifdef CONFIG_FPGA -+ // GIGA mode disable -+ MAC0_CFG_REG &= (~(1<<16)); -+ MAC1_CFG_REG &= (~(1<<16)); -+ MAC2_CFG_REG &= (~(1<<16)); -+#endif -+ -+ if ((init_port & 1) == 1) { -+ memcpy(vlan_table_entry[0].my_mac, plat->eth0_hwaddr, ETH_ALEN); -+ memcpy(arl_table_entry[0].mac, plat->eth0_hwaddr, ETH_ALEN); -+ memcpy(net_device_prive[0].mac, plat->eth0_hwaddr, ETH_ALEN); -+ cns3xxx_gsw_config_mac_port0(); -+ } -+ -+ if (((init_port >> 1) & 1) == 1) { -+ memcpy(vlan_table_entry[1].my_mac, plat->eth1_hwaddr, ETH_ALEN); -+ memcpy(arl_table_entry[1].mac, plat->eth1_hwaddr, ETH_ALEN); -+ memcpy(net_device_prive[1].mac, plat->eth1_hwaddr, ETH_ALEN); -+ cns3xxx_gsw_config_mac_port1(); -+ } -+ -+ if (((init_port >> 2) & 1) == 1) { -+ memcpy(vlan_table_entry[2].my_mac, plat->eth2_hwaddr, ETH_ALEN); -+ memcpy(arl_table_entry[2].mac, plat->eth2_hwaddr, ETH_ALEN); -+ memcpy(net_device_prive[2].mac, plat->eth2_hwaddr, ETH_ALEN); -+ cns3xxx_gsw_config_mac_port2(); -+ } -+ -+ cns3xxx_probe(ring_info); -+ cns3xxx_config_intr(); -+ -+#ifdef CNS3XXX_VLAN_8021Q -+#ifdef CNS3XXX_NIC_MODE_8021Q -+ cns3xxx_nic_mode(1); -+#endif -+#endif -+ spin_lock_init(&tx_lock); -+ spin_lock_init(&rx_lock); -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+ napi_dev = init_napi_dev(napi_dev, &ring_info); -+ #ifdef CNS3XXX_DOUBLE_RX_RING -+ r1_napi_dev = init_napi_dev(r1_napi_dev, &ring_info); -+ #endif -+#endif -+ -+ register_reboot_notifier(&cns3xxx_notifier_reboot); -+ clear_fs_dma_state(0); -+ -+ if (ring_info.num_rx_queues == 2) { -+ // enable RX dobule ring -+ DMA_RING_CTRL_REG |= 1; -+ } -+ -+ if (ring_info.num_tx_queues == 2 ) { -+ // enable TX dobule ring -+ DMA_RING_CTRL_REG |= (1 << 16); -+ } -+ -+ -+ return 0; -+} -+ -+static int __devexit cns3xxx_remove(struct platform_device *pdev) -+{ -+ int i=0; -+ -+#if 1 -+ for (i=0 ; i < NETDEV_SIZE ; ++i) { -+ CNS3XXXPrivate *priv = 0; -+ -+ if (net_dev_array[i]){ -+ priv = netdev_priv(net_dev_array[i]); -+ -+ kfree(priv->tx_ring); -+ priv->tx_ring = 0; -+ -+ kfree(priv->rx_ring); -+ priv->rx_ring = 0; -+ -+ unregister_netdev(net_dev_array[i]); -+ free_netdev(net_dev_array[i]); -+ } -+ -+ -+#if 0 -+ sprintf(netdev_name, "eth%d", i); -+ netdev=__dev_get_by_name(&init_net, netdev_name); -+ // if no unregister_netdev and free_netdev, -+ // after remove module, ifconfig will hang. -+ #if 1 -+ if (netdev) { -+ unregister_netdev(netdev); -+ free_netdev(netdev); -+ } -+#endif -+ #endif -+ } -+#endif -+ -+#ifdef CONFIG_CNS3XXX_NAPI -+ free_netdev(napi_dev); -+ #ifdef CNS3XXX_DOUBLE_RX_RING -+ free_netdev(r1_napi_dev); -+ #endif -+#endif -+ -+ -+#if 0 -+ //star_gsw_buffer_free(); -+#endif -+ unregister_reboot_notifier(&cns3xxx_notifier_reboot); -+} -+ -+ -+// this snippet code ref 8139cp.c -+#if defined(CNS3XXX_VLAN_8021Q) -+void cns3xxx_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ priv->vlgrp = grp; -+ spin_unlock_irqrestore(&priv->lock, flags); -+} -+ -+void cns3xxx_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) -+{ -+ CNS3XXXPrivate *priv = netdev_priv(dev); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&priv->lock, flags); -+ // reference: linux-2.6.24-current/drivers/netvia-velocity.c -+ vlan_group_set_device(priv->vlgrp, vid, NULL); -+ //priv->vlgrp->vlan_devices[vid] = NULL; -+ spin_unlock_irqrestore(&priv->lock, flags); -+} -+ -+#endif -+ -+static struct platform_driver drv = { -+ .driver.name = "cns3xxx-net", -+ .probe = cns3xxx_init, -+ .remove = cns3xxx_remove, -+}; -+ -+static int __init cns3xxx_init_module(void) -+{ -+ return platform_driver_register(&drv); -+} -+ -+static void __exit cns3xxx_exit_module(void) -+{ -+ platform_driver_unregister(&drv); -+} -+ -+MODULE_AUTHOR("Cavium Networks, <tech@XXXX.com>"); -+MODULE_DESCRIPTION("CNS3XXX Switch Driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(cns3xxx_init_module); -+module_exit(cns3xxx_exit_module); -+ ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_phy.c -@@ -0,0 +1,1968 @@ -+/******************************************************************************* -+ * -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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 -+1* 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+#include "cns3xxx_phy.h" -+#include "cns3xxx_symbol.h" -+ -+ -+#if defined(LINUX_KERNEL) -+#include "cns3xxx_tool.h" -+#include <linux/cns3xxx/switch_api.h> // for CAVM_OK ... macro -+#include <linux/delay.h> -+#include "cns3xxx_config.h" -+#else // u-boot -+#include <common.h> -+#include "cns3xxx_switch_type.h" -+#define printk printf -+#endif -+ -+int cns3xxx_phy_reset(u8 phy_addr) -+{ -+ u16 phy_data=0; -+ -+ if (cns3xxx_read_phy(phy_addr, 0, &phy_data) != CAVM_OK) -+ return CAVM_ERR; -+ phy_data |= (0x1 << 15); -+ if (cns3xxx_write_phy(phy_addr, 0, phy_data) != CAVM_OK) -+ return CAVM_ERR; -+ -+ return CAVM_OK; -+} -+ -+// mac_port: 0, 1, 2 -+int cns3xxx_enable_mac_clock(u8 mac_port, u8 en) -+{ -+ switch (mac_port) -+ { -+ case 0: -+ { -+ (en==1)?(PHY_AUTO_ADDR_REG |= 1 << 7) :(PHY_AUTO_ADDR_REG &= (~(1 << 7)) ); -+ break; -+ } -+ case 1: -+ { -+ (en==1)?(PHY_AUTO_ADDR_REG |= (1 << 15)) :(PHY_AUTO_ADDR_REG &= (~(1 << 15)) ); -+ break; -+ } -+ case 2: -+ { -+ (en==1)?(PHY_AUTO_ADDR_REG |= (1 << 23)) :(PHY_AUTO_ADDR_REG &= (~(1 << 23)) ); -+ break; -+ } -+ } -+ -+ return CAVM_OK; -+} -+ -+// dis: 1 disable -+// dis: 0 enable -+int cns3xxx_phy_auto_polling_enable(u8 port, u8 en) -+{ -+ u8 phy_addr[]={5, 13, 21}; -+ -+ PHY_AUTO_ADDR_REG &= (~(1 << phy_addr[port])); -+ if (en) { -+ PHY_AUTO_ADDR_REG |= (1 << phy_addr[port]); -+ } -+ return CAVM_OK; -+} -+ -+// dis: 1 disable -+// dis: 0 enable -+int cns3xxx_mdc_mdio_disable(u8 dis) -+{ -+ -+ PHY_CTRL_REG &= (~(1 << 7)); -+ if (dis) { -+ PHY_CTRL_REG |= (1 << 7); -+ } -+ return CAVM_OK; -+} -+ -+ -+static int cns3xxx_phy_auto_polling_conf(int mac_port, u8 phy_addr) -+{ -+ if ( (mac_port < 0) || (mac_port > 2) ) { -+ return CAVM_ERR; -+ } -+ -+ switch (mac_port) -+ { -+ case 0: -+ { -+ PHY_AUTO_ADDR_REG &= (~0x1f); -+ PHY_AUTO_ADDR_REG |= phy_addr; -+ break; -+ } -+ case 1: -+ { -+ PHY_AUTO_ADDR_REG &= (~(0x1f << 8)); -+ PHY_AUTO_ADDR_REG |= (phy_addr << 8); -+ break; -+ } -+ case 2: -+ { -+ PHY_AUTO_ADDR_REG &= (~(0x1f << 16)); -+ PHY_AUTO_ADDR_REG |= (phy_addr << 16); -+ break; -+ } -+ } -+ cns3xxx_phy_auto_polling_enable(mac_port, 1); -+ return CAVM_OK; -+} -+ -+ -+ -+int cns3xxx_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data) -+{ -+ int delay=0; -+ u32 volatile tmp = PHY_CTRL_REG; -+ -+ PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit -+ // delay -+ for (delay=0; delay<10; delay++); -+ tmp &= (~0x1f); -+ tmp |= phy_addr; -+ -+ tmp &= (~(0x1f << 8)); -+ tmp |= (phy_reg << 8); -+ -+ tmp |= (1 << 14); // read command -+ -+ PHY_CTRL_REG = tmp; -+ -+ // wait command complete -+ while ( ((PHY_CTRL_REG >> 15) & 1) == 0); -+ -+ *read_data = (PHY_CTRL_REG >> 16); -+ -+ PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit -+ -+ return CAVM_OK; -+} -+ -+int cns3xxx_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data) -+{ -+ int delay=0; -+ u32 tmp = PHY_CTRL_REG; -+ -+ PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit -+ // delay -+ for (delay=0; delay<10; delay++); -+ -+ tmp &= (~(0xffff << 16)); -+ tmp |= (write_data << 16); -+ -+ tmp &= (~0x1f); -+ tmp |= phy_addr; -+ -+ tmp &= (~(0x1f << 8)); -+ tmp |= (phy_reg << 8); -+ -+ tmp |= (1 << 13); // write command -+ -+ PHY_CTRL_REG = tmp; -+ -+ // wait command complete -+ while ( ((PHY_CTRL_REG >> 15) & 1) == 0); -+ -+ return CAVM_OK; -+} -+ -+// port 0,1,2 -+void cns3xxx_rxc_dly(u8 port, u8 val) -+{ -+ switch (port) -+ { -+ case 0: -+ { -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 4)); -+ SLK_SKEW_CTRL_REG |= (val << 4); -+ break; -+ } -+ case 1: -+ { -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 12)); -+ SLK_SKEW_CTRL_REG |= (val << 12); -+ break; -+ } -+ case 2: -+ { -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 20)); -+ SLK_SKEW_CTRL_REG |= (val << 20); -+ break; -+ } -+ } -+} -+ -+// port 0,1,2 -+void cns3xxx_txc_dly(u8 port, u8 val) -+{ -+ switch (port) -+ { -+ case 0: -+ { -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 6)); -+ SLK_SKEW_CTRL_REG |= (val << 6); -+ break; -+ } -+ case 1: -+ { -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 14)); -+ SLK_SKEW_CTRL_REG |= (val << 14); -+ break; -+ } -+ case 2: -+ { -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 22)); -+ SLK_SKEW_CTRL_REG |= (val << 22); -+ break; -+ } -+ } -+} -+ -+void cns3xxx_mac2_gtxd_dly(u8 val) -+{ -+ SLK_SKEW_CTRL_REG &= (~(0x3 << 24)); -+ SLK_SKEW_CTRL_REG |= (val << 24); -+} -+ -+// VITESSE suggest use isolate bit. -+int vsc8601_power_down(int phy_addr, int y) -+{ -+ u16 phy_data = 0; -+ /* set isolate bit instead of powerdown */ -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ if (y==1) // set isolate -+ phy_data |= (0x1 << 10); -+ if (y==0) // unset isolate -+ phy_data &= (~(0x1 << 10)); -+ cns3xxx_write_phy(phy_addr, 0, phy_data); -+ -+ return 0; -+} -+ -+ -+// port : 0 => port0 ; port : 1 => port1 -+// y = 1 ; disable AN -+void disable_AN(int port, int y) -+{ -+ u32 mac_port_config=0; -+ -+ switch (port) -+ { -+ case 0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case 1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case 2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ -+ // disable PHY's AN -+ if (y==1) -+ { -+ mac_port_config &= ~(0x1 << 7); -+ } -+ -+ // enable PHY's AN -+ if (y==0) -+ { -+ mac_port_config |= (0x1 << 7); -+ } -+ -+ switch (port) -+ { -+ case 0: -+ { -+ MAC0_CFG_REG = mac_port_config; -+ break; -+ } -+ case 1: -+ { -+ MAC1_CFG_REG = mac_port_config; -+ break; -+ } -+ case 2: -+ { -+ MAC2_CFG_REG = mac_port_config; -+ break; -+ } -+ } -+} -+ -+int cns3xxx_std_phy_power_down(int phy_addr, int y) -+{ -+ u16 phy_data = 0; -+ // power-down or up the PHY -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ if (y==1) // down -+ phy_data |= (0x1 << 11); -+ if (y==0) // up -+ phy_data &= (~(0x1 << 11)); -+ cns3xxx_write_phy(phy_addr, 0, phy_data); -+ -+ phy_data=0; -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ -+ return 0; -+} -+ -+ -+#if defined(LINUX_KERNEL) -+int cns3xxx_spi_tx_rx_n(u32 tx_data, u32 *rx_data, u32 tx_channel, u32 tx_eof_flag) -+{ -+ u8 cns3xxx_spi_tx_rx(u8 tx_channel, u8 tx_eof, u32 tx_data, u32 * rx_data); -+ -+ return cns3xxx_spi_tx_rx(tx_channel, tx_eof_flag, tx_data, rx_data); -+} -+ -+int bcm53115M_reg_read(int page, int offset, u8 *buf, int len) -+{ -+ u32 ch = BCM53115_SPI_CHANNEL; -+ u8 cmd_byte; -+ u32 dumy_word; -+ u32 spi_status; -+ int i; -+ -+ /* -+ * Normal SPI Mode (Command Byte) -+ * Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 -+ * 0 1 1 Mode=0 CHIP_ID2 ID1 ID0(lsb) Rd/Wr(0/1) -+ * -+ */ -+ -+ /* Normal Read Operation */ -+ /* 1. Issue a normal read command(0x60) to poll the SPIF bit in the -+ SPI status register(0XFE) to determine the operation can start */ -+ do -+ { -+ cmd_byte = 0x60; -+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0xFE, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0x00, &spi_status, ch, 1); -+ udelay(100); -+ }while ((spi_status >> ROBO_SPIF_BIT) & 1) ; // wait SPI bit to 0 -+ -+ /* 2. Issue a normal write command(0x61) to write the register page value -+ into the SPI page register(0xFF) */ -+ cmd_byte = 0x61; -+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0xFF, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(page, &dumy_word, ch, 1); -+ -+ /* 3. Issue a normal read command(0x60) to setup the required RobiSwitch register -+ address */ -+ cmd_byte = 0x60; -+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(offset, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0x00, &dumy_word, ch, 1); -+ -+ /* 4. Issue a normal read command(0x60) to poll the RACK bit in the -+ SPI status register(0XFE) to determine the completion of read */ -+ do -+ { -+ cmd_byte = 0x60; -+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0xFE, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0x00, &spi_status, ch, 1); -+ udelay(100); -+ }while (((spi_status >> ROBO_RACK_BIT) & 1) == 0); // wait RACK bit to 1 -+ -+ /* 5. Issue a normal read command(0x60) to read the specific register's conternt -+ placed in the SPI data I/O register(0xF0) */ -+ cmd_byte = 0x60; -+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0xF0, &dumy_word, ch, 0); -+ // read content -+ for (i=0; i<len; i++) { -+ cns3xxx_spi_tx_rx_n(0x00, &dumy_word, ch, ((i==(len-1)) ? 1 : 0)); -+ buf[i] = (u8)dumy_word; -+ } -+ -+ return 0; -+ -+} -+ -+int bcm53115M_reg_write(int page, int offset, u8 *buf, int len) -+{ -+ u32 ch = BCM53115_SPI_CHANNEL; -+ u8 cmd_byte; -+ u32 dumy_word; -+ u32 spi_status; -+ int i; -+ -+ /* -+ * Normal SPI Mode (Command Byte) -+ * Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 -+ * 0 1 1 Mode=0 CHIP_ID2 ID1 ID0(lsb) Rd/Wr(0/1) -+ * -+ */ -+ -+ /* Normal Write Operation */ -+ /* 1. Issue a normal read command(0x60) to poll the SPIF bit in the -+ SPI status register(0XFE) to determine the operation can start */ -+ -+ do -+ { -+ cmd_byte = 0x60; -+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0xFE, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0x00, &spi_status, ch, 1); -+ }while ((spi_status >> ROBO_SPIF_BIT) & 1) ; // wait SPI bit to 0 -+ -+ /* 2. Issue a normal write command(0x61) to write the register page value -+ into the SPI page register(0xFF) */ -+ cmd_byte = 0x61; -+ cns3xxx_spi_tx_rx_n((u32)cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(0xFF, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(page, &dumy_word, ch, 1); -+ -+ /* 3. Issue a normal write command(0x61) and write the address of the accessed -+ register followed by the write content starting from a lower byte */ -+ cmd_byte = 0x61; -+ cns3xxx_spi_tx_rx_n((u32)cmd_byte, &dumy_word, ch, 0); -+ cns3xxx_spi_tx_rx_n(offset, &dumy_word, ch, 0); -+ // write content -+ for (i=0; i<len; i++) { -+ cns3xxx_spi_tx_rx_n((u32)buf[i], &dumy_word, ch, ((i==(len-1)) ? 1 : 0)); -+ } -+ -+ return 0; -+} -+ -+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state); -+ -+void bcm53115M_init_mac(u8 mac_port, u16 phy_addr) -+{ -+ u32 mac_port_config = 0; -+ u8 mac_addr[]={0x0c, 0x10, 0x18}; -+ -+ cns3xxx_enable_mac_clock(mac_port, 1); -+ cns3xxx_phy_auto_polling_enable(mac_port, 0); -+ -+ mac_port_config = SWITCH_REG_VALUE(mac_addr[mac_port]); -+ -+ // enable GMII, MII, reverse MII -+ mac_port_config &= (~(1 << 15)); -+ -+ // enable RGMII -+ mac_port_config |= (1 << 15); -+ -+ // disable GIGA mode -+ mac_port_config &= (~(1<<16)); -+ -+ // enable GIGA mode -+ mac_port_config |= (1<<16); -+ -+ // disable PHY's AN -+ mac_port_config &= (~(0x1 << 7)); -+ -+ // force 1000Mbps -+ mac_port_config &= (~(0x3 << 8)); -+ mac_port_config |= (0x2 << 8); -+ -+ // force duplex -+ mac_port_config |= (0x1 << 10); -+ -+ // TX flow control on -+ mac_port_config |= (0x1 << 12); -+ -+ // RX flow control on -+ mac_port_config |= (0x1 << 11); -+ -+ // Turn off GSW_PORT_TX_CHECK_EN_BIT -+ mac_port_config &= (~(0x1 << 13)); -+ -+ // Turn on GSW_PORT_TX_CHECK_EN_BIT -+ mac_port_config |= (0x1 << 13); -+ -+ SWITCH_REG_VALUE(mac_addr[mac_port]) = mac_port_config; -+} -+ -+typedef struct bcm53115M_vlan_entry_t -+{ -+ u16 vid; -+ u16 forward_map; -+ u16 untag_map; -+}bcm53115M_vlan_entry; -+ -+ -+ -+int bcm53115M_write_vlan(bcm53115M_vlan_entry *v) -+{ -+ u8 bval; -+ u16 wval; -+ u32 dwval; -+ -+ // fill vid -+ wval = (u16)v->vid; -+ bcm53115M_reg_write(0x05, 0x81, (u8*)&wval, 2); -+ -+ // fill table content -+ dwval = 0; -+ dwval |= (v->forward_map & 0x1FF); -+ dwval |= ((v->untag_map& 0x1FF) << 9); -+ bcm53115M_reg_write(0x05, 0x83, (u8*)&wval, 4); -+ -+ // write cmd -+ bval = VLAN_WRITE_CMD; -+ bval |= (1 << VLAN_START_BIT); -+ bcm53115M_reg_write(0x05, 0x80, (u8*)&bval, 1); -+ -+ // wait cmd complete -+ while(1) { -+ bcm53115M_reg_read(0x05, 0x80, (u8*)&bval, 1); -+ if (((bval >> VLAN_START_BIT) & 1) == 0) break; -+ } -+ -+ return CAVM_OK; -+} -+ -+typedef struct bcm_port_cfg_t -+{ -+ u8 link; -+ u8 fdx; -+ BCM_PORT_SPEED speed; -+ u8 rx_flw_ctrl; -+ u8 tx_flw_ctrl; -+ u8 ow; -+}bcm_port_cfg; -+ -+ -+ -+int bcm53115M_mac_port_config(int port, bcm_port_cfg *cfg) -+{ -+ u8 bval = 0; -+ int page, addr; -+ -+ if (cfg->link) bval |= (1<<0); -+ if (cfg->fdx) bval |= (1<<1); -+ bval |= ((cfg->speed&0x3) << 2); -+ if (cfg->rx_flw_ctrl) bval |= (1<<4); -+ if (cfg->tx_flw_ctrl) bval |= (1<<5); -+ -+ if (port == BCM_PORT_IMP) { -+ bval |= (1<<7); // Use content of this register -+ page = 0x00; -+ addr = 0x0E; -+ }else { -+ page = 0x00; -+ addr = 0x58+port; -+ } -+ -+ bcm53115M_reg_write(page, addr, &bval, 1); -+ -+ return 0; -+} -+ -+int bcm53115M_init_internal_phy(void) -+{ -+ int p, page; -+ u16 wval; -+ -+ for (p=BCM_PORT_0; p<=BCM_PORT_4; p++) { -+ page = 0x10+p; -+ -+ // reset phy -+ bcm53115M_reg_read(page, 0x00, (u8*)&wval, 2); -+ wval |= 0x8000; -+ bcm53115M_reg_write(page, 0x00, (u8*)&wval, 2); -+ -+ // config auto-nego & all advertisement -+ bcm53115M_reg_read(page, 0x00, (u8*)&wval, 2); -+ wval |= (1<<12); // auto-nego -+ bcm53115M_reg_write(page, 0x00, (u8*)&wval, 2); -+ -+ bcm53115M_reg_read(page, 0x08, (u8*)&wval, 2); -+ wval |= 0x1E0; // advertisement all -+ bcm53115M_reg_write(page, 0x08, (u8*)&wval, 2); -+ -+ // 1000BASE-T -+ bcm53115M_reg_read(page, 0x12, (u8*)&wval, 2); -+ wval &= ~(1<<12); // automatic master/slave configuration -+ wval |= 0x300; // 1000-base full/half advertisements -+ bcm53115M_reg_write(page, 0x12, (u8*)&wval, 2); -+ } -+ -+ return 0; -+} -+ -+int bcm53115M_led_init(void) -+{ -+ u16 led_func, bval, wval; -+ -+ /* LED function 1G/ACT, 100M/ACT, 10M/ACT, not used */ -+ led_func = 0x2C00; -+ bcm53115M_reg_write(0x00, 0x10, (u8*)&led_func, 2); -+ bcm53115M_reg_write(0x00, 0x12, (u8*)&led_func, 2); -+ -+ /* LED map enable */ -+ wval = 0x1F; // port0~4 -+ bcm53115M_reg_write(0x00, 0x16, (u8*)&wval, 2); -+ -+ /* LED mode map */ -+ wval = 0x1F; // led auto mode -+ bcm53115M_reg_write(0x00, 0x18, (u8*)&wval, 2); -+ bcm53115M_reg_write(0x00, 0x1A, (u8*)&wval, 2); -+ -+ /* LED enable */ -+ bcm53115M_reg_read(0x00, 0x0F, (u8*)&bval, 1); -+ bval |= 0x80; -+ bcm53115M_reg_write(0x00, 0x0F, (u8*)&bval, 1); -+ -+ return 0; -+} -+ -+//#define BCM53115M_DUMMY_SWITCH -+#define BCM53115M_DISABLE_LEARNING -+ -+int bcm53115M_init(u8 mac_port, u16 phy_addr) -+{ -+ u32 u32_val=0; -+ u16 u16_val=0; -+ u8 bval=0; -+ int i=0; -+ bcm53115M_vlan_entry v_ent; -+ bcm_port_cfg pc; -+ u8 page=0, offset=0; -+ -+ printk("bcm53115M init\n"); -+ -+ memset(&v_ent, 0, sizeof(bcm53115M_vlan_entry)); -+ -+ // gpio B pin 18 -+ gpio_direction_output(50, 0); -+ bcm53115M_init_mac(0, 0); -+ bcm53115M_init_mac(1, 1); -+ -+ // read device id -+ bcm53115M_reg_read(0x02, 0x30, (u8*)&u32_val, 4); -+ printk("bcm53115M device id:(0x%x)\r\n", u32_val); -+ -+ if (u32_val != 0x53115) { -+ printk("bad device id(0x%x)\r\n", u32_val); -+ return -1; -+ } -+ -+ u16_val=0; -+ // read phy id -+ bcm53115M_reg_read(0x10, 0x04, (u8 *)&u16_val, 2); -+ printk("bcm53115M phy id_1:(0x%x)\r\n", u16_val); -+ -+ if (u16_val != 0x143) { -+ printk("bad phy id1(0x%x)\r\n", u16_val); -+ return CAVM_ERR; -+ } -+ -+ u16_val=0; -+ // read phy id2 -+ bcm53115M_reg_read(0x10, 0x06, (u8 *)&u16_val, 2); -+ printk("bcm53115M phy id_2:(0x%x)\r\n", u16_val); -+ -+#ifdef BCM53115M_DUMMY_SWITCH -+ bval=0; -+ bcm53115M_reg_read(0x00, 0x0e, (u8 *)&bval, 1); -+ printk("bcm53115M page:0 addr:0x0e ## %x\n", bval); -+ bval |= (1 << 7); -+ bval |= 1; -+ -+ bval = 0x8b; -+ bval |= (1 << 5); -+ bval |= (1 << 4); -+ printk("bval : %x\n", bval); -+ bcm53115M_reg_write(0x00, 0x0e, (u8 *)&bval, 1); -+ bcm53115M_reg_read(0x00, 0x0e, (u8 *)&bval, 1); -+ printk("bcm53115M page:0 addr:0x0e ## %x\n", bval); -+ -+ /* Unmanagement mode */ -+ // Switch Mode. Page 00h,Address 0Bh -+ bval = 0x06; // forward enable, unmanaged mode -+ //bval = 0x3; // forward enable, managed mode -+ bcm53115M_reg_write(0x0, 0xb, &bval, 1); -+ bcm53115M_reg_read(0x0, 0xb, (u8 *)&bval, 1); -+ printk("bcm53115M page:0 addr:0xb ## %x\n", bval); -+ -+ page=0x0; -+ offset=0x5d; // port 5 -+ bval=0x7b; -+ bcm53115M_reg_write(page, offset, (u8 *)&bval, 1); -+ bcm53115M_reg_read(page, offset, (u8 *)&bval, 1); -+ -+ printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, bval); -+ -+ page=0x0; -+ offset=0x58; // port 0 -+ bval=0x7b; -+ bcm53115M_reg_write(page, offset, (u8 *)&bval, 1); -+ bcm53115M_reg_read(page, offset, (u8 *)&bval, 1); -+ printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, bval); -+ -+#ifdef CONFIG_CNS3XXX_JUMBO_FRAME -+ printk("enable BCM53115 jumbo frame\n"); -+ -+ page=0x40; -+ offset=0x01; -+ u32_val=0x013f; // enable 0-5 port and IMP port jumbo frame. MAX frame: 9720 bytes. -+ bcm53115M_reg_write(page, offset, (u8 *)&u32_val, 4); -+ bcm53115M_reg_read(page, offset, (u8 *)&u32_val, 4); -+ printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, u32_val); -+ -+#if 0 -+ page=0x40; -+ offset=0x05; -+ u16_val=0; -+ bcm53115M_reg_write(page, offset, (u8 *)&u16_val, 2); -+#endif -+ -+#endif -+ -+#else // !BCM53115M_DUMMY_SWITCH -+ /* Loop detection disable */ -+ bcm53115M_reg_read(0x72, 0x00, (u8 *)&u16_val, 2); -+ u16_val &= ~(0x3<<11); -+ bcm53115M_reg_write(0x72, 0x00, (u8 *)&u16_val, 2); -+ -+ -+ /* VLAN forwarding mask */ -+ // Bit8 IMP port, Bits[5:0] correspond to ports[5:0] -+ // port 0 <-> port IMP -+ u16_val = 0x103; -+ bcm53115M_reg_write(0x31, 0x0, (u8 *)&u16_val, 2); // port 0 -+ u16_val = 0x103; -+ bcm53115M_reg_write(0x31, 0x10, (u8 *)&u16_val, 2); // IMP -+ -+ -+ // port 4 <-> port 5 -+ u16_val = 0x3c; -+ bcm53115M_reg_write(0x31, 0x08, (u8 *)&u16_val, 2); // port 4 -+ u16_val = 0x3c; -+ bcm53115M_reg_write(0x31, 0x0A, (u8 *)&u16_val, 2); // port 5 -+ -+ -+ // others <-> none -+ u16_val = 0x00; -+ bcm53115M_reg_write(0x31, 0x02, (u8 *)&u16_val, 2); // port 1 -+ bcm53115M_reg_write(0x31, 0x04, (u8 *)&u16_val, 2); // port 2 -+ bcm53115M_reg_write(0x31, 0x06, (u8 *)&u16_val, 2); // port 3 -+ -+ // port 1 <-> port IMP -+ u16_val = 0x103; -+ bcm53115M_reg_write(0x31, 0x2, (u8 *)&u16_val, 2); // port 1 -+ -+ // port 2 <-> port 5 -+ u16_val = 0x3c; -+ bcm53115M_reg_write(0x31, 0x4, (u8 *)&u16_val, 2); // port 2 -+ -+ // port 3 <-> port 5 -+ u16_val = 0x3c; -+ bcm53115M_reg_write(0x31, 0x6, (u8 *)&u16_val, 2); // port 3 -+ -+ /* Create VLAN1 for default port pvid */ -+#if 0 -+ v_ent.vid = 1; -+ v_ent.forward_map = 0x13F; // all ports -+ robo_write_vlan(&v_ent); -+#endif -+ -+ /* Unmanagement mode */ -+ // Switch Mode. Page 00h,Address 0Bh -+ bval = 0x02; // forward enable, unmanaged mode -+ bcm53115M_reg_write(0x0, 0xb, &bval, 1); -+ -+ /* Init port5 & IMP (test giga mode first) */ -+ // IMP port control. Page 00h,Address 08h -+ bval = 0x1C; // RX UCST/MCST/BCST enable -+ bcm53115M_reg_write(0x0, 0x8, &bval, 1); -+ -+ offset=0x5d; // port 5 -+ bval=0x7b; -+ bcm53115M_reg_write(page, offset, (u8 *)&bval, 1); -+ bcm53115M_reg_read(page, offset, (u8 *)&bval, 1); -+ -+ // Speed, dulplex......etc -+ // setting in Gsw_Configure_Gsw_Hardware() -+ -+ // Mgmt configuration, Page 02h, Address 00h -+ bval = 0; -+ bcm53115M_reg_write(0x02, 0x00, &bval, 1); -+ // BRCM header, Page 02h, Address 03h -+ bval = 0; // without additional header information -+ bcm53115M_reg_write(0x02, 0x03, &bval, 1); -+ -+ /* Init front ports, port0-4 */ -+ // MAC -+ pc.speed = BCM_PORT_1G; -+ pc.link = 0; // link detect by robo_port_update() -+ pc.ow = 0; -+ for (i=BCM_PORT_0; i<=BCM_PORT_4; i++) -+ bcm53115M_mac_port_config(i, &pc); -+ // Internal Phy -+ bcm53115M_init_internal_phy(); -+ -+ /* Enable all port, STP_STATE=No spanning tree, TX/RX enable */ -+ // Page 00h, Address 00h-05h -+ bval = 0x0; -+ for (i=0; i<=5; i++) -+ bcm53115M_reg_write(0x0, i, &bval, 1); -+ -+ // Disable broadcast storm control due to h/w strap pin BC_SUPP_EN -+ // Page 41h, Address 10h-13h, bit28&22 -+ -+ // for port 0 ~ 5 -+ for (i=0 ; i <= 0x14; i+=4) { -+ bcm53115M_reg_read(0x41, 0x10+i, (u8 *)&u32_val, 4); -+ u32_val &= ~((1<<28) | (1<<22)); -+ bcm53115M_reg_write(0x41, 0x10+i, (u8 *)&u32_val, 4); -+ } -+ -+ // for IMP port -+ bcm53115M_reg_read(0x41, 0x30, (u8 *)&u32_val, 4); -+ u32_val &= ~((1<<28) | (1<<22)); -+ bcm53115M_reg_write(0x41, 0x30, (u8 *)&u32_val, 4); -+ -+ /* Misc */ -+ // led -+ bcm53115M_led_init(); -+ // multicast fwd rule, Page 00h, Address 2Fh -+ bval = 0; -+ bcm53115M_reg_write(0x00, 0x2F, &bval, 1); -+ -+#ifdef BCM53115M_DISABLE_LEARNING -+ // disable learning -+ page=0x00; -+ offset=0x3c; -+ u16_val=0x13f; -+ bcm53115M_reg_write(page, offset, (u8 *)&u16_val, 2); -+ bcm53115M_reg_read(page, offset, (u8 *)&u16_val, 2); -+ -+ page=0x02; -+ offset=0x06; -+ u32_val=4; -+ bcm53115M_reg_write(page, offset, (u8 *)&u32_val, 4); -+#endif -+#endif -+ return CAVM_OK; -+} -+#endif // defined(LINUX_KERNEL) -+ -+//#define MAC2_RGMII -+#define CNS3XXX_MAC2_IP1001_GIGA_MODE -+ -+void icp_ip1001_init_mac(u8 mac_port, u16 phy_addr) -+{ -+ u32 mac_port_config = 0; -+ u8 mac_addr[]={0x0c, 0x10, 0x18}; -+ -+ cns3xxx_enable_mac_clock(mac_port, 1); -+ -+ mac_port_config = SWITCH_REG_VALUE(mac_addr[mac_port]); -+ -+ //cns3xxx_txc_dly(mac_port, 2); -+ //cns3xxx_rxc_dly(mac_port, 2); -+ //SLK_SKEW_CTRL_REG -+#if 1 -+ -+ // enable GMII, MII, reverse MII -+ mac_port_config &= (~(1 << 15)); -+ -+#ifdef MAC2_RGMII -+ mac_port_config |= (1 << 15); -+#endif -+ -+ // TXC check disable -+ //mac_port_config &= (~(1 << 13)); -+ -+ // disable GIGA mode -+ mac_port_config &= (~(1<<16)); -+ -+#ifdef CNS3XXX_MAC2_IP1001_GIGA_MODE -+ // enable GIGA mode -+ mac_port_config |= (1<<16); -+ -+ //mac_port_config |= (1<<19); -+#endif -+ -+ // disable PHY's AN -+ mac_port_config &= (~(0x1 << 7)); -+ -+ // enable PHY's AN -+ mac_port_config |= (0x1 << 7); -+#else -+ // disable PHY's AN -+ mac_port_config &= (~(0x1 << 7)); -+ // disable GIGA mode -+ mac_port_config &= (~(1<<16)); -+ -+ // force 100Mbps -+ mac_port_config &= (~(0x3 << 8)); -+ mac_port_config |= (0x1 << 8); -+ -+ // force duplex -+ mac_port_config |= (0x1 << 10); -+ -+ // TX flow control off -+ mac_port_config &= (~(0x1 << 12)); -+ -+ // RX flow control off -+ mac_port_config &= (~(0x1 << 11)); -+ -+#if 0 -+ // TX flow control on -+ mac_port_config |= (0x1 << 12); -+ -+ // RX flow control on -+ mac_port_config |= (0x1 << 11); -+#endif -+ -+ // enable GMII, MII, reverse MII -+ mac_port_config &= (~(1 << 15)); -+#endif -+ SWITCH_REG_VALUE(mac_addr[mac_port]) = mac_port_config; -+ -+ // If mac port AN turns on, auto polling needs to turn on. -+ cns3xxx_phy_auto_polling_conf(mac_port, phy_addr); -+ -+} -+ -+int icp_ip1001_init(u8 mac_port, u8 phy_addr) -+{ -+ u16 phy_data = 0; -+ -+ printk("mac_port: %d ## phy_addr: %d\n", mac_port, phy_addr); -+ cns3xxx_mdc_mdio_disable(0); -+ -+#if 0 -+ // GMII2 high speed drive strength -+ IOCDA_REG &= ((~3 << 10)); -+ IOCDA_REG |= (1 << 10); -+#endif -+ IOCDA_REG = 0x55555800; -+ -+ phy_data = get_phy_id(phy_addr); // should be 0x243 -+ -+ printk("ICPLUS IP 1001 phy id : %x\n", phy_data); -+ -+ if (phy_data != 0x0243) { -+ printk("wrong phy id!!\n"); -+ return CAVM_ERR; -+ } -+ -+ -+ cns3xxx_phy_reset(phy_addr); -+ -+ icp_ip1001_init_mac(mac_port, phy_addr); -+ -+ // read advertisement register -+ cns3xxx_read_phy(phy_addr, 0x4, &phy_data); -+ -+ // enable PAUSE frame capability -+ phy_data |= (0x1 << 10); -+ -+ phy_data &= (~(0x1 << 5)); -+ phy_data &= (~(0x1 << 6)); -+ phy_data &= (~(0x1 << 7)); -+ phy_data &= (~(0x1 << 8)); -+ -+#if 1 -+ phy_data |= (0x1 << 5); -+ phy_data |= (0x1 << 6); -+ phy_data |= (0x1 << 7); -+ phy_data |= (0x1 << 8); -+#endif -+ -+ cns3xxx_write_phy(phy_addr, 0x4, phy_data); -+ -+ cns3xxx_read_phy(phy_addr, 9, &phy_data); -+ -+ phy_data &= (~(1<<8)); // remove advertise 1000 half duples -+ phy_data &= (~(1<<9)); // remove advertise 1000 full duples -+#ifdef CNS3XXX_MAC2_IP1001_GIGA_MODE -+ //phy_data |= (1<<8); // add advertise 1000 half duples -+ phy_data |= (1<<9); // add advertise 1000 full duples -+#endif -+ cns3xxx_write_phy(phy_addr, 9, phy_data); -+ -+ cns3xxx_read_phy(phy_addr, 9, &phy_data); -+ -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ // AN enable -+ phy_data |= (0x1 << 12); -+ cns3xxx_write_phy(phy_addr, 0, phy_data); -+ -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ // restart AN -+ phy_data |= (0x1 << 9); -+ cns3xxx_write_phy(phy_addr, 0, phy_data); -+ return 0; -+} -+ -+#define PHY_CONTROL_REG_ADDR 0x00 -+#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04 -+ -+int icp_101a_init_mac(u8 port, u8 phy_addr) -+{ -+ u32 mac_port_config = 0; -+ -+ cns3xxx_enable_mac_clock(port, 1); -+ -+ switch (port) -+ { -+ case 0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case 1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case 2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ // enable GMII, MII, reverse MII -+ mac_port_config &= (~(1 << 15)); -+ -+ // disable PHY's AN, use force mode -+ mac_port_config &= (~(0x1 << 7)); -+#ifdef CONFIG_FPGA_FORCE -+ -+ // force 100Mbps -+ mac_port_config &= (~(0x3 << 8)); -+ mac_port_config |= (0x1 << 8); -+ -+ // force duplex -+ mac_port_config |= (0x1 << 10); -+ -+ // TX flow control on -+ mac_port_config |= (0x1 << 12); -+ -+ // RX flow control on -+ mac_port_config |= (0x1 << 11); -+ -+ // Turn off GSW_PORT_TX_CHECK_EN_BIT -+ mac_port_config &= (~(0x1 << 13)); -+#else -+ // enable PHY's AN -+ mac_port_config |= (0x1 << 7); -+ // If mac port AN turns on, auto polling needs to turn on. -+ cns3xxx_phy_auto_polling_conf(port, phy_addr); -+#endif -+ // normal MII -+ mac_port_config &= (~(1 << 14)); -+ -+ -+ switch (port) -+ { -+ case 0: -+ { -+ MAC0_CFG_REG = mac_port_config; -+ break; -+ } -+ case 1: -+ { -+ MAC1_CFG_REG = mac_port_config; -+ break; -+ } -+ case 2: -+ { -+ MAC2_CFG_REG = mac_port_config; -+ break; -+ } -+ } -+ -+ -+ return CAVM_OK; -+} -+ -+int icp_101a_init(u8 mac_port, u8 phy_addr) -+{ -+ u32 mac_port_config=0; -+ u16 phy_data = 0; -+ -+ cns3xxx_mdc_mdio_disable(0); -+ cns3xxx_phy_reset(phy_addr); -+ -+ phy_data = get_phy_id(mac_port); -+ if (phy_data != 0x0243) { -+ printk("ICPLUS 101A phy id should be 0x243, but the phy id is : %x\n", phy_data); -+ return CAVM_ERR; -+ } -+ printk("phy id : %x\n", phy_data); -+ printk("init IC+101A\n"); -+ -+ icp_101a_init_mac(mac_port, phy_addr); -+ -+ // read advertisement register -+ cns3xxx_read_phy(phy_addr, 0x4, &phy_data); -+ -+ // enable PAUSE frame capability -+ phy_data |= (0x1 << 10); -+ -+ cns3xxx_write_phy(phy_addr, 0x4, phy_data); -+ -+#ifndef CONFIG_FPGA_FORCE -+ -+ switch (mac_port) -+ { -+ case 0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case 1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case 2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+#if 0 -+ if (!(mac_port_config & (0x1 << 5))) { -+ if (cns3xxx_read_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, &phy_data) == CAVM_ERR) -+ { -+ //PDEBUG("\n PORT%d, enable local flow control capability Fail\n", port); -+ return CAVM_ERR; -+ } -+ else -+ { -+ // enable PAUSE frame capability -+ phy_data |= (0x1 << 10); -+ -+ if (cns3xxx_write_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, phy_data) == CAVM_ERR) -+ { -+ //PDEBUG("\nPORT%d, enable PAUSE frame capability Fail\n", port); -+ return CAVM_ERR; -+ } -+ } -+ } -+#endif -+ -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ // an enable -+ phy_data |= (0x1 << 12); -+ -+ // restart AN -+ phy_data |= (0x1 << 9); -+ cns3xxx_write_phy(phy_addr, 0, phy_data); -+ -+ while (1) -+ { -+ //PDEBUG ("\n Polling PHY%d AN \n", port); -+ cns3xxx_read_phy (phy_data, 0, &phy_data); -+ -+ if (phy_data & (0x1 << 9)) { -+ continue; -+ } else { -+ //PDEBUG ("\n PHY%d AN restart is complete \n", port); -+ break; -+ } -+ } -+ -+#endif -+ -+ return CAVM_OK; -+} -+ -+int cns3xxx_config_VSC8601_mac(u8 port) -+{ -+ u32 mac_port_config = 0; -+ -+ switch (port) -+ { -+ case 0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case 1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case 2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ switch (port) -+ { -+ case 0: -+ { -+ MAC0_CFG_REG = mac_port_config; -+ break; -+ } -+ case 1: -+ { -+ MAC1_CFG_REG = mac_port_config; -+ break; -+ } -+ case 2: -+ { -+ MAC2_CFG_REG = mac_port_config; -+ break; -+ } -+ } -+ return CAVM_OK; -+} -+ -+u16 get_phy_id(u8 phy_addr) -+{ -+ u16 read_data; -+ -+ cns3xxx_read_phy(phy_addr, 2, &read_data); -+ -+ return read_data; -+} -+ -+u32 get_vsc8601_recv_err_counter(u8 phy_addr) -+{ -+ u16 read_data=0; -+ cns3xxx_read_phy(phy_addr, 19, &read_data); -+ return read_data; -+} -+ -+u32 get_crc_good_counter(u8 phy_addr) -+{ -+ u16 read_data=0; -+ -+ // enter extended register mode -+ cns3xxx_write_phy(phy_addr, 31, 0x0001); -+ -+ cns3xxx_read_phy(phy_addr, 18, &read_data); -+ -+ // back to normal register mode -+ cns3xxx_write_phy(phy_addr, 31, 0x0000); -+ -+ return read_data; -+} -+ -+int cns3xxx_config_VSC8601(u8 mac_port, u8 phy_addr) -+{ -+ u16 phy_data=0; -+ u32 mac_port_config=0; -+ //u8 tx_skew=1, rx_skew=1; -+ u16 phy_id=0; -+ -+ cns3xxx_mdc_mdio_disable(0); -+ -+ cns3xxx_read_phy(phy_addr, 0, &phy_data); -+ // software reset -+ phy_data |= (0x1 << 15); -+ cns3xxx_write_phy(phy_addr, 0, phy_data); -+ udelay(10); -+ -+ phy_id = get_phy_id(phy_addr); -+ if (phy_id != 0x143) { -+ return CAVM_ERR; -+ } -+ -+ switch (mac_port) -+ { -+ case 0: -+ { -+ mac_port_config = MAC0_CFG_REG; -+ break; -+ } -+ case 1: -+ { -+ mac_port_config = MAC1_CFG_REG; -+ break; -+ } -+ case 2: -+ { -+ mac_port_config = MAC2_CFG_REG; -+ break; -+ } -+ } -+ -+ cns3xxx_enable_mac_clock(mac_port, 1); -+ //phy_auto_polling(mac_port, phy_addr); -+ -+ // enable RGMII-PHY mode -+ mac_port_config |= (0x1 << 15); -+ -+ // If mac AN turns on, auto polling needs to turn on. -+ // enable PHY's AN -+ mac_port_config |= (0x1 << 7); -+ cns3xxx_phy_auto_polling_conf(mac_port, phy_addr); -+ -+ // enable GSW MAC port 0 -+ mac_port_config &= ~(0x1 << 18); -+ -+ // normal MII -+ mac_port_config &= (~(1 << 14)); -+ -+ switch (mac_port) -+ { -+ case 0: -+ { -+ MAC0_CFG_REG = mac_port_config; -+ printk("8601 MAC0_CFG_REG: %x\n", MAC0_CFG_REG); -+ break; -+ } -+ case 1: -+ { -+ MAC1_CFG_REG = mac_port_config; -+ printk("8601 MAC1_CFG_REG: %x\n", MAC1_CFG_REG); -+ break; -+ } -+ case 2: -+ { -+ MAC2_CFG_REG = mac_port_config; -+ break; -+ } -+ } -+ -+ cns3xxx_write_phy(phy_addr, 0x18, 0xf1e7); -+ cns3xxx_write_phy(phy_addr, 0x1c, 0x8e00); -+ cns3xxx_write_phy(phy_addr, 0x10, 0x20); -+ cns3xxx_write_phy(phy_addr, 0x1c, 0xa41f); -+ cns3xxx_write_phy(phy_addr, 0x1c, 0xb41a); -+ cns3xxx_write_phy(phy_addr, 0x1c, 0xb863); -+ cns3xxx_write_phy(phy_addr, 0x17, 0xf04); -+ cns3xxx_write_phy(phy_addr, 0x15, 0x1); -+ cns3xxx_write_phy(phy_addr, 0x17, 0x0); -+ -+ return CAVM_OK; -+} -+ -+ -+ -+#ifdef CONFIG_LIBRA -+void icp_175c_all_phy_power_down(int y) -+{ -+ int i=0; -+ -+ for (i=0 ; i < 5 ; ++i) -+ std_phy_power_down(i, y); -+ -+} -+ -+static int star_gsw_config_icplus_175c_phy4(void) -+{ -+ u16 phy_data = 0, phy_data2 = 0; -+ u32 volatile ii, jj; -+ u8 phy_speed_dup = 0, phy_flowctrl = 0; -+ u32 volatile reg; -+ u8 gsw_mac_0_phy_addr = 0; -+ u8 gsw_mac_1_phy_addr = 1; -+ -+ -+ printk("config IC+175C\n"); -+ /* -+ * Configure MAC port 0 -+ * For IP175C Switch setting -+ * Force 100Mbps, and full-duplex, and flow control on -+ */ -+ reg = GSW_MAC_PORT_0_CONFIG_REG; -+ -+ // disable PHY's AN -+ reg &= ~(0x1 << 7); -+ -+ // disable RGMII-PHY mode -+ reg &= ~(0x1 << 15); -+ -+ // force speed = 100Mbps -+ reg &= ~(0x3 << 8); -+ reg |= (0x1 << 8); -+ -+ // force full-duplex -+ reg |= (0x1 << 10); -+ -+ // force Tx/Rx flow-control on -+ reg |= (0x1 << 11) | (0x1 << 12); -+ -+ GSW_MAC_PORT_0_CONFIG_REG = reg; -+ -+ -+ for (ii = 0; ii < 0x2000; ii++) -+ { -+ reg = GSW_MAC_PORT_0_CONFIG_REG; -+ -+ if ((reg & 0x1) && !(reg & 0x2)) -+ { -+ /* -+ * enable MAC port 0 -+ */ -+ reg &= ~(0x1 << 18); -+ -+ -+ /* -+ * enable the forwarding of unknown, multicast and broadcast packets to CPU -+ */ -+ reg &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27)); -+ -+ /* -+ * include unknown, multicast and broadcast packets into broadcast storm -+ */ -+ reg |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31)); -+ -+ GSW_MAC_PORT_0_CONFIG_REG = reg; -+ -+ break; -+ } -+ else -+ { -+ for (jj = 0; jj < 0x1000; jj++); -+ -+ -+ if ((ii % 4) == 0) -+ printk("\rCheck MAC/PHY 0 Link Status : |"); -+ else if ((ii % 4) == 1) -+ printk("\rCheck MAC/PHY 0 Link Status : /"); -+ else if ((ii % 4) == 2) -+ printk("\rCheck MAC/PHY 0 Link Status : -"); -+ else if ((ii % 4) == 3) -+ printk("\rCheck MAC/PHY 0 Link Status : \\"); -+ } -+ } -+ -+ -+ if (!(reg & 0x1) || (reg & 0x2)) -+ { -+ /* -+ * Port 0 PHY link down or no TXC in Port 0 -+ */ -+ printk("\rCheck MAC/PHY 0 Link Status : DOWN!\n"); -+ -+ return -1; -+ } -+ else -+ { -+ printk("\rCheck MAC/PHY 0 Link Status : UP!\n"); -+ } -+ -+ -+ -+ /* -+ * Configure MAC port 1 -+ */ -+ reg = GSW_MAC_PORT_0_CONFIG_REG; -+ -+ // disable MAC's AN -+ reg &= ~(0x1 << 7); -+ -+ GSW_MAC_PORT_0_CONFIG_REG = reg; -+ -+ -+ /* enable flow control on (PAUSE frame) */ -+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x4, &phy_data); -+ -+ phy_data |= (0x1 << 10); -+ -+ star_gsw_write_phy(gsw_mac_1_phy_addr, 0x4, phy_data); -+ -+#if 1 -+ /* 2007/12/18 Jerry -+ The software reset of IC+ 175C won't reset MII register 29, 30, 31. -+ Router Control Register: bit 7 (TAG_VLAN_EN) is a VLAN related filed which affect vlan setting. -+ Router Control Register: bit 3 (ROUTER_EN) enable router function at MII port. -+ We set them to default to let U-boot properly work. -+ */ -+ phy_data = 0x1001; -+ star_gsw_write_phy(30, 9, phy_data); -+#endif -+ /* restart PHY auto neg. */ -+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x0, &phy_data); -+ -+ phy_data |= (0x1 << 9) | (0x1 << 12); -+ -+ star_gsw_write_phy(gsw_mac_1_phy_addr, 0x0, phy_data); -+ -+ -+ -+ /* wait for PHY auto neg. complete */ -+ for (ii = 0; ii < 0x20; ii++) -+ { -+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x1, &phy_data); -+ -+ if ((phy_data & (0x1 << 2)) && (phy_data & (0x1 << 5))) -+ { -+ break; -+ } -+ else -+ { -+ if ((ii % 4) == 0) -+ printk("\rCheck MAC/PHY 1 Link Status : |"); -+ else if ((ii % 4) == 1) -+ printk("\rCheck MAC/PHY 1 Link Status : /"); -+ else if ((ii % 4) == 2) -+ printk("\rCheck MAC/PHY 1 Link Status : -"); -+ else if ((ii % 4) == 3) -+ printk("\rCheck MAC/PHY 1 Link Status : \\"); -+ } -+ } -+ -+ -+ if (ii >= 0x20) -+ { -+ printk("\rCheck MAC/PHY 1 Link Status : DOWN!\n"); -+ -+ return -1; -+ } -+ else -+ { -+ printk("\rCheck MAC/PHY 1 Link Status : UP!\n"); -+ } -+ -+ -+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x4, &phy_data); -+ -+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x5, &phy_data2); -+ -+ -+ if (phy_data & 0x0400) //FC on -+ { -+ //printk("<FC ON>"); -+ phy_flowctrl = 1; -+ } -+ else -+ { -+ // printk("<FC OFF>"); -+ phy_flowctrl = 0; -+ } -+ -+ -+ phy_speed_dup = 0; -+ -+ if ((phy_data & 0x0100) && (phy_data2 & 0x0100)) //100F -+ { -+ // printk("<100F>"); -+ phy_speed_dup |= (0x1 << 3); //set bit3 for 100F -+ } -+ else if ((phy_data & 0x0080) && (phy_data2 & 0x0080)) //100F -+ { -+ // printk("<100H>"); -+ phy_speed_dup |= (0x1 << 2); -+ } -+ else if ((phy_data & 0x0040) && (phy_data2 & 0x0040)) //100F -+ { -+ // printk("<10F>"); -+ phy_speed_dup |= (0x1 << 1); -+ } -+ else if ((phy_data & 0x0020) && (phy_data2 & 0x0020)) //100F -+ { -+ // printk("<10H>"); -+ phy_speed_dup |= 0x1; -+ } -+ -+ -+ /* -+ * Configure MAC port 1 in forced setting subject to the current PHY status -+ */ -+ reg = GSW_MAC_PORT_1_CONFIG_REG; -+ -+ reg &= ~(0x1 << 7); //AN off -+ -+ reg &= ~(0x3 << 8); -+ -+ if (phy_speed_dup & 0x0C) //100 -+ { -+ //printk("<set 100>"); -+ reg |= (0x01 << 8); -+ } -+ else if (phy_speed_dup & 0x03) //10 -+ { -+ //printk("<set 10>"); -+ reg |= (0x00 << 8); -+ } -+ -+ reg &= ~(0x1 << 11); -+ -+ if (phy_flowctrl) //FC on -+ { -+ //printk("<set FC on>"); -+ reg |= (0x1 << 11); -+ } -+ else -+ { -+ //printk("<set FC off>"); -+ reg |= (0x0 << 11); -+ } -+ -+ reg &= ~(0x1 << 10); -+ -+ if ((phy_speed_dup & 0x2) || (phy_speed_dup & 0x8)) //FullDup -+ { -+ //printk("<set full>"); -+ reg |= (0x1 << 10); -+ } -+ else //HalfDup -+ { -+ //printk("<set half>"); -+ reg |= (0x0 << 10); //Half -+ } -+ -+ GSW_MAC_PORT_1_CONFIG_REG = reg; -+ -+ -+ /* -+ * Check MAC port 1 link status -+ */ -+ for (ii = 0; ii < 0x1000; ii++) -+ { -+ reg = GSW_MAC_PORT_1_CONFIG_REG; -+ -+ if ((reg & 0x1) && !(reg & 0x2)) -+ { -+ /* -+ * enable MAC port 1 -+ */ -+ reg &= ~(0x1 << 18); -+ -+ /* -+ * enable the forwarding of unknown, multicast and broadcast packets to CPU -+ */ -+ reg &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27)); -+ -+ /* -+ * include unknown, multicast and broadcast packets into broadcast storm -+ */ -+ reg |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31)); -+ -+ GSW_MAC_PORT_1_CONFIG_REG = reg; -+ -+ return 0; -+ } -+ } -+ -+ -+ if (ii > 0x1000) -+ { -+ /* -+ * Port 1 PHY link down or no TXC in Port 1 -+ */ -+ printk("\rCheck MAC/PHY 1 Link Status : DOWN!\n"); -+ -+ return -1; -+ } -+ return 0; -+} -+#endif -+ -+#if 0 -+static int star_gsw_config_VSC8201(u8 mac_port, u8 phy_addr) // include cicada 8201 -+{ -+ //u32 mac_port_base = 0; -+ u32 mac_port_config=0; -+ u16 phy_reg; -+ int i; -+ -+ printk("\nconfigure VSC8201\n"); -+ //PDEBUG("mac port : %d phy addr : %d\n", mac_port, phy_addr); -+ /* -+ * Configure MAC port 0 -+ * For Cicada CIS8201 single PHY -+ */ -+ if (mac_port == 0) { -+ //PDEBUG("port 0\n"); -+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG; -+ } -+ if (mac_port == 1) { -+ //PDEBUG("port 1\n"); -+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG; -+ } -+ -+ star_gsw_set_phy_addr(mac_port, phy_addr); -+ //star_gsw_set_phy_addr(1, 1); -+ -+ //mac_port_config = __REG(mac_port_base); -+ -+ // enable PHY's AN -+ mac_port_config |= (0x1 << 7); -+ -+ // enable RGMII-PHY mode -+ mac_port_config |= (0x1 << 15); -+ -+ // enable GSW MAC port 0 -+ mac_port_config &= ~(0x1 << 18); -+ -+ if (mac_port == 0) { -+ //PDEBUG("port 0\n"); -+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config; -+ } -+ if (mac_port == 1) { -+ //PDEBUG("port 1\n"); -+ GSW_MAC_PORT_1_CONFIG_REG = mac_port_config; -+ } -+ -+ /* -+ * Configure Cicada's CIS8201 single PHY -+ */ -+#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH -+ /* near-end loopback mode */ -+ star_gsw_read_phy(phy_addr, 0x0, &phy_reg); -+ phy_reg |= (0x1 << 14); -+ star_gsw_write_phy(phy_addr, 0x0, phy_reg); -+#endif -+ -+ star_gsw_read_phy(phy_addr, 0x1C, &phy_reg); -+ -+ // configure SMI registers have higher priority over MODE/FRC_DPLX, and ANEG_DIS pins -+ phy_reg |= (0x1 << 2); -+ -+ star_gsw_write_phy(phy_addr, 0x1C, phy_reg); -+ -+ star_gsw_read_phy(phy_addr, 0x17, &phy_reg); -+ -+ // enable RGMII MAC interface mode -+ phy_reg &= ~(0xF << 12); -+ phy_reg |= (0x1 << 12); -+ -+ // enable RGMII I/O pins operating from 2.5V supply -+ phy_reg &= ~(0x7 << 9); -+ phy_reg |= (0x1 << 9); -+ -+ star_gsw_write_phy(phy_addr, 0x17, phy_reg); -+ -+ star_gsw_read_phy(phy_addr, 0x4, &phy_reg); -+ -+ // Enable symmetric Pause capable -+ phy_reg |= (0x1 << 10); -+ -+ star_gsw_write_phy(phy_addr, 0x4, phy_reg); -+ -+ -+ -+ if (mac_port == 0) { -+ //PDEBUG("port 0\n"); -+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG; -+ } -+ if (mac_port == 1) { -+ //PDEBUG("port 1\n"); -+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG; -+ } -+ -+ -+ -+ -+ -+ -+ -+ // enable PHY's AN -+ mac_port_config |= (0x1 << 7); -+ -+ if (mac_port == 0) { -+ //PDEBUG("port 0\n"); -+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config; -+ } -+ if (mac_port == 1) { -+ //PDEBUG("port 1\n"); -+ GSW_MAC_PORT_1_CONFIG_REG = mac_port_config; -+ } -+ -+ /* -+ * Enable PHY1 AN restart bit to restart PHY1 AN -+ */ -+ star_gsw_read_phy(phy_addr, 0x0, &phy_reg); -+ -+ phy_reg |= (0x1 << 9) | (0x1 << 12); -+ -+ star_gsw_write_phy(phy_addr, 0x0, phy_reg); -+ -+ /* -+ * Polling until PHY0 AN restart is complete -+ */ -+ for (i = 0; i < 0x1000; i++) { -+ star_gsw_read_phy(phy_addr, 0x1, &phy_reg); -+ -+ if ((phy_reg & (0x1 << 5)) && (phy_reg & (0x1 << 2))) { -+ printk("0x1 phy reg: %x\n", phy_reg); -+ break; -+ } else { -+ udelay(100); -+ } -+ } -+ -+ if (mac_port == 0) { -+ //PDEBUG("port 0\n"); -+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG; -+ } -+ if (mac_port == 1) { -+ //PDEBUG("port 1\n"); -+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG; -+ } -+ -+ if (((mac_port_config & 0x1) == 0) || (mac_port_config & 0x2)) { -+ printk("Check MAC/PHY%s Link Status : DOWN!\n", (mac_port == 0 ? "0" : "1")); -+ } else { -+ printk("Check MAC/PHY%s Link Status : UP!\n", (mac_port == 0 ? "0" : "1")); -+ /* -+ * There is a bug for CIS8201 PHY operating at 10H mode, and we use the following -+ * code segment to work-around -+ */ -+ star_gsw_read_phy(phy_addr, 0x05, &phy_reg); -+ -+ if ((phy_reg & (0x1 << 5)) && (!(phy_reg & (0x1 << 6))) && (!(phy_reg & (0x1 << 7))) && (!(phy_reg & (0x1 << 8)))) { /* 10H,10F/100F/100H off */ -+ star_gsw_read_phy(phy_addr, 0x0a, &phy_reg); -+ -+ if ((!(phy_reg & (0x1 << 10))) && (!(phy_reg & (0x1 << 11)))) { /* 1000F/1000H off */ -+ star_gsw_read_phy(phy_addr, 0x16, &phy_reg); -+ -+ phy_reg |= (0x1 << 13) | (0x1 << 15); // disable "Link integrity check(B13)" & "Echo mode(B15)" -+ -+ star_gsw_write_phy(phy_addr, 0x16, phy_reg); -+ } -+ } -+ } -+ -+ if (mac_port == 0) { -+ // adjust MAC port 0 RX/TX clock skew -+ GSW_BIST_RESULT_TEST_0_REG &= ~((0x3 << 24) | (0x3 << 26)); -+ GSW_BIST_RESULT_TEST_0_REG |= ((0x2 << 24) | (0x2 << 26)); -+ } -+ -+ if (mac_port == 1) { -+ // adjust MAC port 1 RX/TX clock skew -+ GSW_BIST_RESULT_TEST_0_REG &= ~((0x3 << 28) | (0x3 << 30)); -+ GSW_BIST_RESULT_TEST_0_REG |= ((0x2 << 28) | (0x2 << 30)); -+ } -+ -+ return 0; -+} -+ -+ -+ -+ -+static void star_gsw_config_VSC8X01() -+{ -+ u16 phy_id = 0; -+ -+#ifdef CONFIG_DORADO2 -+ star_gsw_set_phy_addr(1,1); -+ star_gsw_read_phy(1, 0x02, &phy_id); -+ // printk("phy id = %X\n", phy_id); -+ if (phy_id == 0x000F) //VSC8201 -+ star_gsw_config_VSC8201(1,1); -+ else -+ star_gsw_config_VSC8601(1,1); -+#else -+#ifdef CONFIG_LEO -+ star_gsw_set_phy_addr(0,0); -+ star_gsw_read_phy(0, 0x02, &phy_id); -+ // printk("phy id = %X\n", phy_id); -+ if (phy_id == 0x000F) //VSC8201 -+ star_gsw_config_VSC8201(0,0); -+ else -+ star_gsw_config_VSC8601(0,0); -+#endif -+#endif -+} -+#endif -+ -+#if defined(CONFIG_DORADO) || defined(CONFIG_DORADO2) -+static int star_gsw_config_port0_VSC7385(void) -+{ -+ u32 mac_port_config=0; -+ int i; -+ -+ printk("config VSC7385\n"); -+ -+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG; -+ -+ // disable PHY's AN -+ mac_port_config &= ~(0x1 << 7); -+ -+ // enable RGMII-PHY mode -+ mac_port_config |= (0x1 << 15); -+ -+ // force speed = 1000Mbps -+ mac_port_config &= ~(0x3 << 8); -+ mac_port_config |= (0x2 << 8); -+ -+ // force full-duplex -+ mac_port_config |= (0x1 << 10); -+ -+ // force Tx/Rx flow-control on -+ mac_port_config |= (0x1 << 11) | (0x1 << 12); -+ -+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config; -+ -+ udelay(1000); -+ -+ for (i = 0; i < 50000; i++) { -+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG; -+ if ((mac_port_config & 0x1) && !(mac_port_config & 0x2)) { -+ break; -+ } else { -+ udelay(100); -+ } -+ } -+ -+ if (!(mac_port_config & 0x1) || (mac_port_config & 0x2)) { -+ printk("MAC0 PHY Link Status : DOWN!\n"); -+ return -1; -+ } else { -+ printk("MAC0 PHY Link Status : UP!\n"); -+ } -+ -+ // enable MAC port 0 -+ mac_port_config &= ~(0x1 << 18); -+ -+ // disable SA learning -+ mac_port_config |= (0x1 << 19); -+ -+ // forward unknown, multicast and broadcast packets to CPU -+ mac_port_config &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27)); -+ -+ // storm rate control for unknown, multicast and broadcast packets -+ mac_port_config |= (0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31); -+ -+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config; -+ -+ // disable MAC port 1 -+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG; -+ mac_port_config |= (0x1 << 18); -+ GSW_MAC_PORT_1_CONFIG_REG = mac_port_config; -+ -+ // adjust MAC port 0 /RX/TX clock skew -+ GSW_BIST_RESULT_TEST_0_REG &= ~((0x3 << 24) | (0x3 << 26)); -+ GSW_BIST_RESULT_TEST_0_REG |= ((0x2 << 24) | (0x2 << 26)); -+ -+ return 0; -+} -+#endif ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_phy.h -@@ -0,0 +1,82 @@ -+/******************************************************************************* -+ * -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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 -+1* 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+#ifndef CNS3XXX_PHY_H -+#define CNS3XXX_PHY_H -+ -+#define LINUX_KERNEL // if don't define LINUX_KERNEL, mean u-boot -+ -+#if defined(LINUX_KERNEL) -+#include <linux/version.h> -+#include <linux/types.h> -+#else // u-boot -+#define __init_or_module -+#include "cns3xxx_symbol.h" -+#endif -+ -+void disable_AN(int port, int y); -+ -+u16 get_phy_id(u8 phy_addr); -+int cns3xxx_std_phy_power_down(int phy_addr, int y); -+u32 get_vsc8601_recv_err_counter(u8 phy_addr); -+u32 get_crc_good_counter(u8 phy_addr); -+int cns3xxx_config_VSC8601(u8 mac_port, u8 phy_addr); -+int vsc8601_power_down(int phy_addr, int y); -+int icp_101a_init(u8 mac_port, u8 phy_addr); -+int bcm53115M_init(u8 mac_port, u16 phy_addr); -+int icp_ip1001_init(u8 mac_port, u8 phy_addr); -+ -+int cns3xxx_phy_auto_polling_enable(u8 port, u8 en); -+ -+int cns3xxx_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data); -+int cns3xxx_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data); -+ -+// wrap cns3xxx_spi_tx_rx() for argument order -+int cns3xxx_spi_tx_rx_n(u32 tx_data, u32 *rx_data, u32 tx_channel, u32 tx_eof_flag); -+ -+// for bcm53115M -+#define ROBO_SPIF_BIT 7 -+#define BCM53115_SPI_CHANNEL 1 -+#define ROBO_RACK_BIT 5 -+ -+#define VLAN_START_BIT 7 -+#define VLAN_WRITE_CMD 0 -+ -+//#define BCM_PORT_1G 2 -+typedef enum -+{ -+ BCM_PORT_10M = 0, -+ BCM_PORT_100M, -+ BCM_PORT_1G, -+}BCM_PORT_SPEED; -+ -+#define BCM_PORT_0 0 -+#define BCM_PORT_1 1 -+#define BCM_PORT_2 2 -+#define BCM_PORT_3 3 -+#define BCM_PORT_4 4 -+#define BCM_PORT_5 5 -+#define BCM_PORT_IMP 6 -+ -+#endif // end #ifndef CNS3XXX_PHY_H ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_sppe_hook.c -@@ -0,0 +1,39 @@ -+/****************************************************************************** -+ * -+ * Copyright (c) 2008 Cavium Networks -+ * -+ * This file is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License, Version 2, as -+ * published by the Free Software Foundation. -+ * -+ * This file is distributed in the hope that it will be useful, -+ * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or -+ * NONINFRINGEMENT. See the GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this file; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or -+ * visit http://www.gnu.org/licenses/. -+ * -+ * This file may also be available under a different license from Cavium. -+ * Contact Cavium Networks for more information -+ * -+ ******************************************************************************/ -+ -+#if defined(CONFIG_CNS3XXX_SPPE) -+#include <linux/module.h> -+#include <linux/cns3xxx/sppe.h> -+ -+int sppe_hook_ready = 0; -+int (*sppe_func_hook)(SPPE_PARAM *param) = NULL; -+int sppe_pci_fp_ready = 0; -+int (*sppe_pci_fp_hook)(SPPE_PARAM *param) = NULL; -+ -+EXPORT_SYMBOL(sppe_hook_ready); -+EXPORT_SYMBOL(sppe_func_hook); -+EXPORT_SYMBOL(sppe_pci_fp_ready); -+EXPORT_SYMBOL(sppe_pci_fp_hook); -+ -+#endif //#if defined(CONFIG_CNS3XXX_SPPE) -+ ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_symbol.h -@@ -0,0 +1,317 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+// the symbol define memory map register. -+ -+#ifndef CNS3XXX_SYMBOL_H -+#define CNS3XXX_SYMBOL_H -+ -+#define DRV_VERSION "Cavium CNS3XXX Switch Driver-0.0.1" -+ -+ -+#define LINUX_KERNEL // if don't define LINUX_KERNEL, mean u-boot -+ -+#if defined(LINUX_KERNEL) -+// linux kernel -+#include <mach/board.h> -+ -+#define SWITCH_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_SWITCH_BASE_VIRT+offset))) -+#define PMU_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_PM_BASE_VIRT+offset))) -+#define MISC_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_MISC_BASE_VIRT+offset))) -+ -+ -+#define NETDEV_SIZE 4097+3 -+ -+#define PORT0_NETDEV_INDEX NETDEV_SIZE-3 -+#define PORT1_NETDEV_INDEX NETDEV_SIZE-2 -+#define PORT2_NETDEV_INDEX NETDEV_SIZE-1 -+ -+#if defined (CONFIG_CNS3XXX_SPPE) -+#define FP_NETDEV_INDEX NETDEV_SIZE-4 -+#endif -+ -+#define PORT0_NETDEV net_dev_array[PORT0_NETDEV_INDEX] -+#define PORT1_NETDEV net_dev_array[PORT1_NETDEV_INDEX] -+#define PORT2_NETDEV net_dev_array[PORT2_NETDEV_INDEX] -+ -+#if defined (CONFIG_CNS3XXX_SPPE) -+#define FP_NETDEV net_dev_array[FP_NETDEV_INDEX] -+#endif -+ -+#else // u-boot -+#include <malloc.h> // for u8, u32 -+ -+#include "cns3000.h" -+#define CAVM_OK 0 -+#define CAVM_ERR 1 -+#define CAVM_NOT_FOUND 2 -+#define CAVM_FOUND 3 -+#define CAVM_FAIL -1 // use minus -+ -+#define SWITCH_REG_VALUE(addr) (*((volatile unsigned int *)(CNS3000_VEGA_SWITCH_BASE+addr))) -+#define PMU_REG_VALUE(addr) (*((volatile unsigned int *)(CNS3000_VEGA_PM_BASE+addr))) -+#define MISC_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3000_VEGA_MISC_BASE+offset))) -+ -+#endif -+ -+// for VLAN and ARL table MB_PMAP -+#define MAC_PORT0_PMAP 1 -+#define MAC_PORT1_PMAP (1 << 1) -+#define MAC_PORT2_PMAP (1 << 4) -+#define CPU_PORT_PMAP (1 << 2) -+ -+ -+ -+// memory map register definition -+ -+//#define PHY_CTRL_REG (*(u32 volatile*(0xff))) -+#define PHY_CTRL_REG SWITCH_REG_VALUE(0x0) -+#define PHY_AUTO_ADDR_REG SWITCH_REG_VALUE(0x04) -+ -+#define MAC_GLOB_CFG_REG SWITCH_REG_VALUE(0x08) -+#define MAC_GLOB_CFG_EXT_REG SWITCH_REG_VALUE(0xf4) -+#define MAC0_CFG_REG SWITCH_REG_VALUE(0x0c) -+#define MAC1_CFG_REG SWITCH_REG_VALUE(0x10) -+#define MAC2_CFG_REG SWITCH_REG_VALUE(0x18) -+#define CPU_CFG_REG SWITCH_REG_VALUE(0x14) -+ -+#define MAC0_PRI_CTRL_REG SWITCH_REG_VALUE(0x1c) -+#define MAC1_PRI_CTRL_REG SWITCH_REG_VALUE(0x20) -+#define CPU_PRI_CTRL_REG SWITCH_REG_VALUE(0x24) -+#define HNAT_PRI_CTRL_REG SWITCH_REG_VALUE(0x28) -+#define MAC2_PRI_CTRL_REG SWITCH_REG_VALUE(0x2c) -+ -+#define MAC0_PRI_CTRL_EXT_REG SWITCH_REG_VALUE(0x30) -+ -+#define ETYPE1_ETYPE0_REG SWITCH_REG_VALUE(0x34) -+#define ETYPE3_ETYPE2_REG SWITCH_REG_VALUE(0x38) -+ -+#define UDP_RANGE0_REG SWITCH_REG_VALUE(0x3c) -+#define UDP_RANGE1_REG SWITCH_REG_VALUE(0x40) -+#define UDP_RANGE2_REG SWITCH_REG_VALUE(0x44) -+#define UDP_RANGE3_REG SWITCH_REG_VALUE(0x48) -+ -+ -+#define PRIO_ETYPE_UDP_REG SWITCH_REG_VALUE(0x4c) -+ -+#define PRIO_IPDSCP_7_0_REG SWITCH_REG_VALUE(0x50) -+#define PRIO_IPDSCP_15_8_REG SWITCH_REG_VALUE(0x54) -+#define PRIO_IPDSCP_23_16_REG SWITCH_REG_VALUE(0x58) -+#define PRIO_IPDSCP_31_24_REG SWITCH_REG_VALUE(0x5c) -+#define PRIO_IPDSCP_39_32_REG SWITCH_REG_VALUE(0x60) -+#define PRIO_IPDSCP_47_40_REG SWITCH_REG_VALUE(0x64) -+#define PRIO_IPDSCP_55_48_REG SWITCH_REG_VALUE(0x68) -+#define PRIO_IPDSCP_63_56_REG SWITCH_REG_VALUE(0x6c) -+ -+#define TC_CTRL_REG SWITCH_REG_VALUE(0x70) -+#define RATE_CTRL_REG SWITCH_REG_VALUE(0x74) -+ -+#define FC_GLOB_THRS_REG SWITCH_REG_VALUE(0x78) -+#define FC_PORT_THRS_REG SWITCH_REG_VALUE(0x7c) -+#define MC_GLOB_THRS_REG SWITCH_REG_VALUE(0x80) -+#define DC_GLOB_THRS_REG SWITCH_REG_VALUE(0x84) -+ -+#define ARL_VLAN_CMD_REG SWITCH_REG_VALUE(0x88) -+ -+#define ARL_CTRL0_REG SWITCH_REG_VALUE(0x8c) -+#define ARL_CTRL1_REG SWITCH_REG_VALUE(0x90) -+#define ARL_CTRL2_REG SWITCH_REG_VALUE(0x94) -+ -+#define VLAN_CFG SWITCH_REG_VALUE(0x098) -+ -+#define MAC1_MAC0_PVID_REG SWITCH_REG_VALUE(0x9c) -+#define MAC2_CPU_PVID_REG SWITCH_REG_VALUE(0xa0) -+ -+#define VLAN_CTRL0_REG SWITCH_REG_VALUE(0xa4) -+#define VLAN_CTRL1_REG SWITCH_REG_VALUE(0xa8) -+#define VLAN_CTRL2_REG SWITCH_REG_VALUE(0xac) -+ -+#define SESSION_ID_1_0_REG SWITCH_REG_VALUE(0xb0) -+#define SESSION_ID_3_2_REG SWITCH_REG_VALUE(0xb4) -+#define SESSION_ID_5_4_REG SWITCH_REG_VALUE(0xb8) -+#define SESSION_ID_7_6_REG SWITCH_REG_VALUE(0xbc) -+#define SESSION_ID_9_8_REG SWITCH_REG_VALUE(0xc0) -+#define SESSION_ID_11_10_REG SWITCH_REG_VALUE(0xc4) -+#define SESSION_ID_13_12_REG SWITCH_REG_VALUE(0xc8) -+#define SESSION_ID_15_14_REG SWITCH_REG_VALUE(0xcc) -+ -+#define INTR_STAT_REG SWITCH_REG_VALUE(0xd0) -+#define INTR_MASK_REG SWITCH_REG_VALUE(0xd4) -+ -+#define SRAM_TEST_REG SWITCH_REG_VALUE(0xd8) -+ -+#define MEM_QUEUE_REG SWITCH_REG_VALUE(0xdc) -+ -+#define SARL_CTRL_REG SWITCH_REG_VALUE(0xe0) -+#define SARL_OQ_GTH_REG SWITCH_REG_VALUE(0xe4) -+#define SARL_OQ_YTH_REG SWITCH_REG_VALUE(0xe8) -+#define SARL_OQ_RTH_REG SWITCH_REG_VALUE(0xec) -+ -+#define SLK_SKEW_CTRL_REG SWITCH_REG_VALUE(0xf0) -+ -+#define DMA_RING_CTRL_REG SWITCH_REG_VALUE(0x100) -+ -+#define DMA_AUTO_POLL_CFG_REG SWITCH_REG_VALUE(0x104) -+ -+#define DELAY_INTR_CFG_REG SWITCH_REG_VALUE(0x108) -+ -+#define TS_DMA_CTRL0_REG SWITCH_REG_VALUE(0x110) -+#define TS_DESC_PTR0_REG SWITCH_REG_VALUE(0x114) -+#define TS_DESC_BASE_ADDR0_REG SWITCH_REG_VALUE(0x118) -+ -+#define FS_DMA_CTRL0_REG SWITCH_REG_VALUE(0x120) -+#define FS_DESC_PTR0_REG SWITCH_REG_VALUE(0x124) -+#define FS_DESC_BASE_ADDR0_REG SWITCH_REG_VALUE(0x128) -+ -+#define TS_DMA_CTRL1_REG SWITCH_REG_VALUE(0x130) -+#define TS_DESC_PTR1_REG SWITCH_REG_VALUE(0x134) -+#define TS_DESC_BASE_ADDR1_REG SWITCH_REG_VALUE(0x138) -+ -+#define FS_DMA_CTRL1_REG SWITCH_REG_VALUE(0x140) -+#define FS_DESC_PTR1_REG SWITCH_REG_VALUE(0x144) -+#define FS_DESC_BASE_ADDR1_REG SWITCH_REG_VALUE(0x148) -+ -+#define TS_DMA_STA_REG SWITCH_REG_VALUE(0x150) -+#define FS_DMA_STA_REG SWITCH_REG_VALUE(0x154) -+ -+#define TS_MRD_CMD_CNT_REG SWITCH_REG_VALUE(0x158) -+#define TS_MWT_CMD_CNT_REG SWITCH_REG_VALUE(0x15c) -+ -+#define FS_MRD_CMD_CNT_REG SWITCH_REG_VALUE(0x160) -+#define FS_MWT_CMD_CNT_REG SWITCH_REG_VALUE(0x164) -+ -+#define C_RXOKPKT_MAC0_REG SWITCH_REG_VALUE(0x300) -+#define C_RXOKBYTE_MAC0_REG SWITCH_REG_VALUE(0x304) -+#define C_RXRUNT_MAC0_REG SWITCH_REG_VALUE(0x308) -+#define C_RXLONG_MAC0_REG SWITCH_REG_VALUE(0x30c) -+#define C_RXDROP_MAC0_REG SWITCH_REG_VALUE(0x310) -+#define C_RXCRC_MAC0_REG SWITCH_REG_VALUE(0x314) -+#define C_RXARLDROP_MAC0_REG SWITCH_REG_VALUE(0x318) -+#define C_VIDROP_MAC0_REG SWITCH_REG_VALUE(0x31c) -+#define C_VEDROP_MAC0_REG SWITCH_REG_VALUE(0x320) -+#define C_RXRL_MAC0_REG SWITCH_REG_VALUE(0x324) -+#define C_RXPAUSE_MAC0_REG SWITCH_REG_VALUE(0x328) -+ -+#define C_TXOKPKT_MAC0_REG SWITCH_REG_VALUE(0x32c) -+#define C_TXOKBYTE_MAC0_REG SWITCH_REG_VALUE(0x330) -+#define C_TXPAUSECOL_MAC0_REG SWITCH_REG_VALUE(0x334) -+ -+#define C_RXOKPKT_MAC1_REG SWITCH_REG_VALUE(0x400) -+#define C_RXOKBYTE_MAC1_REG SWITCH_REG_VALUE(0x404) -+#define C_RXRUNT_MAC1_REG SWITCH_REG_VALUE(0x408) -+#define C_RXLONG_MAC1_REG SWITCH_REG_VALUE(0x40c) -+#define C_RXDROP_MAC1_REG SWITCH_REG_VALUE(0x410) -+#define C_RXCRC_MAC1_REG SWITCH_REG_VALUE(0x414) -+#define C_RXARLDROP_MAC1_REG SWITCH_REG_VALUE(0x418) -+#define C_VIDROP_MAC1_REG SWITCH_REG_VALUE(0x41c) -+#define C_VEDROP_MAC1_REG SWITCH_REG_VALUE(0x420) -+#define C_RXRL_MAC1_REG SWITCH_REG_VALUE(0x424) -+#define C_RXPAUSE_MAC1_REG SWITCH_REG_VALUE(0x428) -+ -+#define C_TXOKPKT_MAC1_REG SWITCH_REG_VALUE(0x42c) -+#define C_TXOKBYTE_MAC1_REG SWITCH_REG_VALUE(0x430) -+#define C_TXPAUSECOL_MAC1_REG SWITCH_REG_VALUE(0x434) -+ -+#define C_TSOKPKT_CPU_REG SWITCH_REG_VALUE(0x500) -+#define C_TSOKBYTE_CPU_REG SWITCH_REG_VALUE(0x504) -+#define C_TSRUNT_CPU_REG SWITCH_REG_VALUE(0x508) -+#define C_TSLONG_CPU_REG SWITCH_REG_VALUE(0x50c) -+#define C_TSNODSTDROP_CPU_REG SWITCH_REG_VALUE(0x510) -+#define C_TSARLDROP_CPU_REG SWITCH_REG_VALUE(0x514) -+#define C_TSVIDROP_CPU_REG SWITCH_REG_VALUE(0x518) -+#define C_TSVEDROP_CPU_REG SWITCH_REG_VALUE(0x51c) -+#define C_TSRL_CPU_REG SWITCH_REG_VALUE(0x520) -+ -+#define C_FSOKPKT_CPU_REG SWITCH_REG_VALUE(0x524) -+#define C_FSOKBYTE_CPU_REG SWITCH_REG_VALUE(0x528) -+ -+#define C_RXOKPKT_MAC2_REG SWITCH_REG_VALUE(0x600) -+#define C_RXOKBYTE_MAC2_REG SWITCH_REG_VALUE(0x604) -+#define C_RXRUNT_MAC2_REG SWITCH_REG_VALUE(0x608) -+#define C_RXLONG_MAC2_REG SWITCH_REG_VALUE(0x60c) -+#define C_RXDROP_MAC2_REG SWITCH_REG_VALUE(0x610) -+#define C_RXCRC_MAC2_REG SWITCH_REG_VALUE(0x614) -+#define C_RXARLDROP_MAC2_REG SWITCH_REG_VALUE(0x618) -+#define C_VIDROP_MAC2_REG SWITCH_REG_VALUE(0x61c) -+#define C_VEDROP_MAC2_REG SWITCH_REG_VALUE(0x620) -+#define C_RXRL_MAC2_REG SWITCH_REG_VALUE(0x624) -+#define C_RXPAUSE_MAC2_REG SWITCH_REG_VALUE(0x628) -+ -+#define C_TXOKPKT_MAC2_REG SWITCH_REG_VALUE(0x62c) -+#define C_TXOKBYTE_MAC2_REG SWITCH_REG_VALUE(0x630) -+#define C_TXPAUSECOL_MAC2_REG SWITCH_REG_VALUE(0x634) -+ -+#define C_TXOKPKT_MAC0_EXT_REG SWITCH_REG_VALUE(0x72c) -+#define C_TXOKBYTE_MAC0_EXT_REG SWITCH_REG_VALUE(0x730) -+ -+#define CLK_GATE_REG PMU_REG_VALUE(0x0) -+#define SOFT_RST_REG PMU_REG_VALUE(0x4) -+#define PLL_HM_PD_CTRL_REG PMU_REG_VALUE(0x1c) -+ -+#define GPIOB_PIN_EN_REG MISC_REG_VALUE(0x18) -+#define IOCDA_REG MISC_REG_VALUE(0x1c) -+ -+#define LEVEL_HIGH 0 -+#define RISING_EDGE 1 -+ -+#ifdef CONFIG_SILICON -+ -+#define STATUS_INTERRUPT_ID 49 -+ -+#define FSRC_RING0_INTERRUPT_ID 51 -+#define FSQF_RING0_INTERRUPT_ID 53 -+ -+#define FSRC_RING1_INTERRUPT_ID 55 -+#define FSQF_RING1_INTERRUPT_ID 57 -+ -+#define TSTC_RING0_INTERRUPT_ID 50 -+ -+#define TSTC_RING1_INTERRUPT_ID 54 -+ -+#define HNAT_INTERRUPT_ID 58 -+ -+#else -+ -+//#define STATUS_INTERRUPT_ID 49 -+#define STATUS_INTERRUPT_ID 38 -+//#define FSRC_RING0_INTERRUPT_ID 51 -+#define FSRC_RING0_INTERRUPT_ID 40 -+ -+#define TSQE_RING0_INTERRUPT_ID 52 -+ -+//#define FSQF_RING0_INTERRUPT_ID 53 -+#define FSQF_RING0_INTERRUPT_ID 42 -+ -+#define FSQF_RING1_INTERRUPT_ID 46 -+#define FSRC_RING1_INTERRUPT_ID 44 -+ -+//#define FSRC_RING1_INTERRUPT_ID 55 -+ -+#define TSTC_RING0_INTERRUPT_ID 39 -+#define TSTC_RING1_INTERRUPT_ID 43 -+ -+#define TSQE_RING1_INTERRUPT_ID 56 -+#define HNAT_INTERRUPT_ID 58 -+#endif // #ifdef CONFIG_SILICON -+ -+#endif ---- /dev/null -+++ b/drivers/net/cns3xxx/cns3xxx_tool.h -@@ -0,0 +1,898 @@ -+/******************************************************************************* -+ * -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+#ifndef CNS3XXX_TOOL_H -+#define CNS3XXX_TOOL_H -+ -+#define PRINT_INFO printk -+ -+#if defined(__KERNEL__) -+ -+#include "cns3xxx.h" -+#include <linux/kernel.h> // for printk -+ -+#else // u-boot -+ -+#endif -+ -+#define SHOW_DEBUG_MESSAGE -+#ifdef SHOW_DEBUG_MESSAGE -+ -+extern int MSG_LEVEL; -+ -+#define NO_MSG 0 -+#define NORMAL_MSG 1 -+#define WARNING_MSG (1 << 1) -+#define CRITICAL_MSG (1 << 2) -+#define DUMP_RX_PKT_INFO (1 << 3) -+#define DUMP_TX_PKT_INFO (1 << 4) -+ -+#define DEBUG_MSG(msg_level, fmt, args...)\ -+{ \ -+ int i=0; \ -+\ -+ for(i=0 ; i < 3 ; ++i) { \ -+ if ((MSG_LEVEL & msg_level) >> i) \ -+ printk(KERN_INFO "*cns3xxx gsw debug* " fmt, ## args); \ -+ } \ -+} -+ -+#endif -+ -+#define GET_MAC_PORT_CFG(port, cfg) \ -+{ \ -+ switch (port) \ -+ { \ -+ case MAC_PORT0: \ -+ { \ -+ cfg = MAC0_CFG_REG; \ -+ break; \ -+ } \ -+ case MAC_PORT1: \ -+ { \ -+ cfg = MAC1_CFG_REG; \ -+ break; \ -+ } \ -+ case MAC_PORT2: \ -+ { \ -+ cfg = MAC2_CFG_REG; \ -+ break; \ -+ } \ -+ } \ -+} -+ -+#define SET_MAC_PORT_CFG(port, cfg) \ -+{ \ -+ switch (port) \ -+ { \ -+ case MAC_PORT0: \ -+ { \ -+ MAC0_CFG_REG = cfg; \ -+ break; \ -+ } \ -+ case MAC_PORT1: \ -+ { \ -+ MAC1_CFG_REG = cfg; \ -+ break; \ -+ } \ -+ case MAC_PORT2: \ -+ { \ -+ MAC2_CFG_REG = cfg; \ -+ break; \ -+ } \ -+ } \ -+} -+ -+#define between(x, start, end) ((x)>=(start) && (x)<=(end)) -+static inline void print_packet(unsigned char *data, int len) -+{ -+ int i,j; -+ -+ printk("packet length: %d%s:\n", len, len>128?"(only show the first 128 bytes)":""); -+#if 0 -+ if(len > 128) { -+ len = 128; -+ } -+#endif -+ for(i=0;len;) { -+ if(len >=16 ) { -+ for(j=0;j<16;j++) { -+ printk("%02x ", data[i++]); -+ } -+ printk("| "); -+ -+ i -= 16; -+ for(j=0;j<16;j++) { -+ if( between(data[i], 0x21, 0x7e) ) { -+ printk("%c", data[i++]); -+ } -+ else { -+ printk("."); -+ i++; -+ } -+ } -+ printk("\n"); -+ -+ len -= 16; -+ } -+ else { -+ /* last line */ -+ -+ for(j=0; j<len; j++) { -+ printk("%02x ", data[i++]); -+ } -+ for(;j<16;j++) { -+ printk(" "); -+ } -+ printk("| "); -+ -+ i -= len; -+ for(j=0;j<len;j++) { -+ if( between(data[i], 0x21, 0x7e) ) { -+ printk("%c", data[i++]); -+ } -+ else { -+ printk("."); -+ i++; -+ } -+ } -+ for(;j<16;j++) { -+ printk(" "); -+ } -+ printk("\n"); -+ -+ len = 0; -+ } -+ } -+ return; -+ -+} -+ -+static inline void cns3xxx_gsw_power_enable(void) -+{ -+ PLL_HM_PD_CTRL_REG &= (~(1 << 2)); // power up PLL_RGMII (for MAC) -+ CLK_GATE_REG |= (1 << 11); // enable switch clock -+} -+ -+static inline void cns3xxx_gsw_software_reset(void) -+{ -+ SOFT_RST_REG &= (~(1 << 11)); -+ SOFT_RST_REG |= (1 << 11); -+} -+ -+ -+ -+ -+// port: -+// 0 : mac port0 -+// 1 : mac port1 -+// 2 : mac port2 -+// 3 : cpu port -+static inline void enable_port(u8 port, u8 enable) -+{ -+ switch (port) -+ { -+ case 0: -+ { -+ (enable==1) ? (MAC0_CFG_REG &= (~(1 << 18)) ) : (MAC0_CFG_REG |= (1 << 18)) ; -+ -+ break; -+ } -+ case 1: -+ { -+ (enable==1) ? (MAC1_CFG_REG &= (~(1 << 18)) ) : (MAC1_CFG_REG |= (1 << 18)) ; -+ break; -+ } -+ case 2: -+ { -+ (enable==1) ? (MAC2_CFG_REG &= (~(1 << 18)) ) : (MAC2_CFG_REG |= (1 << 18)) ; -+ break; -+ } -+ case 3: -+ { -+ (enable==1) ? (CPU_CFG_REG &= (~(1 << 18)) ) : (CPU_CFG_REG |= (1 << 18)) ; -+ break; -+ } -+ } -+} -+ -+static inline int cns3xxx_vlan_table_lookup(VLANTableEntry *entry) -+{ -+ VLAN_CTRL2_REG |= entry->vid; -+ ARL_VLAN_CMD_REG |= (1 << 8); // look up vlan table command -+ -+ // wait for vlan command complete -+ while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ; -+ -+ if (!((ARL_VLAN_CMD_REG >> 10) & 1)) { -+ // not found any entry -+ return CAVM_NOT_FOUND; -+ } -+ -+ entry->valid = ((VLAN_CTRL0_REG >> 31) & 0x1); -+ entry->vid = ((VLAN_CTRL2_REG >> 31) & 0xfff); -+ entry->wan_side = ((VLAN_CTRL0_REG >> 30) & 0x1); -+ entry->etag_pmap = ((VLAN_CTRL0_REG >> 25) & 0x1f); -+ entry->mb_pmap = ((VLAN_CTRL0_REG >> 9) & 0x1f); -+ -+ entry->my_mac[0] = ((VLAN_CTRL1_REG >> 24) & 0xff); -+ entry->my_mac[1] = ((VLAN_CTRL1_REG >> 16) & 0xff); -+ entry->my_mac[2] = ((VLAN_CTRL1_REG >> 8) & 0xff); -+ entry->my_mac[3] = (VLAN_CTRL1_REG & 0xff); -+ -+ entry->my_mac[4] = ((VLAN_CTRL2_REG >> 24) & 0xff); -+ entry->my_mac[5] = ((VLAN_CTRL2_REG >> 16) & 0xff); -+ -+ return CAVM_FOUND; -+} -+ -+static inline int cns3xxx_vlan_table_read(VLANTableEntry *entry) -+{ -+ //printf("VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ ARL_VLAN_CMD_REG &= (~0x3f); -+ ARL_VLAN_CMD_REG |= (entry->vlan_index); -+ ARL_VLAN_CMD_REG |= (1 << 7); // read vlan table command -+ //printf("after read ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG); -+ -+ // wait for vlan command complete -+ while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ; -+ -+ //printf("ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG); -+ //printf("VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ -+ entry->valid = ((VLAN_CTRL0_REG >> 31) & 0x1); -+ entry->vid = ((VLAN_CTRL2_REG) & 0xfff); -+ entry->wan_side = ((VLAN_CTRL0_REG >> 30) & 0x1); -+ entry->etag_pmap = ((VLAN_CTRL0_REG >> 25) & 0x1f); -+ entry->mb_pmap = ((VLAN_CTRL0_REG >> 9) & 0x1f); -+ -+ entry->my_mac[0] = ((VLAN_CTRL1_REG >> 24) & 0xff); -+ entry->my_mac[1] = ((VLAN_CTRL1_REG >> 16) & 0xff); -+ entry->my_mac[2] = ((VLAN_CTRL1_REG >> 8) & 0xff); -+ entry->my_mac[3] = (VLAN_CTRL1_REG & 0xff); -+ -+ entry->my_mac[4] = ((VLAN_CTRL2_REG >> 24) & 0xff); -+ entry->my_mac[5] = ((VLAN_CTRL2_REG >> 16) & 0xff); -+ -+ return CAVM_OK; -+ -+} -+ -+ -+// add a entry in the vlan table -+static inline int cns3xxx_vlan_table_add(VLANTableEntry *entry) -+{ -+ VLAN_CTRL0_REG = 0; -+ VLAN_CTRL1_REG = 0; -+ VLAN_CTRL2_REG = 0; -+ -+#if 0 -+ printk("a [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ printk("a [kernel mode] VLAN_CTRL1_REG: %x\n", VLAN_CTRL1_REG); -+ printk("a [kernel mode] VLAN_CTRL2_REG: %x\n", VLAN_CTRL2_REG); -+#endif -+ -+ //printk("vlan_index: %x\n", entry->vlan_index); -+ VLAN_CTRL0_REG |= (entry->valid << 31); -+ //DEBUG_MSG(NORMAL_MSG, "1 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ VLAN_CTRL0_REG |= (entry->wan_side << 30); -+ //DEBUG_MSG(NORMAL_MSG, "2 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ //printk("entry->etag_pmap: %x\n", entry->etag_pmap); -+ VLAN_CTRL0_REG |= (entry->etag_pmap << 25); -+ //DEBUG_MSG(NORMAL_MSG, "3 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ //printk("entry->mb_pmap: %x\n", entry->mb_pmap); -+ VLAN_CTRL0_REG |= (entry->mb_pmap << 9); -+ //DEBUG_MSG(NORMAL_MSG, "4 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ //printk("bb [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ -+ //printf("vlan index: %d ## add VLAN_CTRL0_REG: %x\n", entry->vlan_index, VLAN_CTRL0_REG); -+ -+ -+ VLAN_CTRL1_REG |= (entry->my_mac[0] << 24); -+ VLAN_CTRL1_REG |= (entry->my_mac[1] << 16); -+ VLAN_CTRL1_REG |= (entry->my_mac[2] << 8); -+ VLAN_CTRL1_REG |= (entry->my_mac[3]); -+ -+ VLAN_CTRL2_REG |= (entry->my_mac[4] << 24); -+ VLAN_CTRL2_REG |= (entry->my_mac[5] << 16); -+ VLAN_CTRL2_REG |= entry->vid; -+ -+#if 0 -+ printk("b [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG); -+ printk("b [kernel mode] VLAN_CTRL1_REG: %x\n", VLAN_CTRL1_REG); -+ printk("b [kernel mode] VLAN_CTRL2_REG: %x\n", VLAN_CTRL2_REG); -+#endif -+ -+ ARL_VLAN_CMD_REG &= (~0x3f); -+ ARL_VLAN_CMD_REG |= (entry->vlan_index); -+ ARL_VLAN_CMD_REG |= (1 << 6); // write vlan table command -+ -+ -+ //printf("after write ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG); -+ -+ // wait for vlan command complete -+ while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ; -+ -+ return CAVM_OK; -+} -+ -+static inline void print_arl_table_entry(ARLTableEntry *entry) -+{ -+ printk("vid: %d\n", entry->vid); -+ printk("pmap: %#x\n", entry->pmap); -+ printk("age_field: %d\n", entry->age_field); -+ printk("vlan_mac: %d\n", entry->vlan_mac); -+ printk("filter: %d\n", entry->filter); -+ printk("mac addr: %x:%x:%x:%x:%x:%x\n", entry->mac[0], entry->mac[1],entry->mac[2],entry->mac[3],entry->mac[4],entry->mac[5]); -+ -+} -+ -+ -+static inline int cns3xxx_arl_table_lookup(ARLTableEntry *entry) -+{ -+ ARL_CTRL0_REG = 0; -+ ARL_CTRL1_REG = 0; -+ ARL_CTRL2_REG = 0; -+ -+ ARL_CTRL0_REG |= (entry->vid << 16); -+ -+ ARL_CTRL1_REG |= (entry->mac[0] << 24); -+ ARL_CTRL1_REG |= (entry->mac[1] << 16); -+ ARL_CTRL1_REG |= (entry->mac[2] << 8); -+ ARL_CTRL1_REG |= entry->mac[3]; -+ -+ ARL_CTRL2_REG |= (entry->mac[4] << 24); -+ ARL_CTRL2_REG |= (entry->mac[5] << 16); -+ -+ ARL_VLAN_CMD_REG |= (1 << 18); // arl table lookup command -+ -+ // wait arl command complete -+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0); -+ -+ if (( (ARL_VLAN_CMD_REG >> 23) & 1)) { -+ // found -+ -+ entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff); -+ entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f); -+ -+ entry->age_field = ((ARL_CTRL2_REG >> 4 ) & 0x7); -+ entry->vlan_mac = ((ARL_CTRL2_REG >> 1 ) & 0x1); -+ entry->filter = (ARL_CTRL2_REG & 0x1); -+ } else { -+ // not found -+ return CAVM_NOT_FOUND; -+ } -+#if 0 -+ printk("[kernel mode] ARL_VLAN_CMD_REG : %#x\n", ARL_VLAN_CMD_REG); -+ printk("[kernel mode] ARL_CTRL0_REG : %#x\n", ARL_CTRL0_REG); -+ printk("[kernel mode] ARL_CTRL1_REG : %#x\n", ARL_CTRL1_REG); -+ printk("[kernel mode] ARL_CTRL2_REG : %#x\n", ARL_CTRL2_REG); -+#endif -+ -+ return CAVM_FOUND; -+} -+ -+static inline int cns3xxx_arl_table_search_again(ARLTableEntry *entry) -+{ -+ ARL_CTRL0_REG = 0; -+ ARL_CTRL1_REG = 0; -+ ARL_CTRL2_REG = 0; -+ -+ ARL_VLAN_CMD_REG |= (1 << 17); // arl table search again command -+ -+ // wait arl command complete -+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0); -+ -+ if ((ARL_VLAN_CMD_REG >> 23) & 1) { -+ -+ // found -+ #if 0 -+ printk("[kernel mode] ARL_VLAN_CMD_REG : %#x\n", ARL_VLAN_CMD_REG); -+ printk("[kernel mode] ARL_CTRL0_REG : %#x\n", ARL_CTRL0_REG); -+ printk("[kernel mode] ARL_CTRL1_REG : %#x\n", ARL_CTRL1_REG); -+ printk("[kernel mode] ARL_CTRL2_REG : %#x\n", ARL_CTRL2_REG); -+ #endif -+ entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff); -+ entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f); -+ -+ entry->age_field = ((ARL_CTRL2_REG >> 4 ) & 0x7); -+ entry->vlan_mac = ((ARL_CTRL2_REG >> 1 ) & 0x1); -+ entry->filter = (ARL_CTRL2_REG & 0x1); -+ -+ entry->mac[0] = (ARL_CTRL1_REG >> 24); -+ entry->mac[1] = (ARL_CTRL1_REG >> 16); -+ entry->mac[2] = (ARL_CTRL1_REG >> 8); -+ entry->mac[3] = ARL_CTRL1_REG; -+ -+ entry->mac[4] = (ARL_CTRL2_REG >> 24); -+ entry->mac[5] = (ARL_CTRL2_REG >> 16); -+ -+ return CAVM_FOUND; -+ } else { -+ // not found -+ return CAVM_NOT_FOUND; -+ } -+} -+ -+static inline int cns3xxx_is_arl_table_end(void) -+{ -+ ARL_CTRL0_REG = 0; -+ ARL_CTRL1_REG = 0; -+ ARL_CTRL2_REG = 0; -+ -+ if (( (ARL_VLAN_CMD_REG >> 22) & 1)) { // search to table end -+ return CAVM_OK; -+ } else { -+ return CAVM_ERR; -+ } -+} -+ -+static inline int cns3xxx_arl_table_search(ARLTableEntry *entry) -+{ -+ ARL_CTRL0_REG = 0; -+ ARL_CTRL1_REG = 0; -+ ARL_CTRL2_REG = 0; -+ -+#if 0 -+ ARL_CTRL0_REG |= (entry->vid << 16); -+ -+ ARL_CTRL1_REG |= (entry->mac[0] << 24); -+ ARL_CTRL1_REG |= (entry->mac[1] << 16); -+ ARL_CTRL1_REG |= (entry->mac[2] << 8); -+ ARL_CTRL1_REG |= entry->mac[3]; -+ -+ ARL_CTRL2_REG |= (entry->mac[4] << 24); -+ ARL_CTRL2_REG |= (entry->mac[5] << 16); -+#endif -+ ARL_VLAN_CMD_REG |= (1 << 16); // arl table search start command -+ -+ // wait arl command complete -+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0); -+ -+ if (((ARL_VLAN_CMD_REG >> 23) & 1)) { -+ // found -+ #if 0 -+ printk("[kernel mode] ARL_VLAN_CMD_REG : %#x\n", ARL_VLAN_CMD_REG); -+ printk("[kernel mode] ARL_CTRL0_REG : %#x\n", ARL_CTRL0_REG); -+ printk("[kernel mode] ARL_CTRL1_REG : %#x\n", ARL_CTRL1_REG); -+ printk("[kernel mode] ARL_CTRL2_REG : %#x\n", ARL_CTRL2_REG); -+ #endif -+ entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff); -+ entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f); -+ -+ entry->age_field = ((ARL_CTRL2_REG >> 4 ) & 0x7); -+ entry->vlan_mac = ((ARL_CTRL2_REG >> 1 ) & 0x1); -+ entry->filter = (ARL_CTRL2_REG & 0x1); -+ -+ entry->mac[0] = (ARL_CTRL1_REG >> 24); -+ entry->mac[1] = (ARL_CTRL1_REG >> 16); -+ entry->mac[2] = (ARL_CTRL1_REG >> 8); -+ entry->mac[3] = ARL_CTRL1_REG; -+ -+ entry->mac[4] = (ARL_CTRL2_REG >> 24); -+ entry->mac[5] = (ARL_CTRL2_REG >> 16); -+ -+ return CAVM_FOUND; -+ } else { -+ // not found -+ return CAVM_NOT_FOUND; -+ } -+} -+ -+ -+// flush all age out entries except static entries -+static inline int cns3xxx_arl_table_flush(void) -+{ -+ ARL_VLAN_CMD_REG |= (1 << 20); // flush arl table command -+ -+ // wait arl command complete -+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0); -+ -+ -+ return CAVM_OK; -+} -+ -+ -+// add a entry in the arl table -+static inline int cns3xxx_arl_table_add(ARLTableEntry *entry) -+{ -+ ARL_CTRL0_REG = 0; -+ ARL_CTRL1_REG = 0; -+ ARL_CTRL2_REG = 0; -+ -+ entry->age_field = 7; // static entry -+ ARL_CTRL0_REG |= (entry->vid << 16); -+ ARL_CTRL0_REG |= (entry->pmap << 9); -+ -+ ARL_CTRL1_REG |= (entry->mac[0] << 24); -+ ARL_CTRL1_REG |= (entry->mac[1] << 16); -+ ARL_CTRL1_REG |= (entry->mac[2] << 8); -+ ARL_CTRL1_REG |= entry->mac[3]; -+ -+ ARL_CTRL2_REG |= (entry->mac[4] << 24); -+ ARL_CTRL2_REG |= (entry->mac[5] << 16); -+ -+ ARL_CTRL2_REG |= (entry->age_field << 4); -+ ARL_CTRL2_REG |= (entry->vlan_mac << 1); -+ ARL_CTRL2_REG |= (entry->filter); -+ -+ //printk("entry->age_field: %d\n", entry->age_field); -+ //printk("ARL_CTRL2_REG: %x\n", ARL_CTRL2_REG); -+ -+ ARL_VLAN_CMD_REG |= (1 << 19); // arl table write command -+ -+ // wait arl command complete -+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0); -+ -+ return CAVM_OK; -+} -+ -+// invalid a entry in the arl table -+static inline int cns3xxx_arl_table_invalid(ARLTableEntry *entry) -+{ -+ entry->age_field = 0; // invalid -+ return cns3xxx_arl_table_add(entry); -+} -+ -+// port: -+// 0 : mac port0 -+// 1 : mac port1 -+// 2 : mac port2 -+// 3 : cpu port -+static inline void cns3xxx_set_pvid(u8 port, u16 pvid) -+{ -+ switch (port) -+ { -+ case 0: -+ { -+ MAC1_MAC0_PVID_REG &= (~0x0fff); -+ MAC1_MAC0_PVID_REG |= pvid; -+ break; -+ } -+ case 1: -+ { -+ MAC1_MAC0_PVID_REG &= (~(0x0fff << 16)); -+ MAC1_MAC0_PVID_REG |= (pvid << 16); -+ break; -+ } -+ case 2: -+ { -+ MAC2_CPU_PVID_REG &= (~(0x0fff << 16)); -+ MAC2_CPU_PVID_REG |= (pvid << 16); -+ break; -+ } -+ case 3: // cpu port -+ { -+ MAC2_CPU_PVID_REG &= (~0x0fff); -+ MAC2_CPU_PVID_REG |= pvid; -+ break; -+ } -+ } -+ -+ -+} -+ -+static inline u16 cns3xxx_get_pvid(u8 port) -+{ -+ // 0, 1, 2, cpu port -+ u16 port_offset[]={0x9c, 0x9c, 0xa0, 0xa0}; -+ // 0, 1, 2, cpu port -+ u16 port_shift[]={0, 16, 16, 0}; -+ -+ return ((SWITCH_REG_VALUE(port_offset[port]) >> port_shift[port]) & 0xfff); -+} -+ -+// which : 0 or 1 -+// enable: 0 or 1 -+static inline int enable_rx_dma(u8 which, u8 enable) -+{ -+ if (which == 0 ) { -+ FS_DMA_CTRL0_REG = enable; -+ } else if (which == 1 ) { -+ FS_DMA_CTRL1_REG = enable; -+ } else { -+ return CAVM_ERR; -+ } -+ return CAVM_OK; -+} -+ -+ -+// which : 0 or 1 -+// enable: 0 or 1 -+static inline int enable_tx_dma(u8 which, u8 enable) -+{ -+ if (which == 0 ) { -+ TS_DMA_CTRL0_REG = enable; -+ } else if (which == 1 ) { -+ TS_DMA_CTRL1_REG = enable; -+ } else { -+ return CAVM_ERR; -+ } -+ return CAVM_OK; -+} -+ -+#define DUMP_TX_DESC_PROC(tx_desc, page, num) \ -+{ \ -+ num += sprintf(page + num,"sdp: %x\n", tx_desc->sdp); \ -+ num += sprintf(page + num,"sdl: %d\n", tx_desc->sdl); \ -+ num += sprintf(page + num,"tco: %d\n", tx_desc->tco); \ -+ num += sprintf(page + num,"uco: %d\n", tx_desc->uco); \ -+ num += sprintf(page + num,"ico: %d\n", tx_desc->ico); \ -+ num += sprintf(page + num,"pri: %d\n", tx_desc->pri); \ -+ num += sprintf(page + num,"fp: %d\n", tx_desc->fp); \ -+ num += sprintf(page + num,"fr: %d\n", tx_desc->fr); \ -+ num += sprintf(page + num,"interrupt: %d\n", tx_desc->interrupt); \ -+ num += sprintf(page + num,"lsd: %d\n", tx_desc->lsd); \ -+ num += sprintf(page + num,"fsd: %d\n", tx_desc->fsd); \ -+ num += sprintf(page + num,"eor: %d\n", tx_desc->eor); \ -+ num += sprintf(page + num,"cown: %d\n", tx_desc->cown); \ -+ \ -+ num += sprintf(page + num,"ctv: %d\n", tx_desc->ctv); \ -+ num += sprintf(page + num,"stv: %d\n", tx_desc->stv); \ -+ num += sprintf(page + num,"sid: %d\n", tx_desc->sid); \ -+ num += sprintf(page + num,"inss: %d\n", tx_desc->inss); \ -+ num += sprintf(page + num,"dels: %d\n", tx_desc->dels); \ -+ num += sprintf(page + num,"pmap: %d\n", tx_desc->pmap); \ -+ num += sprintf(page + num,"mark: %d\n", tx_desc->mark); \ -+ num += sprintf(page + num,"ewan: %d\n", tx_desc->ewan); \ -+ num += sprintf(page + num,"fewan: %d\n", tx_desc->fewan); \ -+ \ -+ num += sprintf(page + num,"c_vid: %d\n", tx_desc->c_vid); \ -+ num += sprintf(page + num,"c_cfs: %d\n", tx_desc->c_cfs); \ -+ num += sprintf(page + num,"c_pri: %d\n", tx_desc->c_pri); \ -+ num += sprintf(page + num,"s_vid: %d\n", tx_desc->s_vid); \ -+ num += sprintf(page + num,"s_dei: %d\n", tx_desc->s_dei); \ -+ num += sprintf(page + num,"s_pri: %d\n", tx_desc->s_pri); \ -+} -+ -+static inline void dump_tx_desc(TXDesc volatile *tx_desc) -+{ -+ printk("sdp: %x\n", tx_desc->sdp); -+ printk("sdl: %d\n", tx_desc->sdl); -+ printk("tco: %d\n", tx_desc->tco); -+ printk("uco: %d\n", tx_desc->uco); -+ printk("ico: %d\n", tx_desc->ico); -+ printk("pri: %d\n", tx_desc->pri); -+ printk("fp: %d\n", tx_desc->fp); -+ printk("fr: %d\n", tx_desc->fr); -+ printk("interrupt: %d\n", tx_desc->interrupt); -+ printk("lsd: %d\n", tx_desc->lsd); -+ printk("fsd: %d\n", tx_desc->fsd); -+ printk("eor: %d\n", tx_desc->eor); -+ printk("cown: %d\n", tx_desc->cown); -+ -+ printk("ctv: %d\n", tx_desc->ctv); -+ printk("stv: %d\n", tx_desc->stv); -+ printk("sid: %d\n", tx_desc->sid); -+ printk("inss: %d\n", tx_desc->inss); -+ printk("dels: %d\n", tx_desc->dels); -+ printk("pmap: %d\n", tx_desc->pmap); -+ printk("mark: %d\n", tx_desc->mark); -+ printk("ewan: %d\n", tx_desc->ewan); -+ printk("fewan: %d\n", tx_desc->fewan); -+ -+ printk("c_vid: %d\n", tx_desc->c_vid); -+ printk("c_cfs: %d\n", tx_desc->c_cfs); -+ printk("c_pri: %d\n", tx_desc->c_pri); -+ printk("s_vid: %d\n", tx_desc->s_vid); -+ printk("s_dei: %d\n", tx_desc->s_dei); -+ printk("s_pri: %d\n", tx_desc->s_pri); -+} -+ -+static inline void dump_rx_desc(RXDesc volatile *rx_desc) -+{ -+ -+ printk("rx_desc: %p\n", rx_desc); -+ //printk("rx_desc: %p ## cown: %d\n", rx_desc, rx_desc->cown); -+ //printk("rx_desc phy addr : %x\n", (u32)page_to_dma(NULL, rx_desc) ); -+#if 0 -+ int i=0; -+ for (i=0; i < 8 ; ++4) { -+ u32 rx_desc_data = *((u32 *)(rx_desc+i)); -+ printk("%d: %#x\n", i, rx_desc_data); -+ } -+#endif -+ -+ printk("sdp: %x\n", rx_desc->sdp); -+ -+ printk("sdl: %d\n", rx_desc->sdl); -+#if 1 -+ printk("l4f: %d\n", rx_desc->l4f); -+ printk("ipf: %d\n", rx_desc->ipf); -+ printk("prot: %d\n", rx_desc->prot); -+ printk("hr: %d\n", rx_desc->hr); -+ printk("lsd: %d\n", rx_desc->lsd); -+ printk("fsd: %d\n", rx_desc->fsd); -+ printk("eor: %d\n", rx_desc->eor); -+#endif -+ printk("cown: %d\n", rx_desc->cown); -+ -+#if 1 -+ printk("ctv: %d\n", rx_desc->ctv); -+ printk("stv: %d\n", rx_desc->stv); -+ printk("unv: %d\n", rx_desc->unv); -+ printk("iwan: %d\n", rx_desc->iwan); -+ printk("exdv: %d\n", rx_desc->exdv); -+ printk("sp: %d\n", rx_desc->sp); -+ printk("crc_err: %d\n", rx_desc->crc_err); -+ printk("un_eth: %d\n", rx_desc->un_eth); -+ printk("tc: %d\n", rx_desc->tc); -+ printk("ip_offset: %d\n", rx_desc->ip_offset); -+ -+ printk("c_vid: %d\n", rx_desc->c_vid); -+ printk("c_cfs: %d\n", rx_desc->c_cfs); -+ printk("c_pri: %d\n", rx_desc->c_pri); -+ printk("s_vid: %d\n", rx_desc->s_vid); -+ printk("s_dei: %d\n", rx_desc->s_dei); -+ printk("s_pri: %d\n", rx_desc->s_pri); -+#endif -+} -+ -+static inline void dump_all_rx_ring(const RXRing *rx_ring, u8 r_index) -+{ -+ int i=0; -+ -+ RXBuffer volatile *rx_buf = get_rx_ring_head(rx_ring); -+ -+ printk("all rx ring: %d\n", r_index); -+ for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) { -+ printk("%d ## rx_buf: %p ## rx_buf->rx_desc: %p\n", i, rx_buf, rx_buf->rx_desc); -+ dump_rx_desc(rx_buf->rx_desc); -+ ++rx_buf; -+ } -+} -+ -+static inline void rx_dma_suspend(u8 enable) -+{ -+#if 1 -+ DMA_AUTO_POLL_CFG_REG &= (~0x00000001); -+ if (enable == 1) -+ DMA_AUTO_POLL_CFG_REG |= 1; -+#endif -+} -+ -+ -+// clear: 0 normal -+// clear: 1 clear -+static inline void clear_fs_dma_state(u8 clear) -+{ -+ DMA_RING_CTRL_REG &= (~(1 << 31)); -+ if (clear==1) { -+ DMA_RING_CTRL_REG |= (1 << 31); -+ } -+} -+ -+// enable: 1 -> IVL -+// enable: 0 -> SVL -+static inline void cns3xxx_ivl(u8 enable) -+{ -+ // SVL -+ MAC_GLOB_CFG_REG &= (~(0x1 << 7)); -+ if (enable == 1) -+ MAC_GLOB_CFG_REG |= (0x1 << 7); -+} -+ -+static inline void cns3xxx_nic_mode(u8 enable) -+{ -+ VLAN_CFG &= (~(1<<15)); -+ if (enable == 1) -+ VLAN_CFG |= (1<<15); -+} -+ -+ -+void gic_mask_irq(unsigned int irq); -+void gic_unmask_irq(unsigned int irq); -+extern void __iomem *gic_cpu_base_addr; -+ -+ -+static inline void cns3xxx_disable_irq(u32 irq) -+{ -+#ifdef CONFIG_SMP -+ disable_irq_nosync(irq); -+#else -+ disable_irq(irq); -+#endif -+ //gic_mask_irq(irq); -+} -+ -+static inline void cns3xxx_enable_irq(u32 irq) -+{ -+ enable_irq(irq); -+ //gic_unmask_irq(irq); -+} -+ -+static inline int cns3xxx_get_tx_hw_index(u8 ring_index) -+{ -+ if (ring_index == 0) { -+ return (TS_DESC_PTR0_REG - TS_DESC_BASE_ADDR0_REG) / sizeof (TXDesc); -+ } else if (ring_index == 1) { -+ return (TS_DESC_PTR1_REG - TS_DESC_BASE_ADDR1_REG) / sizeof (TXDesc); -+ } else { -+ return CAVM_ERR; -+ } -+} -+ -+static inline TXBuffer* get_tx_buffer_by_index(TXRing *tx_ring, int i) -+{ -+ int index = i; -+ -+ index = ((index + get_tx_ring_size(tx_ring) )% get_tx_ring_size(tx_ring)); -+ -+ return tx_ring->head + index; -+} -+ -+static inline int cns3xxx_is_untag_packet(const RXDesc *rx_desc) -+{ -+ return rx_desc->crc_err; -+} -+ -+ -+#ifdef CONFIG_SWITCH_BIG_ENDIAN -+static inline void swap_rx_desc(RXDesc *org_desc, RXDesc *new_desc) -+{ -+ int i=0; -+ void *org_p = org_desc; -+ void *new_p = new_desc; -+ -+ for (i=0; i < 16 ; i+=4) { -+ u32 rx_desc_data = 0; -+ u32 swab_rx_desc_data = 0; -+ -+ rx_desc_data = *((volatile u32 *)(org_p+i)); -+ swab_rx_desc_data = ___swab32(rx_desc_data); -+ -+ *((volatile u32 *)(new_p+i)) = swab_rx_desc_data; -+ } -+} -+ -+static inline void swap_tx_desc(TXDesc *org_desc, TXDesc *new_desc) -+{ -+ int i=0; -+ void *org_p = org_desc; -+ void *new_p = new_desc; -+ -+ for (i=0; i < 16 ; i+=4) { -+ u32 desc_data = *((volatile u32 *)(org_p+i)); -+ u32 swab_desc_data = ___swab32(desc_data); -+ -+ *((volatile u32 *)(new_p+i)) = swab_desc_data; -+ } -+} -+ -+#endif -+ -+ -+static inline int cns3xxx_min_mtu(void) -+{ -+ return 64; -+} -+ -+static inline int cns3xxx_max_mtu(void) -+{ -+ int max_len[]={1518, 1522, 1536, 9600}; -+ -+ return max_len[((PHY_AUTO_ADDR_REG >> 30) & 0x3)]; -+} -+ -+#endif // CNS3XXX_TOOL_H ---- /dev/null -+++ b/drivers/net/cns3xxx/fpga.h -@@ -0,0 +1,306 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+// This macro or function divide two part, -+// one is initial state, another is in netdev open (ifconfig up) function. -+ -+#ifndef FPGA_H -+#define FPGA_H -+ -+#include <linux/types.h> -+ -+#include "cns3xxx_config.h" -+#include "cns3xxx_phy.h" -+ -+//#define FGPA -+ -+ -+#ifdef CONFIG_FPGA -+// init phy or switch chip -+#define INIT_PORT0_PHY cns3xxx_config_VSC8601(0,0); -+#define INIT_PORT1_PHY cns3xxx_config_VSC8601(1,1); -+#define INIT_PORT2_PHY icp_101a_init(2, 2); -+//#define INIT_PORT1_PHY -+ -+// configure mac0/mac1 register -+#define INIT_PORT0_MAC -+#define INIT_PORT1_MAC -+#define INIT_PORT2_MAC -+//#define INIT_PORT1_MAC -+ -+#define PORT0_LINK_DOWN vsc8601_power_down(0, 1); -+#define PORT0_LINK_UP vsc8601_power_down(0, 0); -+ -+#define PORT1_LINK_DOWN vsc8601_power_down(1, 1); -+#define PORT1_LINK_UP vsc8601_power_down(1, 0); -+ -+#define PORT2_LINK_DOWN cns3xxx_std_phy_power_down(2, 1); -+#define PORT2_LINK_UP cns3xxx_std_phy_power_down(2, 0); -+ -+ -+ -+#define MODEL "VEGA FPGA" -+ -+static int rc_port0 = 0; // rc means reference counting, determine port open/close. -+ -+ -+// enable port -+// link down -+static inline void open_port0(void) -+{ -+ if (rc_port0 == 0) { -+ enable_port(0, 1); -+ PRINT_INFO("open mac port 0\n"); -+ // link up -+ PORT0_LINK_UP -+ } else { -+ PRINT_INFO("port 0 already open\n");\ -+ } -+ ++rc_port0; -+} -+ -+static inline void close_port0(void) -+{ -+ --rc_port0; -+ if (rc_port0 == 0) { -+ // link down -+ PORT0_LINK_DOWN -+ enable_port(0, 0); -+ PRINT_INFO("close mac port 0\n");\ -+ } -+} -+ -+static inline void open_port1(void) -+{ -+ -+ enable_port(1, 1); -+ PRINT_INFO("open mac port 1\n"); -+ // link up -+ PORT1_LINK_UP -+} -+ -+static inline void close_port1(void) -+{ -+ enable_port(1, 0); -+ PRINT_INFO("close mac port 1\n"); -+ // link down -+ PORT1_LINK_DOWN -+} -+ -+static inline void open_port2(void) -+{ -+ -+ enable_port(2, 1); -+ PRINT_INFO("open mac port 2\n"); -+ // link up -+ PORT2_LINK_UP -+} -+ -+static inline void close_port2(void) -+{ -+ enable_port(2, 0); -+ PRINT_INFO("close mac port 2\n"); -+ // link down -+ PORT2_LINK_DOWN -+} -+ -+static u8 my_vlan0_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x00}; -+static u8 my_vlan1_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x11}; -+static u8 my_vlan2_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x70}; -+static u8 my_vlan3_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x80}; -+ -+ -+ -+ -+// CNS3XXX_NIC_MODE_8021Q, CNS3XXX_NON_NIC_MODE_8021Q, CNS3XXX_VLAN_BASE_MODE and -+// CNS3XXX_PORT_BASE_MODE, only one macro can be defined -+ -+#ifdef CNS3XXX_VLAN_8021Q -+ #ifndef CNS3XXX_NIC_MODE_8021Q -+ #define CNS3XXX_NON_NIC_MODE_8021Q -+ #endif -+#else -+ //#define CNS3XXX_VLAN_BASE_MODE -+ #define CNS3XXX_PORT_BASE_MODE -+#endif -+ -+#ifdef CNS3XXX_PORT_BASE_MODE -+ -+#define PORT0_PVID 0x1 -+#define PORT1_PVID 0x2 -+#define PORT2_PVID 3 -+#define CPU_PVID 5 -+ -+#define CONFIG_CNS3XXX_PORT_BASE -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac; -+ //{0, 1, 1, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {1, 1, PORT0_PVID, 0, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, 0, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+ //{2, 1, 4, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}, // for cpu -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ //{CPU_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+ //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan8_mac, 7, 0, 0}, -+ //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan9_mac, 7, 0, 0}, -+ //{CPU_PVID, 0x4, my_vlan2_mac, 7, 1, 0}, -+ //{CPU_PVID, MAC_PORT2_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+static NetDevicePriv net_device_prive[]= { -+ /* pmap, is_wan, s-tag, vlan_tag or pvid, rx_func_ptr, tx_func_ptr, open_ptr, close_ptr, which port, mac, VLANTableEntry, ARLTableEntry, NICSetting, netdev s-tag, name */ -+ {MAC_PORT0_PMAP, 0, 1, PORT0_NETDEV_INDEX, rx_port_base, tx_port_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 2, PORT1_NETDEV_INDEX, rx_port_base, tx_port_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_NETDEV_INDEX, rx_port_base, tx_port_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+ -+#endif -+ -+#ifdef CNS3XXX_NON_NIC_MODE_8021Q -+//#error "8021Q" -+#define PORT0_PVID 50 -+#define PORT1_PVID 60 -+#define PORT2_PVID 70 -+#define CPU_PVID 80 -+ -+#define CONFIG_CNS3XXX_PORT_BASE -+//#define CONFIG_CNS3XXX_VLAN_BASE -+//#define CONFIG_HAVE_VLAN_TAG -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; // for cpu -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;C_PORT2_PMAP -+ {1, 1, PORT0_PVID, 0, CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 0, CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+ -+// if used 8021Q, use PORT0_NETDEV_INDEX, don't use VID -+static NetDevicePriv net_device_prive[]= { -+ {MAC_PORT0_PMAP, 0, 1, PORT0_NETDEV_INDEX, rx_port_base, tx_port_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 0, PORT1_NETDEV_INDEX, rx_port_base, tx_port_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_NETDEV_INDEX, rx_port_base, tx_port_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+#endif -+ -+ -+ -+#ifdef CNS3XXX_NIC_MODE_8021Q -+//#error "8021Q" -+#define PORT0_PVID 1 -+#define PORT1_PVID 2 -+#define PORT2_PVID 9 -+#define CPU_PVID 5 -+ -+#define CONFIG_CNS3XXX_PORT_BASE -+//#define CONFIG_CNS3XXX_VLAN_BASE -+//#define CONFIG_HAVE_VLAN_TAG -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; // for cpu -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;C_PORT2_PMAP -+ {1, 1, PORT0_PVID, 1, MAC_PORT0_PMAP|CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP|CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP|CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+ -+// if used 8021Q, use PORT0_NETDEV_INDEX, don't use VID -+static NetDevicePriv net_device_prive[]= { -+ {MAC_PORT0_PMAP, 0, 1, PORT0_NETDEV_INDEX, rx_port_base, tx_port_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 0, PORT1_NETDEV_INDEX, rx_port_base, tx_port_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_NETDEV_INDEX, rx_port_base, tx_port_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+#endif -+ -+#ifdef CNS3XXX_VLAN_BASE_MODE -+//#error "vlan_base" -+// vlan configuration -+ -+#define PORT0_PVID 1 -+#define PORT1_PVID 2 -+#define PORT2_PVID 3 -+#define CPU_PVID 5 -+#define CONFIG_CNS3XXX_VLAN_BASE -+#define CONFIG_HAVE_VLAN_TAG -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; // for cpu -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac; -+ {1, 1, PORT0_PVID, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP | CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+static NetDevicePriv net_device_prive[]= { -+ /* pmap, is_wan, gid, vlan_tag or pvid, rx_func_ptr, tx_func_ptr, open_ptr, close_ptr, which port, mac, VLANTableEntry, ARLTableEntry, NICSetting, netdev name */ -+ {MAC_PORT0_PMAP, 0, 1, PORT0_PVID, rx_port_base, tx_vlan_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 0, PORT1_PVID, rx_port_base, tx_vlan_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_PVID, rx_port_base, tx_vlan_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+#endif -+ -+#endif // CONFIG_FPGA -+#endif // FPGA_H ---- /dev/null -+++ b/drivers/net/cns3xxx/Kconfig -@@ -0,0 +1,58 @@ -+menu "CNS3XXX Gigabit Switch Support" -+ depends on ARCH_CNS3XXX -+ -+config CNS3XXX_GSW -+ tristate "CNS3XXX Gigabit Switch Driver Support" -+ help -+ CNS3XXX Gigabit Switch. -+ -+config CNS3XXX_SPPE -+ bool "CNS3XXX Smart PPE(Packet Processing Engine) Support" -+ depends on CNS3XXX_GSW -+ help -+ PPE(Packet Processing Engine) is a hardware accelerator hook on a port of -+ CNS3XXX Gigabit Switch. -+ -+ This option is used for Smart PPE hook. -+ -+ Say Y if you want to enable Smart PPE function. -+ -+config CNS3XXX_HCIE_TEST -+ bool "CNS3XXX HCIE(Hardware Content Inspection Engine) Support" -+# depends on CNS3XXX_GSW -+ help -+ HCIE is patent-protected layer-7 packet processing engine. -+ -+ This option is used for fundamental HCIE functional test . -+ Say Y if you want to do HCIE functional test. -+ -+ -+#config CNS3XXX_SHNAT_PCI_FASTPATH -+# bool "FastPath(From PCI to WAN) Support" -+# depends on CNS3XXX_SHNAT -+# help -+# Add FastPath Support for Smart HNAT. -+ -+comment "NOTE: 'Validation Board' depends on" -+comment "GPIO_CNS3XXX and SPI_CNS3XXX" -+choice -+ prompt "CNS3XXX Board" -+ depends on CNS3XXX_GSW -+ default FPGA -+ -+config FPGA -+ bool "Fpga" -+ -+config VB -+ bool "Validation Board" -+ help -+ MAC0 and MAC1 connect to BCM53115M. It need enable CNS3XXX SPI and CNS3XXX GPIO option. -+ MAC2 use ICPLUS IP1001 phy. -+ -+#config LEO -+# bool "Leo" -+ -+endchoice -+ -+endmenu -+ ---- /dev/null -+++ b/drivers/net/cns3xxx/Makefile -@@ -0,0 +1,41 @@ -+################################################################################ -+# -+# -+# Copyright (c) 2008 Cavium Networks -+# -+# 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. -+# -+# The full GNU General Public License is included in this distribution in the -+# file called LICENSE. -+# -+# Contact Information: -+# Star semiconduction Linux Support <support@starsemi.com> -+# -+################################################################################ -+ -+# -+# Makefile for the Star GSW ethernet driver -+# -+ -+#obj-y := -+#obj-m := -+ -+obj-$(CONFIG_CNS3XXX_GSW) += cns3xxx.o -+cns3xxx-objs := cns3xxx_phy.o cns3xxx_main.o cns3xxx_ethtool.o -+obj-$(CONFIG_CNS3XXX_SPPE) += cns3xxx_sppe_hook.o -+#endif -+#vega_main.o -+ -+#include $(TOPDIR)/Rules.make ---- /dev/null -+++ b/drivers/net/cns3xxx/vb.h -@@ -0,0 +1,328 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2009 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ ********************************************************************************/ -+ -+// This macro or function divide two part, -+// one is initial state, another is in netdev open (ifconfig up) function. -+ -+#ifndef VB_H -+#define VB_H -+ -+#include <linux/types.h> -+ -+#include "cns3xxx_config.h" -+#include "cns3xxx_phy.h" -+ -+#ifdef CONFIG_VB -+// init phy or switch chip -+#define INIT_PORT0_PHY cns3xxx_config_VSC8601(0, 0); -+#define INIT_PORT1_PHY cns3xxx_config_VSC8601(1, 1); -+#define INIT_PORT2_PHY -+//#define INIT_PORT1_PHY -+ -+// configure mac0/mac1 register -+#define INIT_PORT0_MAC -+#define INIT_PORT1_MAC -+#define INIT_PORT2_MAC -+//#define INIT_PORT1_MAC -+ -+#define PORT0_LINK_DOWN cns3xxx_std_phy_power_down(0, 1); -+#define PORT0_LINK_UP cns3xxx_std_phy_power_down(0, 0); -+ -+#define PORT1_LINK_DOWN cns3xxx_std_phy_power_down(1, 1); -+#define PORT1_LINK_UP cns3xxx_std_phy_power_down(1, 0); -+ -+#define PORT2_LINK_DOWN -+#define PORT2_LINK_UP -+ -+#define MODEL "CNS3XXX validation board" -+ -+static int rc_port0 = 0; // rc means reference counting, determine port open/close. -+ -+#define PRINT_INFO printk -+ -+// enable port -+// link down -+static inline void open_port0(void) -+{ -+ if (rc_port0 == 0) { -+ enable_port(0, 1); -+ // link up -+ PORT0_LINK_UP -+ } -+ ++rc_port0; -+} -+ -+static inline void close_port0(void) -+{ -+ --rc_port0; -+ if (rc_port0 == 0) { -+ // link down -+ PORT0_LINK_DOWN -+ enable_port(0, 0); -+ } -+} -+ -+static inline void open_port1(void) -+{ -+ -+ enable_port(1, 1); -+ // link up -+ PORT1_LINK_UP -+} -+ -+static inline void close_port1(void) -+{ -+ enable_port(1, 0); -+ // link down -+ PORT1_LINK_DOWN -+} -+ -+static inline void open_port2(void) -+{ -+ -+ enable_port(2, 1); -+ // link up -+ PORT2_LINK_UP -+} -+ -+static inline void close_port2(void) -+{ -+ enable_port(2, 0); -+ // link down -+ PORT2_LINK_DOWN -+} -+ -+#if defined (CONFIG_CNS3XXX_SPPE) -+/* only for PPE PCI-to-WAN fast path */ -+static int fp_ref_cnt = 0; -+static inline void open_fp(void) -+{ -+ if (!fp_ref_cnt) { -+ fp_ref_cnt++; -+ } -+} -+ -+static inline void close_fp(void) -+{ -+ if (fp_ref_cnt) { -+ fp_ref_cnt--; -+ } -+} -+#endif -+ -+static u8 my_vlan0_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x00}; -+static u8 my_vlan1_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x11}; -+static u8 my_vlan2_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x70}; -+static u8 my_vlan3_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x80}; -+ -+ -+ -+ -+// CNS3XXX_NIC_MODE_8021Q, CNS3XXX_NON_NIC_MODE_8021Q, CNS3XXX_VLAN_BASE_MODE and -+// CNS3XXX_PORT_BASE_MODE, only one macro can be defined -+ -+#ifdef CNS3XXX_VLAN_8021Q -+ #define CNS3XXX_NIC_MODE_8021Q -+ #ifndef CNS3XXX_NIC_MODE_8021Q -+ #define CNS3XXX_NON_NIC_MODE_8021Q -+ #endif -+#else -+ //#define CNS3XXX_VLAN_BASE_MODE -+ #define CNS3XXX_PORT_BASE_MODE -+#endif -+ -+//#define CNS3XXX_PORT_BASE_MODE -+// -+#ifdef CNS3XXX_NON_NIC_MODE_8021Q -+ -+#define PORT0_PVID 50 -+#define PORT1_PVID 60 -+#define PORT2_PVID 70 -+#define CPU_PVID 80 -+ -+#define CONFIG_CNS3XXX_PORT_BASE -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac; -+ #if 0 -+ {1, 1, PORT0_PVID, 0, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, 0, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+ #endif -+ -+ {1, 1, PORT0_PVID, 0, CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 0, CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+ //{2, 1, 4, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}, // for cpu -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ //{CPU_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+ //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan8_mac, 7, 0, 0}, -+ //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan9_mac, 7, 0, 0}, -+ //{CPU_PVID, 0x4, my_vlan2_mac, 7, 1, 0}, -+ //{CPU_PVID, MAC_PORT2_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+static NetDevicePriv net_device_prive[]= { -+ /* pmap, is_wan, s-tag, vlan_tag or pvid, rx_func_ptr, tx_func_ptr, open_ptr, close_ptr, which port, mac, VLANTableEntry, ARLTableEntry, NICSetting, netdev s-tag, name */ -+ {MAC_PORT0_PMAP, 0, 1, PORT0_NETDEV_INDEX, rx_port_base, tx_port_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 2, PORT1_NETDEV_INDEX, rx_port_base, tx_port_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_NETDEV_INDEX, rx_port_base, tx_port_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+#if defined (CONFIG_CNS3XXX_SPPE) -+ ,{CPU_PORT_PMAP, 0, 1, FP_NETDEV_INDEX, NULL, fp_port_base, -+ open_fp, close_fp, CPU_PORT, my_vlan3_mac, &cpu_vlan_table_entry, -+ 0, 0, "fp"} -+#endif -+ }; -+ -+#endif // CNS3XXX_PORT_BASE_MODE -+ -+#ifdef CNS3XXX_PORT_BASE_MODE -+ -+#define PORT0_PVID 0x1 -+#define PORT1_PVID 0x2 -+#define PORT2_PVID 3 -+#define CPU_PVID 5 -+ -+#define CONFIG_CNS3XXX_PORT_BASE -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac; -+ //{0, 1, 1, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {1, 1, PORT0_PVID, 0, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, 0, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+ //{2, 1, 4, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}, // for cpu -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ //{CPU_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+ //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan8_mac, 7, 0, 0}, -+ //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan9_mac, 7, 0, 0}, -+ //{CPU_PVID, 0x4, my_vlan2_mac, 7, 1, 0}, -+ //{CPU_PVID, MAC_PORT2_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+static NetDevicePriv net_device_prive[]= { -+ /* pmap, is_wan, s-tag, vlan_tag or pvid, rx_func_ptr, tx_func_ptr, open_ptr, close_ptr, which port, mac, VLANTableEntry, ARLTableEntry, NICSetting, netdev s-tag, name */ -+ {MAC_PORT0_PMAP, 0, 1, PORT0_NETDEV_INDEX, rx_port_base, tx_port_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 2, PORT1_NETDEV_INDEX, rx_port_base, tx_port_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_NETDEV_INDEX, rx_port_base, tx_port_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+ -+#endif // CNS3XXX_PORT_BASE_MODE -+ -+#ifdef CNS3XXX_NIC_MODE_8021Q -+//#error "8021Q" -+#define PORT0_PVID 1 -+#define PORT1_PVID 2 -+#define PORT2_PVID 9 -+#define CPU_PVID 5 -+ -+#define CONFIG_CNS3XXX_PORT_BASE -+//#define CONFIG_CNS3XXX_VLAN_BASE -+//#define CONFIG_HAVE_VLAN_TAG -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; // for cpu -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;C_PORT2_PMAP -+ {1, 1, PORT0_PVID, 1, MAC_PORT0_PMAP|CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP|CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP|CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+ -+// if used 8021Q, use PORT0_NETDEV_INDEX, don't use VID -+static NetDevicePriv net_device_prive[]= { -+ {MAC_PORT0_PMAP, 0, 1, PORT0_NETDEV_INDEX, rx_port_base, tx_port_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 0, PORT1_NETDEV_INDEX, rx_port_base, tx_port_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_NETDEV_INDEX, rx_port_base, tx_port_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+#endif // CNS3XXX_NIC_MODE_8021Q -+ -+#ifdef CNS3XXX_VLAN_BASE_MODE -+//#error "vlan_base" -+// vlan configuration -+ -+#define PORT0_PVID 1 -+#define PORT1_PVID 2 -+#define PORT2_PVID 3 -+#define CPU_PVID 5 -+#define CONFIG_CNS3XXX_VLAN_BASE -+#define CONFIG_HAVE_VLAN_TAG -+ -+static VLANTableEntry cpu_vlan_table_entry = {0, 1, CPU_PVID, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}; // for cpu -+ -+static VLANTableEntry vlan_table_entry[] = -+{ -+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac; -+ {1, 1, PORT0_PVID, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac}, -+ {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac}, -+ {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP | CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac}, -+}; -+ -+static ARLTableEntry arl_table_entry[] = -+{ -+ // vid; pmap; *mac; age_field; vlan_mac ; filter -+ {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0}, -+ {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0}, -+ {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0}, -+}; -+ -+static NetDevicePriv net_device_prive[]= { -+ /* pmap, is_wan, gid, vlan_tag or pvid, rx_func_ptr, tx_func_ptr, open_ptr, close_ptr, which port, mac, VLANTableEntry, ARLTableEntry, NICSetting, netdev name */ -+ {MAC_PORT0_PMAP, 0, 1, PORT0_PVID, rx_port_base, tx_vlan_base, open_port0, close_port0, MAC_PORT0, my_vlan0_mac, &vlan_table_entry[0], &arl_table_entry[0], 0, 0}, // eth0 -+ {MAC_PORT1_PMAP, 0, 0, PORT1_PVID, rx_port_base, tx_vlan_base, open_port1, close_port1, MAC_PORT1, my_vlan1_mac, &vlan_table_entry[1], &arl_table_entry[1], 0, 0}, // eth1 -+ {MAC_PORT2_PMAP, 1, 3, PORT2_PVID, rx_port_base, tx_vlan_base, open_port2, close_port2, MAC_PORT2, my_vlan2_mac, &vlan_table_entry[2], &arl_table_entry[2], 0, 0} // eth2 -+ }; -+#endif // CNS3XXX_VLAN_BASE_MODE -+ -+#endif // CONFIG_VB -+#endif // VB_H ---- a/drivers/net/Kconfig -+++ b/drivers/net/Kconfig -@@ -2076,6 +2076,8 @@ menuconfig NETDEV_1000 - - if NETDEV_1000 - -+source "drivers/net/cns3xxx/Kconfig" -+ - config ACENIC - tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support" - depends on PCI ---- a/drivers/net/Makefile -+++ b/drivers/net/Makefile -@@ -6,6 +6,11 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci - - obj-$(CONFIG_E1000) += e1000/ - obj-$(CONFIG_E1000E) += e1000e/ -+obj-$(CONFIG_CNS3XXX_GSW) += cns3xxx/ -+ifeq ($(CONFIG_CNS3XXX_GSW),m) -+ obj-y += cns3xxx/cns3xxx_sppe_hook.o -+endif -+ - obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/ - obj-$(CONFIG_IGB) += igb/ - obj-$(CONFIG_IGBVF) += igbvf/ ---- /dev/null -+++ b/include/linux/cns3xxx/sppe.h -@@ -0,0 +1,1579 @@ -+/* -+ * PROJECT CODE: CNS3XXX Smart Packet Processing Engine -+ * MODULE NAME: sppe.h -+ * DESCRIPTION: -+ * -+ * Change Log -+ * -+ * 1.0.0 25-Dec-2008 -+ * o -+ * -+ */ -+ -+#ifndef _SPPE_H_ -+#define _SPPE_H_ -+ -+#if defined(CONFIG_CNS3XXX_SPPE) -+ -+ -+/* PPE Table Size Def. */ -+#define PPE_TABLE_SIZE_2K (0x0) -+#define PPE_TABLE_SIZE_4K (0x1) -+#define PPE_TABLE_SIZE_8K (0x2) -+#define PPE_TABLE_SIZE_16K (0x3) -+#define PPE_TABLE_SIZE_32K (0x4) -+#define PPE_TABLE_SIZE_64K (0x5) -+#define PPE_TABLE_SIZE_128K (0x6) -+#define PPE_TABLE_SIZE_256K (0x7) -+ -+typedef enum _sppe_cmd { -+ SPPE_CMD_INIT = 0, -+ SPPE_CMD_VERSION, -+ -+ SPPE_CMD_ENABLE, -+ SPPE_CMD_FIREWALL, -+ SPPE_CMD_RULE_CHECK, -+ SPPE_CMD_GRL_CHECK, -+ SPPE_CMD_FLOW_CHECK, -+ SPPE_CMD_RATE_LIMIT_EN, -+ SPPE_CMD_POLICE_EN, -+ SPPE_CMD_RLCFG, -+ SPPE_CMD_FC, /* flow control */ -+ SPPE_CMD_MIRROR_TO_CPU, -+ -+ SPPE_CMD_TCP_SNA_TH, -+ SPPE_CMD_PRDA, -+ SPPE_CMD_AGING, -+ SPPE_CMD_MAX_LENGTH, -+ -+ SPPE_CMD_LANIPV4, -+ SPPE_CMD_WANIPV4, -+ -+ SPPE_CMD_RULE_PPPOE_RELAY, -+ SPPE_CMD_RULE_BRIDGE, -+ SPPE_CMD_RULE_ACL, -+ SPPE_CMD_RULE_ROUTE, -+#if 0 -+ SPPE_CMD_RULE_VSERVER, -+#else -+ SPPE_CMD_RULE_SNAT, -+ SPPE_CMD_RULE_DNAT, -+#endif -+ SPPE_CMD_RULE_GRL, -+ -+ SPPE_CMD_ARP, -+ SPPE_CMD_ARL, -+ SPPE_CMD_PPPOE_SID, -+ -+ SPPE_CMD_FLOW_BRIDGE_IPV4, -+ SPPE_CMD_FLOW_BRIDGE_IPV6, -+ SPPE_CMD_FLOW_ROUTE_IPV4, -+ SPPE_CMD_FLOW_ROUTE_IPV6, -+ SPPE_CMD_FLOW_NAT_IPV4, -+ SPPE_CMD_FLOW_NAT_IPV6, -+ //SPPE_CMD_FLOW_TWICE_NAT, -+ SPPE_CMD_FLOW_MCAST_IPV4, -+ SPPE_CMD_FLOW_MCAST_IPV6, -+ SPPE_CMD_FLOW_BRIDGE_L2, -+ -+ SPPE_CMD_CHGDSCP, -+ SPPE_CMD_CHGPRI, -+ SPPE_CMD_RL_FLOW, -+ SPPE_CMD_RL_RULE, -+ -+ SPPE_CMD_DEBUG, -+ SPPE_CMD_REG, -+ SPPE_CMD_SRAM, -+ SPPE_CMD_DUMP, -+ -+ /* accounting group and drop packet count */ -+ SPPE_CMD_ACCOUNTING_GROUP, -+ SPPE_CMD_DROP_IPCS_ERR, -+ SPPE_CMD_DROP_RATE_LIMIT, -+ SPPE_CMD_DROP_OTHERS, -+ -+ SPPE_CMD_PCI_FP_DEV, -+ -+} SPPE_CMD; -+ -+typedef enum _sppe_op { -+ SPPE_OP_GET = 0, -+ SPPE_OP_SET, -+ SPPE_OP_DELETE, -+ SPPE_OP_DELETE_OUTDATED, /* flow only */ -+ SPPE_OP_UPDATE_COUNTER, /* ACL rule only */ -+ SPPE_OP_CLEAN, -+ SPPE_OP_UNKNOWN -+} SPPE_OP; -+ -+typedef enum _sppe_boolean { -+ SPPE_BOOL_FALSE = 0, -+ SPPE_BOOL_TRUE = 1 -+} SPPE_BOOL; -+ -+ -+typedef enum _sppe_result { -+ SPPE_RESULT_SUCCESS = 0, -+ SPPE_RESULT_FAIL, -+ SPPE_RESULT_UNSUPPORT_CMD, -+ SPPE_RESULT_UNSUPPORT_OP, -+ SPPE_RESULT_INVALID_INDEX, -+ SPPE_RESULT_INVALID_TYPE, -+ SPPE_RESULT_FLOW_NOT_FOUND, -+} SPPE_RESULT; -+ -+typedef enum _sppe_prot { -+ SPPE_PROT_UDP = 0, -+ SPPE_PROT_TCP = 1, -+ SPPE_PROT_PPTP_GRE = 2, -+ SPPE_PROT_OTHERS = 3, -+} SPPE_PROT; -+ -+ -+typedef enum _sppe_l2_select { -+ SPPE_L2S_ARP_TABLE = 0, -+ SPPE_L2S_POLICY_ROUTE = 1, -+ SPPE_L2S_IN_FLOW = 2, -+ SPPE_L2S_RESERVED = 3, -+} SPPE_L2_SELECT; -+ -+typedef enum _sppe_dump_type { -+ SPPE_DUMP_TYPE_FLOW = 0, -+ SPPE_DUMP_TYPE_ARP, -+ SPPE_DUMP_TYPE_RULE -+} SPPE_DUMP_TYPE; -+ -+/* Data Structure */ -+typedef struct _sppe_pppoe_relay { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int unused:31; -+#else -+ unsigned int unused:31; -+ unsigned int valid:1; -+#endif -+ unsigned short lsid; /* PPPoE session ID in LAN side */ -+ unsigned short wsid; /* PPPoE session ID in WAN side */ -+ unsigned char lmac[6]; /* MAC address of PPPoE client */ -+ unsigned char wmac[6]; /* MAC address of PPPoE server */ -+} SPPE_PPPOE_RELAY; -+ -+typedef struct _sppe_bridge { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int wan:1; -+ unsigned int ppp:1; /* enable PPPoE sessoion ID comparison*/ -+ unsigned int psidx:4; /* PPPoE session ID index */ -+ unsigned int kv:1; -+ unsigned int sws:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int fp:1; /* force VLAN priority */ -+ unsigned int pri:3; -+ unsigned int ag:2; -+ unsigned int unused:15; -+#else -+ unsigned int unused:15; -+ unsigned int ag:2; -+ unsigned int pri:3; -+ unsigned int fp:1; /* force VLAN priority */ -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int sws:1; -+ unsigned int kv:1; -+ unsigned int psidx:4; /* PPPoE session ID index */ -+ unsigned int ppp:1; /* enable PPPoE sessoion ID comparison*/ -+ unsigned int wan:1; -+ unsigned int valid:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int svid:12; -+ unsigned int cvid:12; -+ unsigned int loc:8; -+#else -+ unsigned int loc:8; -+ unsigned int cvid:12; -+ unsigned int svid:12; -+#endif -+ -+ unsigned char smac[6]; /* source MAC address */ -+ unsigned char dmac[6]; /* destination MAC address */ -+ unsigned int pkt_cnt; -+} SPPE_BRIDGE; -+ -+typedef struct _sppe_acl { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int ipv6:1; -+ unsigned int wan:1; -+ unsigned int tcp:1; -+ unsigned int udp:1; -+ unsigned int to:4; -+ unsigned int from:4; -+ unsigned int rr:4; -+ unsigned int kv:1; -+ unsigned int sws:1; -+ unsigned int loc:8; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int unused:3; -+#else -+ unsigned int unused:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int loc:8; -+ unsigned int sws:1; -+ unsigned int kv:1; -+ unsigned int rr:4; -+ unsigned int from:4; -+ unsigned int to:4; -+ unsigned int udp:1; -+ unsigned int tcp:1; -+ unsigned int wan:1; -+ unsigned int ipv6:1; -+ unsigned int valid:1; -+#endif -+ -+ unsigned int sip[4]; -+ unsigned int dip[4]; -+ unsigned short sip_mask; -+ unsigned short dip_mask; -+ -+ unsigned short sport_start; -+ unsigned short sport_end; -+ unsigned short dport_start; -+ unsigned short dport_end; -+ unsigned int pkt_cnt; -+} SPPE_ACL; -+ -+typedef struct _sppe_route { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int ipv6:1; -+ unsigned int wan:1; -+ unsigned int rd:1; /* replace dscp */ -+ unsigned int dscp:6; -+ unsigned int pr:1; /* policy route */ -+ unsigned int prs:2; /* policy route select */ -+ unsigned int kv:1; -+ unsigned int sws:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int fp:1; /* force VLAN priority */ -+ unsigned int pri:3; -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+ unsigned int ag:2; -+ unsigned int unused:3; -+#else -+ unsigned int unused:3; -+ unsigned int ag:2; -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int pri:3; -+ unsigned int fp:1; /* force VLAN priority */ -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int sws:1; -+ unsigned int kv:1; -+ unsigned int prs:2; /* policy route select */ -+ unsigned int pr:1; /* policy route */ -+ unsigned int dscp:6; -+ unsigned int rd:1; /* replace dscp */ -+ unsigned int wan:1; -+ unsigned int ipv6:1; -+ unsigned int valid:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused_1:24; -+ unsigned int loc:8; -+#else -+ unsigned int loc:8; -+ unsigned int unused_1:24; -+#endif -+ -+ unsigned int dip[4]; -+ unsigned int sip[4]; -+ unsigned short dip_mask; -+ unsigned short sip_mask; -+ unsigned int pkt_cnt; -+} SPPE_ROUTE; -+ -+#if 0 -+typedef struct _sppe_vserver { -+ unsigned int valid:1; -+ unsigned int tcp:1; -+ unsigned int udp:1; -+ unsigned int dscp_lan:6; -+ unsigned int dscp_wan:6; -+ unsigned int pri_lan:3; -+ unsigned int pri_wan:3; -+ unsigned int unused:11; -+ -+ unsigned int wanip; -+ unsigned int lanip; -+ unsigned short port_start; -+ unsigned short port_end; -+ unsigned int pkt_cnt; -+} SPPE_VSERVER; -+#else -+typedef struct _sppe_snat { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int tcp:1; -+ unsigned int udp:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int kv:1; -+ unsigned int sws:1; -+ unsigned int max_len:2; -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+ unsigned int pr:1; /* policy route */ -+ unsigned int prs:2; /* policy route select */ -+ unsigned int ag:2; -+ unsigned int unused:3; -+#else -+ unsigned int unused:3; -+ unsigned int ag:2; -+ unsigned int prs:2; /* policy route select */ -+ unsigned int pr:1; /* policy route */ -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int max_len:2; -+ unsigned int sws:1; -+ unsigned int kv:1; -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int udp:1; -+ unsigned int tcp:1; -+ unsigned int valid:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused_1:24; -+ unsigned int loc:8; -+#else -+ unsigned int loc:8; -+ unsigned int unused_1:24; -+#endif -+ -+ unsigned int wanip; -+ unsigned int lanip; -+ unsigned short port_start; -+ unsigned short port_end; -+ unsigned int pkt_cnt; -+} SPPE_SNAT; -+ -+typedef struct _sppe_dnat { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int tcp:1; -+ unsigned int udp:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int kv:1; -+ unsigned int sws:1; -+ unsigned int max_len:2; -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+ unsigned int pr:1; /* policy route */ -+ unsigned int prs:2; /* policy route select */ -+ unsigned int ag:2; -+ unsigned int unused:3; -+#else -+ unsigned int unused:3; -+ unsigned int ag:2; -+ unsigned int prs:2; /* policy route select */ -+ unsigned int pr:1; /* policy route */ -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int max_len:2; -+ unsigned int sws:1; -+ unsigned int kv:1; -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int udp:1; -+ unsigned int tcp:1; -+ unsigned int valid:1; -+#endif -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused_1:24; -+ unsigned int loc:8; -+#else -+ unsigned int loc:8; -+ unsigned int unused_1:24; -+#endif -+ -+ unsigned int wanip; -+ unsigned int lanip; -+ unsigned short port_start; -+ unsigned short port_end; -+ unsigned int pkt_cnt; -+} SPPE_DNAT; -+#endif -+typedef struct _sppe_limit { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int drop_red:1; -+ unsigned int pass_green:1; -+ unsigned int force_color:1; -+ unsigned int color_select:2; -+ unsigned int time_stamp:21; -+ unsigned int reserved:6; -+#else -+ unsigned int reserved:6; -+ unsigned int time_stamp:21; -+ unsigned int color_select:2; -+ unsigned int force_color:1; -+ unsigned int pass_green:1; -+ unsigned int drop_red:1; -+#endif -+ unsigned short min_rate; -+ unsigned short max_rate; -+} SPPE_LIMIT; -+ -+typedef struct _sppe_global_rate_limit { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int valid:1; -+ unsigned int wan:1; -+ unsigned int ipv6:1; -+ unsigned int tcp:1; -+ unsigned int udp:1; -+ unsigned int unused:17; -+#else -+ unsigned int unused:17; -+ unsigned int udp:1; -+ unsigned int tcp:1; -+ unsigned int ipv6:1; -+ unsigned int wan:1; -+ unsigned int valid:1; -+#endif -+ -+ unsigned int sip[4]; -+ unsigned int dip[4]; -+ unsigned short sip_mask; -+ unsigned short dip_mask; -+ unsigned short sport_start; -+ unsigned short sport_end; -+ unsigned short dport_start; -+ unsigned short dport_end; -+ SPPE_LIMIT limit; -+} SPPE_GLOBAL_RATE_LIMIT; -+ -+/* -+ * SPPE_CMD_FLOW_BRIDGE_IPV4 -+ * type = 1 , as = 3 -+ */ -+typedef struct _sppe_flow_bridge_ipv4 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int reserved:13; -+#else -+ unsigned int reserved:13; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ -+ unsigned int mac3100; -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ unsigned int sip; -+ unsigned int dip; -+ -+ union { -+ struct { -+ unsigned short src; -+ unsigned short dst; -+ } port; -+ struct { -+ unsigned short call_id; -+ } gre; -+ struct { -+ unsigned char protocol; -+ } others; -+ } l4; -+ -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_BRIDGE_IPV4; -+ -+/* -+ * SPPE_CMD_FLOW_BRIDGE_IPV6 -+ * type = 2 , as = 3 -+ */ -+typedef struct _sppe_flow_bridge_ipv6 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int reserved:13; -+#else -+ unsigned int reserved:13; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ -+ unsigned int mac3100; -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ unsigned int sip[4]; -+ unsigned int dip[4]; -+ union { -+ struct { -+ unsigned short src; -+ unsigned short dst; -+ } port; -+ struct { -+ unsigned short call_id; -+ } gre; -+ struct { -+ unsigned char protocol; -+ } others; -+ } l4; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_BRIDGE_IPV6; -+ -+/* -+ * SPPE_CMD_FLOW_ROUTE_IPV4 -+ * type = 1, as = 0 -+ */ -+typedef struct _sppe_flow_route_ipv4 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+#else -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ unsigned int mac3100; -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ -+ unsigned int sip; -+ unsigned int dip; -+ union { -+ struct { -+ unsigned short src; -+ unsigned short dst; -+ } port; -+ struct { -+ unsigned short call_id; -+ } gre; -+ struct { -+ unsigned char protocol; -+ } others; -+ } l4; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_ROUTE_IPV4; -+ -+/* -+ * SPPE_CMD_FLOW_ROUTE_IPV6 -+ * type = 2, as = 0 -+ */ -+typedef struct _sppe_flow_route_ipv6 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+#else -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ unsigned int mac3100; -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ unsigned int sip[4]; -+ unsigned int dip[4]; -+ union { -+ struct { -+ unsigned short src; -+ unsigned short dst; -+ } port; -+ struct { -+ unsigned short call_id; -+ } gre; -+ struct { -+ unsigned char protocol; -+ } others; -+ } l4; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_ROUTE_IPV6; -+ -+/* -+ * SPPE_CMD_FLOW_NAT_IPV4 -+ * type = 0, as = 1 -+ */ -+typedef struct _sppe_flow_nat_ipv4 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+#else -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ -+ unsigned int mac3100; -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ -+ unsigned int sip; -+ unsigned int dip; -+ union { -+ struct { -+ unsigned short src; -+ unsigned short dst; -+ } port; -+ struct { -+ unsigned short call_id; -+ unsigned short nat_call_id; -+ } gre; -+ struct { -+ unsigned char protocol; -+ } others; -+ } l4; -+ unsigned int nat_ip; -+ unsigned short nat_port; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_NAT_IPV4; -+ -+/* -+ * SPPE_CMD_FLOW_NAT_IPV6 -+ * type = 1, as = 1 -+ */ -+typedef struct _sppe_flow_nat_ipv6 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pd:1; -+ unsigned int pi:1; -+ unsigned int psidx:4; -+#else -+ unsigned int psidx:4; -+ unsigned int pi:1; -+ unsigned int pd:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ unsigned int mac3100; -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ unsigned int sip[4]; -+ unsigned int dip[4]; -+ union { -+ struct { -+ unsigned short src; -+ unsigned short dst; -+ } port; -+ struct { -+ unsigned short call_id; -+ unsigned short nat_call_id; -+ } gre; -+ struct { -+ unsigned char protocol; -+ } others; -+ } l4; -+ unsigned int nat_ip[4]; -+ unsigned short nat_port; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_NAT_IPV6; -+ -+/* -+ * SPPE_CMD_FLOW_TWICE_NAT -+ * type = 0, as = 2 -+ */ -+typedef struct _sppe_flow_twice_nat { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l4_prot:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int psidx:4; -+ unsigned int reserved:2; -+#else -+ unsigned int reserved:2; -+ unsigned int psidx:4; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int l4_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ unsigned int mac3100; -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ unsigned int sip; -+ unsigned int dip; -+ unsigned short sport; -+ unsigned short dport; -+ unsigned int natsip; -+ unsigned int natdip; -+ unsigned short natsport; -+ unsigned short natdport; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_TWICE_NAT; -+ -+/* -+ * SPPE_CMD_FLOW_MULTICAST_IPV4 -+ * type = 0, as = 0 or 3 -+ */ -+typedef struct _sppe_flow_multicast_ipv4 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int bridge:1; -+ unsigned int reserved:7; -+#else -+ unsigned int reserved:7; -+ unsigned int bridge:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ unsigned int mac3100; -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ -+ unsigned int sip; -+ unsigned int dip; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_MCAST_IPV4; -+ -+/* -+ * SPPE_CMD_FLOW_MULTICAST_IPV6 -+ * type = 1, as = 0 or 3 -+ */ -+typedef struct _sppe_flow_multicast_ipv6 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int prs:2; -+ unsigned int kv:1; -+ unsigned int rd:1; -+ unsigned int dscp:6; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int bridge:1; -+ unsigned int reserved:7; -+#else -+ unsigned int reserved:7; -+ unsigned int bridge:1; -+ unsigned int max_len:2; /* Max. length select */ -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int dscp:6; -+ unsigned int rd:1; -+ unsigned int kv:1; -+ unsigned int prs:2; -+ unsigned int l2s:2; /* L2 select */ -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int unused:16; -+ unsigned int mac4732:16; -+#else -+ unsigned int mac4732:16; -+ unsigned int unused:16; -+#endif -+ unsigned int mac3100; -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ -+ unsigned int sip[4]; -+ unsigned int dip[4]; -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_MCAST_IPV6; -+ -+/* -+ * SPPE_CMD_FLOW_LAYER_TWO -+ * type = 2 -+ */ -+typedef struct _sppe_flow_bridge_l2 { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int fw:1; -+ unsigned int s:1; -+ unsigned int sws:1; -+ unsigned int ag:2; -+ unsigned int rl:1; -+ unsigned int l2_prot:2; -+ unsigned int kv:1; -+ unsigned int fp:1; -+ unsigned int pri:3; -+ unsigned int psidx:4; -+ unsigned int reserved:15; -+#else -+ unsigned int reserved:15; -+ unsigned int psidx:4; -+ unsigned int pri:3; -+ unsigned int fp:1; -+ unsigned int kv:1; -+ unsigned int l2_prot:2; -+ unsigned int rl:1; -+ unsigned int ag:2; -+ unsigned int sws:1; -+ unsigned int s:1; -+ unsigned int fw:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int lp:1; -+ unsigned int fr:1; -+ unsigned int pm:4; -+ unsigned int sv:1; -+ unsigned int svid:12; -+ unsigned int cv:1; -+ unsigned int cvid:12; -+#else -+ unsigned int cvid:12; -+ unsigned int cv:1; -+ unsigned int svid:12; -+ unsigned int sv:1; -+ unsigned int pm:4; -+ unsigned int fr:1; -+ unsigned int lp:1; -+#endif -+ -+ unsigned short smac[3]; -+ unsigned short dmac[3]; -+ -+ SPPE_LIMIT limit; -+ unsigned int pkt_cnt; -+} SPPE_FLOW_BRIDGE_L2; -+ -+typedef struct _sppe_arl { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int vid:12; -+ unsigned int pmap:5; -+ unsigned int age:3; -+ unsigned int mymac:1; -+ unsigned int filter:1; -+ unsigned int reserved:10; -+#else -+ unsigned int reserved:10; -+ unsigned int filter:1; -+ unsigned int mymac:1; -+ unsigned int age:3; -+ unsigned int pmap:5; -+ unsigned int vid:12; -+#endif -+ unsigned char mac[6]; -+} SPPE_ARL; -+ -+typedef struct _sppe_init { -+ unsigned int flow_pre_match_paddr; -+ unsigned int flow_pre_match_vaddr; -+ unsigned int flow_body_paddr; -+ unsigned int flow_body_vaddr; -+ unsigned int flow_ext_paddr; -+ unsigned int flow_ext_vaddr; -+ unsigned int flow_size; -+ unsigned int arp_pre_match_paddr; -+ unsigned int arp_pre_match_vaddr; -+ unsigned int arp_body_paddr; -+ unsigned int arp_body_vaddr; -+ unsigned int arp_size; -+ unsigned int ipv6_napt; -+} SPPE_INIT; -+ -+typedef struct _sppe_param_t { -+ SPPE_CMD cmd; -+ SPPE_OP op; -+ -+ union { -+ struct { -+ unsigned char major; -+ unsigned char minor; -+ unsigned char very_minor; -+ unsigned char pre; -+ } sppe_version; -+ -+ SPPE_BOOL sppe_enable; -+ unsigned int sppe_lanip; -+ -+ struct { -+ unsigned int index; -+ unsigned int ip; -+ unsigned int session_id; -+ } sppe_wanip; -+ -+ struct { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int index:2; -+ unsigned int to:4; -+ unsigned int sv:1; -+ unsigned int stag_vid:12; -+ unsigned int cv:1; -+ unsigned int ctag_vid:12; -+#else -+ unsigned int ctag_vid:12; -+ unsigned int cv:1; -+ unsigned int stag_vid:12; -+ unsigned int sv:1; -+ unsigned int to:4; -+ unsigned int index:2; -+#endif -+ unsigned char mac[6]; /* MAC address */ -+ } sppe_prda; -+ -+ struct { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int interval:2; -+ unsigned int mfactor:1; -+ unsigned int ununsed:29; -+#else -+ unsigned int ununsed:29; -+ unsigned int mfactor:1; -+ unsigned int interval:2; -+#endif -+ } sppe_rlcfg; -+ -+ struct { -+ unsigned int index; -+ SPPE_PPPOE_RELAY rule; -+ } sppe_pppoe_relay; -+ -+ struct { -+ unsigned int index; -+ SPPE_BRIDGE rule; -+ } sppe_bridge; -+ -+ struct { -+ unsigned int index; -+ SPPE_ACL rule; -+ } sppe_acl; -+ -+ struct { -+ unsigned int index; -+ SPPE_ROUTE rule; -+ } sppe_route; -+#if 0 -+ struct { -+ unsigned int index; -+ SPPE_VSERVER rule; -+ } sppe_vserver; -+#else -+ struct { -+ unsigned int index; -+ SPPE_SNAT rule; -+ } sppe_snat; -+ -+ struct { -+ unsigned int index; -+ SPPE_DNAT rule; -+ } sppe_dnat; -+#endif -+ struct { -+ unsigned int index; -+ SPPE_GLOBAL_RATE_LIMIT rule; -+ } sppe_grl; -+ -+ struct { -+ unsigned char unit; -+ unsigned char arp; -+ unsigned char bridge; -+ unsigned char tcp; -+ unsigned char udp; -+ unsigned char pptp; -+ unsigned char other; -+ } sppe_agingout; -+ -+ struct { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int index:2; -+ unsigned int reserved:20; -+ unsigned int max:10; -+#else -+ unsigned int max:10; -+ unsigned int reserved:20; -+ unsigned int index:2; -+#endif -+ } sppe_max_length; -+ -+ struct { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int v6:1; -+ unsigned int s:1; -+ unsigned int r:1; -+ unsigned int fr:1; -+ unsigned int to:4; -+ unsigned int unused:24; -+#else -+ unsigned int unused:24; -+ unsigned int to:4; -+ unsigned int fr:1; -+ unsigned int r:1; -+ unsigned int s:1; -+ unsigned int v6:1; -+#endif -+ -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int sv:1; -+ unsigned int stag_vid:12; -+ unsigned int cv:1; -+ unsigned int ctag_vid:12; -+ unsigned int unused_1:6; -+#else -+ unsigned int unused_1:6; -+ unsigned int ctag_vid:12; -+ unsigned int cv:1; -+ unsigned int stag_vid:12; -+ unsigned int sv:1; -+#endif -+ unsigned int ip[4]; -+ unsigned char mac[6]; -+ } sppe_arp; -+ -+ SPPE_ARL sppe_arl; -+ -+ struct { -+ unsigned int sid; -+ unsigned int index; -+ } sppe_pppoe_sid; -+ -+ SPPE_FLOW_BRIDGE_IPV4 flow_bridge_ipv4; -+ SPPE_FLOW_BRIDGE_IPV6 flow_bridge_ipv6; -+ SPPE_FLOW_ROUTE_IPV4 flow_route_ipv4; -+ SPPE_FLOW_ROUTE_IPV6 flow_route_ipv6; -+ SPPE_FLOW_NAT_IPV4 flow_nat_ipv4; -+ SPPE_FLOW_NAT_IPV6 flow_nat_ipv6; -+ SPPE_FLOW_TWICE_NAT flow_twice_nat; -+ SPPE_FLOW_MCAST_IPV4 flow_mcast_ipv4; -+ SPPE_FLOW_MCAST_IPV6 flow_mcast_ipv6; -+ SPPE_FLOW_BRIDGE_L2 flow_bridge_l2; -+ -+ struct { -+ SPPE_DUMP_TYPE type; -+ unsigned short key; -+ unsigned short way; -+ unsigned int raw[23]; -+ } sppe_dump; -+ -+ unsigned int sppe_sna_th; -+ -+ struct { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int enable:1; -+ unsigned int lan:6; -+ unsigned int wan:6; -+ unsigned int reserved:19; -+#else -+ unsigned int reserved:19; -+ unsigned int wan:6; -+ unsigned int lan:6; -+ unsigned int enable:1; -+#endif -+ } sppe_chgdscp; -+ -+ struct { -+#ifndef CONFIG_SWITCH_BIG_ENDIAN -+ unsigned int enable:1; -+ unsigned int lan:3; -+ unsigned int wan:3; -+ unsigned int reserved:25; -+#else -+ unsigned int reserved:25; -+ unsigned int wan:3; -+ unsigned int lan:3; -+ unsigned int enable:1; -+#endif -+ } sppe_chgpri; -+ -+ struct { -+ int enable; -+ int module; -+ int level; -+ } sppe_debug; -+ -+ struct { -+ unsigned int offset; -+ unsigned int data; -+ } sppe_reg; -+ -+ struct { -+ unsigned int offset; -+ unsigned int data; -+ } sppe_sram; -+ -+ struct { -+ char enable; -+ unsigned int max; -+ unsigned int min; -+ char drop_red; -+ char pass_green; -+ } sppe_rl_flow; -+ -+ struct { -+ char enable; -+ unsigned int max; -+ unsigned int min; -+ char drop_red; -+ char pass_green; -+ } sppe_rl_rule; -+ -+ struct { -+ unsigned int index; -+ unsigned short start; -+ unsigned short end; -+ SPPE_LIMIT limit; -+ } sppe_bm_flow; -+ -+ struct { -+ unsigned int index; -+ unsigned int pkt_cnt; -+ unsigned int byte_cnt; -+ } sppe_accounting_group; -+ -+ struct { -+ unsigned int pkt_cnt; -+ } sppe_drop_ipcs_err; /* IP checksum error */ -+ -+ struct { -+ unsigned int pkt_cnt; -+ } sppe_drop_rate_limit; -+ -+ struct { -+ unsigned int pkt_cnt; -+ } sppe_drop_others; -+ -+ struct { -+ unsigned int index; -+ unsigned char name[16]; -+ struct net_device *dev; -+ unsigned int vid; -+ } sppe_pci_fp_dev; -+ -+ SPPE_INIT sppe_init; -+ -+ } data; -+} SPPE_PARAM; -+ -+extern int sppe_hook_ready; -+extern int (*sppe_func_hook)(SPPE_PARAM *param); -+ -+extern int sppe_pci_fp_ready; -+extern int (*sppe_pci_fp_hook)(SPPE_PARAM *param); -+ -+#endif /* CONFIG_CNS3XXX_SPPE */ -+ -+#endif /* _SPPE_H_ */ ---- /dev/null -+++ b/include/linux/cns3xxx/switch_api.h -@@ -0,0 +1,366 @@ -+/******************************************************************************* -+ * -+ * Copyright (c) 2008 Cavium Networks -+ * -+ * 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. -+ * -+ * The full GNU General Public License is included in this distribution in the -+ * file called LICENSE. -+ * -+ * Contact Information: -+ * Technology Support <tech@starsemi.com> -+ * Star Semiconductor 4F, No.1, Chin-Shan 8th St, Hsin-Chu,300 Taiwan, R.O.C -+ * -+ ********************************************************************************/ -+ -+#ifndef SWITCH_API_H_K -+#define SWITCH_API_H_K -+ -+ -+#ifndef __KERNEL__ -+typedef unsigned int u32; -+typedef unsigned short int u16; -+typedef unsigned char u8; -+typedef int s32; -+#else -+ -+#include <linux/types.h> -+ -+#endif -+ -+ -+#define CAVM_OK 0 -+#define CAVM_ERR 1 -+#define CAVM_NOT_FOUND 2 -+#define CAVM_FOUND 3 -+#define CAVM_FAIL -1 // use minus -+ -+#define MAC_PORT0 0 -+#define MAC_PORT1 1 -+#define MAC_PORT2 2 -+#define CPU_PORT 3 -+ -+typedef enum -+{ -+ -+ -+ CNS3XXX_ARL_TABLE_LOOKUP, -+ CNS3XXX_ARL_TABLE_ADD, -+ CNS3XXX_ARL_TABLE_DEL, -+ CNS3XXX_ARL_TABLE_SEARCH, -+ CNS3XXX_ARL_TABLE_SEARCH_AGAIN, -+ CNS3XXX_ARL_IS_TABLE_END, -+ CNS3XXX_ARL_TABLE_FLUSH, -+ -+ CNS3XXX_VLAN_TABLE_LOOKUP, -+ CNS3XXX_VLAN_TABLE_ADD, -+ CNS3XXX_VLAN_TABLE_DEL, -+ CNS3XXX_VLAN_TABLE_READ, -+ -+ CNS3XXX_SKEW_SET, -+ CNS3XXX_SKEW_GET, -+ -+ CNS3XXX_BRIDGE_SET, -+ CNS3XXX_BRIDGE_GET, -+ -+ CNS3XXX_PORT_NEIGHBOR_SET, -+ CNS3XXX_PORT_NEIGHBOR_GET, -+ -+ CNS3XXX_HOL_PREVENT_SET, -+ CNS3XXX_HOL_PREVENT_GET, -+ -+ CNS3XXX_TC_SET, // traffic class, for 1, 2, 4, traffic class -+ CNS3XXX_TC_GET, -+ -+ CNS3XXX_PRI_CTRL_SET, -+ CNS3XXX_PRI_CTRL_GET, -+ -+ CNS3XXX_DMA_RING_CTRL_SET, -+ CNS3XXX_DMA_RING_CTRL_GET, -+ -+ CNS3XXX_PRI_IP_DSCP_SET, -+ CNS3XXX_PRI_IP_DSCP_GET, -+ -+ CNS3XXX_ETYPE_SET, -+ CNS3XXX_ETYPE_GET, -+ -+ CNS3XXX_UDP_RANGE_SET, -+ CNS3XXX_UDP_RANGE_GET, -+ -+ CNS3XXX_ARP_REQUEST_SET, -+ CNS3XXX_ARP_REQUEST_GET, -+ -+ CNS3XXX_RATE_LIMIT_SET, -+ CNS3XXX_RATE_LIMIT_GET, -+ -+ CNS3XXX_QUEUE_WEIGHT_SET, -+ CNS3XXX_QUEUE_WEIGHT_GET, -+ -+ CNS3XXX_FC_RLS_SET, -+ CNS3XXX_FC_RLS_GET, -+ -+ CNS3XXX_FC_SET_SET, -+ CNS3XXX_FC_SET_GET, -+ -+ CNS3XXX_SARL_RLS_SET, -+ CNS3XXX_SARL_RLS_GET, -+ -+ CNS3XXX_SARL_SET_SET, -+ CNS3XXX_SARL_SET_GET, -+ -+ CNS3XXX_SARL_OQ_SET, -+ CNS3XXX_SARL_OQ_GET, -+ -+ CNS3XXX_SARL_ENABLE_SET, -+ CNS3XXX_SARL_ENABLE_GET, -+ -+ CNS3XXX_FC_SET, -+ CNS3XXX_FC_GET, -+ -+ CNS3XXX_IVL_SET, -+ CNS3XXX_IVL_GET, -+ -+ CNS3XXX_WAN_PORT_SET, -+ CNS3XXX_WAN_PORT_GET, -+ -+ CNS3XXX_PVID_GET, -+ CNS3XXX_PVID_SET, -+ -+ CNS3XXX_QA_GET, // queue allocate -+ CNS3XXX_QA_SET, -+ -+ CNS3XXX_PACKET_MAX_LEN_GET, // set maximun frame length. -+ CNS3XXX_PACKET_MAX_LEN_SET, -+ -+ CNS3XXX_BCM53115M_REG_READ, -+ CNS3XXX_BCM53115M_REG_WRITE, -+ -+ CNS3XXX_RXRING_STATUS, -+ CNS3XXX_TXRING_STATUS, -+ -+ CNS3XXX_DUMP_MIB_COUNTER, -+ -+ CNS3XXX_REG_READ, -+ CNS3XXX_REG_WRITE, -+ -+}CNS3XXXIoctlCmd; -+ -+typedef struct -+{ -+ u8 vlan_index; -+ u8 valid; -+ u16 vid; -+ u8 wan_side; -+ u8 etag_pmap; -+ u8 mb_pmap; -+ //u8 my_mac[6]; -+ u8 *my_mac; -+}VLANTableEntry; // for vlan table function -+ -+typedef struct -+{ -+ u16 vid; -+ u8 pmap; -+ //u8 mac[6]; -+ u8 *mac; -+ u8 age_field; -+ u8 vlan_mac; -+ u8 filter; -+}ARLTableEntry; // for arl table function -+ -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ ARLTableEntry entry; -+}CNS3XXXARLTableEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ VLANTableEntry entry; -+}CNS3XXXVLANTableEntry; // for ioctl VLAN table ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ u8 enable; -+}CNS3XXXHOLPreventControl; -+ -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char which_port; // 0, 1, 2, 3 (cpu port) -+ unsigned char type; // 0: C-Neighbor, 1: S-Neighbor -+}CNS3XXXPortNeighborControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char type; // 0: C-Component, 1: S-Component -+}CNS3XXXBridgeControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char tc; // traffic class, for 1, 2, 4, traffic class -+}CNS3XXXTrafficClassControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char which_port; // 0, 1, 2, 3 (cpu port) -+ unsigned int val; -+ unsigned char port_pri; -+ unsigned char udp_pri_en; -+ unsigned char dscp_pri_en; -+ unsigned char vlan_pri_en; -+ unsigned char ether_pri_en; -+}CNS3XXXPriCtrlControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char ts_double_ring_en; -+ unsigned char fs_double_ring_en; -+ unsigned char fs_pkt_allocate; -+}CNS3XXXDmaRingCtrlControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned int ip_dscp_num; // 0 ~ 63 -+ unsigned char pri; // 3 bits -+}CNS3XXXPriIpDscpControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned int etype_num; -+ unsigned int val; -+ unsigned int pri; -+}CNS3XXXEtypeControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned int udp_range_num; -+ unsigned short int port_start; -+ unsigned short int port_end; -+}CNS3XXXUdpRangeEtypeControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char val; // 0: boradcast forward, 1: redirect to the CPU -+}CNS3XXXArpRequestControl; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char which_port; // 0, 1, 2, 3 (port 0 extra dma) -+ unsigned char band_width; -+ unsigned char base_rate; -+ -+}CNS3XXXRateLimitEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char which_port; // 0, 1, 2, 3 (port 0 extra dma) -+ unsigned char sch_mode; -+ unsigned char q0_w; -+ unsigned char q1_w; -+ unsigned char q2_w; -+ unsigned char q3_w; -+}CNS3XXXQueueWeightEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned int val; -+ unsigned char tc; // 0-3 -+ unsigned char gyr; // 0 (green), 1(yellow), 2(red) -+}CNS3XXXSARLEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char port; // 0, 1, 2, 3 (cpu port) -+ unsigned char fc_en; // 0(rx/tx disable), 1(rx enable), 2(tx enable), 3(rx/tx enable) -+}CNS3XXXFCEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char enable; // enable: 1 -> IVL, enable: 0 -> SVL -+}CNS3XXXIVLEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char wan_port; -+}CNS3XXXWANPortEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char which_port; -+ unsigned int pvid; -+}CNS3XXXPVIDEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char qa; // queue allocate -+}CNS3XXXQAEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ unsigned char max_len; // maximum frame length -+}CNS3XXXMaxLenEntry; // for ioctl arl ... -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ u8 page; -+ u8 offset; -+ u32 u32_val; -+ u16 u16_val; -+ u8 u8_val; -+ u8 data_len; -+ -+}CNS3XXXBCM53115M; -+ -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ u32 mib[52]; -+ u16 mib_len; -+}CNS3XXXMIBCounter; -+ -+#if 0 -+typedef struct -+{ -+ CNS3XXXIoctlCmd cmd; -+ TXRing *tx_ring; -+ RXRing *rx_ring; -+}CNS3XXXRingStatus; -+#endif -+ -+ -+#endif ---- a/net/core/dev.c -+++ b/net/core/dev.c -@@ -133,6 +133,10 @@ - - #include "net-sysfs.h" - -+#if defined (CONFIG_CNS3XXX_SPPE) -+#include <linux/cns3xxx/sppe.h> -+#endif -+ - /* Instead of increasing this, you should create a hash table. */ - #define MAX_GRO_SKBS 8 - -@@ -1944,6 +1948,197 @@ int weight_p __read_mostly = 64; - - DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, }; - -+#if defined (CONFIG_CNS3XXX_SPPE) -+static struct net_device *tun_netdev = NULL; -+ -+int sppe_pci_fp(struct sk_buff *skb) -+{ -+ SPPE_PARAM param; -+ struct iphdr *iph; -+#if defined (CONFIG_IPV6) -+ struct ipv6hdr *ipv6h; -+#endif -+ struct tcphdr *th; -+ struct udphdr *uh; -+ int pci_dev_index; -+ -+ if (!sppe_hook_ready) { -+ goto NOT_IN_FP; -+ } -+ -+ if (!sppe_pci_fp_ready) { -+ goto NOT_IN_FP; -+ } -+ -+ /* check device packet comes from, is a registed device? */ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ param.cmd = SPPE_CMD_PCI_FP_DEV; -+ param.op = SPPE_OP_GET; -+ param.data.sppe_pci_fp_dev.dev = skb->dev; -+ sppe_pci_fp_hook(¶m); -+ -+ pci_dev_index = param.data.sppe_pci_fp_dev.index; -+ -+ if ((-1) == pci_dev_index) { -+ goto NOT_IN_FP; -+ } -+ -+ if (!tun_netdev) { -+ tun_netdev = dev_get_by_name(&init_net, "fp"); -+ -+ if (!tun_netdev) { -+ goto NOT_IN_FP; -+ } -+ } -+ -+ /* check PPE status */ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ param.cmd = SPPE_CMD_ENABLE; -+ param.op = SPPE_OP_GET; -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to get PPE status!!\n", __FUNCTION__); -+ goto NOT_IN_FP; -+ } -+ -+ if (!param.data.sppe_enable) { -+ goto NOT_IN_FP; -+ } -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ -+ switch (htons(skb->protocol)) { -+ case ETH_P_IP: -+ iph = (struct iphdr *)skb->data; -+ -+ if (5 != iph->ihl) { goto NOT_IN_FP; } -+ -+ if (iph->frag_off & 0x20) { goto NOT_IN_FP; } -+ -+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4; -+ param.op = SPPE_OP_GET; -+ -+ param.data.flow_nat_ipv4.sip = ntohl(iph->saddr); -+ param.data.flow_nat_ipv4.dip = ntohl(iph->daddr); -+ -+ switch (iph->protocol) { -+ case IPPROTO_TCP: -+ th = (struct tcphdr *) ((int *)iph + 5); /* IP header length is 20 */ -+ -+ if ((th->syn) || (th->fin) || (th->rst)) { goto NOT_IN_FP; } -+ -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_TCP; -+ param.data.flow_nat_ipv4.l4.port.src = ntohs(th->source); -+ param.data.flow_nat_ipv4.l4.port.dst = ntohs(th->dest); -+ break; -+ case IPPROTO_UDP: -+ uh = (struct udphdr *) ((int *)iph + 5); /* IP header length is 20 */ -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_UDP; -+ param.data.flow_nat_ipv4.l4.port.src = ntohs(uh->source); -+ param.data.flow_nat_ipv4.l4.port.dst = ntohs(uh->dest); -+ break; -+ default: -+ goto NOT_IN_FP; -+ } -+ -+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) { -+ goto NOT_IN_FP; -+ } else { -+ struct ethhdr *eth; -+ -+ eth = (struct ethhdr *)skb->mac_header; -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ param.cmd = SPPE_CMD_ARP; -+ param.op = SPPE_OP_SET; -+ param.data.sppe_arp.s = 1; -+ param.data.sppe_arp.ip[0] = iph->saddr; -+ param.data.sppe_arp.mac[0] = eth->h_source[0]; -+ param.data.sppe_arp.mac[1] = eth->h_source[1]; -+ param.data.sppe_arp.mac[2] = eth->h_source[2]; -+ param.data.sppe_arp.mac[3] = eth->h_source[3]; -+ param.data.sppe_arp.mac[4] = eth->h_source[4]; -+ param.data.sppe_arp.mac[5] = eth->h_source[5]; -+ param.data.sppe_arp.unused_1 = pci_dev_index; -+ -+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) { -+ printk("add ARP fail\n"); -+ #if 0 -+ } else { -+ param.data.sppe_arp.unused_1 = 0xf; -+ param.op = SPPE_OP_GET; -+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) { -+ printk("read ARP fail\n"); -+ } else { -+ printk("param.data.sppe_arp.unused_1 %d\n", param.data.sppe_arp.unused_1); -+ } -+ #endif -+ } -+ } -+ break; /* case ETH_P_IP: */ -+#if defined (CONFIG_IPV6) -+ case ETH_P_IPV6: -+ ipv6h = (struct ipv6hdr *)skb->data; -+ switch (ipv6h->nexthdr) { -+ case IPPROTO_TCP: -+ th = (struct tcphdr *) ((int *)ipv6h + 10); /* IPv6 header length is 40 bytes */ -+ -+ if ((th->syn) || (th->fin) || (th->rst)) { goto NOT_IN_FP; } -+ -+ param.data.flow_route_ipv6.l4_prot = SPPE_PROT_TCP; -+ param.data.flow_route_ipv6.l4.port.src = ntohs(th->source); -+ param.data.flow_route_ipv6.l4.port.dst = ntohs(th->dest); -+ param.data.flow_route_ipv6.l4_prot = SPPE_PROT_TCP; -+ break; -+ case IPPROTO_UDP: -+ uh = (struct udphdr *) ((int *)ipv6h + 10); /* IPv6 header length is 40 byte */ -+ param.data.flow_route_ipv6.l4_prot = SPPE_PROT_UDP; -+ param.data.flow_route_ipv6.l4.port.src = ntohs(uh->source); -+ param.data.flow_route_ipv6.l4.port.dst = ntohs(uh->dest); -+ break; -+ default: -+ goto NOT_IN_FP; -+ } -+ -+ param.data.flow_route_ipv6.sip[0] = ntohl(ipv6h->saddr.s6_addr32[0]); -+ param.data.flow_route_ipv6.sip[1] = ntohl(ipv6h->saddr.s6_addr32[1]); -+ param.data.flow_route_ipv6.sip[2] = ntohl(ipv6h->saddr.s6_addr32[2]); -+ param.data.flow_route_ipv6.sip[3] = ntohl(ipv6h->saddr.s6_addr32[3]); -+ param.data.flow_route_ipv6.dip[0] = ntohl(ipv6h->daddr.s6_addr32[0]); -+ param.data.flow_route_ipv6.dip[1] = ntohl(ipv6h->daddr.s6_addr32[1]); -+ param.data.flow_route_ipv6.dip[2] = ntohl(ipv6h->daddr.s6_addr32[2]); -+ param.data.flow_route_ipv6.dip[3] = ntohl(ipv6h->daddr.s6_addr32[3]); -+ -+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6; -+ param.op = SPPE_OP_GET; -+ -+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) { -+ goto NOT_IN_FP; -+ } -+ -+ break; /* case ETH_P_IPV6: */ -+#endif -+ case ETH_P_PPP_SES: -+ break; -+ default: /* unsupport protocol */ -+ goto NOT_IN_FP; -+ } -+ /* Update counter */ -+ skb->dev = tun_netdev; -+ skb->ip_summed = CHECKSUM_NONE; -+ skb_push(skb, ETH_HLEN); -+ -+ dev_queue_xmit(skb); -+ -+return 0; -+ -+NOT_IN_FP: -+ return (-1); -+} -+#endif -+ -+ -+ - - /** - * netif_rx - post buffer to the network code -@@ -1965,6 +2160,12 @@ int netif_rx(struct sk_buff *skb) - struct softnet_data *queue; - unsigned long flags; - -+#if defined (CONFIG_CNS3XXX_SPPE) -+ if (0 == sppe_pci_fp(skb)) { -+ return NET_RX_SUCCESS; -+ } -+#endif -+ - /* if netpoll wants it, pretend we never saw it */ - if (netpoll_rx(skb)) - return NET_RX_DROP; -@@ -2259,6 +2460,12 @@ int netif_receive_skb(struct sk_buff *sk - if (!skb->tstamp.tv64) - net_timestamp(skb); - -+#if defined (CONFIG_CNS3XXX_SPPE) -+ if (0 == sppe_pci_fp(skb)) { -+ return NET_RX_SUCCESS; -+ } -+#endif -+ - if (skb->vlan_tci && vlan_hwaccel_do_receive(skb)) - return NET_RX_SUCCESS; - ---- a/net/netfilter/nf_conntrack_core.c -+++ b/net/netfilter/nf_conntrack_core.c -@@ -42,6 +42,9 @@ - #include <net/netfilter/nf_conntrack_ecache.h> - #include <net/netfilter/nf_nat.h> - #include <net/netfilter/nf_nat_core.h> -+#if defined (CONFIG_CNS3XXX_SPPE) -+#include <linux/cns3xxx/sppe.h> -+#endif - - #define NF_CONNTRACK_VERSION "0.5.0" - -@@ -275,6 +278,92 @@ void nf_ct_insert_dying_list(struct nf_c - } - EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); - -+#if defined (CONFIG_CNS3XXX_SPPE) -+static int sppe_flow_del(struct nf_conn *ct) -+{ -+ if (sppe_hook_ready) { -+ SPPE_PARAM param; -+ -+ struct nf_conntrack_tuple *orig, *reply; -+ -+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; -+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; -+ -+ if (PF_INET == orig->src.l3num) { -+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4; -+ } else if (PF_INET6 == orig->src.l3num) { -+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6; -+ } else { -+ goto SPPE_FLOW_DEL_FINI; -+ } -+ -+ if (IPPROTO_TCP == orig->dst.protonum) { -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_TCP; -+ } else if (IPPROTO_UDP == orig->dst.protonum) { -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_UDP; -+ } else if (IPPROTO_GRE == orig->dst.protonum) { -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_PPTP_GRE; -+ } else { -+ goto SPPE_FLOW_DEL_FINI; -+ } -+ -+ param.op = SPPE_OP_DELETE_OUTDATED; -+ -+ param.data.flow_nat_ipv4.fw = 0; -+ if (SPPE_CMD_FLOW_ROUTE_IPV6 == param.cmd) { -+ param.data.flow_route_ipv6.sip[0] = htonl(orig->src.u3.ip6[0]); -+ param.data.flow_route_ipv6.sip[1] = htonl(orig->src.u3.ip6[1]); -+ param.data.flow_route_ipv6.sip[2] = htonl(orig->src.u3.ip6[2]); -+ param.data.flow_route_ipv6.sip[3] = htonl(orig->src.u3.ip6[3]); -+ param.data.flow_route_ipv6.dip[0] = htonl(orig->dst.u3.ip6[0]); -+ param.data.flow_route_ipv6.dip[1] = htonl(orig->dst.u3.ip6[1]); -+ param.data.flow_route_ipv6.dip[2] = htonl(orig->dst.u3.ip6[2]); -+ param.data.flow_route_ipv6.dip[3] = htonl(orig->dst.u3.ip6[3]); -+ param.data.flow_route_ipv6.l4.port.src = htons(orig->src.u.tcp.port); -+ param.data.flow_route_ipv6.l4.port.dst = htons(orig->dst.u.tcp.port); -+ } else { -+ param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip); -+ param.data.flow_nat_ipv4.l4.port.src = htons(orig->src.u.tcp.port); -+ param.data.flow_nat_ipv4.l4.port.dst = htons(orig->dst.u.tcp.port); -+ } -+ -+ if (SPPE_RESULT_FAIL == sppe_func_hook(¶m)) { -+ return (-1); -+ } -+ -+ param.data.flow_nat_ipv4.fw = 1; -+ -+ if (SPPE_CMD_FLOW_ROUTE_IPV6 == param.cmd) { -+ param.data.flow_route_ipv6.sip[0] = htonl(reply->src.u3.ip6[0]); -+ param.data.flow_route_ipv6.sip[1] = htonl(reply->src.u3.ip6[1]); -+ param.data.flow_route_ipv6.sip[2] = htonl(reply->src.u3.ip6[2]); -+ param.data.flow_route_ipv6.sip[3] = htonl(reply->src.u3.ip6[3]); -+ param.data.flow_route_ipv6.dip[0] = htonl(reply->dst.u3.ip6[0]); -+ param.data.flow_route_ipv6.dip[1] = htonl(reply->dst.u3.ip6[1]); -+ param.data.flow_route_ipv6.dip[2] = htonl(reply->dst.u3.ip6[2]); -+ param.data.flow_route_ipv6.dip[3] = htonl(reply->dst.u3.ip6[3]); -+ -+ param.data.flow_route_ipv6.l4.port.src = htons(reply->src.u.tcp.port); -+ param.data.flow_route_ipv6.l4.port.dst = htons(reply->dst.u.tcp.port); -+ } else { -+ param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip); -+ param.data.flow_nat_ipv4.l4.port.src = htons(reply->src.u.tcp.port); -+ param.data.flow_nat_ipv4.l4.port.dst = htons(reply->dst.u.tcp.port); -+ } -+ -+ if (SPPE_RESULT_FAIL == sppe_func_hook(¶m)) { -+ return (-1); -+ } -+ } -+ -+SPPE_FLOW_DEL_FINI: -+ return 0; -+} -+#endif -+ -+ - static void death_by_timeout(unsigned long ul_conntrack) - { - struct nf_conn *ct = (void *)ul_conntrack; -@@ -289,6 +378,16 @@ static void death_by_timeout(unsigned lo - set_bit(IPS_DYING_BIT, &ct->status); - nf_ct_delete_from_lists(ct); - nf_ct_put(ct); -+ -+#if defined (CONFIG_CNS3XXX_SPPE) -+ if (sppe_flow_del(ct)) { -+ #if 0 -+ ct->timeout.expires = jiffies + (120*HZ); -+ add_timer(&ct->timeout); -+ #endif -+ } -+#endif -+ - } - - /* ---- a/net/netfilter/nf_conntrack_proto_gre.c -+++ b/net/netfilter/nf_conntrack_proto_gre.c -@@ -40,6 +40,10 @@ - #include <linux/netfilter/nf_conntrack_proto_gre.h> - #include <linux/netfilter/nf_conntrack_pptp.h> - -+#if defined (CONFIG_CNS3XXX_SPPE) -+#include <linux/cns3xxx/sppe.h> -+#endif -+ - #define GRE_TIMEOUT (30 * HZ) - #define GRE_STREAM_TIMEOUT (180 * HZ) - -@@ -226,6 +230,57 @@ static int gre_print_conntrack(struct se - (ct->proto.gre.stream_timeout / HZ)); - } - -+#if defined (CONFIG_CNS3XXX_SPPE) -+static int sppe_gre_flow_add(struct nf_conn *ct) -+{ -+ SPPE_PARAM param; -+ struct nf_conntrack_tuple *orig, *reply; -+ -+ if (0 == sppe_hook_ready) { -+ return 0; -+ } -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ -+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; -+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; -+ -+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4; -+ param.op = SPPE_OP_SET; -+ -+ param.data.flow_nat_ipv4.fw = 0; -+ param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip); -+ -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_PPTP_GRE; -+ param.data.flow_nat_ipv4.l4.gre.call_id = htons(orig->dst.u.gre.key); -+ -+ param.data.flow_nat_ipv4.nat_ip = htonl(reply->dst.u3.ip); -+ param.data.flow_nat_ipv4.l4.gre.nat_call_id = htons(reply->src.u.gre.key); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv4 from-LAN flow!!\n", __FUNCTION__); -+ } -+ -+ param.data.flow_nat_ipv4.fw = 1; -+ -+ param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip); -+ param.data.flow_nat_ipv4.l4.gre.call_id = htons(reply->dst.u.gre.key); -+ -+ param.data.flow_nat_ipv4.nat_ip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.l4.gre.nat_call_id = htons(orig->src.u.gre.key); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__); -+ } -+ -+ return 0; -+} -+#endif -+ -+ -+ - /* Returns verdict for packet, and may modify conntrack */ - static int gre_packet(struct nf_conn *ct, - const struct sk_buff *skb, -@@ -242,6 +297,10 @@ static int gre_packet(struct nf_conn *ct - /* Also, more likely to be important, and not a probe. */ - set_bit(IPS_ASSURED_BIT, &ct->status); - nf_conntrack_event_cache(IPCT_STATUS, ct); -+#if defined (CONFIG_CNS3XXX_SPPE) -+ sppe_gre_flow_add(ct); -+#endif -+ - } else - nf_ct_refresh_acct(ct, ctinfo, skb, - ct->proto.gre.timeout); ---- a/net/netfilter/nf_conntrack_proto_tcp.c -+++ b/net/netfilter/nf_conntrack_proto_tcp.c -@@ -29,6 +29,10 @@ - #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> - #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> - -+#if defined (CONFIG_CNS3XXX_SPPE) -+#include <linux/cns3xxx/sppe.h> -+#endif -+ - /* "Be conservative in what you do, - be liberal in what you accept from others." - If it's non-zero, we mark only out of window RST segments as INVALID. */ -@@ -814,6 +818,141 @@ static int tcp_error(struct net *net, - return NF_ACCEPT; - } - -+#if defined (CONFIG_CNS3XXX_SPPE) -+static int sppe_tcp_flow_add_ipv4(struct nf_conn *ct) -+{ -+ SPPE_PARAM param; -+ struct nf_conntrack_tuple *orig, *reply; -+ -+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; -+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; -+ -+#if defined (CONFIG_NF_CONNTRACK_PPTP) -+ if (1723 == htons(orig->dst.u.tcp.port)) { -+ /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */ -+ return 0; -+ } -+#endif -+#if defined (CONFIG_NF_CONNTRACK_FTP) -+ if (21 == htons(orig->dst.u.tcp.port)) { -+ /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */ -+ return 0; -+ } -+#endif -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ -+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4; -+ param.op = SPPE_OP_SET; -+ -+ param.data.flow_nat_ipv4.fw = 0; -+ param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip); -+ -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_TCP; -+ param.data.flow_nat_ipv4.l4.port.src = htons(orig->src.u.tcp.port); -+ param.data.flow_nat_ipv4.l4.port.dst = htons(orig->dst.u.tcp.port); -+ -+ param.data.flow_nat_ipv4.nat_ip = htonl(reply->dst.u3.ip); -+ param.data.flow_nat_ipv4.nat_port = htons(reply->dst.u.tcp.port); -+ param.data.flow_nat_ipv4.max_len = 0x3; -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv4 from-LAN flow!!\n", __FUNCTION__); -+ } -+ -+ param.data.flow_nat_ipv4.fw = 1; -+ param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip); -+ param.data.flow_nat_ipv4.l4.port.src = htons(reply->src.u.tcp.port); -+ param.data.flow_nat_ipv4.l4.port.dst = htons(reply->dst.u.tcp.port); -+ -+ param.data.flow_nat_ipv4.nat_ip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.nat_port = htons(orig->src.u.tcp.port); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__); -+ } -+ -+ return 0; -+} -+ -+static int sppe_tcp_flow_add_ipv6(struct nf_conn *ct) -+{ -+ SPPE_PARAM param; -+ struct nf_conntrack_tuple *orig, *reply; -+ -+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; -+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; -+ -+ if (1723 == htons(orig->dst.u.tcp.port)) { -+ /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */ -+ return 0; -+ } -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ -+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6; -+ param.op = SPPE_OP_SET; -+ -+ /* from-LAN flow */ -+ param.data.flow_route_ipv6.fw = 0; -+ param.data.flow_route_ipv6.sip[0] = htonl(orig->src.u3.ip6[0]); -+ param.data.flow_route_ipv6.sip[1] = htonl(orig->src.u3.ip6[1]); -+ param.data.flow_route_ipv6.sip[2] = htonl(orig->src.u3.ip6[2]); -+ param.data.flow_route_ipv6.sip[3] = htonl(orig->src.u3.ip6[3]); -+ param.data.flow_route_ipv6.dip[0] = htonl(orig->dst.u3.ip6[0]); -+ param.data.flow_route_ipv6.dip[1] = htonl(orig->dst.u3.ip6[1]); -+ param.data.flow_route_ipv6.dip[2] = htonl(orig->dst.u3.ip6[2]); -+ param.data.flow_route_ipv6.dip[3] = htonl(orig->dst.u3.ip6[3]); -+ param.data.flow_route_ipv6.l4_prot = SPPE_PROT_TCP; -+ param.data.flow_route_ipv6.l4.port.src = htons(orig->src.u.tcp.port); -+ param.data.flow_route_ipv6.l4.port.dst = htons(orig->dst.u.tcp.port); -+ param.data.flow_route_ipv6.max_len = 0x3; -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__); -+ } -+ -+ /* from-WAN flow */ -+ param.data.flow_route_ipv6.fw = 1; -+ param.data.flow_route_ipv6.sip[0] = htonl(reply->src.u3.ip6[0]); -+ param.data.flow_route_ipv6.sip[1] = htonl(reply->src.u3.ip6[1]); -+ param.data.flow_route_ipv6.sip[2] = htonl(reply->src.u3.ip6[2]); -+ param.data.flow_route_ipv6.sip[3] = htonl(reply->src.u3.ip6[3]); -+ param.data.flow_route_ipv6.dip[0] = htonl(reply->dst.u3.ip6[0]); -+ param.data.flow_route_ipv6.dip[1] = htonl(reply->dst.u3.ip6[1]); -+ param.data.flow_route_ipv6.dip[2] = htonl(reply->dst.u3.ip6[2]); -+ param.data.flow_route_ipv6.dip[3] = htonl(reply->dst.u3.ip6[3]); -+ param.data.flow_route_ipv6.l4.port.src = htons(reply->src.u.tcp.port); -+ param.data.flow_route_ipv6.l4.port.dst = htons(reply->dst.u.tcp.port); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__); -+ } -+ -+ return 0; -+} -+ -+static int sppe_tcp_flow_add(struct nf_conn *ct) -+{ -+ if (0 == sppe_hook_ready) { -+ return 0; -+ } -+ -+ if (AF_INET == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { -+ sppe_tcp_flow_add_ipv4(ct); -+ return 0; -+ } else if (AF_INET6 == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { -+ sppe_tcp_flow_add_ipv6(ct); -+ return 0; -+ } -+ -+ /* return fail */ -+ return (-1); -+} -+#endif -+ - /* Returns verdict for packet, or -1 for invalid. */ - static int tcp_packet(struct nf_conn *ct, - const struct sk_buff *skb, -@@ -961,11 +1100,18 @@ static int tcp_packet(struct nf_conn *ct - break; - } - -+#if defined (CONFIG_CNS3XXX_SPPE) -+ if(!(th->rst == 1 || th->fin == 1)) { -+#endif - if (!tcp_in_window(ct, &ct->proto.tcp, dir, index, - skb, dataoff, th, pf)) { - spin_unlock_bh(&ct->lock); - return -NF_ACCEPT; - } -+#if defined (CONFIG_CNS3XXX_SPPE) -+ } -+#endif -+ - in_window: - /* From now on we have got in-window packets */ - ct->proto.tcp.last_index = index; -@@ -1015,6 +1161,10 @@ static int tcp_packet(struct nf_conn *ct - connection. */ - set_bit(IPS_ASSURED_BIT, &ct->status); - nf_conntrack_event_cache(IPCT_STATUS, ct); -+#if defined (CONFIG_CNS3XXX_SPPE) -+ /* Add SPPE hardware flow */ -+ sppe_tcp_flow_add(ct); -+#endif - } - nf_ct_refresh_acct(ct, ctinfo, skb, timeout); - ---- a/net/netfilter/nf_conntrack_proto_udp.c -+++ b/net/netfilter/nf_conntrack_proto_udp.c -@@ -24,6 +24,9 @@ - #include <net/netfilter/nf_log.h> - #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> - #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> -+#if defined (CONFIG_CNS3XXX_SPPE) -+#include <linux/cns3xxx/sppe.h> -+#endif - - static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ; - static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ; -@@ -63,6 +66,122 @@ static int udp_print_tuple(struct seq_fi - ntohs(tuple->dst.u.udp.port)); - } - -+#if defined (CONFIG_CNS3XXX_SPPE) -+static int sppe_udp_flow_add_ipv4(struct nf_conn *ct) -+{ -+ SPPE_PARAM param; -+ struct nf_conntrack_tuple *orig, *reply; -+ -+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; -+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ -+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4; -+ param.op = SPPE_OP_SET; -+ -+ param.data.flow_nat_ipv4.fw = 0; -+ param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip); -+ param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_UDP; -+ -+ param.data.flow_nat_ipv4.l4.port.src = htons(orig->src.u.tcp.port); -+ param.data.flow_nat_ipv4.l4.port.dst = htons(orig->dst.u.tcp.port); -+ -+ param.data.flow_nat_ipv4.nat_ip = htonl(reply->dst.u3.ip); -+ param.data.flow_nat_ipv4.nat_port = htons(reply->dst.u.tcp.port); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv4 UDP from-LAN flow!!\n", __FUNCTION__); -+ } -+ param.data.flow_nat_ipv4.fw = 1; -+ param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip); -+ param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip); -+ -+ param.data.flow_nat_ipv4.l4.port.src = htons(reply->src.u.tcp.port); -+ param.data.flow_nat_ipv4.l4.port.dst = htons(reply->dst.u.tcp.port); -+ -+ param.data.flow_nat_ipv4.nat_ip = htonl(orig->src.u3.ip); -+ param.data.flow_nat_ipv4.nat_port = htons(orig->src.u.tcp.port); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__); -+ } -+ -+ return 0; -+} -+ -+static int sppe_udp_flow_add_ipv6(struct nf_conn *ct) -+{ -+ SPPE_PARAM param; -+ struct nf_conntrack_tuple *orig, *reply; -+ -+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; -+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple; -+ -+ memset(¶m, 0, sizeof(SPPE_PARAM)); -+ -+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6; -+ param.op = SPPE_OP_SET; -+ -+ /* from-LAN flow */ -+ param.data.flow_route_ipv6.fw = 0; -+ param.data.flow_route_ipv6.sip[0] = htonl(orig->src.u3.ip6[0]); -+ param.data.flow_route_ipv6.sip[1] = htonl(orig->src.u3.ip6[1]); -+ param.data.flow_route_ipv6.sip[2] = htonl(orig->src.u3.ip6[2]); -+ param.data.flow_route_ipv6.sip[3] = htonl(orig->src.u3.ip6[3]); -+ param.data.flow_route_ipv6.dip[0] = htonl(orig->dst.u3.ip6[0]); -+ param.data.flow_route_ipv6.dip[1] = htonl(orig->dst.u3.ip6[1]); -+ param.data.flow_route_ipv6.dip[2] = htonl(orig->dst.u3.ip6[2]); -+ param.data.flow_route_ipv6.dip[3] = htonl(orig->dst.u3.ip6[3]); -+ param.data.flow_route_ipv6.l4_prot = SPPE_PROT_UDP; -+ param.data.flow_route_ipv6.l4.port.src = htons(orig->src.u.udp.port); -+ param.data.flow_route_ipv6.l4.port.dst = htons(orig->dst.u.udp.port); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__); -+ } -+ -+ /* from-WAN flow */ -+ param.data.flow_route_ipv6.fw = 1; -+ param.data.flow_route_ipv6.sip[0] = htonl(reply->src.u3.ip6[0]); -+ param.data.flow_route_ipv6.sip[1] = htonl(reply->src.u3.ip6[1]); -+ param.data.flow_route_ipv6.sip[2] = htonl(reply->src.u3.ip6[2]); -+ param.data.flow_route_ipv6.sip[3] = htonl(reply->src.u3.ip6[3]); -+ param.data.flow_route_ipv6.dip[0] = htonl(reply->dst.u3.ip6[0]); -+ param.data.flow_route_ipv6.dip[1] = htonl(reply->dst.u3.ip6[1]); -+ param.data.flow_route_ipv6.dip[2] = htonl(reply->dst.u3.ip6[2]); -+ param.data.flow_route_ipv6.dip[3] = htonl(reply->dst.u3.ip6[3]); -+ param.data.flow_route_ipv6.l4.port.src = htons(reply->src.u.udp.port); -+ param.data.flow_route_ipv6.l4.port.dst = htons(reply->dst.u.udp.port); -+ -+ if (sppe_func_hook(¶m)) { -+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__); -+ } -+ -+ return 0; -+} -+ -+static int sppe_udp_flow_add(struct nf_conn *ct) -+{ -+ if (0 == sppe_hook_ready) { -+ return 0; -+ } -+ -+ if (AF_INET == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { -+ sppe_udp_flow_add_ipv4(ct); -+ return 0; -+ } else if (AF_INET6 == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) { -+ sppe_udp_flow_add_ipv6(ct); -+ return 0; -+ } -+ -+ /* return fail */ -+ return (-1); -+} -+#endif -+ -+ - /* Returns verdict for packet, and may modify conntracktype */ - static int udp_packet(struct nf_conn *ct, - const struct sk_buff *skb, -@@ -77,7 +196,15 @@ static int udp_packet(struct nf_conn *ct - nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream); - /* Also, more likely to be important, and not a probe */ - if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) -+#if defined (CONFIG_CNS3XXX_SPPE) -+ { -+#endif - nf_conntrack_event_cache(IPCT_STATUS, ct); -+#if defined (CONFIG_CNS3XXX_SPPE) -+ /* Add SPPE hardware flow */ -+ sppe_udp_flow_add(ct); -+ } -+#endif - } else - nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout); - |