2 +++ b/drivers/net/cns3xxx/cns3xxx_config.h
4 +/*******************************************************************************
6 + * Copyright (c) 2009 Cavium Networks
8 + * This program is free software; you can redistribute it and/or modify it
9 + * under the terms of the GNU General Public License as published by the Free
10 + * Software Foundation; either version 2 of the License, or (at your option)
11 + * any later version.
13 + * This program is distributed in the hope that it will be useful, but WITHOUT
14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 + * You should have received a copy of the GNU General Public License along with
19 + * this program; if not, write to the Free Software Foundation, Inc., 59
20 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 + * The full GNU General Public License is included in this distribution in the
23 + * file called LICENSE.
25 + ********************************************************************************/
27 +#include <linux/version.h>
29 +#ifndef CNS3XXX_CONFIG_H
30 +#define CNS3XXX_CONFIG_H
32 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)
34 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
39 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
40 +#define CNS3XXX_VLAN_8021Q
43 +#ifdef CNS3XXX_VLAN_8021Q
44 +//#define CNS3XXX_NIC_MODE_8021Q // use NIC mode to support 8021Q
48 +#define CONFIG_CNS3XXX_JUMBO_FRAME
50 +#ifdef CONFIG_CNS3XXX_JUMBO_FRAME
51 +#define MAX_PACKET_LEN 9600
53 +#define MAX_PACKET_LEN 1536
56 +//#define CONFIG_SWITCH_BIG_ENDIAN
58 +//#define CONFIG_FPGA_FORCE
60 +//#define CNS3XXX_GIGA_MODE
62 +#define CNS3XXX_SET_ARL_TABLE
63 +#define CNS3XXX_AGE_ENABLE
64 +#define CNS3XXX_LEARN_ENABLE
65 +#define CNS3XXX_CPU_PORT_FC
66 +#define CNS3XXX_CPU_MIB_COUNTER
67 +#define CNS3XXX_MAC0_MIB_COUNTER
68 +#define CNS3XXX_MAC1_MIB_COUNTER
69 +//#define CNS3XXX_MAC2_MIB_COUNTER
71 +//#define ACCEPT_CRC_BAD_PKT
72 +//#define CONFIG_FAST_BRIDGE
73 +//#define CONFIG_HOLP_TEST
76 +#define CONFIG_CNS3XXX_NAPI
77 +#ifdef CONFIG_CNS3XXX_NAPI
78 +#define CNS3XXX_NAPI_WEIGHT 64
80 +//#define CONFIG_NIC_MODE
81 +//#define CNS3XXX_TX_HW_CHECKSUM
82 +//#define CNS3XXX_RX_HW_CHECKSUM
83 +//#define CNS3XXX_STATUS_ISR
84 +//#define CNS3XXX_TEST_ONE_LEG_VLAN
85 +//#define CNS3XXX_TX_DSCP_PROC
88 +#define CNS3XXX_FSQF_RING0_ISR
89 +//#define CNS3XXX_TSTC_RING0_ISR
90 +//#define CNS3XXX_TSTC_RING1_ISR
92 +//#define CNS3XXX_COMPARE_PACKET
93 +//#define CONFIG_FPGA_10
94 +//#define CNS3XXX_CONFIG_SIM_MODE
96 +#define CNS3XXX_8021Q_HW_TX
99 +#ifndef CONFIG_CNS3XXX_SPPE
100 +#define IVL // if no define, use SVL
102 +//#define CNS3XXX_4N // if don't define it, use 4N+2
105 +//#define CNS3XXX_TEST_D_CACHE
106 +#define CNS3XXX_FREE_TX_IN_RX_PATH
111 +//#define DEBUG_PRIO_IPDSCR
112 +#define DEBUG_RX_PROC
113 +#define DEBUG_TX_PROC
114 +//#define DEBUG_PHY_PROC
115 +#define CNS3XXX_PVID_PROC
116 +#define CNS3XXX_SARL_PROC
119 +//#define DOUBLE_RING_TEST
121 +//#define CNS3XXX_DOUBLE_RX_RING
122 +//#define CNS3XXX_DOUBLE_TX_RING
123 +#define CNS3XXX_USE_MASK
125 +#define CNS3XXX_CONFIG_CHANGE_TX_RING
127 +#ifdef CNS3XXX_DOUBLE_RX_RING
128 +#define CNS3XXX_FSQF_RING1_ISR
131 +//#define CNS3XXX_DELAYED_INTERRUPT
133 +#ifdef CNS3XXX_DELAYED_INTERRUPT
134 +#define MAX_PEND_INT_CNT 0x06
135 +#define MAX_PEND_TIME 0x20
138 +//#define CNS3XXX_ENABLE_RINT1
141 +++ b/drivers/net/cns3xxx/cns3xxx_ethtool.c
143 +/*******************************************************************************
146 + * Copyright (c) 2009 Cavium Networks
148 + * This program is free software; you can redistribute it and/or modify it
149 + * under the terms of the GNU General Public License as published by the Free
150 + * Software Foundation; either version 2 of the License, or (at your option)
151 + * any later version.
153 + * This program is distributed in the hope that it will be useful, but WITHOUT
154 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
155 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
158 + * You should have received a copy of the GNU General Public License along with
159 + * this program; if not, write to the Free Software Foundation, Inc., 59
160 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
162 + * The full GNU General Public License is included in this distribution in the
163 + * file called LICENSE.
165 + ********************************************************************************/
167 +//#include <linux/module.h>
168 +#include <linux/types.h>
169 +#include <linux/ethtool.h>
170 +#include <linux/netdevice.h>
171 +#include "cns3xxx_symbol.h"
172 +#include "cns3xxx.h"
173 +#include "cns3xxx_tool.h"
175 +// ethtool support reference e100.c and e1000_ethtool.c .
176 +static void cns3xxx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
178 + strcpy(info->driver, "cns3xxx");
179 + strcpy(info->version, DRV_VERSION);
180 + strcpy(info->fw_version, "N/A");
181 + strcpy(info->bus_info, "N/A");
184 +static void cns3xxx_get_ringparam(struct net_device *netdev,
185 + struct ethtool_ringparam *ring)
187 + CNS3XXXPrivate *priv = netdev_priv(netdev);
189 + ring->rx_max_pending = priv->rx_ring->max_ring_size;
190 + ring->tx_max_pending = priv->tx_ring->max_ring_size;
191 + ring->rx_pending = priv->rx_ring->ring_size;
192 + ring->tx_pending = priv->tx_ring->ring_size;
194 + struct nic *nic = netdev_priv(netdev);
195 + struct param_range *rfds = &nic->params.rfds;
196 + struct param_range *cbs = &nic->params.cbs;
198 + ring->rx_max_pending = rfds->max;
199 + ring->tx_max_pending = cbs->max;
200 + ring->rx_mini_max_pending = 0;
201 + ring->rx_jumbo_max_pending = 0;
202 + ring->rx_pending = rfds->count;
203 + ring->tx_pending = cbs->count;
204 + ring->rx_mini_pending = 0;
205 + ring->rx_jumbo_pending = 0;
211 +static int cns3xxx_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
213 + int cns3xxx_up(void);
214 + int cns3xxx_down(void);
215 + int cns3xxx_close(struct net_device *dev);
216 + int cns3xxx_open(struct net_device *dev);
217 + extern struct net_device *net_dev_array[];
219 + CNS3XXXPrivate *priv = netdev_priv(netdev);
224 + struct nic *nic = netdev_priv(netdev);
225 + struct param_range *rfds = &nic->params.rfds;
226 + struct param_range *cbs = &nic->params.cbs;
228 + if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
231 + if(netif_running(netdev))
233 + rfds->count = max(ring->rx_pending, rfds->min);
234 + rfds->count = min(rfds->count, rfds->max);
235 + cbs->count = max(ring->tx_pending, cbs->min);
236 + cbs->count = min(cbs->count, cbs->max);
237 + DPRINTK(DRV, INFO, "Ring Param settings: rx: %d, tx %d\n",
238 + rfds->count, cbs->count);
239 + if(netif_running(netdev))
243 + //ring->rx_max_pending = RX_DESC_SIZE;
244 + //ring->tx_max_pending = TX_DESC_SIZE;
247 + printk("ring->rx_max_pending: %d\n", ring->rx_max_pending);
248 + printk("ring->tx_max_pending: %d\n", ring->tx_max_pending);
249 + printk("ring->rx_pending: %d\n", ring->rx_pending);
250 + printk("ring->tx_pending: %d\n", ring->tx_pending);
253 + for (i=0 ; i < NETDEV_SIZE ; ++i) {
254 + if(net_dev_array[i] && netif_running(net_dev_array[i])) {
255 + //printk("close net_dev_array[%d]: %s\n", i, net_dev_array[i]);
256 + cns3xxx_close(net_dev_array[i]);
262 + priv->rx_ring->ring_size = min(ring->rx_pending, priv->rx_ring->max_ring_size);
263 + priv->tx_ring->ring_size = min(ring->rx_pending, priv->tx_ring->max_ring_size);
265 + for (i=0 ; i < NETDEV_SIZE ; ++i) {
266 + if(net_dev_array[i] && netif_running(net_dev_array[i])) {
267 + //printk("open net_dev_array[%d]: %s\n", i, net_dev_array[i]);
268 + cns3xxx_open(net_dev_array[i]);
276 +static uint32_t cns3xxx_get_tx_csum(struct net_device *netdev)
278 + //return (netdev->features & NETIF_F_HW_CSUM) != 0;
279 + return (netdev->features & NETIF_F_IP_CSUM) != 0;
282 +static int cns3xxx_set_tx_csum(struct net_device *netdev, uint32_t data)
285 + netdev->features |= NETIF_F_IP_CSUM;
287 + netdev->features &= ~NETIF_F_IP_CSUM;
291 +static uint32_t cns3xxx_get_rx_csum(struct net_device *netdev)
293 + //struct e1000_adapter *adapter = netdev_priv(netdev);
294 + //return adapter->rx_csum;
298 +static int cns3xxx_set_rx_csum(struct net_device *netdev, uint32_t data)
303 +u32 cns3xxx_get_sg(struct net_device *dev)
306 + return (dev->features & NETIF_F_SG) != 0;
312 +int cns3xxx_set_sg(struct net_device *dev, u32 data)
316 + dev->features |= NETIF_F_SG;
318 + dev->features &= ~NETIF_F_SG;
324 +static void cns3xxx_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
326 + u32 mac_port_config = 0;
327 + CNS3XXXPrivate *priv = netdev_priv(netdev);
329 + switch (priv->net_device_priv->which_port)
333 + mac_port_config = MAC0_CFG_REG;
338 + mac_port_config = MAC1_CFG_REG;
343 + mac_port_config = MAC2_CFG_REG;
349 + pause->autoneg = ( ((mac_port_config >> 7) & 1) ? AUTONEG_ENABLE : AUTONEG_DISABLE);
350 + pause->tx_pause = (mac_port_config >> 6) & 1;
351 + pause->rx_pause = (mac_port_config >> 5) & 1;
354 +static int cns3xxx_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
356 + u32 mac_port_config = 0;
357 + CNS3XXXPrivate *priv = netdev_priv(netdev);
359 + switch (priv->net_device_priv->which_port)
363 + mac_port_config = MAC0_CFG_REG;
368 + mac_port_config = MAC1_CFG_REG;
373 + mac_port_config = MAC2_CFG_REG;
379 + mac_port_config &= ~(0x1 << 7); // clean AN
380 + mac_port_config &= ~(0x1 << 11); // clean rx flow control
381 + mac_port_config &= ~(0x1 << 12); // clean tx flow control
383 + mac_port_config |= ( (pause->autoneg << 7) | (pause->rx_pause << 11) | (pause->tx_pause << 12) );
386 + switch (priv->net_device_priv->which_port)
390 + MAC0_CFG_REG = mac_port_config;
395 + MAC1_CFG_REG = mac_port_config;
400 + MAC2_CFG_REG = mac_port_config;
407 +u32 cns3xxx_get_link(struct net_device *netdev)
409 + u32 mac_port_config = 0;
410 + CNS3XXXPrivate *priv = netdev_priv(netdev);
412 + switch (priv->net_device_priv->which_port)
416 + mac_port_config = MAC0_CFG_REG;
421 + mac_port_config = MAC1_CFG_REG;
426 + mac_port_config = MAC2_CFG_REG;
431 + return (mac_port_config & 1 ) ? 1 : 0;
432 + //return netif_carrier_ok(dev) ? 1 : 0;
436 +static int cns3xxx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
439 + u32 mac_port_config = 0;
440 + CNS3XXXPrivate *priv = netdev_priv(netdev);
443 + if (priv->net_device_priv->nic_setting == 0) { // connect to switch chip
445 + GET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config)
447 + 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);
449 + ecmd->duplex = ((mac_port_config >> 4) & 0x1) ? DUPLEX_FULL : DUPLEX_HALF ;
451 + value = ((mac_port_config >> 2) & 0x3);
455 + ecmd->speed = SPEED_10;
458 + ecmd->speed = SPEED_100;
461 + ecmd->speed = SPEED_1000;
465 + ecmd->autoneg = ((mac_port_config >> 7) & 1) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
469 + } else { // connect to PHY chip
476 +// set speed and duplex
477 +int cns3xxx_set_spd_dplx(struct net_device *netdev, u16 spddplx)
479 + u32 mac_port_config = 0;
480 + CNS3XXXPrivate *priv = netdev_priv(netdev);
482 + GET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config)
484 + //printk("mac_port_config: %x\n", mac_port_config);
486 + mac_port_config &= ~(0x3 << 8); // clear speed
487 + mac_port_config &= ~(0x1 << 10); // clear duplex
488 + mac_port_config &= ~(0x1 << 7); // disable AN
491 + case AUTONEG_ENABLE:
492 + mac_port_config |= (0x1 << 7); // enable AN
494 + case SPEED_10 + DUPLEX_HALF:
495 + printk("10, halt\n");
496 + mac_port_config |= (0 << 8); // set speed
497 + mac_port_config |= (0 << 10); // set duplex
498 + //printk("xxx mac_port_config: %x\n", mac_port_config);
500 + case SPEED_10 + DUPLEX_FULL:
501 + mac_port_config |= (0 << 8); // set speed
502 + mac_port_config |= (1 << 10); // set duplex
504 + case SPEED_100 + DUPLEX_HALF:
505 + mac_port_config |= (1 << 8); // set speed
506 + mac_port_config |= (0 << 10); // set duplex
508 + case SPEED_100 + DUPLEX_FULL:
509 + mac_port_config |= (1 << 8); // set speed
510 + mac_port_config |= (1 << 10); // set duplex
512 + case SPEED_1000 + DUPLEX_HALF:
513 + mac_port_config |= (2 << 8); // set speed
514 + mac_port_config |= (0 << 10); // set duplex
516 + case SPEED_1000 + DUPLEX_FULL:
517 + mac_port_config |= (2 << 8); // set speed
518 + mac_port_config |= (1 << 10); // set duplex
521 + //printk("Unsupported Speed/Duplex configuration\n");
525 + SET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config)
530 +static int cns3xxx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
533 + CNS3XXXPrivate *priv = netdev_priv(netdev);
535 + if (priv->net_device_priv->nic_setting == 0) { // connect to switch chip
536 + if (ecmd->autoneg == AUTONEG_ENABLE) {
537 + printk("autoneg\n");
538 + if ((value=cns3xxx_set_spd_dplx(netdev, AUTONEG_ENABLE)) != 0) {
542 + printk("no autoneg\n");
543 + if ((value=cns3xxx_set_spd_dplx(netdev, ecmd->speed + ecmd->duplex)) != 0) {
550 + } else { // connect to PHY chip
558 +static const struct ethtool_ops cns3xxx_ethtool_ops = {
559 + .get_drvinfo = cns3xxx_get_drvinfo,
560 + .get_ringparam = cns3xxx_get_ringparam,
561 + .set_ringparam = cns3xxx_set_ringparam,
562 + .get_rx_csum = cns3xxx_get_rx_csum,
563 + .set_rx_csum = cns3xxx_set_rx_csum,
564 + .get_tx_csum = cns3xxx_get_tx_csum,
565 + .set_tx_csum = cns3xxx_set_tx_csum,
566 + .get_sg = cns3xxx_get_sg,
567 + .set_sg = cns3xxx_set_sg,
568 + .get_pauseparam = cns3xxx_get_pauseparam,
569 + .set_pauseparam = cns3xxx_set_pauseparam,
570 + .get_link = cns3xxx_get_link,
571 + .get_settings = cns3xxx_get_settings,
572 + .set_settings = cns3xxx_set_settings,
575 +void cns3xxx_set_ethtool_ops(struct net_device *netdev)
577 + SET_ETHTOOL_OPS(netdev, &cns3xxx_ethtool_ops);
580 +++ b/drivers/net/cns3xxx/cns3xxx.h
582 +/*******************************************************************************
584 + * Copyright (c) 2009 Cavium Networks
586 + * This program is free software; you can redistribute it and/or modify it
587 + * under the terms of the GNU General Public License as published by the Free
588 + * Software Foundation; either version 2 of the License, or (at your option)
589 + * any later version.
591 + * This program is distributed in the hope that it will be useful, but WITHOUT
592 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
593 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
596 + * You should have received a copy of the GNU General Public License along with
597 + * this program; if not, write to the Free Software Foundation, Inc., 59
598 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
600 + * The full GNU General Public License is included in this distribution in the
601 + * file called LICENSE.
603 + ********************************************************************************/
608 +#include "cns3xxx_symbol.h"
609 +#include "cns3xxx_config.h"
610 +#include <linux/cns3xxx/switch_api.h>
612 +#include <linux/module.h>
613 +#include <linux/init.h>
614 +#include <linux/kernel.h>
615 +#include <linux/bootmem.h>
616 +#include <linux/sched.h>
617 +#include <linux/types.h>
618 +#include <linux/fcntl.h>
619 +#include <linux/interrupt.h>
620 +#include <linux/ptrace.h>
621 +#include <linux/ioport.h>
622 +#include <linux/in.h>
623 +#include <linux/slab.h>
624 +#include <linux/init.h>
625 +#include <linux/proc_fs.h>
626 +#include <linux/reboot.h>
627 +#include <asm/bitops.h>
628 +#include <asm/irq.h>
630 +//#include <asm/hardware.h>
631 +#include <linux/pci.h>
632 +#include <linux/errno.h>
633 +#include <linux/delay.h>
634 +#include <linux/netdevice.h>
635 +#include <linux/etherdevice.h>
636 +#include <linux/skbuff.h>
637 +#include <linux/ip.h>
638 +#include <linux/if_ether.h>
639 +#include <linux/icmp.h>
640 +#include <linux/udp.h>
641 +#include <linux/tcp.h>
642 +#include <linux/if_arp.h>
643 +#include <net/arp.h>
646 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
647 +#include <linux/if_vlan.h>
650 +//#define VERSION "1.0"
655 + int32_t sdp; // segment data pointer
657 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
664 + u32 fp:1; // force priority
666 + u32 rsv_1:3; // reserve
670 + u32 sdl:16; // segment data length
673 + u32 sdl:16; // segment data length
677 + u32 rsv_1:3; // reserve
679 + u32 fp:1; // force priority
688 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
714 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
730 + u8 alignment[16]; // for alignment 32 byte
732 +} __attribute__((packed)) TXDesc;
738 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
760 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
792 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
808 + u8 alignment[16]; // for alignment 32 byte
810 +} __attribute__((packed)) RXDesc;
814 + struct sk_buff *skb; // for free skb
817 + unsigned long tx_index;
822 + struct sk_buff *skb; // rx path need to fill some skb field, ex: length ...
831 + TXDesc *tx_desc_head_vir_addr;
832 + dma_addr_t tx_desc_head_phy_addr;
833 + u32 cur_index; // for put send packet
834 + spinlock_t tx_lock;
835 + u32 non_free_tx_skb;
836 + u32 free_tx_skb_index;
844 + RXDesc *rx_desc_head_vir_addr;
845 + dma_addr_t rx_desc_head_phy_addr;
854 + CNS3XXXIoctlCmd cmd;
861 +#define RX_RING0(priv) (priv->rx_ring[0])
862 +#define TX_RING0(priv) (priv->tx_ring[0])
865 +static inline u32 get_rx_ring_size(const RXRing *ring)
867 + //printk("rx ring->ring_size: %d\n", ring->ring_size);
868 + return ring->ring_size;
871 +static inline u32 get_tx_ring_size(TXRing *ring)
873 + //printk("tx ring->ring_size: %d\n", ring->ring_size);
874 + return ring->ring_size;
877 +static inline RXBuffer *get_rx_ring_head(const RXRing *rx_ring)
879 + return rx_ring->head;
882 +static inline TXBuffer *get_tx_ring_head(TXRing *tx_ring)
884 + return tx_ring->head;
887 +static inline RXBuffer *get_cur_rx_buffer(RXRing *rx_ring)
889 + return rx_ring->head + rx_ring->cur_index;
892 +static inline TXBuffer *get_cur_tx_buffer(TXRing *tx_ring)
894 + return tx_ring->head + tx_ring->cur_index;
897 +static inline u32 get_rx_head_phy_addr(RXRing *rx_ring)
899 + return rx_ring->rx_desc_head_phy_addr;
902 +static inline u32 get_tx_ring_head_phy_addr(TXRing *tx_ring)
904 + return tx_ring->tx_desc_head_phy_addr;
908 +static inline u32 get_rx_cur_index(RXRing *rx_ring)
910 + return rx_ring->cur_index;
913 +static inline u32 get_tx_cur_index(TXRing *tx_ring)
915 + return tx_ring->cur_index;
918 +static inline u32 get_tx_cur_phy_addr(u8 ring_num)
921 + return TS_DESC_PTR0_REG;
923 + return TS_DESC_PTR1_REG;
927 +static inline void rx_index_next(RXRing *ring)
929 + ring->cur_index = ((ring->cur_index + 1) % ring->ring_size);
931 +static inline void tx_index_next(TXRing *ring)
933 + ring->cur_index = ((ring->cur_index + 1) % ring->ring_size);
938 +struct CNS3XXXPrivate_;
940 +typedef int (*RXFuncPtr)(struct sk_buff *skb, RXDesc*tx_desc_ptr, const struct CNS3XXXPrivate_* );
941 +typedef int (*TXFuncPtr)(TXDesc*tx_desc_ptr, const struct CNS3XXXPrivate_*, struct sk_buff *);
942 +typedef void (*OpenPtr)(void);
943 +typedef void (*ClosePtr)(void);
946 +// for ethtool set operate
952 + int pmap; // for port base, force route
953 + int is_wan; // mean the net device is WAN side.
956 + //u8 mac_type; // VLAN base, or port base;
959 + // do port base mode and vlan base mode work
965 + //NICSetting *nic_setting;
966 + u8 *mac; // point to a mac address array
967 + VLANTableEntry *vlan_table_entry;
968 + ARLTableEntry *arl_table_entry;
969 + NICSetting *nic_setting;
970 + const char *name; // 16 bytes, reference include/linux/netdevice.h IFNAMSIZ
982 +/* store this information for the driver.. */
983 +typedef struct CNS3XXXPrivate_
989 + struct net_device_stats stats;
992 + int is_wan; // mean the net device is WAN side.
994 + u8 mac_type; // VLAN base, or port base;
996 + struct napi_struct napi;
997 + struct work_struct reset_task;
1000 + //NICSetting *nic_setting;
1001 + char name[IFNAMSIZ]; // 16 bytes, reference include/linux/netdevice.h IFNAMSIZ
1004 + NetDevicePriv *net_device_priv;
1007 + u32 rx_s_vid[4096]; // record receive s vid (0x9100 ...)
1008 + u32 rx_c_vid[4096]; // record receive c vid (0x8100 ...)
1009 +#ifdef CONFIG_CNS3XXX_NAPI
1010 + volatile unsigned long is_qf; // determine rx ring queue full state
1013 +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
1014 + struct vlan_group *vlgrp;
1021 +int rx_port_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv);
1023 +int rx_vlan_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv);
1025 +int tx_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb);
1028 +int tx_vlan_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb);
1029 +#if defined (CONFIG_CNS3XXX_SPPE)
1030 +int fp_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb);
1035 +++ b/drivers/net/cns3xxx/cns3xxx_main.c
1037 +/*******************************************************************************
1039 + * Copyright (c) 2009 Cavium Networks
1041 + * This program is free software; you can redistribute it and/or modify it
1042 + * under the terms of the GNU General Public License as published by the Free
1043 + * Software Foundation; either version 2 of the License, or (at your option)
1044 + * any later version.
1046 + * This program is distributed in the hope that it will be useful, but WITHOUT
1047 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1048 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1051 + * You should have received a copy of the GNU General Public License along with
1052 + * this program; if not, write to the Free Software Foundation, Inc., 59
1053 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
1055 + * The full GNU General Public License is included in this distribution in the
1056 + * file called LICENSE.
1058 + ********************************************************************************/
1060 +#include <linux/module.h>
1061 +#include <mach/board.h>
1062 +#include <linux/platform_device.h>
1063 +#include "cns3xxx.h"
1064 +#include "cns3xxx_tool.h"
1065 +#include "cns3xxx_config.h"
1067 +#if defined (CONFIG_CNS3XXX_SPPE)
1068 +#include <linux/cns3xxx/sppe.h>
1069 +#define PACKET_REASON_TO_CPU (0x2C)
1072 +#define RX_SDP_ALIGN 64
1082 +#define CPU_CACHE_BYTES 64
1083 +#define CPU_CACHE_ALIGN(X) (((X) + (CPU_CACHE_BYTES-1)) & ~(CPU_CACHE_BYTES-1))
1086 +#define QUEUE_WEIGHT_SET(port, ctl) \
1088 + MAC##port##_PRI_CTRL_REG &= ~(0x3ffff); \
1089 + MAC##port##_PRI_CTRL_REG |= (ctl.sch_mode << 16); \
1090 + MAC##port##_PRI_CTRL_REG |= (ctl.q0_w); \
1091 + MAC##port##_PRI_CTRL_REG |= (ctl.q1_w << 4); \
1092 + MAC##port##_PRI_CTRL_REG |= (ctl.q2_w << 8); \
1093 + MAC##port##_PRI_CTRL_REG |= (ctl.q3_w << 12); \
1096 +#define QUEUE_WEIGHT_GET(port, ctl) \
1098 + ctl.sch_mode = ((MAC##port##_PRI_CTRL_REG >> 16 ) & 0x3); \
1099 + ctl.q0_w = ((MAC##port##_PRI_CTRL_REG >> 0 ) & 0x7); \
1100 + ctl.q1_w = ((MAC##port##_PRI_CTRL_REG >> 4 ) & 0x7); \
1101 + ctl.q2_w = ((MAC##port##_PRI_CTRL_REG >> 8 ) & 0x7); \
1102 + ctl.q3_w = ((MAC##port##_PRI_CTRL_REG >> 12 ) & 0x7); \
1105 +int cns3xxx_send_packet(struct sk_buff *skb, struct net_device *netdev);
1106 +static int install_isr_rc = 0;
1107 +static int rc_setup_rx_tx = 0; // rc means reference counting.
1108 +static struct net_device *intr_netdev;
1109 +struct net_device *net_dev_array[NETDEV_SIZE];
1110 +spinlock_t tx_lock;
1111 +spinlock_t rx_lock;
1112 +u8 fast_bridge_en=1;
1116 +int init_port=7; // bit map 7 means port 0, 1 and 2, default is 7.
1117 +//module_param(init_port, u8, S_IRUGO);
1118 +module_param(init_port, int, 0);
1120 +u8 ring_index=0; // 0 or 1
1122 +#ifdef CNS3XXX_DELAYED_INTERRUPT
1123 +static u32 max_pend_int_cnt=MAX_PEND_INT_CNT, max_pend_time=MAX_PEND_TIME;
1126 +#ifdef CONFIG_CNS3XXX_NAPI
1127 +struct net_device *napi_dev;
1128 + #ifdef CNS3XXX_DOUBLE_RX_RING
1129 + struct net_device *r1_napi_dev; // ring1 napi dev
1133 +const u32 MAX_RX_DESC_SIZE = 512;
1134 +const u32 MAX_TX_DESC_SIZE = 512;
1135 +const u32 RX_DESC_SIZE = 128;
1136 +//const u32 RX_DESC_SIZE = 5;
1137 +const u32 TX_DESC_SIZE = 120;
1142 +// only for debug (proc)
1143 +RingInfo g_ring_info;
1145 +int MSG_LEVEL = NORMAL_MSG;
1147 +#ifdef CNS3XXX_STATUS_ISR
1148 +const char *cns3xxx_gsw_status_tbl[] = {
1149 + "\nMAC0_Q_FULL\n",
1150 + "\nMAC1_Q_FULL\n",
1152 + "\nHNAT_Q_FULL\n",
1153 + "\nMAC2_Q_FULL\n",
1154 + "\nMAC0_Q_EXT_FULL\n",
1155 + "\nGLOBAL_Q_FULL\n",
1156 + "\nBUFFER_FULL\n",
1157 + "\nMIB_COUNTER_TH\n",
1159 + "\nMAC0_INTRUDER\n",
1160 + "\nMAC1_INTRUDER\n",
1161 + "\nCPU_INTRUDER\n",
1162 + "\nMAC2_INTRUDER\n",
1163 + "\nMAC0_STATUS_CHG\n",
1164 + "\nMAC1_STATUS_CHG\n",
1165 + "\nMAC2_STATUS_CHG\n",
1166 + "\nMAC0_NO_LINK_DROP\n",
1167 + "\nMAC1_NO_LINK_DROP\n",
1168 + "\nMAC2_NO_LINK_DROP\n",
1169 + "\nMAC0_RX_ERROR_DROP\n",
1170 + "\nMAC1_RX_ERROR_DROP\n",
1171 + "\nMAC2_RX_ERROR_DROP\n",
1172 + "\nMAC0_NO_DESTINATION_DROP\n",
1173 + "\nMAC1_NO_DESTINATION_DROP\n",
1174 + "\nMAC2_NO_DESTINATION_DROP\n",
1175 + "\nMAC0_RMC_PAUSE_DROP\n",
1176 + "\nMAC1_RMC_PAUSE_DROP\n",
1177 + "\nMAC2_RMC_PAUSE_DROP\n",
1178 + "\nMAC0_LOCAL_DROP\n",
1179 + "\nMAC1_LOCAL_DROP\n",
1180 + "\nMAC2_LOCAL_DROP\n",
1184 +#define MIN_PACKET_LEN 14
1186 +void cns3xxx_write_pri_mask(u8 pri_mask);
1188 +static int cns3xxx_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr);
1190 +static struct notifier_block cns3xxx_notifier_reboot = {
1191 + .notifier_call = cns3xxx_notify_reboot,
1196 +#if defined(CNS3XXX_VLAN_8021Q)
1197 +void cns3xxx_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid);
1198 +void cns3xxx_vlan_rx_register(struct net_device *dev, struct vlan_group *grp);
1201 +void take_off_vlan_header(struct sk_buff *skb)
1203 + // take off VLAN header
1204 + memmove(skb->data + 4, skb->data, 12);
1206 + //skb_ptr->data += 4;
1207 + skb_reserve(skb, 4);
1211 + skb->len -= 4; // minus 4 byte vlan tag
1214 +int rx_port_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv)
1216 + if (skb->data[12] == 0x81 && skb->data[13] == 0x00) // VLAN header
1218 + take_off_vlan_header(skb);
1219 + print_packet(skb->data, skb->len);
1224 +int rx_vlan_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv)
1229 +int tx_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb)
1231 +#if defined(CNS3XXX_VLAN_8021Q) && defined (CNS3XXX_8021Q_HW_TX)
1232 + if (skb && priv->vlgrp != NULL && vlan_tx_tag_present(skb))
1234 + tx_desc_ptr->c_vid = cpu_to_le16(vlan_tx_tag_get(skb));
1235 + tx_desc_ptr->ctv=1;
1236 + tx_desc_ptr->fr = 0;
1242 + tx_desc_ptr->ctv = 0;
1243 + tx_desc_ptr->pmap = priv->net_device_priv->pmap;
1244 + tx_desc_ptr->fr = 1;
1251 +int tx_vlan_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb)
1253 +#if defined(CNS3XXX_VLAN_8021Q)
1255 + if (skb && priv->vlgrp != NULL && vlan_tx_tag_present(skb)) {
1256 + tx_desc_ptr->c_vid = cpu_to_le16(vlan_tx_tag_get(skb));
1259 + tx_desc_ptr->c_vid = priv->net_device_priv->vlan_tag;
1262 + tx_desc_ptr->ctv=1;
1263 + tx_desc_ptr->fr = 0;
1268 +#if defined (CONFIG_CNS3XXX_SPPE)
1269 +int fp_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb)
1272 + tx_desc_ptr->fr = 1;
1273 + tx_desc_ptr->pmap = 0x8;
1275 + tx_desc_ptr->fr = 0;
1276 + tx_desc_ptr->ctv = 1;
1277 + tx_desc_ptr->c_vid = 80;
1283 +static inline struct sk_buff *cns3xxx_alloc_skb(void)
1285 + struct sk_buff *skb;
1288 + skb = dev_alloc_skb(MAX_PACKET_LEN + 2 + RX_SDP_ALIGN);
1290 + if (unlikely(!skb)) {
1293 + pci_dma_sync_single_for_device(NULL, virt_to_phys(skb->data), MAX_PACKET_LEN+2+RX_SDP_ALIGN, PCI_DMA_FROMDEVICE);
1295 + align_64=CPU_CACHE_ALIGN((u32)skb->data);
1296 + skb_reserve(skb, align_64-(u32)skb->data); /* 16 bytes alignment */
1299 + skb_reserve(skb, NET_IP_ALIGN); /* 16 bytes alignment */
1307 +static int free_rx_skb(RXRing *rx_ring)
1310 + RXBuffer *rx_buffer = rx_ring->head;
1311 + //RXDesc *rx_desc = rx_ring.rx_desc_head_vir_addr;
1313 + for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) {
1314 + if (rx_buffer->rx_desc->cown==0 && rx_buffer->skb) {
1315 + dev_kfree_skb(rx_buffer->skb);
1322 +int cns3xxx_setup_all_rx_resources(RXRing *rx_ring, u8 ring_num)
1325 + RXBuffer *rx_buffer = 0;
1326 + RXDesc *rx_desc = 0;
1329 + ncnb_buf = dma_alloc_coherent(NULL, 2*1024* get_rx_ring_size(rx_ring), &ncnb_buf_phy, GFP_KERNEL);
1330 + printk("NCB_BUF: %08X PHY: %08X \n", ncnb_buf, ncnb_buf_phy);
1334 + // alloc RXDesc array
1335 + 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);
1336 + if (!rx_ring->rx_desc_head_vir_addr) {
1340 + memset(rx_ring->rx_desc_head_vir_addr, 0, sizeof(RXDesc) * get_rx_ring_size(rx_ring));
1342 + // alloc RXBuffer array
1343 + rx_ring->head = kmalloc(sizeof(RXBuffer) * get_rx_ring_size(rx_ring), GFP_KERNEL);
1345 + if (!rx_ring->head) {
1349 + rx_buffer = rx_ring->head;
1350 + for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) {
1355 + rx_buffer = rx_ring->head;
1356 + rx_desc = rx_ring->rx_desc_head_vir_addr;
1357 + for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i, ++rx_buffer, ++rx_desc) {
1358 + rx_buffer->rx_desc = rx_desc;
1359 + rx_buffer->skb = cns3xxx_alloc_skb();
1361 + if (!rx_buffer->skb) {
1363 + free_rx_skb(rx_ring);
1364 + kfree(rx_ring->head);
1365 + 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);
1369 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1371 + RXDesc tmp_rx_desc;
1373 + memset(&tmp_rx_desc, 0, sizeof(RXDesc));
1374 + tmp_rx_desc.sdp = (u32)virt_to_phys(rx_buffer->skb->data);
1375 + tmp_rx_desc.sdl = MAX_PACKET_LEN;
1376 + if (i == (get_rx_ring_size(rx_ring)-1) ){
1377 + tmp_rx_desc.eor = 1;
1379 + tmp_rx_desc.fsd = 1;
1380 + tmp_rx_desc.lsd = 1;
1381 + swap_rx_desc(&tmp_rx_desc, rx_buffer->rx_desc);
1385 + rx_buffer->rx_desc->sdp = (u32)virt_to_phys(rx_buffer->skb->data);
1386 + rx_buffer->rx_desc->sdl = MAX_PACKET_LEN;
1387 + if (i == (get_rx_ring_size(rx_ring)-1) ){
1388 + rx_buffer->rx_desc->eor = 1;
1390 + rx_buffer->rx_desc->fsd = 1;
1391 + rx_buffer->rx_desc->lsd = 1;
1395 + rx_ring->cur_index = 0 ;
1397 + if (ring_num == 0){
1398 + FS_DESC_PTR0_REG = rx_ring->rx_desc_head_phy_addr;
1399 + FS_DESC_BASE_ADDR0_REG = rx_ring->rx_desc_head_phy_addr;
1401 + } else if (ring_num == 1){
1402 + FS_DESC_PTR1_REG = rx_ring->rx_desc_head_phy_addr;
1403 + FS_DESC_BASE_ADDR1_REG = rx_ring->rx_desc_head_phy_addr;
1409 +static int cns3xxx_setup_all_tx_resources(TXRing *tx_ring, u8 ring_num)
1412 + TXBuffer *tx_buffer = 0;
1413 + TXDesc *tx_desc = 0;
1416 + spin_lock_init(&(tx_ring->tx_lock));
1418 + 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);
1419 + if (!tx_ring->tx_desc_head_vir_addr) {
1423 + memset(tx_ring->tx_desc_head_vir_addr, 0, sizeof(TXDesc) * get_tx_ring_size(tx_ring));
1424 + tx_ring->head = kmalloc(sizeof(TXBuffer) * get_tx_ring_size(tx_ring), GFP_KERNEL);
1426 + tx_buffer = tx_ring->head;
1427 + tx_desc = tx_ring->tx_desc_head_vir_addr;
1428 + for (i=0 ; i < get_tx_ring_size(tx_ring) ; ++i, ++tx_buffer, ++tx_desc) {
1429 + tx_buffer->tx_desc = tx_desc;
1431 + tx_buffer->tx_desc->cown = 1;
1432 + tx_buffer->skb = 0;
1433 + if (i == (get_tx_ring_size(tx_ring)-1) ){
1434 + tx_buffer->tx_desc->eor = 1;
1436 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1437 + swap_tx_desc(tx_buffer->tx_desc, tx_buffer->tx_desc);
1442 + tx_ring->cur_index = 0 ;
1444 + if (ring_num == 0){
1445 + TS_DESC_PTR0_REG = tx_ring->tx_desc_head_phy_addr;
1446 + TS_DESC_BASE_ADDR0_REG = tx_ring->tx_desc_head_phy_addr;
1447 + } else if (ring_num == 1){
1448 + TS_DESC_PTR1_REG = tx_ring->tx_desc_head_phy_addr;
1449 + TS_DESC_BASE_ADDR1_REG = tx_ring->tx_desc_head_phy_addr;
1454 +int cns3xxx_free_all_rx_resources(RXRing *rx_ring)
1456 + free_rx_skb(rx_ring);
1457 + kfree(rx_ring->head);
1458 + 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);
1462 +static int free_tx_skb(TXRing *tx_ring)
1465 + TXBuffer *tx_buffer = tx_ring->head;
1467 + for (i=0 ; i < get_tx_ring_size(tx_ring) ; ++i) {
1468 + if (tx_buffer->skb) {
1469 + dev_kfree_skb(tx_buffer->skb);
1470 + tx_buffer->skb = 0;
1476 +int cns3xxx_free_all_tx_resources(TXRing *tx_ring)
1478 + free_tx_skb(tx_ring);
1479 + kfree(tx_ring->head);
1480 + 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);
1484 +static int cns3xxx_free_rx_tx_res(CNS3XXXPrivate *priv)
1489 + if (rc_setup_rx_tx == 0) {
1490 + enable_port(3, 0); // disable cpu port
1492 + // stop RX/TX ring0 dma
1493 + enable_rx_dma(0, 0);
1494 + enable_tx_dma(0, 0);
1496 + for (i=0 ; i < priv->num_rx_queues ; ++i) {
1497 + cns3xxx_free_all_rx_resources(priv->rx_ring+i);
1498 + memset(priv->rx_ring + i, 0, sizeof(RXRing));
1501 + for (i=0 ; i < priv->num_tx_queues ; ++i) {
1502 + cns3xxx_free_all_tx_resources(priv->tx_ring+i);
1503 + memset(priv->tx_ring + i, 0, sizeof(TXRing));
1511 +static int cns3xxx_setup_rx_tx_res(CNS3XXXPrivate *priv)
1515 + if (rc_setup_rx_tx == 0) {
1516 + clear_fs_dma_state(1);
1517 + FS_DESC_PTR0_REG = 0;
1518 + FS_DESC_BASE_ADDR0_REG = 0;
1519 + FS_DESC_PTR1_REG = 0;
1520 + FS_DESC_BASE_ADDR1_REG = 0;
1521 + TS_DESC_PTR0_REG = 0;
1522 + TS_DESC_BASE_ADDR0_REG = 0;
1523 + TS_DESC_PTR1_REG = 0;
1524 + TS_DESC_BASE_ADDR1_REG = 0;
1526 + for (i=0 ; i < priv->num_tx_queues ; ++i) {
1527 + spin_lock_init(&((priv->tx_ring+i)->tx_lock));
1528 + (priv->tx_ring+i)->max_ring_size = MAX_TX_DESC_SIZE;
1529 + (priv->tx_ring+i)->ring_size = TX_DESC_SIZE;
1530 + if (cns3xxx_setup_all_tx_resources(priv->tx_ring+i, i) != CAVM_OK)
1534 + for (i=0 ; i < priv->num_rx_queues ; ++i) {
1535 + (priv->rx_ring+i)->max_ring_size = MAX_RX_DESC_SIZE;
1536 + (priv->rx_ring+i)->ring_size = RX_DESC_SIZE;
1537 + if (cns3xxx_setup_all_rx_resources(priv->rx_ring+i, i) != CAVM_OK)
1541 + clear_fs_dma_state(0);
1547 +int free_tx_desc_skb(TXRing *tx_ring, u8 ring_num)
1551 + //u32 tssd_current=0;
1552 + TXBuffer *tx_buffer = 0;
1553 + u32 tx_ring_size = get_tx_ring_size(tx_ring);
1554 + // check curent hw index previous tx descriptor
1555 + u32 cur_index = cns3xxx_get_tx_hw_index(ring_num) - 1;
1557 + tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index);
1561 + for (i=0 ; i < tx_ring_size ; ++i) {
1562 + if (tx_buffer->tx_desc->cown == 1 && tx_buffer->skb) {
1563 + dev_kfree_skb_any(tx_buffer->skb);
1565 + //tx_buffer->tx_desc->cown == 1;
1569 + // --tx_desc_pair_ptr
1571 + tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index);
1578 +void do_arl_lookup(void)
1582 +inline void assign_netdev(RXBuffer volatile *rx_buffer)
1584 + RXDesc * rx_desc=0;
1585 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1586 + RXDesc tmp_rx_desc;
1587 + rx_desc = &tmp_rx_desc;
1588 + swap_rx_desc(rx_buffer->rx_desc, rx_desc);
1590 + rx_desc = rx_buffer->rx_desc;
1594 +#if defined(CONFIG_CNS3XXX_PORT_BASE) || defined(CNS3XXX_VLAN_8021Q)
1600 + switch (rx_desc->sp)
1604 + rx_buffer->skb->dev = PORT0_NETDEV;
1609 + rx_buffer->skb->dev = PORT1_NETDEV;
1614 + rx_buffer->skb->dev = PORT2_NETDEV;
1621 +#ifdef CONFIG_CNS3XXX_VLAN_BASE
1625 + vlan_tag = rx_desc->c_vid;
1626 + rx_buffer->skb->dev = net_dev_array[vlan_tag];
1633 +#if defined(CNS3XXX_VLAN_8021Q)
1634 +static int cns3xxx_vlan_rx(CNS3XXXPrivate *priv, struct sk_buff *skb, u16 vlan_tag)
1636 + return vlan_hwaccel_receive_skb(skb, priv->vlgrp, vlan_tag);
1640 +// old_priv has ring index information, current version only uses the information.
1641 +static int cns3xxx_get_rfd_buff(RXBuffer volatile *rx_buffer, CNS3XXXPrivate *old_priv)
1643 + CNS3XXXPrivate *priv=0;
1644 + //RXDesc volatile *rxdesc_ptr = rx_buffer->rx_desc;
1645 + struct sk_buff *skb;
1646 + //unsigned char *data;
1650 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1652 + RXDesc tmp_rx_desc;
1654 + rx_desc = &tmp_rx_desc;
1655 + swap_rx_desc(rx_buffer->rx_desc, rx_desc);
1658 + rx_desc = rx_buffer->rx_desc;
1661 + //rxdesc_ptr = rxring.vir_addr + index;
1662 + skb = rx_buffer->skb;
1663 + len = rx_desc->sdl;
1667 + if (MSG_LEVEL == DUMP_RX_PKT_INFO) {
1668 + print_packet(skb->data, len);
1673 + pci_dma_sync_single_for_device(NULL, virt_to_phys(skb->data), len, PCI_DMA_FROMDEVICE);
1674 +#if defined (CONFIG_CNS3XXX_SPPE)
1675 + if (PACKET_REASON_TO_CPU == rx_buffer->rx_desc->hr) {
1676 + if (sppe_pci_fp_ready) {
1678 + int pci_dev_index;
1679 + struct iphdr *iph;
1681 + skb_put(skb, len);
1682 + iph = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
1684 + memset(¶m, 0, sizeof(SPPE_PARAM));
1685 + param.cmd = SPPE_CMD_ARP;
1686 + param.op = SPPE_OP_GET;
1687 + param.data.sppe_arp.ip[0] = iph->daddr;
1688 + if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) {
1689 + goto NOT_IN_PCI_FP;
1691 + pci_dev_index = param.data.sppe_arp.unused_1;
1693 + param.cmd = SPPE_CMD_PCI_FP_DEV;
1694 + param.op = SPPE_OP_GET;
1695 + param.data.sppe_pci_fp_dev.dev = NULL;
1696 + param.data.sppe_pci_fp_dev.index = pci_dev_index;
1697 + if (SPPE_RESULT_SUCCESS != sppe_pci_fp_hook(¶m)) {
1698 + goto NOT_IN_PCI_FP;
1700 + skb->dev = param.data.sppe_pci_fp_dev.dev;
1703 + dev_queue_xmit(skb);
1705 + skb->dev->hard_start_xmit(skb, skb->dev);
1714 +#ifdef CNS3XXX_NON_NIC_MODE_8021Q
1715 + if (cns3xxx_is_untag_packet(rx_desc) == 1)
1716 + take_off_vlan_header(skb);
1719 +#ifdef CONFIG_CNS3XXX_PORT_BASE
1720 + assign_netdev(rx_buffer);
1722 + if (rx_buffer->skb->dev) // if skb->dev is 0, means VLAN base
1723 + goto determine_dev_ok;
1725 +#endif /* CONFIG_CNS3XXX_PORT_BASE */
1728 +#ifdef CONFIG_CNS3XXX_VLAN_BASE
1730 +#ifdef CONFIG_HAVE_VLAN_TAG
1732 +#if defined(CNS3XXX_VLAN_8021Q)
1733 + // some funcion need netdev like eth_type_trans(), so need to assign it.
1734 + skb->dev = intr_netdev;
1735 + // 8021Q module will determine right netdev by vlan tag.
1736 +#else // defined(CNS3XXX_VLAN_8021Q)
1738 + assign_netdev(rx_buffer);
1740 + take_off_vlan_header(skb);
1741 + if (MSG_LEVEL == 5)
1742 + print_packet(skb->data, 32);
1744 + if ( rx_buffer->skb->dev == 0){
1749 +#endif // CNS3XXX_VLAN_8021Q
1751 +#else /* CONFIG_HAVE_VLAN_TAG */
1753 +#ifdef CNS3XXX_RX_DESC_VLAN_INFO
1754 +// get VLAN information by RX descriptor field
1758 +#endif // CONFIG_HAVE_VLAN_TAG
1760 +#endif // CONFIG_CNS3XXX_VLAN_BASE
1763 +#ifdef CONFIG_CNS3XXX_PORT_BASE
1767 + skb_put(skb, len);
1770 + priv = netdev_priv(skb->dev);
1773 + DEBUG_MSG(WARNING_MSG, "skb_ptr->dev==NULL\n");
1777 +#ifdef CNS3XXX_RX_HW_CHECKSUM
1778 + switch (rx_desc->prot)
1785 + if ( rx_desc->l4f == 0) { // tcp/udp checksum is correct
1786 + skb->ip_summed = CHECKSUM_UNNECESSARY;
1788 + skb->ip_summed = CHECKSUM_NONE;
1794 + skb->ip_summed = CHECKSUM_NONE;
1799 + skb->ip_summed = CHECKSUM_NONE;
1800 +#endif // CNS3XXX_RX_HW_CHECKSUM
1803 + // this line must, if no, packet will not send to network layer
1804 +#ifdef CONFIG_FAST_BRIDGE
1805 + if (fast_bridge_en == 0)
1807 + skb->protocol = eth_type_trans(skb, skb->dev);
1809 + skb->dev->last_rx = jiffies;
1810 + priv->stats.rx_packets++;
1811 + priv->stats.rx_bytes += len;
1813 +#ifdef CONFIG_FAST_BRIDGE
1814 + if (fast_bridge_en == 1) {
1816 + skb->ip_summed = CHECKSUM_NONE;
1817 + if ( skb->dev == PORT0_NETDEV) {
1818 + skb->dev = PORT1_NETDEV;
1819 + } else if ( skb->dev == PORT1_NETDEV) {
1820 + skb->dev = PORT0_NETDEV;
1822 + //skb->dev->hard_start_xmit(skb, skb->dev);
1823 + cns3xxx_send_packet(skb, skb->dev);
1825 +#endif // #ifdef CONFIG_FAST_BRIDGE
1828 +//#if defined(CNS3XXX_VLAN_8021Q)
1830 + if (priv->vlgrp != NULL)
1832 + //cns3xxx_vlan_rx(priv, skb, rx_buffer->rx_desc->c_vid);
1833 + cns3xxx_vlan_rx(priv, skb, rx_buffer->rx_desc->c_vid);
1834 + //cns3xxx_vlan_rx(priv, skb, swab16(le32_to_cpu(rx_buffer->rx_desc->c_vid)) );
1838 + #ifdef CONFIG_CNS3XXX_NAPI
1839 + netif_receive_skb(skb);
1845 +#ifdef CONFIG_FAST_BRIDGE
1849 + //vlan_hwaccel_receive_skb(skb, priv->vlgrp, 1);
1854 + //DEBUG_MSG(NORMAL_MSG, "freepacket\n");
1855 + dev_kfree_skb_any(skb);
1860 +inline u32 get_rx_hw_index(CNS3XXXPrivate *priv)
1862 + return ((FS_DESC_PTR0_REG - get_rx_head_phy_addr(&RX_RING0(priv))) / sizeof(RXDesc) );
1865 +inline int get_rx_hw_index_by_reg(u8 ring_num)
1867 + if (ring_num == 0 ) {
1868 + return ((FS_DESC_PTR0_REG - FS_DESC_BASE_ADDR0_REG) / sizeof(RXDesc) );
1869 + } else if (ring_num == 1 ) {
1870 + return ((FS_DESC_PTR1_REG - FS_DESC_BASE_ADDR1_REG) / sizeof(RXDesc) );
1876 +void dump_rxring(void)
1879 + RXBuffer *rx_buffer = 0;
1881 + rx_buffer = get_rx_ring_head(g_ring_info.rx_ring+0);
1882 + for (j=0 ; j < get_rx_ring_size(g_ring_info.rx_ring+0); ++j, ++rx_buffer) {
1883 + printk("[%d] ## rx_buffer->rx_desc->cown: %d\n", j, rx_buffer->rx_desc->cown);
1887 +#ifdef CONFIG_CNS3XXX_NAPI
1888 +void cns3xxx_receive_packet(CNS3XXXPrivate *priv, int mode, int *work_done, int work_to_do)
1890 +void cns3xxx_receive_packet(CNS3XXXPrivate *priv, int mode)
1894 + //int fssd_current;
1895 + RXBuffer volatile *rx_buffer = 0;
1896 + RXDesc volatile *rx_desc=0;
1897 + struct sk_buff *skb;
1898 +#ifndef CONFIG_CNS3XXX_NAPI
1899 + int fsqf = 0; // Queue Full Mode =0
1901 + int i, rxcount = 0;
1902 + u8 queue_index = priv->ring_index;
1904 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1905 + RXDesc tmp_rx_desc;
1908 + rx_buffer = get_cur_rx_buffer(&(priv->rx_ring[queue_index]));
1910 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1911 + rx_desc = &tmp_rx_desc;
1912 + swap_rx_desc(rx_buffer->rx_desc, rx_desc);
1914 + rx_desc = rx_buffer->rx_desc;
1917 + fssd_index = get_rx_hw_index_by_reg(queue_index);
1919 + if (fssd_index > get_rx_cur_index(&priv->rx_ring[queue_index]) ) {
1920 + rxcount = fssd_index - get_rx_cur_index(&priv->rx_ring[queue_index]);
1921 + } else if (fssd_index < get_rx_cur_index(&priv->rx_ring[queue_index])) {
1922 + rxcount = (get_rx_ring_size(&priv->rx_ring[queue_index]) - get_rx_cur_index(&priv->rx_ring[queue_index]) ) + fssd_index;
1923 + } else { // fssd_index == rxring.cur_index
1924 + if (rx_desc->cown == 0) { // if rx_desc->cown is 1, we can receive the RX descriptor.
1925 + enable_rx_dma(0, 1);
1926 + goto receive_packet_exit;
1929 +#ifndef CONFIG_CNS3XXX_NAPI
1932 + rxcount = get_rx_ring_size(&priv->rx_ring[queue_index]);
1935 +#ifndef CONFIG_CNS3XXX_NAPI
1938 + rxcount = get_rx_ring_size(&priv->rx_ring[queue_index]);
1942 +#ifdef CNS3XXX_FREE_TX_IN_RX_PATH
1943 + free_tx_desc_skb(priv->tx_ring + 0, 0);
1944 +#ifdef CNS3XXX_DOUBLE_TX_RING
1945 + free_tx_desc_skb(priv->tx_ring + 1, 1);
1949 + for (i = 0; i < rxcount; i++) {
1951 + if (rx_desc->cown != 0) { // start to get packet
1952 + // Alloc New skb_buff
1953 + skb = cns3xxx_alloc_skb();
1956 + cns3xxx_get_rfd_buff(rx_buffer, priv);
1957 + rx_buffer->skb = skb;
1959 + rx_desc->sdp = (u32)virt_to_phys(skb->data);
1961 + rx_desc->sdl = MAX_PACKET_LEN;
1964 + rx_desc->cown = 0; // set cbit to 0
1965 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1966 + swap_rx_desc(rx_desc, rx_buffer->rx_desc);
1969 +#ifdef CONFIG_CNS3XXX_NAPI
1971 + if (*work_done >= work_to_do) {
1973 + rx_index_next(&priv->rx_ring[queue_index]); // rx_ring.cur_index points to next
1974 + rx_buffer = get_cur_rx_buffer(&priv->rx_ring[queue_index]);
1975 + rx_desc = rx_buffer->rx_desc;
1981 + // I will add dev->lp.stats->rx_dropped, it will effect the performance
1982 + //PDEBUG("%s: Alloc sk_buff fail, reuse the buffer\n", __FUNCTION__);
1983 + rx_desc->cown = 0; // set cbit to 0
1984 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
1985 + swap_rx_desc(rx_desc, rx_buffer->rx_desc);
1990 + } else { // cown is 0, no packets
1996 + rx_index_next(&priv->rx_ring[queue_index]); // rx_ring.cur_index points to next
1997 + rx_buffer = get_cur_rx_buffer(&priv->rx_ring[queue_index]);
1998 + rx_desc = rx_buffer->rx_desc;
2000 + } // end for (i = 0; i < rxcount; i++)
2003 +#ifndef CONFIG_CNS3XXX_NAPI
2005 + priv->rx_ring[queue_index].cur_index = fssd_index;
2007 + enable_rx_dma(0, 1);
2012 + //spin_unlock(&rx_lock);
2013 +receive_packet_exit:
2017 +irqreturn_t cns3xxx_fsrc_ring0_isr(int irq, void *dev_id)
2019 + struct net_device *netdev = dev_id;
2020 + CNS3XXXPrivate *priv = netdev_priv(netdev);
2022 + priv->ring_index=0;
2024 +#ifdef CONFIG_CNS3XXX_NAPI
2026 + CNS3XXXPrivate *priv = netdev_priv(napi_dev);
2027 + priv->ring_index=0;
2029 +#ifdef CNS3XXX_USE_MASK
2030 + cns3xxx_write_pri_mask(0xb0);
2032 + cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID);
2035 + //if (likely(netif_rx_schedule_prep(napi_dev, &priv->napi))) {
2036 + if (likely(napi_schedule_prep(&priv->napi))) {
2037 + //__netif_rx_schedule(napi_dev, &priv->napi);
2038 + __napi_schedule(&priv->napi);
2040 +#ifdef CNS3XXX_USE_MASK
2041 + cns3xxx_write_pri_mask(0xf0);
2043 + cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
2047 +#else // !CONFIG_CNS3XXX_NAPI
2049 +#ifdef CNS3XXX_USE_MASK
2050 + cns3xxx_write_pri_mask(0xb0);
2052 + cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID);
2053 + cns3xxx_disable_irq(FSQF_RING0_INTERRUPT_ID);
2056 + cns3xxx_receive_packet(priv, 0); // Receive Once
2058 +#ifdef CNS3XXX_USE_MASK
2059 + cns3xxx_write_pri_mask(0xf0);
2061 + cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
2062 + cns3xxx_enable_irq(FSQF_RING0_INTERRUPT_ID);
2064 + enable_rx_dma(0, 1);
2067 + return IRQ_HANDLED;
2071 +#if defined(CNS3XXX_DOUBLE_RX_RING)
2072 +irqreturn_t cns3xxx_fsrc_ring1_isr(int irq, void *dev_id)
2074 + struct net_device *netdev = dev_id;
2075 + CNS3XXXPrivate *priv = netdev_priv(netdev);
2076 + priv->ring_index=1;
2079 +#if defined(CONFIG_CNS3XXX_NAPI) && defined(CNS3XXX_DOUBLE_RX_RING)
2081 + CNS3XXXPrivate *priv = netdev_priv(r1_napi_dev);
2082 + priv->ring_index=1;
2084 + cns3xxx_disable_irq(FSRC_RING1_INTERRUPT_ID);
2086 + if (likely(napi_schedule_prep(&priv->napi))) {
2087 + __napi_schedule(&priv->napi);
2089 + cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID);
2094 + cns3xxx_disable_irq(CNS3XXX_FSRC_RING1_INTERRUPT_ID);
2095 + cns3xxx_disable_irq(CNS3XXX_FSQF_RING1_INTERRUPT_ID);
2096 + cns3xxx_receive_packet(priv, 0); // Receive Once
2097 + enable_rx_dma(1, 1);
2099 + cns3xxx_enable_irq(CNS3XXX_FSRC_RING1_INTERRUPT_ID);
2100 + cns3xxx_enable_irq(CNS3XXX_FSQF_RING1_INTERRUPT_ID);
2103 + return IRQ_HANDLED;
2107 +int cns3xxx_check_enough_tx_descriptor(TXRing *tx_ring, int need_free_tx_desc)
2111 + TXDesc *tx_desc=0;
2112 + u32 cur_index = get_tx_cur_index(tx_ring);
2113 + TXBuffer *tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index);
2115 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
2116 + TXDesc tmp_tx_desc;
2117 + tx_desc = &tmp_tx_desc;
2118 + swap_tx_desc(tx_buffer->tx_desc, tx_desc);
2120 + tx_desc = tx_buffer->tx_desc;
2124 + for (i=0 ; i < need_free_tx_desc ; ++i) {
2125 + if ( tx_desc->cown == 0 ) {
2126 + return 0; // no free TX descriptor
2128 + tx_buffer = get_tx_buffer_by_index(tx_ring, ++cur_index);
2134 +// if return CAVM_ERR, means pad is fail, the packet cannot send by switch.
2136 +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)
2138 + //TXDesc *tx_desc_ptr = tx_buffer->tx_desc;
2141 + TXDesc *tx_desc_ptr = 0;
2142 +#ifdef CONFIG_SWTICH_BIG_ENDIAN
2143 + TXDesc tmp_tx_desc;
2144 + tx_desc_ptr = &tmp_tx_desc;
2145 + swap_tx_desc(tx_buffer->tx_desc, tx_desc_ptr);
2147 + tx_desc_ptr = tx_buffer->tx_desc;
2152 + if (tx_buffer->skb) {
2153 + dev_kfree_skb_any(tx_buffer->skb);
2154 + tx_buffer->skb = 0 ;
2156 + //++tx_ring.non_free_tx_skb;
2159 + tx_buffer->skb = skb; /* for free skb */
2160 + tx_desc_ptr->sdp = virt_to_phys(data);
2161 + tx_buffer->j = tt;
2162 + tx_buffer->tx_index = cns3xxx_get_tx_hw_index(0);
2167 + static u16 previous_sn_num=10;
2171 + memcpy(&e_type, skb->data + 12, 2);
2172 + e_type = be16_to_cpu(e_type);
2174 + if (e_type == 0x0800) {
2175 + memcpy(&sn_num, skb->data + 0x28, 2);
2176 + sn_num = be16_to_cpu(sn_num);
2178 + if ( previous_sn_num == sn_num)
2181 + previous_sn_num = sn_num;
2188 +#ifdef CNS3XXX_TX_HW_CHECKSUM
2189 + tx_desc_ptr->ico = 1;
2190 + tx_desc_ptr->uco = 1;
2191 + tx_desc_ptr->tco = 1;
2193 + tx_desc_ptr->ico = 0;
2194 + tx_desc_ptr->uco = 0;
2195 + tx_desc_ptr->tco = 0;
2198 +#ifdef CNS3XXX_TSTC_RING0_ISR
2199 + tx_desc_ptr->interrupt = 1;
2201 + tx_desc_ptr->interrupt = 0;
2204 + /* fill 0 to MIN_PACKET_LEN size */
2205 + // can change MIN_PACKET_LEN to 14
2206 + if (sg==0 && len < MIN_PACKET_LEN) {
2207 + if (skb_padto(skb, MIN_PACKET_LEN))
2210 + //memset(skb->data + len, 0, MIN_PACKET_LEN - len);
2211 + //skb->len = MIN_PACKET_LEN;
2212 + tx_desc_ptr->sdl = MIN_PACKET_LEN;
2214 + tx_desc_ptr->sdl = len;
2217 + dma_cache_maint(data, tx_desc_ptr->sdl, PCI_DMA_TODEVICE);
2219 + /* VLAN base or port base function to set TX descriptor */
2220 + /* reference: tx_//port_base(), tx_vlan_base() */
2221 + priv->net_device_priv->tx_func(tx_desc_ptr, priv, skb);
2222 + tx_desc_ptr->fsd = fsd;
2223 + tx_desc_ptr->lsd = lsd;
2225 + /* NOT SG packet */
2226 + if( fsd == 1 && lsd == 1)
2227 + tx_desc_ptr->cown = 0;
2229 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
2230 + swap_tx_desc(tx_desc_ptr, tx_buffer->tx_desc);
2236 +int cns3xxx_send_packet(struct sk_buff *skb, struct net_device *netdev)
2239 + CNS3XXXPrivate *priv = netdev_priv(netdev);
2240 + TXBuffer *tx_buffer = 0;
2241 + unsigned long flags;
2242 + int nr_frags =skb_shinfo(skb)->nr_frags;
2244 + TXDesc *tx_desc[10]; // FIXME: ensure to maximum sg size
2245 + int tx_desc_count=0;
2249 + if (MSG_LEVEL == DUMP_TX_PKT_INFO) {
2250 + print_packet(tx_buffer->skb->data, tx_buffer->tx_desc->sdl);
2251 + //dump_tx_desc(tx_buffer->tx_desc);
2255 + spin_lock_irqsave(&tx_lock, flags);
2257 + if (cns3xxx_check_enough_tx_descriptor(priv->tx_ring + ring_index, (nr_frags==0 ) ? 1 : nr_frags) == 0) {
2258 + // no enough tx descriptor
2259 + spin_unlock_irqrestore(&tx_lock, flags);
2260 + // re-queue the skb
2261 + return NETDEV_TX_BUSY;
2264 + tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2266 + if (nr_frags == 0) { // non scatter/gather I/O
2268 + fill_a_skb_to_tx_desc(tx_buffer, skb->data, skb->len, skb, priv, 0, 1, 1);
2270 + tx_index_next(priv->tx_ring + ring_index);
2272 + } else { // scatter/gather I/O
2273 + struct skb_frag_struct *frag = 0;
2276 + fill_a_skb_to_tx_desc(tx_buffer, skb->data, skb->len - skb->data_len, 0, priv, 1, 1, 0);
2277 + tx_desc[tx_desc_count++] = tx_buffer->tx_desc;
2278 + tx_index_next(priv->tx_ring + ring_index);
2279 + tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2281 + for (i=0 ; i < nr_frags-1 ; ++i) {
2282 + frag = &skb_shinfo(skb)->frags[i];
2284 + fill_a_skb_to_tx_desc(tx_buffer, page_address(frag->page) + frag->page_offset, frag->size, 0, priv, 1, 0, 0);
2285 + tx_desc[tx_desc_count++] = tx_buffer->tx_desc;
2287 + tx_index_next(priv->tx_ring + ring_index);
2288 + tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2290 + frag = &skb_shinfo(skb)->frags[nr_frags-1];
2293 + fill_a_skb_to_tx_desc(tx_buffer, page_address(frag->page) + frag->page_offset, frag->size, skb, priv, 1, 0, 1);
2294 + tx_desc[tx_desc_count++] = tx_buffer->tx_desc;
2296 + tx_index_next(priv->tx_ring + ring_index);
2297 + tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2301 + if( nr_frags != 0) {
2303 + for (i = 0; i < tx_desc_count ; i++ )
2304 + tx_desc[i]->cown = 0 ;
2308 + enable_tx_dma(ring_index, 1);
2310 + priv->stats.tx_packets++;
2311 + priv->stats.tx_bytes += skb->len;
2312 + netdev->trans_start = jiffies;
2314 + spin_unlock_irqrestore(&tx_lock, flags);
2315 + return NETDEV_TX_OK;
2319 +#ifdef CNS3XXX_FSQF_RING0_ISR
2320 +irqreturn_t cns3xxx_fsqf_ring0_isr(int irq, void *dev_id)
2322 +#ifndef CONFIG_CNS3XXX_NAPI
2323 + struct net_device *netdev = dev_id;
2324 + CNS3XXXPrivate *priv = netdev_priv(netdev);
2327 +#ifdef CONFIG_CNS3XXX_NAPI
2329 + CNS3XXXPrivate *priv = netdev_priv(napi_dev);
2330 + // because in normal state, fsql only invoke once and set_bit is atomic function.
2331 + // so I don't mask it.
2332 + set_bit(0, &priv->is_qf);
2335 +#ifdef CNS3XXX_USE_MASK
2336 + cns3xxx_write_pri_mask(0xb0);
2338 + cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID);
2339 + cns3xxx_disable_irq(FSQF_RING0_INTERRUPT_ID);
2343 + cns3xxx_receive_packet(priv, 1); // Receive at Queue Full Mode
2345 +#ifdef CNS3XXX_USE_MASK
2346 + cns3xxx_write_pri_mask(0xf0);
2348 + cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
2349 + cns3xxx_enable_irq(FSQF_RING0_INTERRUPT_ID);
2352 + enable_rx_dma(0, 1);
2353 +#endif // CONFIG_CNS3XXX_NAPI
2355 + return IRQ_HANDLED;
2360 +#if defined(CNS3XXX_DOUBLE_RX_RING)
2361 +#ifdef CNS3XXX_FSQF_RING1_ISR
2362 +irqreturn_t cns3xxx_fsqf_ring1_isr(int irq, void *dev_id)
2364 + struct net_device *netdev = dev_id;
2365 + CNS3XXXPrivate *priv = netdev_priv(netdev);
2366 + //INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSQF_BIT_INDEX);
2368 +#ifdef CONFIG_CNS3XXX_NAPI
2370 + CNS3XXXPrivate *priv = netdev_priv(r1_napi_dev);
2371 + // because in normal state, fsqf only invoke once and set_bit is atomic function.
2372 + // so don't mask it.
2373 + set_bit(0, &priv->is_qf);
2376 + cns3xxx_disable_irq(FSRC_RING1_INTERRUPT_ID);
2377 + cns3xxx_disable_irq(FSQF_RING1_INTERRUPT_ID);
2379 + cns3xxx_receive_packet(priv, 1); // Receive at Queue Full Mode
2380 + enable_rx_dma(1, 1);
2382 + cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID);
2383 + cns3xxx_enable_irq(FSQF_RING1_INTERRUPT_ID);
2385 + return IRQ_HANDLED;
2388 +#endif //#if defined(CNS3XXX_DOUBLE_RX_RING)
2391 +#ifdef CNS3XXX_STATUS_ISR
2392 +irqreturn_t cns3xxx_status_isr(int irq, void *dev_id)
2394 + u32 int_status = INTR_STAT_REG;
2397 + cns3xxx_disable_irq(STATUS_INTERRUPT_ID);
2398 + for (i = 0; i < 32; i++) {
2399 + if (int_status & (1 << i)) {
2400 + PRINT_INFO(cns3xxx_gsw_status_tbl[i]);
2403 + INTR_STAT_REG = 0xffffffff; // write 1 for clear.
2404 + cns3xxx_enable_irq(STATUS_INTERRUPT_ID);
2405 + return IRQ_HANDLED;
2410 +#ifdef CNS3XXX_TSTC_RING0_ISR
2411 +irqreturn_t cns3xxx_tstc_ring0_isr(int irq, void *dev_id)
2413 + return IRQ_HANDLED;
2418 +static int cns3xxx_install_isr(struct net_device *dev)
2421 + CNS3XXXPrivate *priv = netdev_priv(dev);
2423 + if (install_isr_rc == 0) {
2425 + retval = request_irq(FSRC_RING0_INTERRUPT_ID, cns3xxx_fsrc_ring0_isr, IRQF_SHARED, "FSRC_RING0", intr_netdev);
2431 +#ifdef CNS3XXX_FSQF_RING0_ISR
2432 + retval = request_irq(FSQF_RING0_INTERRUPT_ID, cns3xxx_fsqf_ring0_isr, IRQF_SHARED, "FSQF_RING0", intr_netdev);
2435 + PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "FSQF_RING0", FSQF_RING0_INTERRUPT_ID, retval);
2440 +#ifdef CNS3XXX_TSTC_RING0_ISR
2441 + retval = request_irq(TSTC_RING0_INTERRUPT_ID, cns3xxx_tstc_ring0_isr, IRQF_SHARED, "TSTC_RING0", intr_netdev);
2444 + PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "TSTC_RING0", FSQF_RING0_INTERRUPT_ID, retval);
2451 + if (priv->num_rx_queues == 2) {
2452 +#if defined(CNS3XXX_DOUBLE_RX_RING)
2453 + retval = request_irq(FSRC_RING1_INTERRUPT_ID, cns3xxx_fsrc_ring1_isr, IRQF_SHARED, "FSRC_RING1", intr_netdev);
2459 +#ifdef CNS3XXX_FSQF_RING1_ISR
2460 + retval = request_irq(FSQF_RING1_INTERRUPT_ID, cns3xxx_fsqf_ring1_isr, IRQF_SHARED, "FSQF_RING1", intr_netdev);
2463 + PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "FSQF_RING1", FSQF_RING1_INTERRUPT_ID, retval);
2471 +#ifdef CNS3XXX_STATUS_ISR
2472 + retval = request_irq(STATUS_INTERRUPT_ID, cns3xxx_status_isr, IRQF_SHARED, "GSW_STATUS", intr_netdev);
2475 + PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "GSW STATUS INT", STATUS_INTERRUPT_ID, retval);
2478 + INTR_MASK_REG = 0;
2486 +#ifdef CONFIG_CNS3XXX_NAPI
2488 + CNS3XXXPrivate *sp = netdev_priv(napi_dev);
2489 + napi_enable(&sp->napi);
2490 + netif_start_queue(napi_dev);
2492 +#ifdef CNS3XXX_DOUBLE_RX_RING
2493 + sp = netdev_priv(r1_napi_dev);
2494 + napi_enable(&sp->napi);
2495 + netif_start_queue(r1_napi_dev);
2499 + // enable cpu port
2500 + enable_port(3, 1);
2502 + } // end if (install_isr_rc == 0)
2510 +int cns3xxx_open(struct net_device *dev)
2512 + CNS3XXXPrivate *priv = netdev_priv(dev);
2513 + //static int init_state=0;
2515 + if (cns3xxx_setup_rx_tx_res(priv) != CAVM_OK) {
2519 + netif_start_queue(dev);
2520 + priv->net_device_priv->open();
2522 + cns3xxx_install_isr(dev);
2524 + enable_rx_dma(0, 1);
2526 + if (priv->num_rx_queues == 2)
2527 + enable_rx_dma(1, 1);
2529 + netif_carrier_on(dev);
2534 +static int cns3xxx_uninstall_isr(struct net_device *dev)
2536 + CNS3XXXPrivate *priv = netdev_priv(dev);
2538 + if (install_isr_rc == 0) {
2539 + enable_port(3, 0);
2540 + free_irq(FSRC_RING0_INTERRUPT_ID, intr_netdev);
2541 +#ifdef CNS3XXX_STATUS_ISR
2542 + free_irq(STATUS_INTERRUPT_ID, intr_netdev);
2545 +#ifdef CNS3XXX_FSQF_RING0_ISR
2546 + free_irq(FSQF_RING0_INTERRUPT_ID, intr_netdev);
2549 +#ifdef CNS3XXX_TSTC_RING0_ISR
2550 + free_irq(TSTC_RING0_INTERRUPT_ID, intr_netdev);
2553 + if (priv->num_rx_queues == 2) {
2554 + free_irq(FSRC_RING1_INTERRUPT_ID, intr_netdev);
2556 +#ifdef CNS3XXX_FSQF_RING1_ISR
2557 + free_irq(FSQF_RING1_INTERRUPT_ID, intr_netdev);
2563 +#ifdef CONFIG_CNS3XXX_NAPI
2565 + CNS3XXXPrivate *sp = netdev_priv(napi_dev);
2567 + napi_disable(&sp->napi);
2568 + netif_stop_queue(napi_dev);
2569 +#ifdef CNS3XXX_DOUBLE_RX_RING
2570 + sp = netdev_priv(r1_napi_dev);
2572 + napi_disable(&sp->napi);
2573 + netif_stop_queue(r1_napi_dev);
2584 +int cns3xxx_close(struct net_device *dev)
2586 + CNS3XXXPrivate *priv = netdev_priv(dev);
2588 + enable_rx_dma(0, 0);
2589 + enable_tx_dma(0, 0);
2591 + if (priv->num_rx_queues == 2)
2592 + enable_tx_dma(1, 0);
2594 + if (priv->num_tx_queues == 2)
2595 + enable_rx_dma(1, 0);
2597 + netif_stop_queue(dev);
2599 + priv->net_device_priv->close();
2600 + cns3xxx_uninstall_isr(dev);
2601 + cns3xxx_free_rx_tx_res(priv);
2602 + netif_carrier_off(dev);
2608 +//#define MAC_PORT(p) MAC##p##_CFG_REG
2610 +void broadcast_storm_cfg(u8 port, u8 boradcast, u8 multicast, u8 unknown)
2616 + (boradcast == 1) ? (MAC0_CFG_REG |= (1 << 30)) : (MAC0_CFG_REG &= (~(1 << 30))) ;
2617 + (multicast == 1) ? (MAC0_CFG_REG |= (1 << 29)) : (MAC0_CFG_REG &= (~(1 << 29))) ;
2618 + (unknown == 1) ? (MAC0_CFG_REG |= (1 << 28)) : (MAC0_CFG_REG &= (~(1 << 28))) ;
2623 + (boradcast == 1) ? (MAC1_CFG_REG |= (1 << 30)) : (MAC1_CFG_REG &= (~(1 << 30))) ;
2624 + (multicast == 1) ? (MAC1_CFG_REG |= (1 << 29)) : (MAC1_CFG_REG &= (~(1 << 29))) ;
2625 + (unknown == 1) ? (MAC1_CFG_REG |= (1 << 28)) : (MAC1_CFG_REG &= (~(1 << 28))) ;
2630 + (boradcast == 1) ? (MAC2_CFG_REG |= (1 << 30)) : (MAC2_CFG_REG &= (~(1 << 30))) ;
2631 + (multicast == 1) ? (MAC2_CFG_REG |= (1 << 29)) : (MAC2_CFG_REG &= (~(1 << 29))) ;
2632 + (unknown == 1) ? (MAC2_CFG_REG |= (1 << 28)) : (MAC2_CFG_REG &= (~(1 << 28))) ;
2638 +void broadcast_storm_rate(u8 rate)
2640 + TC_CTRL_REG &= (~(0xf << 24));
2641 + TC_CTRL_REG |= (rate << 24);
2644 +// port: 0, 1, 2 ; port0, port1 and port2
2645 +// config general mac port configuration
2646 +void cns3xxx_general_mac_cfg(u8 port)
2654 + cfg = MAC0_CFG_REG;
2659 + cfg = MAC1_CFG_REG;
2664 + cfg = MAC2_CFG_REG;
2670 + // txc_check_en: 1
2676 +#ifdef CNS3XXX_LEARN_ENABLE
2678 + cfg &= (~(1 << 19));
2684 + // blocking_state: 0
2685 + cfg &= (~(1 << 20));
2688 + cfg &= (~(1 << 21));
2690 +#ifdef CNS3XXX_AGE_ENABLE
2696 + cfg &= (~(1 << 22));
2700 + cfg &= (~(1 << 23));
2706 + MAC0_CFG_REG = cfg;
2711 + MAC1_CFG_REG = cfg;
2716 + MAC2_CFG_REG = cfg;
2723 +void cns3xxx_configu_cpu_port(void)
2725 + // Set CPU port to general configuration
2727 +#ifdef CNS3XXX_LEARN_ENABLE
2728 + CPU_CFG_REG &= (~(1 << 19));
2731 + CPU_CFG_REG |= (1 << 19);
2734 +#ifdef CNS3XXX_AGE_ENABLE
2736 + CPU_CFG_REG |= (1 << 22);
2739 + CPU_CFG_REG &= (~(1 << 22));
2743 + CPU_CFG_REG &= (~(1 << 23));
2746 + CPU_CFG_REG |= (1 << 29);
2749 + CPU_CFG_REG &= (~(1 << 30));
2751 + CPU_CFG_REG |= (1 << 30);
2754 + // cpu flow control disable
2755 + CPU_CFG_REG &= (~(1 << 31));
2756 +#ifdef CNS3XXX_CPU_PORT_FC
2757 + // cpu flow control enable
2758 + CPU_CFG_REG |= (1 << 31);
2763 +static void __init cns3xxx_gsw_hw_init(void)
2765 + //u32 mac_port_config;
2767 + //u32 cfg_reg = 0;
2768 + u32 reg_config = 0;
2770 +#ifdef CONFIG_SILICON
2772 + //GPIOB_PIN_EN_REG |= (1 << 14); //enable GMII2_CRS
2773 + //GPIOB_PIN_EN_REG |= (1 << 15); //enable GMII2_COL
2774 + GPIOB_PIN_EN_REG |= (1 << 20); //enable MDC
2775 + GPIOB_PIN_EN_REG |= (1 << 21); //enable MDIO
2777 + cns3xxx_gsw_power_enable();
2778 + cns3xxx_gsw_software_reset();
2781 +#ifdef CNS3XXX_CONFIG_SIM_MODE
2782 + SLK_SKEW_CTRL_REG |= (1 << 31);
2787 + while (((SRAM_TEST_REG >> 20) & 1) == 0);
2790 + clear_fs_dma_state(1);
2793 + // disable port mac0, mac1, mac2, cpu port
2794 + enable_port(0, 0);
2795 + enable_port(1, 0);
2796 + enable_port(2, 0);
2797 + enable_port(3, 0);
2799 + // disable RX0/TX0 RX1/TX1 DMA
2800 + enable_tx_dma(0, 0);
2801 + enable_tx_dma(1, 0);
2802 + enable_rx_dma(0, 0);
2803 + enable_rx_dma(1, 0);
2805 + INTR_STAT_REG = 0xffffffff; // write 1 for clear.
2807 +#ifdef CNS3XXX_DELAYED_INTERRUPT
2808 + DELAY_INTR_CFG_REG = (1 << 16) | (max_pend_int_cnt << 8) | (max_pend_time);
2811 + reg_config = PHY_AUTO_ADDR_REG;
2812 + reg_config &= ~(3 << 30);
2813 +#ifdef CONFIG_CNS3XXX_JUMBO_FRAME
2814 + reg_config |= (3 << 30); // maximum frame length: 9600 bytes
2816 + reg_config |= (2 << 30); // maximum frame length: 1536 bytes
2819 + PHY_AUTO_ADDR_REG = reg_config;
2822 + // Set general value for MAC_GLOB_CFG_REG
2823 + // age_time: 2 ^(1-1) * 300 sec
2824 + MAC_GLOB_CFG_REG &= (~0xf);
2825 + MAC_GLOB_CFG_REG |= 1;
2828 + // bkoff_mode: 111 follow standard
2829 + MAC_GLOB_CFG_REG &= (~(0x7 << 9));
2830 + MAC_GLOB_CFG_REG |= (0x7 << 9);
2833 + MAC_GLOB_CFG_REG &= (~(0xf << 12));
2834 + MAC_GLOB_CFG_REG |= (0xa << 12);
2837 + MAC_GLOB_CFG_REG &= (~(0x3 << 16));
2838 + MAC_GLOB_CFG_REG |= (0x2 << 16);
2841 + MAC_GLOB_CFG_REG &= (~(0x1 << 28));
2844 + MAC_GLOB_CFG_REG &= (~(0x3 << 18));
2845 + MAC_GLOB_CFG_REG |= (0x3 << 18);
2847 + // crc_stripping: 1
2848 + MAC_GLOB_CFG_REG |= (0x1 << 20);
2851 + // ACCEPT_CRC_BAD_PKT : 0
2852 + MAC_GLOB_CFG_REG &= (~(0x1 << 21));
2854 +#ifdef ACCEPT_CRC_BAD_PKT
2855 + MAC_GLOB_CFG_REG |= (0x1 << 21);
2859 + MAC_GLOB_CFG_REG &= (~(0x1 << 7));
2862 + // IVL: 1 (IVL), 0 (SVL)
2863 + MAC_GLOB_CFG_REG |= (0x1 << 7);
2868 + MAC_GLOB_CFG_REG &= (~(0x1 << 26));
2870 + // Firewall_mode: 0
2871 + MAC_GLOB_CFG_REG &= (~(0x1 << 27));
2875 + cns3xxx_general_mac_cfg(0);
2876 + cns3xxx_general_mac_cfg(1);
2877 + cns3xxx_general_mac_cfg(2);
2878 + cns3xxx_configu_cpu_port();
2880 + // write vlan table
2881 + // set cpu port vlan table
2882 + cns3xxx_vlan_table_add(&cpu_vlan_table_entry);
2883 + for (i=0 ; i < sizeof(vlan_table_entry)/sizeof(VLANTableEntry) ; ++i)
2884 + cns3xxx_vlan_table_add(&vlan_table_entry[i]);
2886 + cns3xxx_set_pvid(0, PORT0_PVID);
2887 + cns3xxx_set_pvid(1, PORT1_PVID);
2888 + cns3xxx_set_pvid(2, PORT2_PVID);
2889 + cns3xxx_set_pvid(3, CPU_PVID);
2891 +#ifdef CNS3XXX_SET_ARL_TABLE
2893 + cns3xxx_arl_table_flush();
2897 +static int cns3xxx_set_mac_addr(struct net_device *dev, void *p)
2899 + //struct sockaddr *sock_addr = addr;
2900 + CNS3XXXPrivate *priv = netdev_priv(dev);
2902 + struct sockaddr *addr= p;
2905 + spin_lock_irq(&priv->lock);
2908 + if (!is_valid_ether_addr(addr->sa_data))
2909 + return -EADDRNOTAVAIL;
2911 + // 1. delete old arl mac entry
2912 + // 2. add new arl mac entry
2913 + // 3. copy new mac to netdev field
2915 + if (priv->net_device_priv->arl_table_entry) {
2916 + cns3xxx_arl_table_invalid(priv->net_device_priv->arl_table_entry);
2917 + memcpy(priv->net_device_priv->arl_table_entry->mac, addr->sa_data, dev->addr_len);
2918 + //print_arl_table_entry(priv->net_device_priv->arl_table_entry);
2919 + cns3xxx_arl_table_add(priv->net_device_priv->arl_table_entry);
2921 + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
2923 + spin_unlock_irq(&priv->lock);
2928 +int set_fc_rls(struct ifreq *ifr)
2930 + CNS3XXXSARLEntry ctl;
2932 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2934 + FC_GLOB_THRS_REG &= (~(0x1ff << 16));
2935 + FC_GLOB_THRS_REG |= (ctl.val << 16);
2939 +int get_fc_rls(struct ifreq *ifr)
2941 + CNS3XXXSARLEntry ctl;
2943 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2946 + ctl.val = ((FC_GLOB_THRS_REG >> 16) & 0x1ff);
2948 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
2953 +int set_fc_set(struct ifreq *ifr)
2955 + CNS3XXXSARLEntry ctl;
2957 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2959 + FC_GLOB_THRS_REG &= (~0x1ff);
2960 + FC_GLOB_THRS_REG |= ctl.val;
2964 +int get_fc_set(struct ifreq *ifr)
2966 + CNS3XXXSARLEntry ctl;
2968 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2971 + ctl.val = ((FC_GLOB_THRS_REG) & 0x1ff);
2973 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
2979 +int set_sarl_rls(struct ifreq *ifr)
2981 + CNS3XXXSARLEntry ctl;
2983 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2985 + SARL_CTRL_REG &= (~(0x1ff << 12));
2986 + SARL_CTRL_REG |= (ctl.val << 12);
2990 +int get_sarl_rls(struct ifreq *ifr)
2992 + CNS3XXXSARLEntry ctl;
2994 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2997 + ctl.val = ((SARL_CTRL_REG >> 12) & 0x1ff);
2999 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3004 +int set_sarl_enable(struct ifreq *ifr)
3006 + CNS3XXXSARLEntry ctl;
3008 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3010 + SARL_CTRL_REG &= (~(0x1 << 31));
3011 + SARL_CTRL_REG |= (ctl.val << 31);
3015 +int get_sarl_enable(struct ifreq *ifr)
3017 + CNS3XXXSARLEntry ctl;
3019 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3021 + ctl.val = ((SARL_CTRL_REG >> 31 ) & 0x1);
3022 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3026 +int set_sarl_set(struct ifreq *ifr)
3028 + CNS3XXXSARLEntry ctl;
3030 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3032 + SARL_CTRL_REG &= (~0x1ff);
3033 + SARL_CTRL_REG |= ctl.val;
3037 +int get_sarl_set(struct ifreq *ifr)
3039 + CNS3XXXSARLEntry ctl;
3041 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3044 + ctl.val = ((SARL_CTRL_REG) & 0x1ff);
3046 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3051 +int set_sarl_oq(struct ifreq *ifr)
3053 + CNS3XXXSARLEntry ctl;
3054 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3061 + SARL_OQ_GTH_REG &= (~(0xff << ctl.tc*8));
3062 + SARL_OQ_GTH_REG |= (ctl.val << ctl.tc*8);
3067 + SARL_OQ_YTH_REG &= (~(0xff << ctl.tc*8));
3068 + SARL_OQ_YTH_REG |= (ctl.val << ctl.tc*8);
3073 + SARL_OQ_RTH_REG &= (~(0xff << ctl.tc*8));
3074 + SARL_OQ_RTH_REG |= (ctl.val << ctl.tc*8);
3081 +int get_sarl_oq(struct ifreq *ifr)
3083 + CNS3XXXSARLEntry ctl;
3085 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3092 + ctl.val = ((SARL_OQ_GTH_REG >> ctl.tc*8) & 0xff);
3097 + ctl.val = ((SARL_OQ_YTH_REG >> ctl.tc*8) & 0xff);
3102 + ctl.val = ((SARL_OQ_RTH_REG >> ctl.tc*8) & 0xff);
3107 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3112 +int set_queue_weight(struct ifreq *ifr)
3114 + CNS3XXXQueueWeightEntry ctl;
3116 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQueueWeightEntry)) )
3118 + switch (ctl.which_port)
3122 + QUEUE_WEIGHT_SET(0, ctl)
3127 + QUEUE_WEIGHT_SET(1, ctl)
3132 + QUEUE_WEIGHT_SET(2, ctl)
3135 + case 3: // cpu port
3137 + CPU_PRI_CTRL_REG &= ~(0x3ffff);
3138 + CPU_PRI_CTRL_REG |= (ctl.sch_mode << 16);
3139 + CPU_PRI_CTRL_REG |= (ctl.q0_w);
3140 + CPU_PRI_CTRL_REG |= (ctl.q1_w << 4);
3141 + CPU_PRI_CTRL_REG |= (ctl.q2_w << 8);
3142 + CPU_PRI_CTRL_REG |= (ctl.q3_w << 12);
3145 + case 4: // PPE port
3147 + HNAT_PRI_CTRL_REG &= ~(0x3ffff);
3148 + HNAT_PRI_CTRL_REG |= (ctl.sch_mode << 16);
3149 + HNAT_PRI_CTRL_REG |= (ctl.q0_w);
3150 + HNAT_PRI_CTRL_REG |= (ctl.q1_w << 4);
3151 + HNAT_PRI_CTRL_REG |= (ctl.q2_w << 8);
3152 + HNAT_PRI_CTRL_REG |= (ctl.q3_w << 12);
3162 +int get_queue_weight(struct ifreq *ifr)
3164 + CNS3XXXQueueWeightEntry ctl;
3166 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQueueWeightEntry)) )
3169 + switch (ctl.which_port)
3173 + QUEUE_WEIGHT_GET(0, ctl)
3178 + QUEUE_WEIGHT_GET(1, ctl)
3183 + QUEUE_WEIGHT_GET(2, ctl)
3188 + ctl.sch_mode = ((CPU_PRI_CTRL_REG >> 16 ) & 0x3);
3189 + ctl.q0_w = ((CPU_PRI_CTRL_REG >> 0 ) & 0x7);
3190 + ctl.q1_w = ((CPU_PRI_CTRL_REG >> 4 ) & 0x7);
3191 + ctl.q2_w = ((CPU_PRI_CTRL_REG >> 8 ) & 0x7);
3192 + ctl.q3_w = ((CPU_PRI_CTRL_REG >> 12 ) & 0x7);
3197 + ctl.sch_mode = ((HNAT_PRI_CTRL_REG >> 16 ) & 0x3);
3198 + ctl.q0_w = ((HNAT_PRI_CTRL_REG >> 0 ) & 0x7);
3199 + ctl.q1_w = ((HNAT_PRI_CTRL_REG >> 4 ) & 0x7);
3200 + ctl.q2_w = ((HNAT_PRI_CTRL_REG >> 8 ) & 0x7);
3201 + ctl.q3_w = ((HNAT_PRI_CTRL_REG >> 12 ) & 0x7);
3206 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXQueueWeightEntry)) )
3212 +int set_rate_limit(struct ifreq *ifr)
3214 + CNS3XXXRateLimitEntry ctl;
3216 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXRateLimitEntry)) )
3218 + switch (ctl.which_port)
3222 + RATE_CTRL_REG &= (~(0x7f << 8));
3223 + RATE_CTRL_REG |= ( ctl.band_width << 8);
3224 + RATE_CTRL_REG &= (~(0x3));
3225 + RATE_CTRL_REG |= ctl.base_rate;
3230 + RATE_CTRL_REG &= (~(0x7f << 16));
3231 + RATE_CTRL_REG |= ( ctl.band_width << 16);
3232 + RATE_CTRL_REG &= (~(0x3 << 2));
3233 + RATE_CTRL_REG |= (ctl.base_rate << 2);
3238 + RATE_CTRL_REG &= (~(0x7f << 24));
3239 + RATE_CTRL_REG |= ( ctl.band_width << 24);
3240 + RATE_CTRL_REG &= (~(0x3 << 4));
3241 + RATE_CTRL_REG |= (ctl.base_rate << 4);
3244 + case 3: // port 0 extra dma
3246 + TC_CTRL_REG &= (~0x7f);
3247 + TC_CTRL_REG |= ctl.band_width;
3248 + RATE_CTRL_REG &= (~(0x3 << 6));
3249 + RATE_CTRL_REG |= (ctl.base_rate << 6);
3259 +int get_rate_limit(struct ifreq *ifr)
3261 + CNS3XXXRateLimitEntry ctl;
3263 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXRateLimitEntry)) )
3265 + switch (ctl.which_port)
3269 + ctl.band_width = (RATE_CTRL_REG >> 8) & 0x7f;
3270 + ctl.base_rate = RATE_CTRL_REG & 0x3;
3275 + ctl.band_width = (RATE_CTRL_REG >> 16) & 0x7f;
3276 + ctl.base_rate = (RATE_CTRL_REG >> 2) & 0x3;
3281 + ctl.band_width = (RATE_CTRL_REG >> 24) & 0x7f;
3282 + ctl.base_rate = (RATE_CTRL_REG >> 4) & 0x3;
3285 + case 3: // port 0 extra dma
3287 + ctl.band_width = (TC_CTRL_REG) & 0x7f;
3288 + ctl.base_rate = (RATE_CTRL_REG >> 6) & 0x3;
3297 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXRateLimitEntry)) )
3303 +int set_fc(struct ifreq *ifr)
3305 + CNS3XXXFCEntry ctl;
3306 + u32 port_offset[]={0x0c, 0x10, 0x18, 0x14}; // 0x14 is cpu port offset
3310 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXFCEntry)) )
3313 + val = SWITCH_REG_VALUE(port_offset[ctl.port]);
3314 + if (ctl.port == 3) { // cpu port, only can set rx fc
3315 + val &= (~(1 << 31));
3319 + val &= (~(1 << 11)); // disable rx fc
3320 + val &= (~(1 << 12)); // disable tx fc
3321 + val |= (ctl.fc_en << 11);
3324 + SWITCH_REG_VALUE(port_offset[ctl.port]) = val;
3328 +int get_fc(struct ifreq *ifr)
3330 + CNS3XXXFCEntry ctl;
3331 + u32 port_offset[]={0x0c, 0x10, 0x18, 0x14}; // 0x14 is cpu port offset
3334 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXFCEntry)) )
3337 + val = SWITCH_REG_VALUE(port_offset[ctl.port]);
3338 + if (ctl.port == 3) { // cpu port, only can set rx fc
3339 + ctl.fc_en = ((val >> 31) & 1);
3341 + ctl.fc_en = ((val >> 11) & 3);
3345 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXFCEntry)) )
3351 +int set_ivl(struct ifreq *ifr)
3353 + CNS3XXXIVLEntry ctl;
3355 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXIVLEntry)) )
3358 + cns3xxx_ivl(ctl.enable);
3363 +int get_ivl(struct ifreq *ifr)
3365 + CNS3XXXIVLEntry ctl;
3367 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXIVLEntry)) )
3370 + ctl.enable = ((MAC_GLOB_CFG_REG >> 7) & 0x1);
3372 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXIVLEntry)) )
3378 +int set_wan_port(struct ifreq *ifr)
3380 + CNS3XXXWANPortEntry ctl;
3382 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXWANPortEntry)) )
3384 + VLAN_CFG &= (~(0x1f << 8));
3385 + VLAN_CFG |= (ctl.wan_port << 8);
3389 +int get_wan_port(struct ifreq *ifr)
3391 + CNS3XXXWANPortEntry ctl;
3393 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXWANPortEntry)) )
3396 + ctl.wan_port = ((VLAN_CFG >> 8) & 0x1f);
3398 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXWANPortEntry)) )
3404 +int set_pvid(struct ifreq *ifr)
3406 + CNS3XXXPVIDEntry ctl;
3408 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPVIDEntry)) )
3410 + cns3xxx_set_pvid(ctl.which_port, ctl.pvid);
3415 +int get_pvid(struct ifreq *ifr)
3417 + CNS3XXXPVIDEntry ctl;
3419 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPVIDEntry)) )
3422 + ctl.pvid = cns3xxx_get_pvid(ctl.which_port);
3423 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPVIDEntry)) )
3428 +int set_qa(struct ifreq *ifr)
3430 + CNS3XXXQAEntry ctl;
3432 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQAEntry)) )
3435 + MAC_GLOB_CFG_EXT_REG &= ~(0x7 << 27);
3436 + MAC_GLOB_CFG_EXT_REG |= (ctl.qa << 27);
3441 +int get_qa(struct ifreq *ifr)
3443 + CNS3XXXQAEntry ctl;
3445 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQAEntry)) )
3448 + ctl.qa = (MAC_GLOB_CFG_EXT_REG >> 27) & 0x7;
3450 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXQAEntry)) )
3455 +int get_packet_max_len(struct ifreq *ifr)
3457 + CNS3XXXMaxLenEntry ctl;
3459 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXMaxLenEntry)) )
3462 + ctl.max_len = (PHY_AUTO_ADDR_REG >> 30) & 0x3;
3464 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXMaxLenEntry)) )
3469 +int set_packet_max_len(struct ifreq *ifr)
3471 + CNS3XXXMaxLenEntry ctl;
3473 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXMaxLenEntry)) )
3476 + PHY_AUTO_ADDR_REG &= (~(3 << 30));
3477 + PHY_AUTO_ADDR_REG |= (ctl.max_len << 30);
3482 +int set_udp_range(struct ifreq *ifr)
3484 + CNS3XXXUdpRangeEtypeControl conf;
3486 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXUdpRangeEtypeControl)) )
3489 + switch (conf.udp_range_num)
3493 + UDP_RANGE0_REG = 0;
3494 + UDP_RANGE0_REG |= conf.port_start;
3495 + UDP_RANGE0_REG |= (conf.port_end << 16);
3500 + UDP_RANGE1_REG = 0;
3501 + UDP_RANGE1_REG |= conf.port_start;
3502 + UDP_RANGE1_REG |= (conf.port_end << 16);
3507 + UDP_RANGE2_REG = 0;
3508 + UDP_RANGE2_REG |= conf.port_start;
3509 + UDP_RANGE2_REG |= (conf.port_end << 16);
3514 + UDP_RANGE3_REG = 0;
3515 + UDP_RANGE3_REG |= conf.port_start;
3516 + UDP_RANGE3_REG |= (conf.port_end << 16);
3524 +int get_udp_range(struct ifreq *ifr)
3526 + CNS3XXXUdpRangeEtypeControl conf;
3528 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXUdpRangeEtypeControl)) )
3531 + switch (conf.udp_range_num)
3535 + conf.port_start = (UDP_RANGE0_REG & 0xffff);
3536 + conf.port_end = ((UDP_RANGE0_REG >> 16 )& 0xffff);
3541 + conf.port_start = (UDP_RANGE1_REG & 0xffff);
3542 + conf.port_end = ((UDP_RANGE1_REG >> 16 )& 0xffff);
3547 + conf.port_start = (UDP_RANGE2_REG & 0xffff);
3548 + conf.port_end = ((UDP_RANGE2_REG >> 16 )& 0xffff);
3553 + conf.port_start = (UDP_RANGE3_REG & 0xffff);
3554 + conf.port_end = ((UDP_RANGE3_REG >> 16 )& 0xffff);
3559 + if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXEtypeControl)) )
3565 +int get_etype(struct ifreq *ifr)
3567 + CNS3XXXEtypeControl conf;
3569 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXEtypeControl)) )
3571 + switch (conf.etype_num)
3575 + conf.val = (ETYPE1_ETYPE0_REG & 0xffff);
3576 + conf.pri = (PRIO_ETYPE_UDP_REG & 0x7);
3581 + conf.val = ((ETYPE1_ETYPE0_REG >> 16 )& 0xffff);
3582 + conf.pri = ((PRIO_ETYPE_UDP_REG >> 4) & 0x7);
3587 + conf.val = (ETYPE3_ETYPE2_REG & 0xffff);
3588 + conf.pri = ((PRIO_ETYPE_UDP_REG >> 8) & 0x7);
3593 + conf.val = ((ETYPE3_ETYPE2_REG >> 16 )& 0xffff);
3594 + conf.pri = ((PRIO_ETYPE_UDP_REG >> 12) & 0x7);
3598 + if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXEtypeControl)) )
3604 +int set_etype(struct ifreq *ifr)
3606 + CNS3XXXEtypeControl conf;
3608 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXEtypeControl)) )
3610 + switch (conf.etype_num)
3614 + ETYPE1_ETYPE0_REG &= (~0xffff);
3615 + ETYPE1_ETYPE0_REG |= conf.val;
3617 + PRIO_ETYPE_UDP_REG &= (~7);
3618 + PRIO_ETYPE_UDP_REG |= (conf.pri);
3623 + ETYPE1_ETYPE0_REG &= (~(0xffff << 16));
3624 + ETYPE1_ETYPE0_REG |= (conf.val << 16);
3626 + PRIO_ETYPE_UDP_REG &= (~(7 << 4));
3627 + PRIO_ETYPE_UDP_REG |= (conf.pri << 4);
3632 + ETYPE3_ETYPE2_REG &= (~0xffff);
3633 + ETYPE3_ETYPE2_REG |= conf.val;
3635 + PRIO_ETYPE_UDP_REG &= (~(7 << 8));
3636 + PRIO_ETYPE_UDP_REG |= (conf.pri << 8);
3641 + ETYPE3_ETYPE2_REG &= (~(0xffff << 16));
3642 + ETYPE3_ETYPE2_REG |= (conf.val << 16);
3644 + PRIO_ETYPE_UDP_REG &= (~(7 << 12));
3645 + PRIO_ETYPE_UDP_REG |= (conf.pri << 12);
3652 +int get_pri_ip_dscp(struct ifreq *ifr)
3654 + CNS3XXXPriIpDscpControl conf;
3656 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXPriIpDscpControl)) )
3659 + if ( 0 <= conf.ip_dscp_num && conf.ip_dscp_num <= 7) {
3660 + conf.pri = ((PRIO_IPDSCP_7_0_REG >> (conf.ip_dscp_num * 4)) & 0x7);
3661 + } else if ( 8 <= conf.ip_dscp_num && conf.ip_dscp_num <= 15) {
3662 + conf.pri = ((PRIO_IPDSCP_15_8_REG >> ((conf.ip_dscp_num-8) * 4)) & 0x7);
3663 + } else if ( 16 <= conf.ip_dscp_num && conf.ip_dscp_num <= 23) {
3664 + conf.pri = ((PRIO_IPDSCP_23_16_REG >> ((conf.ip_dscp_num-16) * 4)) & 0x7);
3665 + } else if ( 24 <= conf.ip_dscp_num && conf.ip_dscp_num <= 31) {
3666 + conf.pri = ((PRIO_IPDSCP_31_24_REG >> ((conf.ip_dscp_num-24) * 4)) & 0x7);
3667 + } else if ( 32 <= conf.ip_dscp_num && conf.ip_dscp_num <= 39) {
3668 + conf.pri = ((PRIO_IPDSCP_39_32_REG >> ((conf.ip_dscp_num-32) * 4)) & 0x7);
3669 + } else if ( 40 <= conf.ip_dscp_num && conf.ip_dscp_num <= 47) {
3670 + conf.pri = ((PRIO_IPDSCP_47_40_REG >> ((conf.ip_dscp_num-40) * 4)) & 0x7);
3671 + } else if ( 48 <= conf.ip_dscp_num && conf.ip_dscp_num <= 55) {
3672 + conf.pri = ((PRIO_IPDSCP_55_48_REG >> ((conf.ip_dscp_num-48) * 4)) & 0x7);
3673 + } else if ( 56 <= conf.ip_dscp_num && conf.ip_dscp_num <= 63) {
3674 + conf.pri = ((PRIO_IPDSCP_63_56_REG >> ((conf.ip_dscp_num-56) * 4)) & 0x7);
3680 + if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXPriIpDscpControl)) )
3686 +int set_pri_ip_dscp(struct ifreq *ifr)
3688 + CNS3XXXPriIpDscpControl conf;
3690 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXPriIpDscpControl)) )
3693 + if ( 0 <= conf.ip_dscp_num && conf.ip_dscp_num <= 7) {
3694 + PRIO_IPDSCP_7_0_REG &= (~(0x7 << (conf.ip_dscp_num * 4) ) );
3695 + PRIO_IPDSCP_7_0_REG |= (conf.pri << (conf.ip_dscp_num * 4));
3696 + } else if ( 8 <= conf.ip_dscp_num && conf.ip_dscp_num <= 15) {
3697 + PRIO_IPDSCP_15_8_REG &= (~(0x7 << ((conf.ip_dscp_num-8) * 4) ) );
3698 + PRIO_IPDSCP_15_8_REG |= (conf.pri << ((conf.ip_dscp_num-8) * 4));
3699 + } else if ( 16 <= conf.ip_dscp_num && conf.ip_dscp_num <= 23) {
3700 + PRIO_IPDSCP_23_16_REG &= (~(0x7 << ((conf.ip_dscp_num-16) * 4) ) );
3701 + PRIO_IPDSCP_23_16_REG |= (conf.pri << ((conf.ip_dscp_num-16) * 4));
3703 + } else if ( 24 <= conf.ip_dscp_num && conf.ip_dscp_num <= 31) {
3704 + PRIO_IPDSCP_31_24_REG &= (~(0x7 << ((conf.ip_dscp_num-24) * 4) ) );
3705 + PRIO_IPDSCP_31_24_REG |= (conf.pri << ((conf.ip_dscp_num-24) * 4));
3707 + } else if ( 32 <= conf.ip_dscp_num && conf.ip_dscp_num <= 39) {
3708 + PRIO_IPDSCP_39_32_REG &= (~(0x7 << ((conf.ip_dscp_num-32) * 4) ) );
3709 + PRIO_IPDSCP_39_32_REG |= (conf.pri << ((conf.ip_dscp_num-32) * 4));
3711 + } else if ( 40 <= conf.ip_dscp_num && conf.ip_dscp_num <= 47) {
3712 + PRIO_IPDSCP_47_40_REG &= (~(0x7 << ((conf.ip_dscp_num-40) * 4) ) );
3713 + PRIO_IPDSCP_47_40_REG |= (conf.pri << ((conf.ip_dscp_num-40) * 4));
3714 + } else if ( 48 <= conf.ip_dscp_num && conf.ip_dscp_num <= 55) {
3715 + PRIO_IPDSCP_55_48_REG &= (~(0x7 << ((conf.ip_dscp_num-48) * 4) ) );
3716 + PRIO_IPDSCP_55_48_REG |= (conf.pri << ((conf.ip_dscp_num-48) * 4));
3717 + } else if ( 56 <= conf.ip_dscp_num && conf.ip_dscp_num <= 63) {
3718 + PRIO_IPDSCP_63_56_REG &= (~(0x7 << ((conf.ip_dscp_num-56) * 4) ) );
3719 + PRIO_IPDSCP_63_56_REG |= (conf.pri << ((conf.ip_dscp_num-56) * 4));
3727 +int bcm53115M_reg_read_ioctl(struct ifreq *ifr)
3729 + int bcm53115M_reg_read(int page, int offset, u8 *buf, int len);
3730 + CNS3XXXBCM53115M conf;
3731 + int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
3734 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXBCM53115M)) )
3736 + printk("conf.page: %x\n", conf.page);
3737 + printk("conf.offset: %x\n", conf.offset);
3738 + printk("conf.data_len: %x\n", conf.data_len);
3739 + switch (conf.data_len)
3743 + bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u8_val, 1);
3744 + printk("conf.u8_val: %x\n", conf.u8_val);
3749 + bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u16_val, 2);
3750 + printk("conf.u16_val: %x\n", conf.u16_val);
3755 + bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u32_val, 4);
3756 + printk("conf.u32_val: %x\n", conf.u32_val);
3761 + printk("[kernel mode]: don't support date length: %d\n", conf.data_len);
3767 + if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXBCM53115M)) )
3772 +int bcm53115M_reg_write_ioctl(struct ifreq *ifr)
3774 + int bcm53115M_reg_write(int page, int offset, u8 *buf, int len);
3775 + CNS3XXXBCM53115M conf;
3777 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXBCM53115M)) )
3780 + switch (conf.data_len)
3784 + bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u8_val, 1);
3789 + bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u16_val, 2);
3794 + bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u32_val, 4);
3799 + printk("[kernel mode]: don't support date length: %d\n", conf.data_len);
3806 +int get_rxring(struct ifreq *ifr)
3808 + CNS3XXXRingStatus conf;
3810 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXRingStatus)) )
3812 + conf.rx_ring=g_ring_info.rx_ring;
3814 + if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXRingStatus)) )
3819 +int dump_mib_counter(struct ifreq *ifr)
3821 + CNS3XXXMIBCounter conf;
3824 + if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXMIBCounter)) )
3827 + for (addr=0x300; addr <= 0x334 ; addr+=4)
3828 + conf.mib[i++]=SWITCH_REG_VALUE(addr);
3829 + for (addr=0x400; addr <= 0x434 ; addr+=4)
3830 + conf.mib[i++]=SWITCH_REG_VALUE(addr);
3831 + for (addr=0x600; addr <= 0x634 ; addr+=4)
3832 + conf.mib[i++]=SWITCH_REG_VALUE(addr);
3833 + // cpu mib counter
3834 + for (addr=0x500; addr <= 0x528 ; addr+=4)
3835 + conf.mib[i++]=SWITCH_REG_VALUE(addr);
3837 + if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXMIBCounter)) )
3842 +// reference e100.c
3843 +int cns3xxx_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
3845 + CNS3XXXIoctlCmd ioctl_cmd;
3847 + //printk("cns3xxx_do_ioctl begin\n");
3849 + if (cmd != SIOCDEVPRIVATE) {
3850 + return -EOPNOTSUPP;
3852 + if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(CNS3XXXIoctlCmd)))
3855 + //printk("ioctl_cmd: %d\n", ioctl_cmd);
3856 + switch (ioctl_cmd) {
3857 + case CNS3XXX_ARP_REQUEST_SET:
3859 + CNS3XXXArpRequestControl ctl;
3861 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXArpRequestControl)) )
3864 + (ctl.val==0) ? (MAC_GLOB_CFG_REG &= (~(1 << 23)) ): (MAC_GLOB_CFG_REG |= (1 << 23) );
3868 + case CNS3XXX_ARP_REQUEST_GET:
3870 + CNS3XXXArpRequestControl ctl;
3872 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXArpRequestControl)) )
3875 + ctl.val = ((MAC_GLOB_CFG_REG >> 23) & 1);
3877 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXArpRequestControl)) )
3882 + case CNS3XXX_HOL_PREVENT_SET:
3884 + CNS3XXXHOLPreventControl ctl;
3886 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXHOLPreventControl)) )
3888 + (ctl.enable == 1) ? (TC_CTRL_REG |= (1 << 29)) : (TC_CTRL_REG &= (~(1 << 29))) ;
3892 + case CNS3XXX_HOL_PREVENT_GET:
3894 + CNS3XXXHOLPreventControl ctl;
3896 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXHOLPreventControl)) )
3899 + ctl.enable = ((TC_CTRL_REG >> 29) & 0x1);
3901 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXHOLPreventControl)) )
3906 + // for S component or C conponent
3907 + case CNS3XXX_BRIDGE_SET:
3909 + CNS3XXXBridgeControl ctl;
3911 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXBridgeControl)) )
3913 + (ctl.type == 1) ? (VLAN_CFG |= (1 << 1)) : (VLAN_CFG &= (~(1 << 1))) ;
3917 + case CNS3XXX_BRIDGE_GET:
3919 + CNS3XXXBridgeControl ctl;
3921 + ctl.type = ((VLAN_CFG >> 1) & 0x1);
3922 + printk("[kernel mode] ctl.type: %d\n", ctl.type);
3924 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXBridgeControl)) )
3930 + case CNS3XXX_PORT_NEIGHBOR_SET:
3932 + CNS3XXXPortNeighborControl ctl;
3934 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPortNeighborControl)) )
3936 + switch (ctl.which_port)
3940 + (ctl.type == 1) ? (VLAN_CFG |= (1 << 4)) : (VLAN_CFG &= (~(1 << 4))) ;
3945 + (ctl.type == 1) ? (VLAN_CFG |= (1 << 5)) : (VLAN_CFG &= (~(1 << 5))) ;
3950 + (ctl.type == 1) ? (VLAN_CFG |= (1 << 7)) : (VLAN_CFG &= (~(1 << 7))) ;
3953 + case 3: // cpu port
3955 + (ctl.type == 1) ? (VLAN_CFG |= (1 << 6)) : (VLAN_CFG &= (~(1 << 6))) ;
3964 + case CNS3XXX_PORT_NEIGHBOR_GET:
3966 + CNS3XXXPortNeighborControl ctl;
3968 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPortNeighborControl)) )
3970 + switch (ctl.which_port)
3974 + ctl.type = ((VLAN_CFG >> 4 ) & 0x1);
3979 + ctl.type = ((VLAN_CFG >> 5 ) & 0x1);
3984 + ctl.type = ((VLAN_CFG >> 7 ) & 0x1);
3987 + case 3: // cpu port
3989 + ctl.type = ((VLAN_CFG >> 6 ) & 0x1);
3994 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPortNeighborControl)) )
4000 + case CNS3XXX_VLAN_TABLE_LOOKUP:
4002 + CNS3XXXVLANTableEntry ctl;
4004 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) )
4006 + if (cns3xxx_vlan_table_lookup(&ctl.entry) == CAVM_NOT_FOUND) {
4007 + return CAVM_NOT_FOUND;
4010 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry)))
4013 + return CAVM_FOUND;
4015 + case CNS3XXX_VLAN_TABLE_READ:
4017 + CNS3XXXVLANTableEntry ctl;
4019 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) )
4023 + cns3xxx_vlan_table_read(&ctl.entry);
4024 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry)))
4029 + case CNS3XXX_VLAN_TABLE_ADD:
4031 + CNS3XXXVLANTableEntry ctl;
4033 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) )
4035 + cns3xxx_vlan_table_add(&ctl.entry);
4036 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry)))
4042 + case CNS3XXX_ARL_TABLE_ADD:
4044 + CNS3XXXARLTableEntry ctl;
4046 + printk("[kernel mode] CNS3XXX_ARL_TABLE_ADD\n");
4047 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4049 + cns3xxx_arl_table_add(&ctl.entry);
4050 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4057 + case CNS3XXX_ARL_TABLE_DEL:
4059 + CNS3XXXARLTableEntry ctl;
4061 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4063 + cns3xxx_arl_table_invalid(&ctl.entry);
4064 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4069 + case CNS3XXX_VLAN_TABLE_DEL:
4071 + CNS3XXXARLTableEntry ctl;
4073 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4075 + cns3xxx_arl_table_invalid(&ctl.entry);
4077 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4080 + return CAVM_FOUND;
4083 + case CNS3XXX_ARL_TABLE_SEARCH:
4085 + CNS3XXXARLTableEntry ctl;
4087 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4089 + if (cns3xxx_arl_table_search(&ctl.entry) == CAVM_NOT_FOUND){
4090 + printk("[kernel mode] not found\n");
4091 + return CAVM_NOT_FOUND;
4093 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4096 + return CAVM_FOUND;
4098 + case CNS3XXX_ARL_IS_TABLE_END:
4100 + CNS3XXXARLTableEntry ctl;
4102 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4104 + if (cns3xxx_is_arl_table_end() == CAVM_ERR)
4106 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4112 + case CNS3XXX_ARL_TABLE_SEARCH_AGAIN:
4114 + CNS3XXXARLTableEntry ctl;
4116 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4118 + if (cns3xxx_arl_table_search_again(&ctl.entry) == CAVM_NOT_FOUND)
4119 + return CAVM_NOT_FOUND;
4120 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4123 + return CAVM_FOUND;
4126 + case CNS3XXX_ARL_TABLE_FLUSH:
4128 + CNS3XXXARLTableEntry ctl;
4130 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4133 + cns3xxx_arl_table_flush();
4135 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4138 + return CAVM_FOUND;
4143 + case CNS3XXX_ARL_TABLE_LOOKUP:
4145 + CNS3XXXARLTableEntry ctl;
4148 + printk("[kernel mode] in CNS3XXX_ARL_TABLE_LOOKUP\n");
4149 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4151 + if (cns3xxx_arl_table_lookup(&ctl.entry) == CAVM_NOT_FOUND)
4152 + return CAVM_NOT_FOUND;
4153 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4156 + return CAVM_FOUND;
4159 + case CNS3XXX_TC_SET:
4161 + CNS3XXXTrafficClassControl ctl;
4163 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXTrafficClassControl)) )
4165 + TC_CTRL_REG &= (~(0x3 << 30));
4166 + TC_CTRL_REG |= (ctl.tc << 30);
4169 + case CNS3XXX_TC_GET:
4171 + CNS3XXXTrafficClassControl ctl;
4173 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXTrafficClassControl)) )
4176 + ctl.tc = ((TC_CTRL_REG >> 30) & 0x3);
4178 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXTrafficClassControl)) )
4184 + case CNS3XXX_PRI_CTRL_SET:
4186 + CNS3XXXPriCtrlControl ctl;
4188 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPriCtrlControl)) )
4191 + switch (ctl.which_port)
4195 + MAC0_PRI_CTRL_REG &= (~(0x7 << 24));
4196 + MAC0_PRI_CTRL_REG &= (~(0xf << 18));
4198 + MAC0_PRI_CTRL_REG |= (ctl.port_pri << 24);
4200 + MAC0_PRI_CTRL_REG |= (ctl.ether_pri_en << 18);
4201 + MAC0_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19);
4202 + MAC0_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20);
4203 + MAC0_PRI_CTRL_REG |= (ctl.udp_pri_en << 21);
4208 + MAC1_PRI_CTRL_REG &= (~(0x7 << 24));
4209 + MAC1_PRI_CTRL_REG &= (~(0xf << 18));
4211 + MAC1_PRI_CTRL_REG |= (ctl.port_pri << 24);
4213 + MAC1_PRI_CTRL_REG |= (ctl.ether_pri_en << 18);
4214 + MAC1_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19);
4215 + MAC1_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20);
4216 + MAC1_PRI_CTRL_REG |= (ctl.udp_pri_en << 21);
4221 + MAC2_PRI_CTRL_REG &= (~(0x7 << 24));
4222 + MAC2_PRI_CTRL_REG &= (~(0xf << 18));
4224 + MAC2_PRI_CTRL_REG |= (ctl.port_pri << 24);
4226 + MAC2_PRI_CTRL_REG |= (ctl.ether_pri_en << 18);
4227 + MAC2_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19);
4228 + MAC2_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20);
4229 + MAC2_PRI_CTRL_REG |= (ctl.udp_pri_en << 21);
4234 + printk("[kernel mode] CPU_PRI_CTRL_REG: %#x\n", CPU_PRI_CTRL_REG);
4235 + CPU_PRI_CTRL_REG &= (~(0x7 << 24));
4236 + CPU_PRI_CTRL_REG &= (~(0xf << 18));
4238 + CPU_PRI_CTRL_REG |= (ctl.port_pri << 24);
4240 + CPU_PRI_CTRL_REG |= (ctl.ether_pri_en << 18);
4241 + CPU_PRI_CTRL_REG |= (ctl.vlan_pri_en << 19);
4242 + CPU_PRI_CTRL_REG |= (ctl.dscp_pri_en << 20);
4243 + CPU_PRI_CTRL_REG |= (ctl.udp_pri_en << 21);
4251 + case CNS3XXX_PRI_CTRL_GET:
4253 + CNS3XXXPriCtrlControl ctl;
4255 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPriCtrlControl)) )
4259 + if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPriCtrlControl)) )
4265 + case CNS3XXX_DMA_RING_CTRL_SET:
4267 + CNS3XXXDmaRingCtrlControl ctl;
4269 + if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXDmaRingCtrlControl)) )
4272 + (ctl.ts_double_ring_en == 0) ? DMA_RING_CTRL_REG &= (~(0x1 << 16)) : (DMA_RING_CTRL_REG |= (ctl.ts_double_ring_en << 16));
4273 + (ctl.fs_double_ring_en == 0) ? DMA_RING_CTRL_REG &= (~(0x1 << 0)) : (DMA_RING_CTRL_REG |= (ctl.fs_double_ring_en << 0));
4274 + (ctl.fs_pkt_allocate == 0) ? DMA_RING_CTRL_REG &= (~(0x1 << 1)) : (DMA_RING_CTRL_REG |= (ctl.fs_pkt_allocate << 1));
4277 + case CNS3XXX_PRI_IP_DSCP_SET:
4279 + return set_pri_ip_dscp(ifr);
4281 + case CNS3XXX_PRI_IP_DSCP_GET:
4283 + return get_pri_ip_dscp(ifr);
4286 + case CNS3XXX_ETYPE_SET:
4288 + return set_etype(ifr);
4290 + case CNS3XXX_ETYPE_GET:
4292 + return get_etype(ifr);
4295 + case CNS3XXX_UDP_RANGE_SET:
4297 + return set_udp_range(ifr);
4299 + case CNS3XXX_UDP_RANGE_GET:
4301 + return get_udp_range(ifr);
4304 + case CNS3XXX_RATE_LIMIT_SET:
4306 + return set_rate_limit(ifr);
4308 + case CNS3XXX_RATE_LIMIT_GET:
4310 + return get_rate_limit(ifr);
4312 + case CNS3XXX_QUEUE_WEIGHT_SET:
4314 + return set_queue_weight(ifr);
4316 + case CNS3XXX_QUEUE_WEIGHT_GET:
4318 + return get_queue_weight(ifr);
4321 + case CNS3XXX_FC_RLS_SET:
4323 + return set_fc_rls(ifr);
4325 + case CNS3XXX_FC_RLS_GET:
4327 + return get_fc_rls(ifr);
4330 + case CNS3XXX_FC_SET_SET:
4332 + return set_fc_set(ifr);
4334 + case CNS3XXX_FC_SET_GET:
4336 + return get_fc_set(ifr);
4339 + case CNS3XXX_SARL_RLS_SET:
4341 + return set_sarl_rls(ifr);
4343 + case CNS3XXX_SARL_RLS_GET:
4345 + return get_sarl_rls(ifr);
4348 + case CNS3XXX_SARL_SET_SET:
4350 + return set_sarl_set(ifr);
4352 + case CNS3XXX_SARL_SET_GET:
4354 + return get_sarl_set(ifr);
4357 + case CNS3XXX_SARL_OQ_SET:
4359 + return set_sarl_oq(ifr);
4361 + case CNS3XXX_SARL_OQ_GET:
4363 + return get_sarl_oq(ifr);
4366 + case CNS3XXX_SARL_ENABLE_SET:
4368 + return set_sarl_enable(ifr);
4370 + case CNS3XXX_SARL_ENABLE_GET:
4372 + return get_sarl_enable(ifr);
4375 + case CNS3XXX_FC_SET:
4377 + return set_fc(ifr);
4379 + case CNS3XXX_FC_GET:
4381 + return get_fc(ifr);
4384 + case CNS3XXX_IVL_SET:
4386 + return set_ivl(ifr);
4388 + case CNS3XXX_IVL_GET:
4390 + return get_ivl(ifr);
4393 + case CNS3XXX_WAN_PORT_SET:
4395 + return set_wan_port(ifr);
4397 + case CNS3XXX_WAN_PORT_GET:
4399 + return get_wan_port(ifr);
4402 + case CNS3XXX_PVID_SET:
4404 + return set_pvid(ifr);
4406 + case CNS3XXX_PVID_GET:
4408 + return get_pvid(ifr);
4411 + case CNS3XXX_QA_GET:
4413 + return get_qa(ifr);
4415 + case CNS3XXX_QA_SET:
4417 + return set_qa(ifr);
4420 + case CNS3XXX_PACKET_MAX_LEN_GET:
4422 + return get_packet_max_len(ifr);
4424 + case CNS3XXX_PACKET_MAX_LEN_SET:
4426 + return set_packet_max_len(ifr);
4429 + case CNS3XXX_BCM53115M_REG_READ:
4431 + return bcm53115M_reg_read_ioctl(ifr);
4433 + case CNS3XXX_BCM53115M_REG_WRITE:
4435 + return bcm53115M_reg_write_ioctl(ifr);
4439 + case CNS3XXX_RXRING_STATUS:
4441 + return get_rxring(ifr);
4444 + case CNS3XXX_DUMP_MIB_COUNTER:
4446 + return dump_mib_counter(ifr);
4452 + printk("[kernel mode] don't match any command\n");
4456 + } // end switch (ioctl_cmd)
4460 +#ifdef CONFIG_CNS3XXX_NAPI
4461 +static int cns3xxx_poll(struct napi_struct *napi, int budget)
4464 + CNS3XXXPrivate *sp = container_of(napi, CNS3XXXPrivate, napi);
4465 + int work_done = 0;
4466 + int work_to_do = budget; // define minima value
4468 + cns3xxx_receive_packet(sp, 0, &work_done, work_to_do);
4470 + budget -= work_done;
4473 + if (test_bit(0, (unsigned long *)&sp->is_qf) == 1){
4474 + clear_bit(0, (unsigned long *)&sp->is_qf);
4475 + enable_rx_dma(sp->ring_index, 1);
4479 + //netif_rx_complete(napi_dev, &sp->napi);
4480 + napi_complete(napi);
4481 +#ifdef CNS3XXX_USE_MASK
4482 + cns3xxx_write_pri_mask(0xf0);
4484 + if (sp->ring_index == 0)
4485 + cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
4487 + cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID);
4496 +static struct net_device_stats *cns3xxx_get_stats(struct net_device *dev)
4498 + CNS3XXXPrivate *priv = netdev_priv(dev);
4500 + return &priv->stats;
4503 +static int cns3xxx_change_mtu(struct net_device *dev, int new_mtu)
4505 + if (new_mtu < cns3xxx_min_mtu() || new_mtu > cns3xxx_max_mtu())
4508 + dev->mtu = new_mtu;
4513 +static void cns3xxx_timeout(struct net_device *dev)
4515 + //star_gsw_enable(dev);
4516 + netif_wake_queue(dev);
4517 + dev->trans_start = jiffies;
4521 +static const struct net_device_ops cns3xxx_netdev_ops = {
4522 + .ndo_open = cns3xxx_open,
4523 + .ndo_stop = cns3xxx_close,
4524 + .ndo_start_xmit = cns3xxx_send_packet,
4525 + //.ndo_validate_addr = eth_validate_addr,
4526 + //.ndo_set_multicast_list = cns3xxx_set_multicast_list,
4527 + .ndo_set_mac_address = cns3xxx_set_mac_addr,
4528 + .ndo_change_mtu = cns3xxx_change_mtu,
4529 + .ndo_do_ioctl = cns3xxx_do_ioctl,
4530 + .ndo_tx_timeout = cns3xxx_timeout,
4531 + .ndo_get_stats = cns3xxx_get_stats,
4533 +#if defined(CNS3XXX_VLAN_8021Q)
4534 + .ndo_vlan_rx_register = cns3xxx_vlan_rx_register,
4535 + //.ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,
4536 + .ndo_vlan_rx_kill_vid = cns3xxx_vlan_rx_kill_vid,
4539 +#ifdef CONFIG_NET_POLL_CONTROLLER
4540 + .ndo_poll_controller = cns3xxx_netpoll,
4543 +#endif // LINUX2631
4545 +static int __init cns3xxx_probe(RingInfo ring_info)
4547 + void cns3xxx_set_ethtool_ops(struct net_device *netdev);
4549 + int netdev_size = sizeof(net_device_prive)/sizeof(NetDevicePriv);
4551 + struct net_device *netdev=0;
4552 + CNS3XXXPrivate *priv=0;
4553 + struct sockaddr sock_addr;
4555 + for (i=0 ; i < netdev_size ; ++i) {
4556 + if (init_port & (1 << i)) {
4558 + netdev = alloc_etherdev(sizeof(CNS3XXXPrivate));
4561 + goto err_alloc_etherdev;
4563 + if (net_device_prive[i].name)
4564 + strcpy(netdev->name, net_device_prive[i].name);
4567 + net_dev_array[net_device_prive[i].vlan_tag] = netdev;
4568 + if (intr_netdev==0)
4569 + intr_netdev = netdev;
4571 + SET_NETDEV_DEV(netdev, NULL);
4572 + priv = netdev_priv(netdev);
4573 + spin_lock_init(&priv->lock);
4574 + memset(priv, 0, sizeof(CNS3XXXPrivate));
4577 + priv->num_rx_queues = ring_info.num_rx_queues;
4578 + priv->num_tx_queues = ring_info.num_tx_queues;
4579 + priv->rx_ring = ring_info.rx_ring;
4580 + priv->tx_ring = ring_info.tx_ring;
4583 + priv->net_device_priv = &net_device_prive[i];
4585 + // set netdev MAC address
4586 + memcpy(sock_addr.sa_data, net_device_prive[i].mac, 6);
4587 + cns3xxx_set_mac_addr(netdev, &sock_addr);
4590 + netdev->netdev_ops = &cns3xxx_netdev_ops;
4593 + cns3xxx_set_ethtool_ops(netdev);
4595 + //netdev->base_addr = IO_ADDRESS(GSW_BASE_ADDR);
4596 + netdev->base_addr = 0;
4597 + netdev->open = cns3xxx_open;
4598 + netdev->stop = cns3xxx_close;
4599 + netdev->hard_start_xmit = cns3xxx_send_packet;
4600 + //netdev->hard_start_xmit = 0;
4601 + netdev->do_ioctl = cns3xxx_do_ioctl;
4602 + netdev->change_mtu = cns3xxx_change_mtu;
4604 + //netdev->get_stats = cns3xxx_get_stats;
4605 + netdev->watchdog_timeo = 5 * HZ; // ref e1000_main.c
4606 + netdev->tx_timeout = cns3xxx_timeout;
4607 + netdev->set_mac_address = cns3xxx_set_mac_addr;
4610 +#if defined(CNS3XXX_TX_HW_CHECKSUM)
4611 + netdev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG);
4612 + //netdev->features |= (NETIF_F_HW_CSUM | NETIF_F_SG);
4616 +#ifdef CONFIG_CNS3XXX_NAPI
4617 + //netif_napi_add(netdev, &priv->napi, cns3xxx_poll, CNS3XXX_NAPI_WEIGHT);
4620 +#if defined(CNS3XXX_VLAN_8021Q)
4621 + // do not let 8021Q module insert vlan tag
4622 + // can use the snippet code to get vlan tage
4623 + // if (priv->vlgrp && vlan_tx_tag_present(skb))
4624 + // vlan_tag = cpu_to_be16(vlan_tx_tag_get(skb));
4625 +#ifdef CNS3XXX_8021Q_HW_TX
4626 + // hardware support insert VLAN tag on TX path
4627 + netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
4629 + netdev->features |= NETIF_F_HW_VLAN_RX; // remove NETIF_F_HW_VLAN_TX flag that 8021Q module to insert vlan tag.
4632 + //netdev->vlan_rx_register = cns3xxx_vlan_rx_register;
4633 + //netdev->vlan_rx_kill_vid = cns3xxx_vlan_rx_kill_vid;
4637 + err = register_netdev(netdev);
4639 + goto err_register_netdev;
4642 + netif_carrier_off(netdev);
4645 + } // for (i=0 ; i < netdev_size ; ++i)
4650 +err_register_netdev:
4651 + free_netdev(netdev);
4653 +err_alloc_etherdev:
4657 +int cns3xxx_gsw_config_mac_port0(void)
4665 +int cns3xxx_gsw_config_mac_port1(void)
4673 +int cns3xxx_gsw_config_mac_port2(void)
4681 +static int cns3xxx_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr)
4684 + enable_rx_dma(0, 0);
4685 + enable_tx_dma(0, 0);
4686 + enable_rx_dma(1, 0);
4687 + enable_tx_dma(1, 0);
4690 + enable_port(0, 0);
4691 + enable_port(1, 0);
4692 + enable_port(2, 0);
4693 + enable_port(3, 0);
4694 + return NOTIFY_DONE;
4697 +#ifdef CONFIG_CNS3XXX_NAPI
4698 +static struct net_device *init_napi_dev(struct net_device *ndev, const RingInfo *ring_info)
4700 + CNS3XXXPrivate *priv;
4702 + ndev = alloc_etherdev(sizeof(CNS3XXXPrivate));
4706 + priv = netdev_priv(ndev);
4707 + memset(priv, 0, sizeof(CNS3XXXPrivate));
4709 + //priv = netdev_priv(napi_dev);
4710 + priv->num_rx_queues = ring_info->num_rx_queues;
4711 + priv->num_tx_queues = ring_info->num_tx_queues;
4712 + priv->rx_ring = ring_info->rx_ring;
4713 + priv->tx_ring = ring_info->tx_ring;
4714 + //priv->is_qf=0; // because of memset, so need not the line
4716 + netif_napi_add(ndev, &priv->napi , cns3xxx_poll, CNS3XXX_NAPI_WEIGHT);
4718 + set_bit(__LINK_STATE_START, &ndev->state);
4725 +void cns3xxx_config_intr(void)
4729 + get_interrupt_type(FSRC_RING0_INTERRUPT_ID, &v);
4731 + set_interrupt_type(FSRC_RING0_INTERRUPT_ID, RISING_EDGE);
4732 + get_interrupt_type(FSRC_RING0_INTERRUPT_ID, &v);
4734 + get_interrupt_type(FSRC_RING1_INTERRUPT_ID, &v);
4735 + set_interrupt_type(FSRC_RING1_INTERRUPT_ID, RISING_EDGE);
4736 + get_interrupt_type(FSRC_RING1_INTERRUPT_ID, &v);
4738 + get_interrupt_type(FSQF_RING0_INTERRUPT_ID, &v);
4739 + set_interrupt_type(FSQF_RING0_INTERRUPT_ID, RISING_EDGE);
4740 + get_interrupt_type(FSQF_RING0_INTERRUPT_ID, &v);
4742 + get_interrupt_type(FSQF_RING1_INTERRUPT_ID, &v);
4743 + set_interrupt_type(FSQF_RING1_INTERRUPT_ID, RISING_EDGE);
4744 + get_interrupt_type(FSQF_RING1_INTERRUPT_ID, &v);
4746 + #ifdef CNS3XXX_USE_MASK
4747 + get_interrupt_pri(FSRC_RING0_INTERRUPT_ID, &v);
4748 + set_interrupt_pri(FSRC_RING0_INTERRUPT_ID, 0xc);
4749 + get_interrupt_pri(FSRC_RING0_INTERRUPT_ID, &v);
4751 + get_interrupt_pri(FSRC_RING1_INTERRUPT_ID, &v);
4752 + set_interrupt_pri(FSRC_RING1_INTERRUPT_ID, 0xc);
4753 + get_interrupt_pri(FSRC_RING1_INTERRUPT_ID, &v);
4755 + get_interrupt_pri(FSQF_RING1_INTERRUPT_ID, &v);
4756 + set_interrupt_pri(FSQF_RING1_INTERRUPT_ID, 0xc);
4757 + get_interrupt_pri(FSQF_RING1_INTERRUPT_ID, &v);
4759 + #ifndef CONFIG_CNS3XXX_NAPI
4760 + set_interrupt_pri(FSQF_RING0_INTERRUPT_ID, 0xc);
4764 + #endif // CNS3XXX_USE_MASK
4768 +static int __devinit cns3xxx_init(struct platform_device *pdev)
4770 + // when tx_ring/rx_ring alloc memory,
4771 + // don't free them until cns3xxx_exit_module
4773 + struct eth_plat_info *plat = pdev->dev.platform_data;
4774 + init_port = plat->ports;
4775 + memcpy(cpu_vlan_table_entry.my_mac, plat->cpu_hwaddr, ETH_ALEN);
4776 +#if defined (CONFIG_CNS3XXX_SPPE)
4777 + memcpy(net_device_prive[3].mac, plat->cpu_hwaddr, ETH_ALEN);
4780 + RingInfo ring_info;
4782 + //spin_lock_init(&star_gsw_send_lock);
4785 +#ifdef CNS3XXX_DOUBLE_RX_RING
4786 + ring_info.num_rx_queues = 2;
4788 + ring_info.num_rx_queues = 1;
4791 +#ifdef CNS3XXX_DOUBLE_TX_RING
4792 + ring_info.num_tx_queues = 2;
4794 + ring_info.num_tx_queues = 1;
4797 + ring_info.rx_ring = kcalloc(ring_info.num_rx_queues, sizeof(RXRing), GFP_KERNEL);
4798 + if (!ring_info.rx_ring)
4801 + for (i=0 ; i < ring_info.num_rx_queues ; ++i) {
4802 + memset(ring_info.rx_ring + i, 0, sizeof(RXRing));
4806 + ring_info.tx_ring = kcalloc(ring_info.num_tx_queues, sizeof(TXRing), GFP_KERNEL);
4809 + if (!ring_info.tx_ring)
4812 + for (i=0 ; i < ring_info.num_tx_queues ; ++i) {
4813 + memset(ring_info.tx_ring + i, 0, sizeof(TXRing));
4817 + g_ring_info = ring_info;
4819 + cns3xxx_gsw_hw_init();
4822 + // GIGA mode disable
4823 + MAC0_CFG_REG &= (~(1<<16));
4824 + MAC1_CFG_REG &= (~(1<<16));
4825 + MAC2_CFG_REG &= (~(1<<16));
4828 + if ((init_port & 1) == 1) {
4829 + memcpy(vlan_table_entry[0].my_mac, plat->eth0_hwaddr, ETH_ALEN);
4830 + memcpy(arl_table_entry[0].mac, plat->eth0_hwaddr, ETH_ALEN);
4831 + memcpy(net_device_prive[0].mac, plat->eth0_hwaddr, ETH_ALEN);
4832 + cns3xxx_gsw_config_mac_port0();
4835 + if (((init_port >> 1) & 1) == 1) {
4836 + memcpy(vlan_table_entry[1].my_mac, plat->eth1_hwaddr, ETH_ALEN);
4837 + memcpy(arl_table_entry[1].mac, plat->eth1_hwaddr, ETH_ALEN);
4838 + memcpy(net_device_prive[1].mac, plat->eth1_hwaddr, ETH_ALEN);
4839 + cns3xxx_gsw_config_mac_port1();
4842 + if (((init_port >> 2) & 1) == 1) {
4843 + memcpy(vlan_table_entry[2].my_mac, plat->eth2_hwaddr, ETH_ALEN);
4844 + memcpy(arl_table_entry[2].mac, plat->eth2_hwaddr, ETH_ALEN);
4845 + memcpy(net_device_prive[2].mac, plat->eth2_hwaddr, ETH_ALEN);
4846 + cns3xxx_gsw_config_mac_port2();
4849 + cns3xxx_probe(ring_info);
4850 + cns3xxx_config_intr();
4852 +#ifdef CNS3XXX_VLAN_8021Q
4853 +#ifdef CNS3XXX_NIC_MODE_8021Q
4854 + cns3xxx_nic_mode(1);
4857 + spin_lock_init(&tx_lock);
4858 + spin_lock_init(&rx_lock);
4860 +#ifdef CONFIG_CNS3XXX_NAPI
4861 + napi_dev = init_napi_dev(napi_dev, &ring_info);
4862 + #ifdef CNS3XXX_DOUBLE_RX_RING
4863 + r1_napi_dev = init_napi_dev(r1_napi_dev, &ring_info);
4867 + register_reboot_notifier(&cns3xxx_notifier_reboot);
4868 + clear_fs_dma_state(0);
4870 + if (ring_info.num_rx_queues == 2) {
4871 + // enable RX dobule ring
4872 + DMA_RING_CTRL_REG |= 1;
4875 + if (ring_info.num_tx_queues == 2 ) {
4876 + // enable TX dobule ring
4877 + DMA_RING_CTRL_REG |= (1 << 16);
4884 +static int __devexit cns3xxx_remove(struct platform_device *pdev)
4889 + for (i=0 ; i < NETDEV_SIZE ; ++i) {
4890 + CNS3XXXPrivate *priv = 0;
4892 + if (net_dev_array[i]){
4893 + priv = netdev_priv(net_dev_array[i]);
4895 + kfree(priv->tx_ring);
4896 + priv->tx_ring = 0;
4898 + kfree(priv->rx_ring);
4899 + priv->rx_ring = 0;
4901 + unregister_netdev(net_dev_array[i]);
4902 + free_netdev(net_dev_array[i]);
4907 + sprintf(netdev_name, "eth%d", i);
4908 + netdev=__dev_get_by_name(&init_net, netdev_name);
4909 + // if no unregister_netdev and free_netdev,
4910 + // after remove module, ifconfig will hang.
4913 + unregister_netdev(netdev);
4914 + free_netdev(netdev);
4921 +#ifdef CONFIG_CNS3XXX_NAPI
4922 + free_netdev(napi_dev);
4923 + #ifdef CNS3XXX_DOUBLE_RX_RING
4924 + free_netdev(r1_napi_dev);
4930 + //star_gsw_buffer_free();
4932 + unregister_reboot_notifier(&cns3xxx_notifier_reboot);
4936 +// this snippet code ref 8139cp.c
4937 +#if defined(CNS3XXX_VLAN_8021Q)
4938 +void cns3xxx_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
4940 + CNS3XXXPrivate *priv = netdev_priv(dev);
4941 + unsigned long flags;
4943 + spin_lock_irqsave(&priv->lock, flags);
4944 + priv->vlgrp = grp;
4945 + spin_unlock_irqrestore(&priv->lock, flags);
4948 +void cns3xxx_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
4950 + CNS3XXXPrivate *priv = netdev_priv(dev);
4951 + unsigned long flags;
4953 + spin_lock_irqsave(&priv->lock, flags);
4954 + // reference: linux-2.6.24-current/drivers/netvia-velocity.c
4955 + vlan_group_set_device(priv->vlgrp, vid, NULL);
4956 + //priv->vlgrp->vlan_devices[vid] = NULL;
4957 + spin_unlock_irqrestore(&priv->lock, flags);
4962 +static struct platform_driver drv = {
4963 + .driver.name = "cns3xxx-net",
4964 + .probe = cns3xxx_init,
4965 + .remove = cns3xxx_remove,
4968 +static int __init cns3xxx_init_module(void)
4970 + return platform_driver_register(&drv);
4973 +static void __exit cns3xxx_exit_module(void)
4975 + platform_driver_unregister(&drv);
4978 +MODULE_AUTHOR("Cavium Networks, <tech@XXXX.com>");
4979 +MODULE_DESCRIPTION("CNS3XXX Switch Driver");
4980 +MODULE_LICENSE("GPL");
4981 +MODULE_VERSION(DRV_VERSION);
4983 +module_init(cns3xxx_init_module);
4984 +module_exit(cns3xxx_exit_module);
4987 +++ b/drivers/net/cns3xxx/cns3xxx_phy.c
4989 +/*******************************************************************************
4992 + * Copyright (c) 2009 Cavium Networks
4994 + * This program is free software; you can redistribute it and/or modify it
4995 + * under the terms of the GNU General Public License as published by the Free
4996 + * Software Foundation; either version 2 of the License, or (at your option)
4997 + * any later version.
4999 + * This program is distributed in the hope that it will be useful, but WITHOUT
5000 +1* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5001 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
5004 + * You should have received a copy of the GNU General Public License along with
5005 + * this program; if not, write to the Free Software Foundation, Inc., 59
5006 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
5008 + * The full GNU General Public License is included in this distribution in the
5009 + * file called LICENSE.
5011 + ********************************************************************************/
5013 +#include "cns3xxx_phy.h"
5014 +#include "cns3xxx_symbol.h"
5017 +#if defined(LINUX_KERNEL)
5018 +#include "cns3xxx_tool.h"
5019 +#include <linux/cns3xxx/switch_api.h> // for CAVM_OK ... macro
5020 +#include <linux/delay.h>
5021 +#include "cns3xxx_config.h"
5023 +#include <common.h>
5024 +#include "cns3xxx_switch_type.h"
5025 +#define printk printf
5028 +int cns3xxx_phy_reset(u8 phy_addr)
5032 + if (cns3xxx_read_phy(phy_addr, 0, &phy_data) != CAVM_OK)
5034 + phy_data |= (0x1 << 15);
5035 + if (cns3xxx_write_phy(phy_addr, 0, phy_data) != CAVM_OK)
5041 +// mac_port: 0, 1, 2
5042 +int cns3xxx_enable_mac_clock(u8 mac_port, u8 en)
5048 + (en==1)?(PHY_AUTO_ADDR_REG |= 1 << 7) :(PHY_AUTO_ADDR_REG &= (~(1 << 7)) );
5053 + (en==1)?(PHY_AUTO_ADDR_REG |= (1 << 15)) :(PHY_AUTO_ADDR_REG &= (~(1 << 15)) );
5058 + (en==1)?(PHY_AUTO_ADDR_REG |= (1 << 23)) :(PHY_AUTO_ADDR_REG &= (~(1 << 23)) );
5068 +int cns3xxx_phy_auto_polling_enable(u8 port, u8 en)
5070 + u8 phy_addr[]={5, 13, 21};
5072 + PHY_AUTO_ADDR_REG &= (~(1 << phy_addr[port]));
5074 + PHY_AUTO_ADDR_REG |= (1 << phy_addr[port]);
5081 +int cns3xxx_mdc_mdio_disable(u8 dis)
5084 + PHY_CTRL_REG &= (~(1 << 7));
5086 + PHY_CTRL_REG |= (1 << 7);
5092 +static int cns3xxx_phy_auto_polling_conf(int mac_port, u8 phy_addr)
5094 + if ( (mac_port < 0) || (mac_port > 2) ) {
5102 + PHY_AUTO_ADDR_REG &= (~0x1f);
5103 + PHY_AUTO_ADDR_REG |= phy_addr;
5108 + PHY_AUTO_ADDR_REG &= (~(0x1f << 8));
5109 + PHY_AUTO_ADDR_REG |= (phy_addr << 8);
5114 + PHY_AUTO_ADDR_REG &= (~(0x1f << 16));
5115 + PHY_AUTO_ADDR_REG |= (phy_addr << 16);
5119 + cns3xxx_phy_auto_polling_enable(mac_port, 1);
5125 +int cns3xxx_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data)
5128 + u32 volatile tmp = PHY_CTRL_REG;
5130 + PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit
5132 + for (delay=0; delay<10; delay++);
5136 + tmp &= (~(0x1f << 8));
5137 + tmp |= (phy_reg << 8);
5139 + tmp |= (1 << 14); // read command
5141 + PHY_CTRL_REG = tmp;
5143 + // wait command complete
5144 + while ( ((PHY_CTRL_REG >> 15) & 1) == 0);
5146 + *read_data = (PHY_CTRL_REG >> 16);
5148 + PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit
5153 +int cns3xxx_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data)
5156 + u32 tmp = PHY_CTRL_REG;
5158 + PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit
5160 + for (delay=0; delay<10; delay++);
5162 + tmp &= (~(0xffff << 16));
5163 + tmp |= (write_data << 16);
5168 + tmp &= (~(0x1f << 8));
5169 + tmp |= (phy_reg << 8);
5171 + tmp |= (1 << 13); // write command
5173 + PHY_CTRL_REG = tmp;
5175 + // wait command complete
5176 + while ( ((PHY_CTRL_REG >> 15) & 1) == 0);
5182 +void cns3xxx_rxc_dly(u8 port, u8 val)
5188 + SLK_SKEW_CTRL_REG &= (~(0x3 << 4));
5189 + SLK_SKEW_CTRL_REG |= (val << 4);
5194 + SLK_SKEW_CTRL_REG &= (~(0x3 << 12));
5195 + SLK_SKEW_CTRL_REG |= (val << 12);
5200 + SLK_SKEW_CTRL_REG &= (~(0x3 << 20));
5201 + SLK_SKEW_CTRL_REG |= (val << 20);
5208 +void cns3xxx_txc_dly(u8 port, u8 val)
5214 + SLK_SKEW_CTRL_REG &= (~(0x3 << 6));
5215 + SLK_SKEW_CTRL_REG |= (val << 6);
5220 + SLK_SKEW_CTRL_REG &= (~(0x3 << 14));
5221 + SLK_SKEW_CTRL_REG |= (val << 14);
5226 + SLK_SKEW_CTRL_REG &= (~(0x3 << 22));
5227 + SLK_SKEW_CTRL_REG |= (val << 22);
5233 +void cns3xxx_mac2_gtxd_dly(u8 val)
5235 + SLK_SKEW_CTRL_REG &= (~(0x3 << 24));
5236 + SLK_SKEW_CTRL_REG |= (val << 24);
5239 +// VITESSE suggest use isolate bit.
5240 +int vsc8601_power_down(int phy_addr, int y)
5243 + /* set isolate bit instead of powerdown */
5244 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
5245 + if (y==1) // set isolate
5246 + phy_data |= (0x1 << 10);
5247 + if (y==0) // unset isolate
5248 + phy_data &= (~(0x1 << 10));
5249 + cns3xxx_write_phy(phy_addr, 0, phy_data);
5255 +// port : 0 => port0 ; port : 1 => port1
5256 +// y = 1 ; disable AN
5257 +void disable_AN(int port, int y)
5259 + u32 mac_port_config=0;
5265 + mac_port_config = MAC0_CFG_REG;
5270 + mac_port_config = MAC1_CFG_REG;
5275 + mac_port_config = MAC2_CFG_REG;
5281 + // disable PHY's AN
5284 + mac_port_config &= ~(0x1 << 7);
5287 + // enable PHY's AN
5290 + mac_port_config |= (0x1 << 7);
5297 + MAC0_CFG_REG = mac_port_config;
5302 + MAC1_CFG_REG = mac_port_config;
5307 + MAC2_CFG_REG = mac_port_config;
5313 +int cns3xxx_std_phy_power_down(int phy_addr, int y)
5316 + // power-down or up the PHY
5317 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
5319 + phy_data |= (0x1 << 11);
5321 + phy_data &= (~(0x1 << 11));
5322 + cns3xxx_write_phy(phy_addr, 0, phy_data);
5325 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
5331 +#if defined(LINUX_KERNEL)
5332 +int cns3xxx_spi_tx_rx_n(u32 tx_data, u32 *rx_data, u32 tx_channel, u32 tx_eof_flag)
5334 + u8 cns3xxx_spi_tx_rx(u8 tx_channel, u8 tx_eof, u32 tx_data, u32 * rx_data);
5336 + return cns3xxx_spi_tx_rx(tx_channel, tx_eof_flag, tx_data, rx_data);
5339 +int bcm53115M_reg_read(int page, int offset, u8 *buf, int len)
5341 + u32 ch = BCM53115_SPI_CHANNEL;
5348 + * Normal SPI Mode (Command Byte)
5349 + * Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
5350 + * 0 1 1 Mode=0 CHIP_ID2 ID1 ID0(lsb) Rd/Wr(0/1)
5354 + /* Normal Read Operation */
5355 + /* 1. Issue a normal read command(0x60) to poll the SPIF bit in the
5356 + SPI status register(0XFE) to determine the operation can start */
5360 + cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5361 + cns3xxx_spi_tx_rx_n(0xFE, &dumy_word, ch, 0);
5362 + cns3xxx_spi_tx_rx_n(0x00, &spi_status, ch, 1);
5364 + }while ((spi_status >> ROBO_SPIF_BIT) & 1) ; // wait SPI bit to 0
5366 + /* 2. Issue a normal write command(0x61) to write the register page value
5367 + into the SPI page register(0xFF) */
5369 + cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5370 + cns3xxx_spi_tx_rx_n(0xFF, &dumy_word, ch, 0);
5371 + cns3xxx_spi_tx_rx_n(page, &dumy_word, ch, 1);
5373 + /* 3. Issue a normal read command(0x60) to setup the required RobiSwitch register
5376 + cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5377 + cns3xxx_spi_tx_rx_n(offset, &dumy_word, ch, 0);
5378 + cns3xxx_spi_tx_rx_n(0x00, &dumy_word, ch, 1);
5380 + /* 4. Issue a normal read command(0x60) to poll the RACK bit in the
5381 + SPI status register(0XFE) to determine the completion of read */
5385 + cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5386 + cns3xxx_spi_tx_rx_n(0xFE, &dumy_word, ch, 0);
5387 + cns3xxx_spi_tx_rx_n(0x00, &spi_status, ch, 1);
5389 + }while (((spi_status >> ROBO_RACK_BIT) & 1) == 0); // wait RACK bit to 1
5391 + /* 5. Issue a normal read command(0x60) to read the specific register's conternt
5392 + placed in the SPI data I/O register(0xF0) */
5394 + cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5395 + cns3xxx_spi_tx_rx_n(0xF0, &dumy_word, ch, 0);
5397 + for (i=0; i<len; i++) {
5398 + cns3xxx_spi_tx_rx_n(0x00, &dumy_word, ch, ((i==(len-1)) ? 1 : 0));
5399 + buf[i] = (u8)dumy_word;
5406 +int bcm53115M_reg_write(int page, int offset, u8 *buf, int len)
5408 + u32 ch = BCM53115_SPI_CHANNEL;
5415 + * Normal SPI Mode (Command Byte)
5416 + * Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0
5417 + * 0 1 1 Mode=0 CHIP_ID2 ID1 ID0(lsb) Rd/Wr(0/1)
5421 + /* Normal Write Operation */
5422 + /* 1. Issue a normal read command(0x60) to poll the SPIF bit in the
5423 + SPI status register(0XFE) to determine the operation can start */
5428 + cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5429 + cns3xxx_spi_tx_rx_n(0xFE, &dumy_word, ch, 0);
5430 + cns3xxx_spi_tx_rx_n(0x00, &spi_status, ch, 1);
5431 + }while ((spi_status >> ROBO_SPIF_BIT) & 1) ; // wait SPI bit to 0
5433 + /* 2. Issue a normal write command(0x61) to write the register page value
5434 + into the SPI page register(0xFF) */
5436 + cns3xxx_spi_tx_rx_n((u32)cmd_byte, &dumy_word, ch, 0);
5437 + cns3xxx_spi_tx_rx_n(0xFF, &dumy_word, ch, 0);
5438 + cns3xxx_spi_tx_rx_n(page, &dumy_word, ch, 1);
5440 + /* 3. Issue a normal write command(0x61) and write the address of the accessed
5441 + register followed by the write content starting from a lower byte */
5443 + cns3xxx_spi_tx_rx_n((u32)cmd_byte, &dumy_word, ch, 0);
5444 + cns3xxx_spi_tx_rx_n(offset, &dumy_word, ch, 0);
5446 + for (i=0; i<len; i++) {
5447 + cns3xxx_spi_tx_rx_n((u32)buf[i], &dumy_word, ch, ((i==(len-1)) ? 1 : 0));
5453 +int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
5455 +void bcm53115M_init_mac(u8 mac_port, u16 phy_addr)
5457 + u32 mac_port_config = 0;
5458 + u8 mac_addr[]={0x0c, 0x10, 0x18};
5460 + cns3xxx_enable_mac_clock(mac_port, 1);
5461 + cns3xxx_phy_auto_polling_enable(mac_port, 0);
5463 + mac_port_config = SWITCH_REG_VALUE(mac_addr[mac_port]);
5465 + // enable GMII, MII, reverse MII
5466 + mac_port_config &= (~(1 << 15));
5469 + mac_port_config |= (1 << 15);
5471 + // disable GIGA mode
5472 + mac_port_config &= (~(1<<16));
5474 + // enable GIGA mode
5475 + mac_port_config |= (1<<16);
5477 + // disable PHY's AN
5478 + mac_port_config &= (~(0x1 << 7));
5481 + mac_port_config &= (~(0x3 << 8));
5482 + mac_port_config |= (0x2 << 8);
5485 + mac_port_config |= (0x1 << 10);
5487 + // TX flow control on
5488 + mac_port_config |= (0x1 << 12);
5490 + // RX flow control on
5491 + mac_port_config |= (0x1 << 11);
5493 + // Turn off GSW_PORT_TX_CHECK_EN_BIT
5494 + mac_port_config &= (~(0x1 << 13));
5496 + // Turn on GSW_PORT_TX_CHECK_EN_BIT
5497 + mac_port_config |= (0x1 << 13);
5499 + SWITCH_REG_VALUE(mac_addr[mac_port]) = mac_port_config;
5502 +typedef struct bcm53115M_vlan_entry_t
5507 +}bcm53115M_vlan_entry;
5511 +int bcm53115M_write_vlan(bcm53115M_vlan_entry *v)
5518 + wval = (u16)v->vid;
5519 + bcm53115M_reg_write(0x05, 0x81, (u8*)&wval, 2);
5521 + // fill table content
5523 + dwval |= (v->forward_map & 0x1FF);
5524 + dwval |= ((v->untag_map& 0x1FF) << 9);
5525 + bcm53115M_reg_write(0x05, 0x83, (u8*)&wval, 4);
5528 + bval = VLAN_WRITE_CMD;
5529 + bval |= (1 << VLAN_START_BIT);
5530 + bcm53115M_reg_write(0x05, 0x80, (u8*)&bval, 1);
5532 + // wait cmd complete
5534 + bcm53115M_reg_read(0x05, 0x80, (u8*)&bval, 1);
5535 + if (((bval >> VLAN_START_BIT) & 1) == 0) break;
5541 +typedef struct bcm_port_cfg_t
5545 + BCM_PORT_SPEED speed;
5553 +int bcm53115M_mac_port_config(int port, bcm_port_cfg *cfg)
5558 + if (cfg->link) bval |= (1<<0);
5559 + if (cfg->fdx) bval |= (1<<1);
5560 + bval |= ((cfg->speed&0x3) << 2);
5561 + if (cfg->rx_flw_ctrl) bval |= (1<<4);
5562 + if (cfg->tx_flw_ctrl) bval |= (1<<5);
5564 + if (port == BCM_PORT_IMP) {
5565 + bval |= (1<<7); // Use content of this register
5573 + bcm53115M_reg_write(page, addr, &bval, 1);
5578 +int bcm53115M_init_internal_phy(void)
5583 + for (p=BCM_PORT_0; p<=BCM_PORT_4; p++) {
5587 + bcm53115M_reg_read(page, 0x00, (u8*)&wval, 2);
5589 + bcm53115M_reg_write(page, 0x00, (u8*)&wval, 2);
5591 + // config auto-nego & all advertisement
5592 + bcm53115M_reg_read(page, 0x00, (u8*)&wval, 2);
5593 + wval |= (1<<12); // auto-nego
5594 + bcm53115M_reg_write(page, 0x00, (u8*)&wval, 2);
5596 + bcm53115M_reg_read(page, 0x08, (u8*)&wval, 2);
5597 + wval |= 0x1E0; // advertisement all
5598 + bcm53115M_reg_write(page, 0x08, (u8*)&wval, 2);
5601 + bcm53115M_reg_read(page, 0x12, (u8*)&wval, 2);
5602 + wval &= ~(1<<12); // automatic master/slave configuration
5603 + wval |= 0x300; // 1000-base full/half advertisements
5604 + bcm53115M_reg_write(page, 0x12, (u8*)&wval, 2);
5610 +int bcm53115M_led_init(void)
5612 + u16 led_func, bval, wval;
5614 + /* LED function 1G/ACT, 100M/ACT, 10M/ACT, not used */
5615 + led_func = 0x2C00;
5616 + bcm53115M_reg_write(0x00, 0x10, (u8*)&led_func, 2);
5617 + bcm53115M_reg_write(0x00, 0x12, (u8*)&led_func, 2);
5619 + /* LED map enable */
5620 + wval = 0x1F; // port0~4
5621 + bcm53115M_reg_write(0x00, 0x16, (u8*)&wval, 2);
5623 + /* LED mode map */
5624 + wval = 0x1F; // led auto mode
5625 + bcm53115M_reg_write(0x00, 0x18, (u8*)&wval, 2);
5626 + bcm53115M_reg_write(0x00, 0x1A, (u8*)&wval, 2);
5629 + bcm53115M_reg_read(0x00, 0x0F, (u8*)&bval, 1);
5631 + bcm53115M_reg_write(0x00, 0x0F, (u8*)&bval, 1);
5636 +//#define BCM53115M_DUMMY_SWITCH
5637 +#define BCM53115M_DISABLE_LEARNING
5639 +int bcm53115M_init(u8 mac_port, u16 phy_addr)
5645 + bcm53115M_vlan_entry v_ent;
5647 + u8 page=0, offset=0;
5649 + printk("bcm53115M init\n");
5651 + memset(&v_ent, 0, sizeof(bcm53115M_vlan_entry));
5654 + gpio_direction_output(50, 0);
5655 + bcm53115M_init_mac(0, 0);
5656 + bcm53115M_init_mac(1, 1);
5659 + bcm53115M_reg_read(0x02, 0x30, (u8*)&u32_val, 4);
5660 + printk("bcm53115M device id:(0x%x)\r\n", u32_val);
5662 + if (u32_val != 0x53115) {
5663 + printk("bad device id(0x%x)\r\n", u32_val);
5669 + bcm53115M_reg_read(0x10, 0x04, (u8 *)&u16_val, 2);
5670 + printk("bcm53115M phy id_1:(0x%x)\r\n", u16_val);
5672 + if (u16_val != 0x143) {
5673 + printk("bad phy id1(0x%x)\r\n", u16_val);
5679 + bcm53115M_reg_read(0x10, 0x06, (u8 *)&u16_val, 2);
5680 + printk("bcm53115M phy id_2:(0x%x)\r\n", u16_val);
5682 +#ifdef BCM53115M_DUMMY_SWITCH
5684 + bcm53115M_reg_read(0x00, 0x0e, (u8 *)&bval, 1);
5685 + printk("bcm53115M page:0 addr:0x0e ## %x\n", bval);
5692 + printk("bval : %x\n", bval);
5693 + bcm53115M_reg_write(0x00, 0x0e, (u8 *)&bval, 1);
5694 + bcm53115M_reg_read(0x00, 0x0e, (u8 *)&bval, 1);
5695 + printk("bcm53115M page:0 addr:0x0e ## %x\n", bval);
5697 + /* Unmanagement mode */
5698 + // Switch Mode. Page 00h,Address 0Bh
5699 + bval = 0x06; // forward enable, unmanaged mode
5700 + //bval = 0x3; // forward enable, managed mode
5701 + bcm53115M_reg_write(0x0, 0xb, &bval, 1);
5702 + bcm53115M_reg_read(0x0, 0xb, (u8 *)&bval, 1);
5703 + printk("bcm53115M page:0 addr:0xb ## %x\n", bval);
5706 + offset=0x5d; // port 5
5708 + bcm53115M_reg_write(page, offset, (u8 *)&bval, 1);
5709 + bcm53115M_reg_read(page, offset, (u8 *)&bval, 1);
5711 + printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, bval);
5714 + offset=0x58; // port 0
5716 + bcm53115M_reg_write(page, offset, (u8 *)&bval, 1);
5717 + bcm53115M_reg_read(page, offset, (u8 *)&bval, 1);
5718 + printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, bval);
5720 +#ifdef CONFIG_CNS3XXX_JUMBO_FRAME
5721 + printk("enable BCM53115 jumbo frame\n");
5725 + u32_val=0x013f; // enable 0-5 port and IMP port jumbo frame. MAX frame: 9720 bytes.
5726 + bcm53115M_reg_write(page, offset, (u8 *)&u32_val, 4);
5727 + bcm53115M_reg_read(page, offset, (u8 *)&u32_val, 4);
5728 + printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, u32_val);
5734 + bcm53115M_reg_write(page, offset, (u8 *)&u16_val, 2);
5739 +#else // !BCM53115M_DUMMY_SWITCH
5740 + /* Loop detection disable */
5741 + bcm53115M_reg_read(0x72, 0x00, (u8 *)&u16_val, 2);
5742 + u16_val &= ~(0x3<<11);
5743 + bcm53115M_reg_write(0x72, 0x00, (u8 *)&u16_val, 2);
5746 + /* VLAN forwarding mask */
5747 + // Bit8 IMP port, Bits[5:0] correspond to ports[5:0]
5748 + // port 0 <-> port IMP
5750 + bcm53115M_reg_write(0x31, 0x0, (u8 *)&u16_val, 2); // port 0
5752 + bcm53115M_reg_write(0x31, 0x10, (u8 *)&u16_val, 2); // IMP
5755 + // port 4 <-> port 5
5757 + bcm53115M_reg_write(0x31, 0x08, (u8 *)&u16_val, 2); // port 4
5759 + bcm53115M_reg_write(0x31, 0x0A, (u8 *)&u16_val, 2); // port 5
5762 + // others <-> none
5764 + bcm53115M_reg_write(0x31, 0x02, (u8 *)&u16_val, 2); // port 1
5765 + bcm53115M_reg_write(0x31, 0x04, (u8 *)&u16_val, 2); // port 2
5766 + bcm53115M_reg_write(0x31, 0x06, (u8 *)&u16_val, 2); // port 3
5768 + // port 1 <-> port IMP
5770 + bcm53115M_reg_write(0x31, 0x2, (u8 *)&u16_val, 2); // port 1
5772 + // port 2 <-> port 5
5774 + bcm53115M_reg_write(0x31, 0x4, (u8 *)&u16_val, 2); // port 2
5776 + // port 3 <-> port 5
5778 + bcm53115M_reg_write(0x31, 0x6, (u8 *)&u16_val, 2); // port 3
5780 + /* Create VLAN1 for default port pvid */
5783 + v_ent.forward_map = 0x13F; // all ports
5784 + robo_write_vlan(&v_ent);
5787 + /* Unmanagement mode */
5788 + // Switch Mode. Page 00h,Address 0Bh
5789 + bval = 0x02; // forward enable, unmanaged mode
5790 + bcm53115M_reg_write(0x0, 0xb, &bval, 1);
5792 + /* Init port5 & IMP (test giga mode first) */
5793 + // IMP port control. Page 00h,Address 08h
5794 + bval = 0x1C; // RX UCST/MCST/BCST enable
5795 + bcm53115M_reg_write(0x0, 0x8, &bval, 1);
5797 + offset=0x5d; // port 5
5799 + bcm53115M_reg_write(page, offset, (u8 *)&bval, 1);
5800 + bcm53115M_reg_read(page, offset, (u8 *)&bval, 1);
5802 + // Speed, dulplex......etc
5803 + // setting in Gsw_Configure_Gsw_Hardware()
5805 + // Mgmt configuration, Page 02h, Address 00h
5807 + bcm53115M_reg_write(0x02, 0x00, &bval, 1);
5808 + // BRCM header, Page 02h, Address 03h
5809 + bval = 0; // without additional header information
5810 + bcm53115M_reg_write(0x02, 0x03, &bval, 1);
5812 + /* Init front ports, port0-4 */
5814 + pc.speed = BCM_PORT_1G;
5815 + pc.link = 0; // link detect by robo_port_update()
5817 + for (i=BCM_PORT_0; i<=BCM_PORT_4; i++)
5818 + bcm53115M_mac_port_config(i, &pc);
5820 + bcm53115M_init_internal_phy();
5822 + /* Enable all port, STP_STATE=No spanning tree, TX/RX enable */
5823 + // Page 00h, Address 00h-05h
5825 + for (i=0; i<=5; i++)
5826 + bcm53115M_reg_write(0x0, i, &bval, 1);
5828 + // Disable broadcast storm control due to h/w strap pin BC_SUPP_EN
5829 + // Page 41h, Address 10h-13h, bit28&22
5832 + for (i=0 ; i <= 0x14; i+=4) {
5833 + bcm53115M_reg_read(0x41, 0x10+i, (u8 *)&u32_val, 4);
5834 + u32_val &= ~((1<<28) | (1<<22));
5835 + bcm53115M_reg_write(0x41, 0x10+i, (u8 *)&u32_val, 4);
5839 + bcm53115M_reg_read(0x41, 0x30, (u8 *)&u32_val, 4);
5840 + u32_val &= ~((1<<28) | (1<<22));
5841 + bcm53115M_reg_write(0x41, 0x30, (u8 *)&u32_val, 4);
5845 + bcm53115M_led_init();
5846 + // multicast fwd rule, Page 00h, Address 2Fh
5848 + bcm53115M_reg_write(0x00, 0x2F, &bval, 1);
5850 +#ifdef BCM53115M_DISABLE_LEARNING
5851 + // disable learning
5855 + bcm53115M_reg_write(page, offset, (u8 *)&u16_val, 2);
5856 + bcm53115M_reg_read(page, offset, (u8 *)&u16_val, 2);
5861 + bcm53115M_reg_write(page, offset, (u8 *)&u32_val, 4);
5866 +#endif // defined(LINUX_KERNEL)
5868 +//#define MAC2_RGMII
5869 +#define CNS3XXX_MAC2_IP1001_GIGA_MODE
5871 +void icp_ip1001_init_mac(u8 mac_port, u16 phy_addr)
5873 + u32 mac_port_config = 0;
5874 + u8 mac_addr[]={0x0c, 0x10, 0x18};
5876 + cns3xxx_enable_mac_clock(mac_port, 1);
5878 + mac_port_config = SWITCH_REG_VALUE(mac_addr[mac_port]);
5880 + //cns3xxx_txc_dly(mac_port, 2);
5881 + //cns3xxx_rxc_dly(mac_port, 2);
5882 + //SLK_SKEW_CTRL_REG
5885 + // enable GMII, MII, reverse MII
5886 + mac_port_config &= (~(1 << 15));
5889 + mac_port_config |= (1 << 15);
5892 + // TXC check disable
5893 + //mac_port_config &= (~(1 << 13));
5895 + // disable GIGA mode
5896 + mac_port_config &= (~(1<<16));
5898 +#ifdef CNS3XXX_MAC2_IP1001_GIGA_MODE
5899 + // enable GIGA mode
5900 + mac_port_config |= (1<<16);
5902 + //mac_port_config |= (1<<19);
5905 + // disable PHY's AN
5906 + mac_port_config &= (~(0x1 << 7));
5908 + // enable PHY's AN
5909 + mac_port_config |= (0x1 << 7);
5911 + // disable PHY's AN
5912 + mac_port_config &= (~(0x1 << 7));
5913 + // disable GIGA mode
5914 + mac_port_config &= (~(1<<16));
5917 + mac_port_config &= (~(0x3 << 8));
5918 + mac_port_config |= (0x1 << 8);
5921 + mac_port_config |= (0x1 << 10);
5923 + // TX flow control off
5924 + mac_port_config &= (~(0x1 << 12));
5926 + // RX flow control off
5927 + mac_port_config &= (~(0x1 << 11));
5930 + // TX flow control on
5931 + mac_port_config |= (0x1 << 12);
5933 + // RX flow control on
5934 + mac_port_config |= (0x1 << 11);
5937 + // enable GMII, MII, reverse MII
5938 + mac_port_config &= (~(1 << 15));
5940 + SWITCH_REG_VALUE(mac_addr[mac_port]) = mac_port_config;
5942 + // If mac port AN turns on, auto polling needs to turn on.
5943 + cns3xxx_phy_auto_polling_conf(mac_port, phy_addr);
5947 +int icp_ip1001_init(u8 mac_port, u8 phy_addr)
5951 + printk("mac_port: %d ## phy_addr: %d\n", mac_port, phy_addr);
5952 + cns3xxx_mdc_mdio_disable(0);
5955 + // GMII2 high speed drive strength
5956 + IOCDA_REG &= ((~3 << 10));
5957 + IOCDA_REG |= (1 << 10);
5959 + IOCDA_REG = 0x55555800;
5961 + phy_data = get_phy_id(phy_addr); // should be 0x243
5963 + printk("ICPLUS IP 1001 phy id : %x\n", phy_data);
5965 + if (phy_data != 0x0243) {
5966 + printk("wrong phy id!!\n");
5971 + cns3xxx_phy_reset(phy_addr);
5973 + icp_ip1001_init_mac(mac_port, phy_addr);
5975 + // read advertisement register
5976 + cns3xxx_read_phy(phy_addr, 0x4, &phy_data);
5978 + // enable PAUSE frame capability
5979 + phy_data |= (0x1 << 10);
5981 + phy_data &= (~(0x1 << 5));
5982 + phy_data &= (~(0x1 << 6));
5983 + phy_data &= (~(0x1 << 7));
5984 + phy_data &= (~(0x1 << 8));
5987 + phy_data |= (0x1 << 5);
5988 + phy_data |= (0x1 << 6);
5989 + phy_data |= (0x1 << 7);
5990 + phy_data |= (0x1 << 8);
5993 + cns3xxx_write_phy(phy_addr, 0x4, phy_data);
5995 + cns3xxx_read_phy(phy_addr, 9, &phy_data);
5997 + phy_data &= (~(1<<8)); // remove advertise 1000 half duples
5998 + phy_data &= (~(1<<9)); // remove advertise 1000 full duples
5999 +#ifdef CNS3XXX_MAC2_IP1001_GIGA_MODE
6000 + //phy_data |= (1<<8); // add advertise 1000 half duples
6001 + phy_data |= (1<<9); // add advertise 1000 full duples
6003 + cns3xxx_write_phy(phy_addr, 9, phy_data);
6005 + cns3xxx_read_phy(phy_addr, 9, &phy_data);
6007 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
6009 + phy_data |= (0x1 << 12);
6010 + cns3xxx_write_phy(phy_addr, 0, phy_data);
6012 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
6014 + phy_data |= (0x1 << 9);
6015 + cns3xxx_write_phy(phy_addr, 0, phy_data);
6019 +#define PHY_CONTROL_REG_ADDR 0x00
6020 +#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
6022 +int icp_101a_init_mac(u8 port, u8 phy_addr)
6024 + u32 mac_port_config = 0;
6026 + cns3xxx_enable_mac_clock(port, 1);
6032 + mac_port_config = MAC0_CFG_REG;
6037 + mac_port_config = MAC1_CFG_REG;
6042 + mac_port_config = MAC2_CFG_REG;
6047 + // enable GMII, MII, reverse MII
6048 + mac_port_config &= (~(1 << 15));
6050 + // disable PHY's AN, use force mode
6051 + mac_port_config &= (~(0x1 << 7));
6052 +#ifdef CONFIG_FPGA_FORCE
6055 + mac_port_config &= (~(0x3 << 8));
6056 + mac_port_config |= (0x1 << 8);
6059 + mac_port_config |= (0x1 << 10);
6061 + // TX flow control on
6062 + mac_port_config |= (0x1 << 12);
6064 + // RX flow control on
6065 + mac_port_config |= (0x1 << 11);
6067 + // Turn off GSW_PORT_TX_CHECK_EN_BIT
6068 + mac_port_config &= (~(0x1 << 13));
6070 + // enable PHY's AN
6071 + mac_port_config |= (0x1 << 7);
6072 + // If mac port AN turns on, auto polling needs to turn on.
6073 + cns3xxx_phy_auto_polling_conf(port, phy_addr);
6076 + mac_port_config &= (~(1 << 14));
6083 + MAC0_CFG_REG = mac_port_config;
6088 + MAC1_CFG_REG = mac_port_config;
6093 + MAC2_CFG_REG = mac_port_config;
6102 +int icp_101a_init(u8 mac_port, u8 phy_addr)
6104 + u32 mac_port_config=0;
6107 + cns3xxx_mdc_mdio_disable(0);
6108 + cns3xxx_phy_reset(phy_addr);
6110 + phy_data = get_phy_id(mac_port);
6111 + if (phy_data != 0x0243) {
6112 + printk("ICPLUS 101A phy id should be 0x243, but the phy id is : %x\n", phy_data);
6115 + printk("phy id : %x\n", phy_data);
6116 + printk("init IC+101A\n");
6118 + icp_101a_init_mac(mac_port, phy_addr);
6120 + // read advertisement register
6121 + cns3xxx_read_phy(phy_addr, 0x4, &phy_data);
6123 + // enable PAUSE frame capability
6124 + phy_data |= (0x1 << 10);
6126 + cns3xxx_write_phy(phy_addr, 0x4, phy_data);
6128 +#ifndef CONFIG_FPGA_FORCE
6134 + mac_port_config = MAC0_CFG_REG;
6139 + mac_port_config = MAC1_CFG_REG;
6144 + mac_port_config = MAC2_CFG_REG;
6150 + if (!(mac_port_config & (0x1 << 5))) {
6151 + if (cns3xxx_read_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, &phy_data) == CAVM_ERR)
6153 + //PDEBUG("\n PORT%d, enable local flow control capability Fail\n", port);
6158 + // enable PAUSE frame capability
6159 + phy_data |= (0x1 << 10);
6161 + if (cns3xxx_write_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, phy_data) == CAVM_ERR)
6163 + //PDEBUG("\nPORT%d, enable PAUSE frame capability Fail\n", port);
6170 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
6172 + phy_data |= (0x1 << 12);
6175 + phy_data |= (0x1 << 9);
6176 + cns3xxx_write_phy(phy_addr, 0, phy_data);
6180 + //PDEBUG ("\n Polling PHY%d AN \n", port);
6181 + cns3xxx_read_phy (phy_data, 0, &phy_data);
6183 + if (phy_data & (0x1 << 9)) {
6186 + //PDEBUG ("\n PHY%d AN restart is complete \n", port);
6196 +int cns3xxx_config_VSC8601_mac(u8 port)
6198 + u32 mac_port_config = 0;
6204 + mac_port_config = MAC0_CFG_REG;
6209 + mac_port_config = MAC1_CFG_REG;
6214 + mac_port_config = MAC2_CFG_REG;
6223 + MAC0_CFG_REG = mac_port_config;
6228 + MAC1_CFG_REG = mac_port_config;
6233 + MAC2_CFG_REG = mac_port_config;
6240 +u16 get_phy_id(u8 phy_addr)
6244 + cns3xxx_read_phy(phy_addr, 2, &read_data);
6249 +u32 get_vsc8601_recv_err_counter(u8 phy_addr)
6252 + cns3xxx_read_phy(phy_addr, 19, &read_data);
6256 +u32 get_crc_good_counter(u8 phy_addr)
6260 + // enter extended register mode
6261 + cns3xxx_write_phy(phy_addr, 31, 0x0001);
6263 + cns3xxx_read_phy(phy_addr, 18, &read_data);
6265 + // back to normal register mode
6266 + cns3xxx_write_phy(phy_addr, 31, 0x0000);
6271 +int cns3xxx_config_VSC8601(u8 mac_port, u8 phy_addr)
6274 + u32 mac_port_config=0;
6275 + //u8 tx_skew=1, rx_skew=1;
6278 + cns3xxx_mdc_mdio_disable(0);
6280 + cns3xxx_read_phy(phy_addr, 0, &phy_data);
6282 + phy_data |= (0x1 << 15);
6283 + cns3xxx_write_phy(phy_addr, 0, phy_data);
6286 + phy_id = get_phy_id(phy_addr);
6287 + if (phy_id != 0x143) {
6295 + mac_port_config = MAC0_CFG_REG;
6300 + mac_port_config = MAC1_CFG_REG;
6305 + mac_port_config = MAC2_CFG_REG;
6310 + cns3xxx_enable_mac_clock(mac_port, 1);
6311 + //phy_auto_polling(mac_port, phy_addr);
6313 + // enable RGMII-PHY mode
6314 + mac_port_config |= (0x1 << 15);
6316 + // If mac AN turns on, auto polling needs to turn on.
6317 + // enable PHY's AN
6318 + mac_port_config |= (0x1 << 7);
6319 + cns3xxx_phy_auto_polling_conf(mac_port, phy_addr);
6321 + // enable GSW MAC port 0
6322 + mac_port_config &= ~(0x1 << 18);
6325 + mac_port_config &= (~(1 << 14));
6331 + MAC0_CFG_REG = mac_port_config;
6332 + printk("8601 MAC0_CFG_REG: %x\n", MAC0_CFG_REG);
6337 + MAC1_CFG_REG = mac_port_config;
6338 + printk("8601 MAC1_CFG_REG: %x\n", MAC1_CFG_REG);
6343 + MAC2_CFG_REG = mac_port_config;
6348 + cns3xxx_write_phy(phy_addr, 0x18, 0xf1e7);
6349 + cns3xxx_write_phy(phy_addr, 0x1c, 0x8e00);
6350 + cns3xxx_write_phy(phy_addr, 0x10, 0x20);
6351 + cns3xxx_write_phy(phy_addr, 0x1c, 0xa41f);
6352 + cns3xxx_write_phy(phy_addr, 0x1c, 0xb41a);
6353 + cns3xxx_write_phy(phy_addr, 0x1c, 0xb863);
6354 + cns3xxx_write_phy(phy_addr, 0x17, 0xf04);
6355 + cns3xxx_write_phy(phy_addr, 0x15, 0x1);
6356 + cns3xxx_write_phy(phy_addr, 0x17, 0x0);
6363 +#ifdef CONFIG_LIBRA
6364 +void icp_175c_all_phy_power_down(int y)
6368 + for (i=0 ; i < 5 ; ++i)
6369 + std_phy_power_down(i, y);
6373 +static int star_gsw_config_icplus_175c_phy4(void)
6375 + u16 phy_data = 0, phy_data2 = 0;
6376 + u32 volatile ii, jj;
6377 + u8 phy_speed_dup = 0, phy_flowctrl = 0;
6379 + u8 gsw_mac_0_phy_addr = 0;
6380 + u8 gsw_mac_1_phy_addr = 1;
6383 + printk("config IC+175C\n");
6385 + * Configure MAC port 0
6386 + * For IP175C Switch setting
6387 + * Force 100Mbps, and full-duplex, and flow control on
6389 + reg = GSW_MAC_PORT_0_CONFIG_REG;
6391 + // disable PHY's AN
6392 + reg &= ~(0x1 << 7);
6394 + // disable RGMII-PHY mode
6395 + reg &= ~(0x1 << 15);
6397 + // force speed = 100Mbps
6398 + reg &= ~(0x3 << 8);
6399 + reg |= (0x1 << 8);
6401 + // force full-duplex
6402 + reg |= (0x1 << 10);
6404 + // force Tx/Rx flow-control on
6405 + reg |= (0x1 << 11) | (0x1 << 12);
6407 + GSW_MAC_PORT_0_CONFIG_REG = reg;
6410 + for (ii = 0; ii < 0x2000; ii++)
6412 + reg = GSW_MAC_PORT_0_CONFIG_REG;
6414 + if ((reg & 0x1) && !(reg & 0x2))
6417 + * enable MAC port 0
6419 + reg &= ~(0x1 << 18);
6423 + * enable the forwarding of unknown, multicast and broadcast packets to CPU
6425 + reg &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
6428 + * include unknown, multicast and broadcast packets into broadcast storm
6430 + reg |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31));
6432 + GSW_MAC_PORT_0_CONFIG_REG = reg;
6438 + for (jj = 0; jj < 0x1000; jj++);
6441 + if ((ii % 4) == 0)
6442 + printk("\rCheck MAC/PHY 0 Link Status : |");
6443 + else if ((ii % 4) == 1)
6444 + printk("\rCheck MAC/PHY 0 Link Status : /");
6445 + else if ((ii % 4) == 2)
6446 + printk("\rCheck MAC/PHY 0 Link Status : -");
6447 + else if ((ii % 4) == 3)
6448 + printk("\rCheck MAC/PHY 0 Link Status : \\");
6453 + if (!(reg & 0x1) || (reg & 0x2))
6456 + * Port 0 PHY link down or no TXC in Port 0
6458 + printk("\rCheck MAC/PHY 0 Link Status : DOWN!\n");
6464 + printk("\rCheck MAC/PHY 0 Link Status : UP!\n");
6470 + * Configure MAC port 1
6472 + reg = GSW_MAC_PORT_0_CONFIG_REG;
6474 + // disable MAC's AN
6475 + reg &= ~(0x1 << 7);
6477 + GSW_MAC_PORT_0_CONFIG_REG = reg;
6480 + /* enable flow control on (PAUSE frame) */
6481 + star_gsw_read_phy(gsw_mac_1_phy_addr, 0x4, &phy_data);
6483 + phy_data |= (0x1 << 10);
6485 + star_gsw_write_phy(gsw_mac_1_phy_addr, 0x4, phy_data);
6488 + /* 2007/12/18 Jerry
6489 + The software reset of IC+ 175C won't reset MII register 29, 30, 31.
6490 + Router Control Register: bit 7 (TAG_VLAN_EN) is a VLAN related filed which affect vlan setting.
6491 + Router Control Register: bit 3 (ROUTER_EN) enable router function at MII port.
6492 + We set them to default to let U-boot properly work.
6494 + phy_data = 0x1001;
6495 + star_gsw_write_phy(30, 9, phy_data);
6497 + /* restart PHY auto neg. */
6498 + star_gsw_read_phy(gsw_mac_1_phy_addr, 0x0, &phy_data);
6500 + phy_data |= (0x1 << 9) | (0x1 << 12);
6502 + star_gsw_write_phy(gsw_mac_1_phy_addr, 0x0, phy_data);
6506 + /* wait for PHY auto neg. complete */
6507 + for (ii = 0; ii < 0x20; ii++)
6509 + star_gsw_read_phy(gsw_mac_1_phy_addr, 0x1, &phy_data);
6511 + if ((phy_data & (0x1 << 2)) && (phy_data & (0x1 << 5)))
6517 + if ((ii % 4) == 0)
6518 + printk("\rCheck MAC/PHY 1 Link Status : |");
6519 + else if ((ii % 4) == 1)
6520 + printk("\rCheck MAC/PHY 1 Link Status : /");
6521 + else if ((ii % 4) == 2)
6522 + printk("\rCheck MAC/PHY 1 Link Status : -");
6523 + else if ((ii % 4) == 3)
6524 + printk("\rCheck MAC/PHY 1 Link Status : \\");
6531 + printk("\rCheck MAC/PHY 1 Link Status : DOWN!\n");
6537 + printk("\rCheck MAC/PHY 1 Link Status : UP!\n");
6541 + star_gsw_read_phy(gsw_mac_1_phy_addr, 0x4, &phy_data);
6543 + star_gsw_read_phy(gsw_mac_1_phy_addr, 0x5, &phy_data2);
6546 + if (phy_data & 0x0400) //FC on
6548 + //printk("<FC ON>");
6553 + // printk("<FC OFF>");
6558 + phy_speed_dup = 0;
6560 + if ((phy_data & 0x0100) && (phy_data2 & 0x0100)) //100F
6562 + // printk("<100F>");
6563 + phy_speed_dup |= (0x1 << 3); //set bit3 for 100F
6565 + else if ((phy_data & 0x0080) && (phy_data2 & 0x0080)) //100F
6567 + // printk("<100H>");
6568 + phy_speed_dup |= (0x1 << 2);
6570 + else if ((phy_data & 0x0040) && (phy_data2 & 0x0040)) //100F
6572 + // printk("<10F>");
6573 + phy_speed_dup |= (0x1 << 1);
6575 + else if ((phy_data & 0x0020) && (phy_data2 & 0x0020)) //100F
6577 + // printk("<10H>");
6578 + phy_speed_dup |= 0x1;
6583 + * Configure MAC port 1 in forced setting subject to the current PHY status
6585 + reg = GSW_MAC_PORT_1_CONFIG_REG;
6587 + reg &= ~(0x1 << 7); //AN off
6589 + reg &= ~(0x3 << 8);
6591 + if (phy_speed_dup & 0x0C) //100
6593 + //printk("<set 100>");
6594 + reg |= (0x01 << 8);
6596 + else if (phy_speed_dup & 0x03) //10
6598 + //printk("<set 10>");
6599 + reg |= (0x00 << 8);
6602 + reg &= ~(0x1 << 11);
6604 + if (phy_flowctrl) //FC on
6606 + //printk("<set FC on>");
6607 + reg |= (0x1 << 11);
6611 + //printk("<set FC off>");
6612 + reg |= (0x0 << 11);
6615 + reg &= ~(0x1 << 10);
6617 + if ((phy_speed_dup & 0x2) || (phy_speed_dup & 0x8)) //FullDup
6619 + //printk("<set full>");
6620 + reg |= (0x1 << 10);
6624 + //printk("<set half>");
6625 + reg |= (0x0 << 10); //Half
6628 + GSW_MAC_PORT_1_CONFIG_REG = reg;
6632 + * Check MAC port 1 link status
6634 + for (ii = 0; ii < 0x1000; ii++)
6636 + reg = GSW_MAC_PORT_1_CONFIG_REG;
6638 + if ((reg & 0x1) && !(reg & 0x2))
6641 + * enable MAC port 1
6643 + reg &= ~(0x1 << 18);
6646 + * enable the forwarding of unknown, multicast and broadcast packets to CPU
6648 + reg &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
6651 + * include unknown, multicast and broadcast packets into broadcast storm
6653 + reg |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31));
6655 + GSW_MAC_PORT_1_CONFIG_REG = reg;
6665 + * Port 1 PHY link down or no TXC in Port 1
6667 + printk("\rCheck MAC/PHY 1 Link Status : DOWN!\n");
6676 +static int star_gsw_config_VSC8201(u8 mac_port, u8 phy_addr) // include cicada 8201
6678 + //u32 mac_port_base = 0;
6679 + u32 mac_port_config=0;
6683 + printk("\nconfigure VSC8201\n");
6684 + //PDEBUG("mac port : %d phy addr : %d\n", mac_port, phy_addr);
6686 + * Configure MAC port 0
6687 + * For Cicada CIS8201 single PHY
6689 + if (mac_port == 0) {
6690 + //PDEBUG("port 0\n");
6691 + mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6693 + if (mac_port == 1) {
6694 + //PDEBUG("port 1\n");
6695 + mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6698 + star_gsw_set_phy_addr(mac_port, phy_addr);
6699 + //star_gsw_set_phy_addr(1, 1);
6701 + //mac_port_config = __REG(mac_port_base);
6703 + // enable PHY's AN
6704 + mac_port_config |= (0x1 << 7);
6706 + // enable RGMII-PHY mode
6707 + mac_port_config |= (0x1 << 15);
6709 + // enable GSW MAC port 0
6710 + mac_port_config &= ~(0x1 << 18);
6712 + if (mac_port == 0) {
6713 + //PDEBUG("port 0\n");
6714 + GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6716 + if (mac_port == 1) {
6717 + //PDEBUG("port 1\n");
6718 + GSW_MAC_PORT_1_CONFIG_REG = mac_port_config;
6722 + * Configure Cicada's CIS8201 single PHY
6724 +#ifdef CONFIG_STAR9100_SHNAT_PCI_FASTPATH
6725 + /* near-end loopback mode */
6726 + star_gsw_read_phy(phy_addr, 0x0, &phy_reg);
6727 + phy_reg |= (0x1 << 14);
6728 + star_gsw_write_phy(phy_addr, 0x0, phy_reg);
6731 + star_gsw_read_phy(phy_addr, 0x1C, &phy_reg);
6733 + // configure SMI registers have higher priority over MODE/FRC_DPLX, and ANEG_DIS pins
6734 + phy_reg |= (0x1 << 2);
6736 + star_gsw_write_phy(phy_addr, 0x1C, phy_reg);
6738 + star_gsw_read_phy(phy_addr, 0x17, &phy_reg);
6740 + // enable RGMII MAC interface mode
6741 + phy_reg &= ~(0xF << 12);
6742 + phy_reg |= (0x1 << 12);
6744 + // enable RGMII I/O pins operating from 2.5V supply
6745 + phy_reg &= ~(0x7 << 9);
6746 + phy_reg |= (0x1 << 9);
6748 + star_gsw_write_phy(phy_addr, 0x17, phy_reg);
6750 + star_gsw_read_phy(phy_addr, 0x4, &phy_reg);
6752 + // Enable symmetric Pause capable
6753 + phy_reg |= (0x1 << 10);
6755 + star_gsw_write_phy(phy_addr, 0x4, phy_reg);
6759 + if (mac_port == 0) {
6760 + //PDEBUG("port 0\n");
6761 + mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6763 + if (mac_port == 1) {
6764 + //PDEBUG("port 1\n");
6765 + mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6774 + // enable PHY's AN
6775 + mac_port_config |= (0x1 << 7);
6777 + if (mac_port == 0) {
6778 + //PDEBUG("port 0\n");
6779 + GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6781 + if (mac_port == 1) {
6782 + //PDEBUG("port 1\n");
6783 + GSW_MAC_PORT_1_CONFIG_REG = mac_port_config;
6787 + * Enable PHY1 AN restart bit to restart PHY1 AN
6789 + star_gsw_read_phy(phy_addr, 0x0, &phy_reg);
6791 + phy_reg |= (0x1 << 9) | (0x1 << 12);
6793 + star_gsw_write_phy(phy_addr, 0x0, phy_reg);
6796 + * Polling until PHY0 AN restart is complete
6798 + for (i = 0; i < 0x1000; i++) {
6799 + star_gsw_read_phy(phy_addr, 0x1, &phy_reg);
6801 + if ((phy_reg & (0x1 << 5)) && (phy_reg & (0x1 << 2))) {
6802 + printk("0x1 phy reg: %x\n", phy_reg);
6809 + if (mac_port == 0) {
6810 + //PDEBUG("port 0\n");
6811 + mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6813 + if (mac_port == 1) {
6814 + //PDEBUG("port 1\n");
6815 + mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6818 + if (((mac_port_config & 0x1) == 0) || (mac_port_config & 0x2)) {
6819 + printk("Check MAC/PHY%s Link Status : DOWN!\n", (mac_port == 0 ? "0" : "1"));
6821 + printk("Check MAC/PHY%s Link Status : UP!\n", (mac_port == 0 ? "0" : "1"));
6823 + * There is a bug for CIS8201 PHY operating at 10H mode, and we use the following
6824 + * code segment to work-around
6826 + star_gsw_read_phy(phy_addr, 0x05, &phy_reg);
6828 + if ((phy_reg & (0x1 << 5)) && (!(phy_reg & (0x1 << 6))) && (!(phy_reg & (0x1 << 7))) && (!(phy_reg & (0x1 << 8)))) { /* 10H,10F/100F/100H off */
6829 + star_gsw_read_phy(phy_addr, 0x0a, &phy_reg);
6831 + if ((!(phy_reg & (0x1 << 10))) && (!(phy_reg & (0x1 << 11)))) { /* 1000F/1000H off */
6832 + star_gsw_read_phy(phy_addr, 0x16, &phy_reg);
6834 + phy_reg |= (0x1 << 13) | (0x1 << 15); // disable "Link integrity check(B13)" & "Echo mode(B15)"
6836 + star_gsw_write_phy(phy_addr, 0x16, phy_reg);
6841 + if (mac_port == 0) {
6842 + // adjust MAC port 0 RX/TX clock skew
6843 + GSW_BIST_RESULT_TEST_0_REG &= ~((0x3 << 24) | (0x3 << 26));
6844 + GSW_BIST_RESULT_TEST_0_REG |= ((0x2 << 24) | (0x2 << 26));
6847 + if (mac_port == 1) {
6848 + // adjust MAC port 1 RX/TX clock skew
6849 + GSW_BIST_RESULT_TEST_0_REG &= ~((0x3 << 28) | (0x3 << 30));
6850 + GSW_BIST_RESULT_TEST_0_REG |= ((0x2 << 28) | (0x2 << 30));
6859 +static void star_gsw_config_VSC8X01()
6863 +#ifdef CONFIG_DORADO2
6864 + star_gsw_set_phy_addr(1,1);
6865 + star_gsw_read_phy(1, 0x02, &phy_id);
6866 + // printk("phy id = %X\n", phy_id);
6867 + if (phy_id == 0x000F) //VSC8201
6868 + star_gsw_config_VSC8201(1,1);
6870 + star_gsw_config_VSC8601(1,1);
6873 + star_gsw_set_phy_addr(0,0);
6874 + star_gsw_read_phy(0, 0x02, &phy_id);
6875 + // printk("phy id = %X\n", phy_id);
6876 + if (phy_id == 0x000F) //VSC8201
6877 + star_gsw_config_VSC8201(0,0);
6879 + star_gsw_config_VSC8601(0,0);
6885 +#if defined(CONFIG_DORADO) || defined(CONFIG_DORADO2)
6886 +static int star_gsw_config_port0_VSC7385(void)
6888 + u32 mac_port_config=0;
6891 + printk("config VSC7385\n");
6893 + mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6895 + // disable PHY's AN
6896 + mac_port_config &= ~(0x1 << 7);
6898 + // enable RGMII-PHY mode
6899 + mac_port_config |= (0x1 << 15);
6901 + // force speed = 1000Mbps
6902 + mac_port_config &= ~(0x3 << 8);
6903 + mac_port_config |= (0x2 << 8);
6905 + // force full-duplex
6906 + mac_port_config |= (0x1 << 10);
6908 + // force Tx/Rx flow-control on
6909 + mac_port_config |= (0x1 << 11) | (0x1 << 12);
6911 + GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6915 + for (i = 0; i < 50000; i++) {
6916 + mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6917 + if ((mac_port_config & 0x1) && !(mac_port_config & 0x2)) {
6924 + if (!(mac_port_config & 0x1) || (mac_port_config & 0x2)) {
6925 + printk("MAC0 PHY Link Status : DOWN!\n");
6928 + printk("MAC0 PHY Link Status : UP!\n");
6931 + // enable MAC port 0
6932 + mac_port_config &= ~(0x1 << 18);
6934 + // disable SA learning
6935 + mac_port_config |= (0x1 << 19);
6937 + // forward unknown, multicast and broadcast packets to CPU
6938 + mac_port_config &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
6940 + // storm rate control for unknown, multicast and broadcast packets
6941 + mac_port_config |= (0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31);
6943 + GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6945 + // disable MAC port 1
6946 + mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6947 + mac_port_config |= (0x1 << 18);
6948 + GSW_MAC_PORT_1_CONFIG_REG = mac_port_config;
6950 + // adjust MAC port 0 /RX/TX clock skew
6951 + GSW_BIST_RESULT_TEST_0_REG &= ~((0x3 << 24) | (0x3 << 26));
6952 + GSW_BIST_RESULT_TEST_0_REG |= ((0x2 << 24) | (0x2 << 26));
6958 +++ b/drivers/net/cns3xxx/cns3xxx_phy.h
6960 +/*******************************************************************************
6963 + * Copyright (c) 2009 Cavium Networks
6965 + * This program is free software; you can redistribute it and/or modify it
6966 + * under the terms of the GNU General Public License as published by the Free
6967 + * Software Foundation; either version 2 of the License, or (at your option)
6968 + * any later version.
6970 + * This program is distributed in the hope that it will be useful, but WITHOUT
6971 +1* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6972 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
6975 + * You should have received a copy of the GNU General Public License along with
6976 + * this program; if not, write to the Free Software Foundation, Inc., 59
6977 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6979 + * The full GNU General Public License is included in this distribution in the
6980 + * file called LICENSE.
6982 + ********************************************************************************/
6984 +#ifndef CNS3XXX_PHY_H
6985 +#define CNS3XXX_PHY_H
6987 +#define LINUX_KERNEL // if don't define LINUX_KERNEL, mean u-boot
6989 +#if defined(LINUX_KERNEL)
6990 +#include <linux/version.h>
6991 +#include <linux/types.h>
6993 +#define __init_or_module
6994 +#include "cns3xxx_symbol.h"
6997 +void disable_AN(int port, int y);
6999 +u16 get_phy_id(u8 phy_addr);
7000 +int cns3xxx_std_phy_power_down(int phy_addr, int y);
7001 +u32 get_vsc8601_recv_err_counter(u8 phy_addr);
7002 +u32 get_crc_good_counter(u8 phy_addr);
7003 +int cns3xxx_config_VSC8601(u8 mac_port, u8 phy_addr);
7004 +int vsc8601_power_down(int phy_addr, int y);
7005 +int icp_101a_init(u8 mac_port, u8 phy_addr);
7006 +int bcm53115M_init(u8 mac_port, u16 phy_addr);
7007 +int icp_ip1001_init(u8 mac_port, u8 phy_addr);
7009 +int cns3xxx_phy_auto_polling_enable(u8 port, u8 en);
7011 +int cns3xxx_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data);
7012 +int cns3xxx_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data);
7014 +// wrap cns3xxx_spi_tx_rx() for argument order
7015 +int cns3xxx_spi_tx_rx_n(u32 tx_data, u32 *rx_data, u32 tx_channel, u32 tx_eof_flag);
7018 +#define ROBO_SPIF_BIT 7
7019 +#define BCM53115_SPI_CHANNEL 1
7020 +#define ROBO_RACK_BIT 5
7022 +#define VLAN_START_BIT 7
7023 +#define VLAN_WRITE_CMD 0
7025 +//#define BCM_PORT_1G 2
7033 +#define BCM_PORT_0 0
7034 +#define BCM_PORT_1 1
7035 +#define BCM_PORT_2 2
7036 +#define BCM_PORT_3 3
7037 +#define BCM_PORT_4 4
7038 +#define BCM_PORT_5 5
7039 +#define BCM_PORT_IMP 6
7041 +#endif // end #ifndef CNS3XXX_PHY_H
7043 +++ b/drivers/net/cns3xxx/cns3xxx_sppe_hook.c
7045 +/******************************************************************************
7047 + * Copyright (c) 2008 Cavium Networks
7049 + * This file is free software; you can redistribute it and/or modify
7050 + * it under the terms of the GNU General Public License, Version 2, as
7051 + * published by the Free Software Foundation.
7053 + * This file is distributed in the hope that it will be useful,
7054 + * but AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty of
7055 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
7056 + * NONINFRINGEMENT. See the GNU General Public License for more details.
7058 + * You should have received a copy of the GNU General Public License
7059 + * along with this file; if not, write to the Free Software
7060 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA or
7061 + * visit http://www.gnu.org/licenses/.
7063 + * This file may also be available under a different license from Cavium.
7064 + * Contact Cavium Networks for more information
7066 + ******************************************************************************/
7068 +#if defined(CONFIG_CNS3XXX_SPPE)
7069 +#include <linux/module.h>
7070 +#include <linux/cns3xxx/sppe.h>
7072 +int sppe_hook_ready = 0;
7073 +int (*sppe_func_hook)(SPPE_PARAM *param) = NULL;
7074 +int sppe_pci_fp_ready = 0;
7075 +int (*sppe_pci_fp_hook)(SPPE_PARAM *param) = NULL;
7077 +EXPORT_SYMBOL(sppe_hook_ready);
7078 +EXPORT_SYMBOL(sppe_func_hook);
7079 +EXPORT_SYMBOL(sppe_pci_fp_ready);
7080 +EXPORT_SYMBOL(sppe_pci_fp_hook);
7082 +#endif //#if defined(CONFIG_CNS3XXX_SPPE)
7085 +++ b/drivers/net/cns3xxx/cns3xxx_symbol.h
7087 +/*******************************************************************************
7089 + * Copyright (c) 2009 Cavium Networks
7091 + * This program is free software; you can redistribute it and/or modify it
7092 + * under the terms of the GNU General Public License as published by the Free
7093 + * Software Foundation; either version 2 of the License, or (at your option)
7094 + * any later version.
7096 + * This program is distributed in the hope that it will be useful, but WITHOUT
7097 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7098 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
7101 + * You should have received a copy of the GNU General Public License along with
7102 + * this program; if not, write to the Free Software Foundation, Inc., 59
7103 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
7105 + * The full GNU General Public License is included in this distribution in the
7106 + * file called LICENSE.
7108 + ********************************************************************************/
7110 +// the symbol define memory map register.
7112 +#ifndef CNS3XXX_SYMBOL_H
7113 +#define CNS3XXX_SYMBOL_H
7115 +#define DRV_VERSION "Cavium CNS3XXX Switch Driver-0.0.1"
7118 +#define LINUX_KERNEL // if don't define LINUX_KERNEL, mean u-boot
7120 +#if defined(LINUX_KERNEL)
7122 +#include <mach/board.h>
7124 +#define SWITCH_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_SWITCH_BASE_VIRT+offset)))
7125 +#define PMU_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_PM_BASE_VIRT+offset)))
7126 +#define MISC_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3XXX_MISC_BASE_VIRT+offset)))
7129 +#define NETDEV_SIZE 4097+3
7131 +#define PORT0_NETDEV_INDEX NETDEV_SIZE-3
7132 +#define PORT1_NETDEV_INDEX NETDEV_SIZE-2
7133 +#define PORT2_NETDEV_INDEX NETDEV_SIZE-1
7135 +#if defined (CONFIG_CNS3XXX_SPPE)
7136 +#define FP_NETDEV_INDEX NETDEV_SIZE-4
7139 +#define PORT0_NETDEV net_dev_array[PORT0_NETDEV_INDEX]
7140 +#define PORT1_NETDEV net_dev_array[PORT1_NETDEV_INDEX]
7141 +#define PORT2_NETDEV net_dev_array[PORT2_NETDEV_INDEX]
7143 +#if defined (CONFIG_CNS3XXX_SPPE)
7144 +#define FP_NETDEV net_dev_array[FP_NETDEV_INDEX]
7148 +#include <malloc.h> // for u8, u32
7150 +#include "cns3000.h"
7153 +#define CAVM_NOT_FOUND 2
7154 +#define CAVM_FOUND 3
7155 +#define CAVM_FAIL -1 // use minus
7157 +#define SWITCH_REG_VALUE(addr) (*((volatile unsigned int *)(CNS3000_VEGA_SWITCH_BASE+addr)))
7158 +#define PMU_REG_VALUE(addr) (*((volatile unsigned int *)(CNS3000_VEGA_PM_BASE+addr)))
7159 +#define MISC_REG_VALUE(offset) (*((volatile unsigned int *)(CNS3000_VEGA_MISC_BASE+offset)))
7163 +// for VLAN and ARL table MB_PMAP
7164 +#define MAC_PORT0_PMAP 1
7165 +#define MAC_PORT1_PMAP (1 << 1)
7166 +#define MAC_PORT2_PMAP (1 << 4)
7167 +#define CPU_PORT_PMAP (1 << 2)
7171 +// memory map register definition
7173 +//#define PHY_CTRL_REG (*(u32 volatile*(0xff)))
7174 +#define PHY_CTRL_REG SWITCH_REG_VALUE(0x0)
7175 +#define PHY_AUTO_ADDR_REG SWITCH_REG_VALUE(0x04)
7177 +#define MAC_GLOB_CFG_REG SWITCH_REG_VALUE(0x08)
7178 +#define MAC_GLOB_CFG_EXT_REG SWITCH_REG_VALUE(0xf4)
7179 +#define MAC0_CFG_REG SWITCH_REG_VALUE(0x0c)
7180 +#define MAC1_CFG_REG SWITCH_REG_VALUE(0x10)
7181 +#define MAC2_CFG_REG SWITCH_REG_VALUE(0x18)
7182 +#define CPU_CFG_REG SWITCH_REG_VALUE(0x14)
7184 +#define MAC0_PRI_CTRL_REG SWITCH_REG_VALUE(0x1c)
7185 +#define MAC1_PRI_CTRL_REG SWITCH_REG_VALUE(0x20)
7186 +#define CPU_PRI_CTRL_REG SWITCH_REG_VALUE(0x24)
7187 +#define HNAT_PRI_CTRL_REG SWITCH_REG_VALUE(0x28)
7188 +#define MAC2_PRI_CTRL_REG SWITCH_REG_VALUE(0x2c)
7190 +#define MAC0_PRI_CTRL_EXT_REG SWITCH_REG_VALUE(0x30)
7192 +#define ETYPE1_ETYPE0_REG SWITCH_REG_VALUE(0x34)
7193 +#define ETYPE3_ETYPE2_REG SWITCH_REG_VALUE(0x38)
7195 +#define UDP_RANGE0_REG SWITCH_REG_VALUE(0x3c)
7196 +#define UDP_RANGE1_REG SWITCH_REG_VALUE(0x40)
7197 +#define UDP_RANGE2_REG SWITCH_REG_VALUE(0x44)
7198 +#define UDP_RANGE3_REG SWITCH_REG_VALUE(0x48)
7201 +#define PRIO_ETYPE_UDP_REG SWITCH_REG_VALUE(0x4c)
7203 +#define PRIO_IPDSCP_7_0_REG SWITCH_REG_VALUE(0x50)
7204 +#define PRIO_IPDSCP_15_8_REG SWITCH_REG_VALUE(0x54)
7205 +#define PRIO_IPDSCP_23_16_REG SWITCH_REG_VALUE(0x58)
7206 +#define PRIO_IPDSCP_31_24_REG SWITCH_REG_VALUE(0x5c)
7207 +#define PRIO_IPDSCP_39_32_REG SWITCH_REG_VALUE(0x60)
7208 +#define PRIO_IPDSCP_47_40_REG SWITCH_REG_VALUE(0x64)
7209 +#define PRIO_IPDSCP_55_48_REG SWITCH_REG_VALUE(0x68)
7210 +#define PRIO_IPDSCP_63_56_REG SWITCH_REG_VALUE(0x6c)
7212 +#define TC_CTRL_REG SWITCH_REG_VALUE(0x70)
7213 +#define RATE_CTRL_REG SWITCH_REG_VALUE(0x74)
7215 +#define FC_GLOB_THRS_REG SWITCH_REG_VALUE(0x78)
7216 +#define FC_PORT_THRS_REG SWITCH_REG_VALUE(0x7c)
7217 +#define MC_GLOB_THRS_REG SWITCH_REG_VALUE(0x80)
7218 +#define DC_GLOB_THRS_REG SWITCH_REG_VALUE(0x84)
7220 +#define ARL_VLAN_CMD_REG SWITCH_REG_VALUE(0x88)
7222 +#define ARL_CTRL0_REG SWITCH_REG_VALUE(0x8c)
7223 +#define ARL_CTRL1_REG SWITCH_REG_VALUE(0x90)
7224 +#define ARL_CTRL2_REG SWITCH_REG_VALUE(0x94)
7226 +#define VLAN_CFG SWITCH_REG_VALUE(0x098)
7228 +#define MAC1_MAC0_PVID_REG SWITCH_REG_VALUE(0x9c)
7229 +#define MAC2_CPU_PVID_REG SWITCH_REG_VALUE(0xa0)
7231 +#define VLAN_CTRL0_REG SWITCH_REG_VALUE(0xa4)
7232 +#define VLAN_CTRL1_REG SWITCH_REG_VALUE(0xa8)
7233 +#define VLAN_CTRL2_REG SWITCH_REG_VALUE(0xac)
7235 +#define SESSION_ID_1_0_REG SWITCH_REG_VALUE(0xb0)
7236 +#define SESSION_ID_3_2_REG SWITCH_REG_VALUE(0xb4)
7237 +#define SESSION_ID_5_4_REG SWITCH_REG_VALUE(0xb8)
7238 +#define SESSION_ID_7_6_REG SWITCH_REG_VALUE(0xbc)
7239 +#define SESSION_ID_9_8_REG SWITCH_REG_VALUE(0xc0)
7240 +#define SESSION_ID_11_10_REG SWITCH_REG_VALUE(0xc4)
7241 +#define SESSION_ID_13_12_REG SWITCH_REG_VALUE(0xc8)
7242 +#define SESSION_ID_15_14_REG SWITCH_REG_VALUE(0xcc)
7244 +#define INTR_STAT_REG SWITCH_REG_VALUE(0xd0)
7245 +#define INTR_MASK_REG SWITCH_REG_VALUE(0xd4)
7247 +#define SRAM_TEST_REG SWITCH_REG_VALUE(0xd8)
7249 +#define MEM_QUEUE_REG SWITCH_REG_VALUE(0xdc)
7251 +#define SARL_CTRL_REG SWITCH_REG_VALUE(0xe0)
7252 +#define SARL_OQ_GTH_REG SWITCH_REG_VALUE(0xe4)
7253 +#define SARL_OQ_YTH_REG SWITCH_REG_VALUE(0xe8)
7254 +#define SARL_OQ_RTH_REG SWITCH_REG_VALUE(0xec)
7256 +#define SLK_SKEW_CTRL_REG SWITCH_REG_VALUE(0xf0)
7258 +#define DMA_RING_CTRL_REG SWITCH_REG_VALUE(0x100)
7260 +#define DMA_AUTO_POLL_CFG_REG SWITCH_REG_VALUE(0x104)
7262 +#define DELAY_INTR_CFG_REG SWITCH_REG_VALUE(0x108)
7264 +#define TS_DMA_CTRL0_REG SWITCH_REG_VALUE(0x110)
7265 +#define TS_DESC_PTR0_REG SWITCH_REG_VALUE(0x114)
7266 +#define TS_DESC_BASE_ADDR0_REG SWITCH_REG_VALUE(0x118)
7268 +#define FS_DMA_CTRL0_REG SWITCH_REG_VALUE(0x120)
7269 +#define FS_DESC_PTR0_REG SWITCH_REG_VALUE(0x124)
7270 +#define FS_DESC_BASE_ADDR0_REG SWITCH_REG_VALUE(0x128)
7272 +#define TS_DMA_CTRL1_REG SWITCH_REG_VALUE(0x130)
7273 +#define TS_DESC_PTR1_REG SWITCH_REG_VALUE(0x134)
7274 +#define TS_DESC_BASE_ADDR1_REG SWITCH_REG_VALUE(0x138)
7276 +#define FS_DMA_CTRL1_REG SWITCH_REG_VALUE(0x140)
7277 +#define FS_DESC_PTR1_REG SWITCH_REG_VALUE(0x144)
7278 +#define FS_DESC_BASE_ADDR1_REG SWITCH_REG_VALUE(0x148)
7280 +#define TS_DMA_STA_REG SWITCH_REG_VALUE(0x150)
7281 +#define FS_DMA_STA_REG SWITCH_REG_VALUE(0x154)
7283 +#define TS_MRD_CMD_CNT_REG SWITCH_REG_VALUE(0x158)
7284 +#define TS_MWT_CMD_CNT_REG SWITCH_REG_VALUE(0x15c)
7286 +#define FS_MRD_CMD_CNT_REG SWITCH_REG_VALUE(0x160)
7287 +#define FS_MWT_CMD_CNT_REG SWITCH_REG_VALUE(0x164)
7289 +#define C_RXOKPKT_MAC0_REG SWITCH_REG_VALUE(0x300)
7290 +#define C_RXOKBYTE_MAC0_REG SWITCH_REG_VALUE(0x304)
7291 +#define C_RXRUNT_MAC0_REG SWITCH_REG_VALUE(0x308)
7292 +#define C_RXLONG_MAC0_REG SWITCH_REG_VALUE(0x30c)
7293 +#define C_RXDROP_MAC0_REG SWITCH_REG_VALUE(0x310)
7294 +#define C_RXCRC_MAC0_REG SWITCH_REG_VALUE(0x314)
7295 +#define C_RXARLDROP_MAC0_REG SWITCH_REG_VALUE(0x318)
7296 +#define C_VIDROP_MAC0_REG SWITCH_REG_VALUE(0x31c)
7297 +#define C_VEDROP_MAC0_REG SWITCH_REG_VALUE(0x320)
7298 +#define C_RXRL_MAC0_REG SWITCH_REG_VALUE(0x324)
7299 +#define C_RXPAUSE_MAC0_REG SWITCH_REG_VALUE(0x328)
7301 +#define C_TXOKPKT_MAC0_REG SWITCH_REG_VALUE(0x32c)
7302 +#define C_TXOKBYTE_MAC0_REG SWITCH_REG_VALUE(0x330)
7303 +#define C_TXPAUSECOL_MAC0_REG SWITCH_REG_VALUE(0x334)
7305 +#define C_RXOKPKT_MAC1_REG SWITCH_REG_VALUE(0x400)
7306 +#define C_RXOKBYTE_MAC1_REG SWITCH_REG_VALUE(0x404)
7307 +#define C_RXRUNT_MAC1_REG SWITCH_REG_VALUE(0x408)
7308 +#define C_RXLONG_MAC1_REG SWITCH_REG_VALUE(0x40c)
7309 +#define C_RXDROP_MAC1_REG SWITCH_REG_VALUE(0x410)
7310 +#define C_RXCRC_MAC1_REG SWITCH_REG_VALUE(0x414)
7311 +#define C_RXARLDROP_MAC1_REG SWITCH_REG_VALUE(0x418)
7312 +#define C_VIDROP_MAC1_REG SWITCH_REG_VALUE(0x41c)
7313 +#define C_VEDROP_MAC1_REG SWITCH_REG_VALUE(0x420)
7314 +#define C_RXRL_MAC1_REG SWITCH_REG_VALUE(0x424)
7315 +#define C_RXPAUSE_MAC1_REG SWITCH_REG_VALUE(0x428)
7317 +#define C_TXOKPKT_MAC1_REG SWITCH_REG_VALUE(0x42c)
7318 +#define C_TXOKBYTE_MAC1_REG SWITCH_REG_VALUE(0x430)
7319 +#define C_TXPAUSECOL_MAC1_REG SWITCH_REG_VALUE(0x434)
7321 +#define C_TSOKPKT_CPU_REG SWITCH_REG_VALUE(0x500)
7322 +#define C_TSOKBYTE_CPU_REG SWITCH_REG_VALUE(0x504)
7323 +#define C_TSRUNT_CPU_REG SWITCH_REG_VALUE(0x508)
7324 +#define C_TSLONG_CPU_REG SWITCH_REG_VALUE(0x50c)
7325 +#define C_TSNODSTDROP_CPU_REG SWITCH_REG_VALUE(0x510)
7326 +#define C_TSARLDROP_CPU_REG SWITCH_REG_VALUE(0x514)
7327 +#define C_TSVIDROP_CPU_REG SWITCH_REG_VALUE(0x518)
7328 +#define C_TSVEDROP_CPU_REG SWITCH_REG_VALUE(0x51c)
7329 +#define C_TSRL_CPU_REG SWITCH_REG_VALUE(0x520)
7331 +#define C_FSOKPKT_CPU_REG SWITCH_REG_VALUE(0x524)
7332 +#define C_FSOKBYTE_CPU_REG SWITCH_REG_VALUE(0x528)
7334 +#define C_RXOKPKT_MAC2_REG SWITCH_REG_VALUE(0x600)
7335 +#define C_RXOKBYTE_MAC2_REG SWITCH_REG_VALUE(0x604)
7336 +#define C_RXRUNT_MAC2_REG SWITCH_REG_VALUE(0x608)
7337 +#define C_RXLONG_MAC2_REG SWITCH_REG_VALUE(0x60c)
7338 +#define C_RXDROP_MAC2_REG SWITCH_REG_VALUE(0x610)
7339 +#define C_RXCRC_MAC2_REG SWITCH_REG_VALUE(0x614)
7340 +#define C_RXARLDROP_MAC2_REG SWITCH_REG_VALUE(0x618)
7341 +#define C_VIDROP_MAC2_REG SWITCH_REG_VALUE(0x61c)
7342 +#define C_VEDROP_MAC2_REG SWITCH_REG_VALUE(0x620)
7343 +#define C_RXRL_MAC2_REG SWITCH_REG_VALUE(0x624)
7344 +#define C_RXPAUSE_MAC2_REG SWITCH_REG_VALUE(0x628)
7346 +#define C_TXOKPKT_MAC2_REG SWITCH_REG_VALUE(0x62c)
7347 +#define C_TXOKBYTE_MAC2_REG SWITCH_REG_VALUE(0x630)
7348 +#define C_TXPAUSECOL_MAC2_REG SWITCH_REG_VALUE(0x634)
7350 +#define C_TXOKPKT_MAC0_EXT_REG SWITCH_REG_VALUE(0x72c)
7351 +#define C_TXOKBYTE_MAC0_EXT_REG SWITCH_REG_VALUE(0x730)
7353 +#define CLK_GATE_REG PMU_REG_VALUE(0x0)
7354 +#define SOFT_RST_REG PMU_REG_VALUE(0x4)
7355 +#define PLL_HM_PD_CTRL_REG PMU_REG_VALUE(0x1c)
7357 +#define GPIOB_PIN_EN_REG MISC_REG_VALUE(0x18)
7358 +#define IOCDA_REG MISC_REG_VALUE(0x1c)
7360 +#define LEVEL_HIGH 0
7361 +#define RISING_EDGE 1
7363 +#ifdef CONFIG_SILICON
7365 +#define STATUS_INTERRUPT_ID 49
7367 +#define FSRC_RING0_INTERRUPT_ID 51
7368 +#define FSQF_RING0_INTERRUPT_ID 53
7370 +#define FSRC_RING1_INTERRUPT_ID 55
7371 +#define FSQF_RING1_INTERRUPT_ID 57
7373 +#define TSTC_RING0_INTERRUPT_ID 50
7375 +#define TSTC_RING1_INTERRUPT_ID 54
7377 +#define HNAT_INTERRUPT_ID 58
7381 +//#define STATUS_INTERRUPT_ID 49
7382 +#define STATUS_INTERRUPT_ID 38
7383 +//#define FSRC_RING0_INTERRUPT_ID 51
7384 +#define FSRC_RING0_INTERRUPT_ID 40
7386 +#define TSQE_RING0_INTERRUPT_ID 52
7388 +//#define FSQF_RING0_INTERRUPT_ID 53
7389 +#define FSQF_RING0_INTERRUPT_ID 42
7391 +#define FSQF_RING1_INTERRUPT_ID 46
7392 +#define FSRC_RING1_INTERRUPT_ID 44
7394 +//#define FSRC_RING1_INTERRUPT_ID 55
7396 +#define TSTC_RING0_INTERRUPT_ID 39
7397 +#define TSTC_RING1_INTERRUPT_ID 43
7399 +#define TSQE_RING1_INTERRUPT_ID 56
7400 +#define HNAT_INTERRUPT_ID 58
7401 +#endif // #ifdef CONFIG_SILICON
7405 +++ b/drivers/net/cns3xxx/cns3xxx_tool.h
7407 +/*******************************************************************************
7410 + * Copyright (c) 2009 Cavium Networks
7412 + * This program is free software; you can redistribute it and/or modify it
7413 + * under the terms of the GNU General Public License as published by the Free
7414 + * Software Foundation; either version 2 of the License, or (at your option)
7415 + * any later version.
7417 + * This program is distributed in the hope that it will be useful, but WITHOUT
7418 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
7419 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
7422 + * You should have received a copy of the GNU General Public License along with
7423 + * this program; if not, write to the Free Software Foundation, Inc., 59
7424 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
7426 + * The full GNU General Public License is included in this distribution in the
7427 + * file called LICENSE.
7429 + ********************************************************************************/
7431 +#ifndef CNS3XXX_TOOL_H
7432 +#define CNS3XXX_TOOL_H
7434 +#define PRINT_INFO printk
7436 +#if defined(__KERNEL__)
7438 +#include "cns3xxx.h"
7439 +#include <linux/kernel.h> // for printk
7445 +#define SHOW_DEBUG_MESSAGE
7446 +#ifdef SHOW_DEBUG_MESSAGE
7448 +extern int MSG_LEVEL;
7451 +#define NORMAL_MSG 1
7452 +#define WARNING_MSG (1 << 1)
7453 +#define CRITICAL_MSG (1 << 2)
7454 +#define DUMP_RX_PKT_INFO (1 << 3)
7455 +#define DUMP_TX_PKT_INFO (1 << 4)
7457 +#define DEBUG_MSG(msg_level, fmt, args...)\
7461 + for(i=0 ; i < 3 ; ++i) { \
7462 + if ((MSG_LEVEL & msg_level) >> i) \
7463 + printk(KERN_INFO "*cns3xxx gsw debug* " fmt, ## args); \
7469 +#define GET_MAC_PORT_CFG(port, cfg) \
7475 + cfg = MAC0_CFG_REG; \
7480 + cfg = MAC1_CFG_REG; \
7485 + cfg = MAC2_CFG_REG; \
7491 +#define SET_MAC_PORT_CFG(port, cfg) \
7497 + MAC0_CFG_REG = cfg; \
7502 + MAC1_CFG_REG = cfg; \
7507 + MAC2_CFG_REG = cfg; \
7513 +#define between(x, start, end) ((x)>=(start) && (x)<=(end))
7514 +static inline void print_packet(unsigned char *data, int len)
7518 + printk("packet length: %d%s:\n", len, len>128?"(only show the first 128 bytes)":"");
7526 + for(j=0;j<16;j++) {
7527 + printk("%02x ", data[i++]);
7532 + for(j=0;j<16;j++) {
7533 + if( between(data[i], 0x21, 0x7e) ) {
7534 + printk("%c", data[i++]);
7548 + for(j=0; j<len; j++) {
7549 + printk("%02x ", data[i++]);
7557 + for(j=0;j<len;j++) {
7558 + if( between(data[i], 0x21, 0x7e) ) {
7559 + printk("%c", data[i++]);
7578 +static inline void cns3xxx_gsw_power_enable(void)
7580 + PLL_HM_PD_CTRL_REG &= (~(1 << 2)); // power up PLL_RGMII (for MAC)
7581 + CLK_GATE_REG |= (1 << 11); // enable switch clock
7584 +static inline void cns3xxx_gsw_software_reset(void)
7586 + SOFT_RST_REG &= (~(1 << 11));
7587 + SOFT_RST_REG |= (1 << 11);
7598 +static inline void enable_port(u8 port, u8 enable)
7604 + (enable==1) ? (MAC0_CFG_REG &= (~(1 << 18)) ) : (MAC0_CFG_REG |= (1 << 18)) ;
7610 + (enable==1) ? (MAC1_CFG_REG &= (~(1 << 18)) ) : (MAC1_CFG_REG |= (1 << 18)) ;
7615 + (enable==1) ? (MAC2_CFG_REG &= (~(1 << 18)) ) : (MAC2_CFG_REG |= (1 << 18)) ;
7620 + (enable==1) ? (CPU_CFG_REG &= (~(1 << 18)) ) : (CPU_CFG_REG |= (1 << 18)) ;
7626 +static inline int cns3xxx_vlan_table_lookup(VLANTableEntry *entry)
7628 + VLAN_CTRL2_REG |= entry->vid;
7629 + ARL_VLAN_CMD_REG |= (1 << 8); // look up vlan table command
7631 + // wait for vlan command complete
7632 + while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ;
7634 + if (!((ARL_VLAN_CMD_REG >> 10) & 1)) {
7635 + // not found any entry
7636 + return CAVM_NOT_FOUND;
7639 + entry->valid = ((VLAN_CTRL0_REG >> 31) & 0x1);
7640 + entry->vid = ((VLAN_CTRL2_REG >> 31) & 0xfff);
7641 + entry->wan_side = ((VLAN_CTRL0_REG >> 30) & 0x1);
7642 + entry->etag_pmap = ((VLAN_CTRL0_REG >> 25) & 0x1f);
7643 + entry->mb_pmap = ((VLAN_CTRL0_REG >> 9) & 0x1f);
7645 + entry->my_mac[0] = ((VLAN_CTRL1_REG >> 24) & 0xff);
7646 + entry->my_mac[1] = ((VLAN_CTRL1_REG >> 16) & 0xff);
7647 + entry->my_mac[2] = ((VLAN_CTRL1_REG >> 8) & 0xff);
7648 + entry->my_mac[3] = (VLAN_CTRL1_REG & 0xff);
7650 + entry->my_mac[4] = ((VLAN_CTRL2_REG >> 24) & 0xff);
7651 + entry->my_mac[5] = ((VLAN_CTRL2_REG >> 16) & 0xff);
7653 + return CAVM_FOUND;
7656 +static inline int cns3xxx_vlan_table_read(VLANTableEntry *entry)
7658 + //printf("VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7659 + ARL_VLAN_CMD_REG &= (~0x3f);
7660 + ARL_VLAN_CMD_REG |= (entry->vlan_index);
7661 + ARL_VLAN_CMD_REG |= (1 << 7); // read vlan table command
7662 + //printf("after read ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG);
7664 + // wait for vlan command complete
7665 + while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ;
7667 + //printf("ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG);
7668 + //printf("VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7670 + entry->valid = ((VLAN_CTRL0_REG >> 31) & 0x1);
7671 + entry->vid = ((VLAN_CTRL2_REG) & 0xfff);
7672 + entry->wan_side = ((VLAN_CTRL0_REG >> 30) & 0x1);
7673 + entry->etag_pmap = ((VLAN_CTRL0_REG >> 25) & 0x1f);
7674 + entry->mb_pmap = ((VLAN_CTRL0_REG >> 9) & 0x1f);
7676 + entry->my_mac[0] = ((VLAN_CTRL1_REG >> 24) & 0xff);
7677 + entry->my_mac[1] = ((VLAN_CTRL1_REG >> 16) & 0xff);
7678 + entry->my_mac[2] = ((VLAN_CTRL1_REG >> 8) & 0xff);
7679 + entry->my_mac[3] = (VLAN_CTRL1_REG & 0xff);
7681 + entry->my_mac[4] = ((VLAN_CTRL2_REG >> 24) & 0xff);
7682 + entry->my_mac[5] = ((VLAN_CTRL2_REG >> 16) & 0xff);
7689 +// add a entry in the vlan table
7690 +static inline int cns3xxx_vlan_table_add(VLANTableEntry *entry)
7692 + VLAN_CTRL0_REG = 0;
7693 + VLAN_CTRL1_REG = 0;
7694 + VLAN_CTRL2_REG = 0;
7697 + printk("a [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7698 + printk("a [kernel mode] VLAN_CTRL1_REG: %x\n", VLAN_CTRL1_REG);
7699 + printk("a [kernel mode] VLAN_CTRL2_REG: %x\n", VLAN_CTRL2_REG);
7702 + //printk("vlan_index: %x\n", entry->vlan_index);
7703 + VLAN_CTRL0_REG |= (entry->valid << 31);
7704 + //DEBUG_MSG(NORMAL_MSG, "1 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7705 + VLAN_CTRL0_REG |= (entry->wan_side << 30);
7706 + //DEBUG_MSG(NORMAL_MSG, "2 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7707 + //printk("entry->etag_pmap: %x\n", entry->etag_pmap);
7708 + VLAN_CTRL0_REG |= (entry->etag_pmap << 25);
7709 + //DEBUG_MSG(NORMAL_MSG, "3 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7710 + //printk("entry->mb_pmap: %x\n", entry->mb_pmap);
7711 + VLAN_CTRL0_REG |= (entry->mb_pmap << 9);
7712 + //DEBUG_MSG(NORMAL_MSG, "4 [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7713 + //printk("bb [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7715 + //printf("vlan index: %d ## add VLAN_CTRL0_REG: %x\n", entry->vlan_index, VLAN_CTRL0_REG);
7718 + VLAN_CTRL1_REG |= (entry->my_mac[0] << 24);
7719 + VLAN_CTRL1_REG |= (entry->my_mac[1] << 16);
7720 + VLAN_CTRL1_REG |= (entry->my_mac[2] << 8);
7721 + VLAN_CTRL1_REG |= (entry->my_mac[3]);
7723 + VLAN_CTRL2_REG |= (entry->my_mac[4] << 24);
7724 + VLAN_CTRL2_REG |= (entry->my_mac[5] << 16);
7725 + VLAN_CTRL2_REG |= entry->vid;
7728 + printk("b [kernel mode] VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7729 + printk("b [kernel mode] VLAN_CTRL1_REG: %x\n", VLAN_CTRL1_REG);
7730 + printk("b [kernel mode] VLAN_CTRL2_REG: %x\n", VLAN_CTRL2_REG);
7733 + ARL_VLAN_CMD_REG &= (~0x3f);
7734 + ARL_VLAN_CMD_REG |= (entry->vlan_index);
7735 + ARL_VLAN_CMD_REG |= (1 << 6); // write vlan table command
7738 + //printf("after write ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG);
7740 + // wait for vlan command complete
7741 + while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ;
7746 +static inline void print_arl_table_entry(ARLTableEntry *entry)
7748 + printk("vid: %d\n", entry->vid);
7749 + printk("pmap: %#x\n", entry->pmap);
7750 + printk("age_field: %d\n", entry->age_field);
7751 + printk("vlan_mac: %d\n", entry->vlan_mac);
7752 + printk("filter: %d\n", entry->filter);
7753 + 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]);
7758 +static inline int cns3xxx_arl_table_lookup(ARLTableEntry *entry)
7760 + ARL_CTRL0_REG = 0;
7761 + ARL_CTRL1_REG = 0;
7762 + ARL_CTRL2_REG = 0;
7764 + ARL_CTRL0_REG |= (entry->vid << 16);
7766 + ARL_CTRL1_REG |= (entry->mac[0] << 24);
7767 + ARL_CTRL1_REG |= (entry->mac[1] << 16);
7768 + ARL_CTRL1_REG |= (entry->mac[2] << 8);
7769 + ARL_CTRL1_REG |= entry->mac[3];
7771 + ARL_CTRL2_REG |= (entry->mac[4] << 24);
7772 + ARL_CTRL2_REG |= (entry->mac[5] << 16);
7774 + ARL_VLAN_CMD_REG |= (1 << 18); // arl table lookup command
7776 + // wait arl command complete
7777 + while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7779 + if (( (ARL_VLAN_CMD_REG >> 23) & 1)) {
7782 + entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff);
7783 + entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f);
7785 + entry->age_field = ((ARL_CTRL2_REG >> 4 ) & 0x7);
7786 + entry->vlan_mac = ((ARL_CTRL2_REG >> 1 ) & 0x1);
7787 + entry->filter = (ARL_CTRL2_REG & 0x1);
7790 + return CAVM_NOT_FOUND;
7793 + printk("[kernel mode] ARL_VLAN_CMD_REG : %#x\n", ARL_VLAN_CMD_REG);
7794 + printk("[kernel mode] ARL_CTRL0_REG : %#x\n", ARL_CTRL0_REG);
7795 + printk("[kernel mode] ARL_CTRL1_REG : %#x\n", ARL_CTRL1_REG);
7796 + printk("[kernel mode] ARL_CTRL2_REG : %#x\n", ARL_CTRL2_REG);
7799 + return CAVM_FOUND;
7802 +static inline int cns3xxx_arl_table_search_again(ARLTableEntry *entry)
7804 + ARL_CTRL0_REG = 0;
7805 + ARL_CTRL1_REG = 0;
7806 + ARL_CTRL2_REG = 0;
7808 + ARL_VLAN_CMD_REG |= (1 << 17); // arl table search again command
7810 + // wait arl command complete
7811 + while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7813 + if ((ARL_VLAN_CMD_REG >> 23) & 1) {
7817 + printk("[kernel mode] ARL_VLAN_CMD_REG : %#x\n", ARL_VLAN_CMD_REG);
7818 + printk("[kernel mode] ARL_CTRL0_REG : %#x\n", ARL_CTRL0_REG);
7819 + printk("[kernel mode] ARL_CTRL1_REG : %#x\n", ARL_CTRL1_REG);
7820 + printk("[kernel mode] ARL_CTRL2_REG : %#x\n", ARL_CTRL2_REG);
7822 + entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff);
7823 + entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f);
7825 + entry->age_field = ((ARL_CTRL2_REG >> 4 ) & 0x7);
7826 + entry->vlan_mac = ((ARL_CTRL2_REG >> 1 ) & 0x1);
7827 + entry->filter = (ARL_CTRL2_REG & 0x1);
7829 + entry->mac[0] = (ARL_CTRL1_REG >> 24);
7830 + entry->mac[1] = (ARL_CTRL1_REG >> 16);
7831 + entry->mac[2] = (ARL_CTRL1_REG >> 8);
7832 + entry->mac[3] = ARL_CTRL1_REG;
7834 + entry->mac[4] = (ARL_CTRL2_REG >> 24);
7835 + entry->mac[5] = (ARL_CTRL2_REG >> 16);
7837 + return CAVM_FOUND;
7840 + return CAVM_NOT_FOUND;
7844 +static inline int cns3xxx_is_arl_table_end(void)
7846 + ARL_CTRL0_REG = 0;
7847 + ARL_CTRL1_REG = 0;
7848 + ARL_CTRL2_REG = 0;
7850 + if (( (ARL_VLAN_CMD_REG >> 22) & 1)) { // search to table end
7857 +static inline int cns3xxx_arl_table_search(ARLTableEntry *entry)
7859 + ARL_CTRL0_REG = 0;
7860 + ARL_CTRL1_REG = 0;
7861 + ARL_CTRL2_REG = 0;
7864 + ARL_CTRL0_REG |= (entry->vid << 16);
7866 + ARL_CTRL1_REG |= (entry->mac[0] << 24);
7867 + ARL_CTRL1_REG |= (entry->mac[1] << 16);
7868 + ARL_CTRL1_REG |= (entry->mac[2] << 8);
7869 + ARL_CTRL1_REG |= entry->mac[3];
7871 + ARL_CTRL2_REG |= (entry->mac[4] << 24);
7872 + ARL_CTRL2_REG |= (entry->mac[5] << 16);
7874 + ARL_VLAN_CMD_REG |= (1 << 16); // arl table search start command
7876 + // wait arl command complete
7877 + while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7879 + if (((ARL_VLAN_CMD_REG >> 23) & 1)) {
7882 + printk("[kernel mode] ARL_VLAN_CMD_REG : %#x\n", ARL_VLAN_CMD_REG);
7883 + printk("[kernel mode] ARL_CTRL0_REG : %#x\n", ARL_CTRL0_REG);
7884 + printk("[kernel mode] ARL_CTRL1_REG : %#x\n", ARL_CTRL1_REG);
7885 + printk("[kernel mode] ARL_CTRL2_REG : %#x\n", ARL_CTRL2_REG);
7887 + entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff);
7888 + entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f);
7890 + entry->age_field = ((ARL_CTRL2_REG >> 4 ) & 0x7);
7891 + entry->vlan_mac = ((ARL_CTRL2_REG >> 1 ) & 0x1);
7892 + entry->filter = (ARL_CTRL2_REG & 0x1);
7894 + entry->mac[0] = (ARL_CTRL1_REG >> 24);
7895 + entry->mac[1] = (ARL_CTRL1_REG >> 16);
7896 + entry->mac[2] = (ARL_CTRL1_REG >> 8);
7897 + entry->mac[3] = ARL_CTRL1_REG;
7899 + entry->mac[4] = (ARL_CTRL2_REG >> 24);
7900 + entry->mac[5] = (ARL_CTRL2_REG >> 16);
7902 + return CAVM_FOUND;
7905 + return CAVM_NOT_FOUND;
7910 +// flush all age out entries except static entries
7911 +static inline int cns3xxx_arl_table_flush(void)
7913 + ARL_VLAN_CMD_REG |= (1 << 20); // flush arl table command
7915 + // wait arl command complete
7916 + while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7923 +// add a entry in the arl table
7924 +static inline int cns3xxx_arl_table_add(ARLTableEntry *entry)
7926 + ARL_CTRL0_REG = 0;
7927 + ARL_CTRL1_REG = 0;
7928 + ARL_CTRL2_REG = 0;
7930 + entry->age_field = 7; // static entry
7931 + ARL_CTRL0_REG |= (entry->vid << 16);
7932 + ARL_CTRL0_REG |= (entry->pmap << 9);
7934 + ARL_CTRL1_REG |= (entry->mac[0] << 24);
7935 + ARL_CTRL1_REG |= (entry->mac[1] << 16);
7936 + ARL_CTRL1_REG |= (entry->mac[2] << 8);
7937 + ARL_CTRL1_REG |= entry->mac[3];
7939 + ARL_CTRL2_REG |= (entry->mac[4] << 24);
7940 + ARL_CTRL2_REG |= (entry->mac[5] << 16);
7942 + ARL_CTRL2_REG |= (entry->age_field << 4);
7943 + ARL_CTRL2_REG |= (entry->vlan_mac << 1);
7944 + ARL_CTRL2_REG |= (entry->filter);
7946 + //printk("entry->age_field: %d\n", entry->age_field);
7947 + //printk("ARL_CTRL2_REG: %x\n", ARL_CTRL2_REG);
7949 + ARL_VLAN_CMD_REG |= (1 << 19); // arl table write command
7951 + // wait arl command complete
7952 + while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7957 +// invalid a entry in the arl table
7958 +static inline int cns3xxx_arl_table_invalid(ARLTableEntry *entry)
7960 + entry->age_field = 0; // invalid
7961 + return cns3xxx_arl_table_add(entry);
7969 +static inline void cns3xxx_set_pvid(u8 port, u16 pvid)
7975 + MAC1_MAC0_PVID_REG &= (~0x0fff);
7976 + MAC1_MAC0_PVID_REG |= pvid;
7981 + MAC1_MAC0_PVID_REG &= (~(0x0fff << 16));
7982 + MAC1_MAC0_PVID_REG |= (pvid << 16);
7987 + MAC2_CPU_PVID_REG &= (~(0x0fff << 16));
7988 + MAC2_CPU_PVID_REG |= (pvid << 16);
7991 + case 3: // cpu port
7993 + MAC2_CPU_PVID_REG &= (~0x0fff);
7994 + MAC2_CPU_PVID_REG |= pvid;
8002 +static inline u16 cns3xxx_get_pvid(u8 port)
8004 + // 0, 1, 2, cpu port
8005 + u16 port_offset[]={0x9c, 0x9c, 0xa0, 0xa0};
8006 + // 0, 1, 2, cpu port
8007 + u16 port_shift[]={0, 16, 16, 0};
8009 + return ((SWITCH_REG_VALUE(port_offset[port]) >> port_shift[port]) & 0xfff);
8014 +static inline int enable_rx_dma(u8 which, u8 enable)
8016 + if (which == 0 ) {
8017 + FS_DMA_CTRL0_REG = enable;
8018 + } else if (which == 1 ) {
8019 + FS_DMA_CTRL1_REG = enable;
8029 +static inline int enable_tx_dma(u8 which, u8 enable)
8031 + if (which == 0 ) {
8032 + TS_DMA_CTRL0_REG = enable;
8033 + } else if (which == 1 ) {
8034 + TS_DMA_CTRL1_REG = enable;
8041 +#define DUMP_TX_DESC_PROC(tx_desc, page, num) \
8043 + num += sprintf(page + num,"sdp: %x\n", tx_desc->sdp); \
8044 + num += sprintf(page + num,"sdl: %d\n", tx_desc->sdl); \
8045 + num += sprintf(page + num,"tco: %d\n", tx_desc->tco); \
8046 + num += sprintf(page + num,"uco: %d\n", tx_desc->uco); \
8047 + num += sprintf(page + num,"ico: %d\n", tx_desc->ico); \
8048 + num += sprintf(page + num,"pri: %d\n", tx_desc->pri); \
8049 + num += sprintf(page + num,"fp: %d\n", tx_desc->fp); \
8050 + num += sprintf(page + num,"fr: %d\n", tx_desc->fr); \
8051 + num += sprintf(page + num,"interrupt: %d\n", tx_desc->interrupt); \
8052 + num += sprintf(page + num,"lsd: %d\n", tx_desc->lsd); \
8053 + num += sprintf(page + num,"fsd: %d\n", tx_desc->fsd); \
8054 + num += sprintf(page + num,"eor: %d\n", tx_desc->eor); \
8055 + num += sprintf(page + num,"cown: %d\n", tx_desc->cown); \
8057 + num += sprintf(page + num,"ctv: %d\n", tx_desc->ctv); \
8058 + num += sprintf(page + num,"stv: %d\n", tx_desc->stv); \
8059 + num += sprintf(page + num,"sid: %d\n", tx_desc->sid); \
8060 + num += sprintf(page + num,"inss: %d\n", tx_desc->inss); \
8061 + num += sprintf(page + num,"dels: %d\n", tx_desc->dels); \
8062 + num += sprintf(page + num,"pmap: %d\n", tx_desc->pmap); \
8063 + num += sprintf(page + num,"mark: %d\n", tx_desc->mark); \
8064 + num += sprintf(page + num,"ewan: %d\n", tx_desc->ewan); \
8065 + num += sprintf(page + num,"fewan: %d\n", tx_desc->fewan); \
8067 + num += sprintf(page + num,"c_vid: %d\n", tx_desc->c_vid); \
8068 + num += sprintf(page + num,"c_cfs: %d\n", tx_desc->c_cfs); \
8069 + num += sprintf(page + num,"c_pri: %d\n", tx_desc->c_pri); \
8070 + num += sprintf(page + num,"s_vid: %d\n", tx_desc->s_vid); \
8071 + num += sprintf(page + num,"s_dei: %d\n", tx_desc->s_dei); \
8072 + num += sprintf(page + num,"s_pri: %d\n", tx_desc->s_pri); \
8075 +static inline void dump_tx_desc(TXDesc volatile *tx_desc)
8077 + printk("sdp: %x\n", tx_desc->sdp);
8078 + printk("sdl: %d\n", tx_desc->sdl);
8079 + printk("tco: %d\n", tx_desc->tco);
8080 + printk("uco: %d\n", tx_desc->uco);
8081 + printk("ico: %d\n", tx_desc->ico);
8082 + printk("pri: %d\n", tx_desc->pri);
8083 + printk("fp: %d\n", tx_desc->fp);
8084 + printk("fr: %d\n", tx_desc->fr);
8085 + printk("interrupt: %d\n", tx_desc->interrupt);
8086 + printk("lsd: %d\n", tx_desc->lsd);
8087 + printk("fsd: %d\n", tx_desc->fsd);
8088 + printk("eor: %d\n", tx_desc->eor);
8089 + printk("cown: %d\n", tx_desc->cown);
8091 + printk("ctv: %d\n", tx_desc->ctv);
8092 + printk("stv: %d\n", tx_desc->stv);
8093 + printk("sid: %d\n", tx_desc->sid);
8094 + printk("inss: %d\n", tx_desc->inss);
8095 + printk("dels: %d\n", tx_desc->dels);
8096 + printk("pmap: %d\n", tx_desc->pmap);
8097 + printk("mark: %d\n", tx_desc->mark);
8098 + printk("ewan: %d\n", tx_desc->ewan);
8099 + printk("fewan: %d\n", tx_desc->fewan);
8101 + printk("c_vid: %d\n", tx_desc->c_vid);
8102 + printk("c_cfs: %d\n", tx_desc->c_cfs);
8103 + printk("c_pri: %d\n", tx_desc->c_pri);
8104 + printk("s_vid: %d\n", tx_desc->s_vid);
8105 + printk("s_dei: %d\n", tx_desc->s_dei);
8106 + printk("s_pri: %d\n", tx_desc->s_pri);
8109 +static inline void dump_rx_desc(RXDesc volatile *rx_desc)
8112 + printk("rx_desc: %p\n", rx_desc);
8113 + //printk("rx_desc: %p ## cown: %d\n", rx_desc, rx_desc->cown);
8114 + //printk("rx_desc phy addr : %x\n", (u32)page_to_dma(NULL, rx_desc) );
8117 + for (i=0; i < 8 ; ++4) {
8118 + u32 rx_desc_data = *((u32 *)(rx_desc+i));
8119 + printk("%d: %#x\n", i, rx_desc_data);
8123 + printk("sdp: %x\n", rx_desc->sdp);
8125 + printk("sdl: %d\n", rx_desc->sdl);
8127 + printk("l4f: %d\n", rx_desc->l4f);
8128 + printk("ipf: %d\n", rx_desc->ipf);
8129 + printk("prot: %d\n", rx_desc->prot);
8130 + printk("hr: %d\n", rx_desc->hr);
8131 + printk("lsd: %d\n", rx_desc->lsd);
8132 + printk("fsd: %d\n", rx_desc->fsd);
8133 + printk("eor: %d\n", rx_desc->eor);
8135 + printk("cown: %d\n", rx_desc->cown);
8138 + printk("ctv: %d\n", rx_desc->ctv);
8139 + printk("stv: %d\n", rx_desc->stv);
8140 + printk("unv: %d\n", rx_desc->unv);
8141 + printk("iwan: %d\n", rx_desc->iwan);
8142 + printk("exdv: %d\n", rx_desc->exdv);
8143 + printk("sp: %d\n", rx_desc->sp);
8144 + printk("crc_err: %d\n", rx_desc->crc_err);
8145 + printk("un_eth: %d\n", rx_desc->un_eth);
8146 + printk("tc: %d\n", rx_desc->tc);
8147 + printk("ip_offset: %d\n", rx_desc->ip_offset);
8149 + printk("c_vid: %d\n", rx_desc->c_vid);
8150 + printk("c_cfs: %d\n", rx_desc->c_cfs);
8151 + printk("c_pri: %d\n", rx_desc->c_pri);
8152 + printk("s_vid: %d\n", rx_desc->s_vid);
8153 + printk("s_dei: %d\n", rx_desc->s_dei);
8154 + printk("s_pri: %d\n", rx_desc->s_pri);
8158 +static inline void dump_all_rx_ring(const RXRing *rx_ring, u8 r_index)
8162 + RXBuffer volatile *rx_buf = get_rx_ring_head(rx_ring);
8164 + printk("all rx ring: %d\n", r_index);
8165 + for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) {
8166 + printk("%d ## rx_buf: %p ## rx_buf->rx_desc: %p\n", i, rx_buf, rx_buf->rx_desc);
8167 + dump_rx_desc(rx_buf->rx_desc);
8172 +static inline void rx_dma_suspend(u8 enable)
8175 + DMA_AUTO_POLL_CFG_REG &= (~0x00000001);
8177 + DMA_AUTO_POLL_CFG_REG |= 1;
8184 +static inline void clear_fs_dma_state(u8 clear)
8186 + DMA_RING_CTRL_REG &= (~(1 << 31));
8188 + DMA_RING_CTRL_REG |= (1 << 31);
8192 +// enable: 1 -> IVL
8193 +// enable: 0 -> SVL
8194 +static inline void cns3xxx_ivl(u8 enable)
8197 + MAC_GLOB_CFG_REG &= (~(0x1 << 7));
8199 + MAC_GLOB_CFG_REG |= (0x1 << 7);
8202 +static inline void cns3xxx_nic_mode(u8 enable)
8204 + VLAN_CFG &= (~(1<<15));
8206 + VLAN_CFG |= (1<<15);
8210 +void gic_mask_irq(unsigned int irq);
8211 +void gic_unmask_irq(unsigned int irq);
8212 +extern void __iomem *gic_cpu_base_addr;
8215 +static inline void cns3xxx_disable_irq(u32 irq)
8218 + disable_irq_nosync(irq);
8222 + //gic_mask_irq(irq);
8225 +static inline void cns3xxx_enable_irq(u32 irq)
8228 + //gic_unmask_irq(irq);
8231 +static inline int cns3xxx_get_tx_hw_index(u8 ring_index)
8233 + if (ring_index == 0) {
8234 + return (TS_DESC_PTR0_REG - TS_DESC_BASE_ADDR0_REG) / sizeof (TXDesc);
8235 + } else if (ring_index == 1) {
8236 + return (TS_DESC_PTR1_REG - TS_DESC_BASE_ADDR1_REG) / sizeof (TXDesc);
8242 +static inline TXBuffer* get_tx_buffer_by_index(TXRing *tx_ring, int i)
8246 + index = ((index + get_tx_ring_size(tx_ring) )% get_tx_ring_size(tx_ring));
8248 + return tx_ring->head + index;
8251 +static inline int cns3xxx_is_untag_packet(const RXDesc *rx_desc)
8253 + return rx_desc->crc_err;
8257 +#ifdef CONFIG_SWITCH_BIG_ENDIAN
8258 +static inline void swap_rx_desc(RXDesc *org_desc, RXDesc *new_desc)
8261 + void *org_p = org_desc;
8262 + void *new_p = new_desc;
8264 + for (i=0; i < 16 ; i+=4) {
8265 + u32 rx_desc_data = 0;
8266 + u32 swab_rx_desc_data = 0;
8268 + rx_desc_data = *((volatile u32 *)(org_p+i));
8269 + swab_rx_desc_data = ___swab32(rx_desc_data);
8271 + *((volatile u32 *)(new_p+i)) = swab_rx_desc_data;
8275 +static inline void swap_tx_desc(TXDesc *org_desc, TXDesc *new_desc)
8278 + void *org_p = org_desc;
8279 + void *new_p = new_desc;
8281 + for (i=0; i < 16 ; i+=4) {
8282 + u32 desc_data = *((volatile u32 *)(org_p+i));
8283 + u32 swab_desc_data = ___swab32(desc_data);
8285 + *((volatile u32 *)(new_p+i)) = swab_desc_data;
8292 +static inline int cns3xxx_min_mtu(void)
8297 +static inline int cns3xxx_max_mtu(void)
8299 + int max_len[]={1518, 1522, 1536, 9600};
8301 + return max_len[((PHY_AUTO_ADDR_REG >> 30) & 0x3)];
8304 +#endif // CNS3XXX_TOOL_H
8306 +++ b/drivers/net/cns3xxx/fpga.h
8308 +/*******************************************************************************
8310 + * Copyright (c) 2009 Cavium Networks
8312 + * This program is free software; you can redistribute it and/or modify it
8313 + * under the terms of the GNU General Public License as published by the Free
8314 + * Software Foundation; either version 2 of the License, or (at your option)
8315 + * any later version.
8317 + * This program is distributed in the hope that it will be useful, but WITHOUT
8318 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8319 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
8322 + * You should have received a copy of the GNU General Public License along with
8323 + * this program; if not, write to the Free Software Foundation, Inc., 59
8324 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
8326 + * The full GNU General Public License is included in this distribution in the
8327 + * file called LICENSE.
8329 + ********************************************************************************/
8331 +// This macro or function divide two part,
8332 +// one is initial state, another is in netdev open (ifconfig up) function.
8337 +#include <linux/types.h>
8339 +#include "cns3xxx_config.h"
8340 +#include "cns3xxx_phy.h"
8346 +// init phy or switch chip
8347 +#define INIT_PORT0_PHY cns3xxx_config_VSC8601(0,0);
8348 +#define INIT_PORT1_PHY cns3xxx_config_VSC8601(1,1);
8349 +#define INIT_PORT2_PHY icp_101a_init(2, 2);
8350 +//#define INIT_PORT1_PHY
8352 +// configure mac0/mac1 register
8353 +#define INIT_PORT0_MAC
8354 +#define INIT_PORT1_MAC
8355 +#define INIT_PORT2_MAC
8356 +//#define INIT_PORT1_MAC
8358 +#define PORT0_LINK_DOWN vsc8601_power_down(0, 1);
8359 +#define PORT0_LINK_UP vsc8601_power_down(0, 0);
8361 +#define PORT1_LINK_DOWN vsc8601_power_down(1, 1);
8362 +#define PORT1_LINK_UP vsc8601_power_down(1, 0);
8364 +#define PORT2_LINK_DOWN cns3xxx_std_phy_power_down(2, 1);
8365 +#define PORT2_LINK_UP cns3xxx_std_phy_power_down(2, 0);
8369 +#define MODEL "VEGA FPGA"
8371 +static int rc_port0 = 0; // rc means reference counting, determine port open/close.
8376 +static inline void open_port0(void)
8378 + if (rc_port0 == 0) {
8379 + enable_port(0, 1);
8380 + PRINT_INFO("open mac port 0\n");
8384 + PRINT_INFO("port 0 already open\n");\
8389 +static inline void close_port0(void)
8392 + if (rc_port0 == 0) {
8395 + enable_port(0, 0);
8396 + PRINT_INFO("close mac port 0\n");\
8400 +static inline void open_port1(void)
8403 + enable_port(1, 1);
8404 + PRINT_INFO("open mac port 1\n");
8409 +static inline void close_port1(void)
8411 + enable_port(1, 0);
8412 + PRINT_INFO("close mac port 1\n");
8417 +static inline void open_port2(void)
8420 + enable_port(2, 1);
8421 + PRINT_INFO("open mac port 2\n");
8426 +static inline void close_port2(void)
8428 + enable_port(2, 0);
8429 + PRINT_INFO("close mac port 2\n");
8434 +static u8 my_vlan0_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x00};
8435 +static u8 my_vlan1_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x11};
8436 +static u8 my_vlan2_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x70};
8437 +static u8 my_vlan3_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x80};
8442 +// CNS3XXX_NIC_MODE_8021Q, CNS3XXX_NON_NIC_MODE_8021Q, CNS3XXX_VLAN_BASE_MODE and
8443 +// CNS3XXX_PORT_BASE_MODE, only one macro can be defined
8445 +#ifdef CNS3XXX_VLAN_8021Q
8446 + #ifndef CNS3XXX_NIC_MODE_8021Q
8447 + #define CNS3XXX_NON_NIC_MODE_8021Q
8450 + //#define CNS3XXX_VLAN_BASE_MODE
8451 + #define CNS3XXX_PORT_BASE_MODE
8454 +#ifdef CNS3XXX_PORT_BASE_MODE
8456 +#define PORT0_PVID 0x1
8457 +#define PORT1_PVID 0x2
8458 +#define PORT2_PVID 3
8461 +#define CONFIG_CNS3XXX_PORT_BASE
8463 +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};
8465 +static VLANTableEntry vlan_table_entry[] =
8467 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;
8468 + //{0, 1, 1, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8469 + {1, 1, PORT0_PVID, 0, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8470 + {2, 1, PORT1_PVID, 0, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8471 + {3, 1, PORT2_PVID, 1, 0, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8472 + //{2, 1, 4, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}, // for cpu
8475 +static ARLTableEntry arl_table_entry[] =
8477 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8478 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8479 + //{CPU_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8480 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8481 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
8482 + //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan8_mac, 7, 0, 0},
8483 + //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan9_mac, 7, 0, 0},
8484 + //{CPU_PVID, 0x4, my_vlan2_mac, 7, 1, 0},
8485 + //{CPU_PVID, MAC_PORT2_PMAP, my_vlan2_mac, 7, 1, 0},
8488 +static NetDevicePriv net_device_prive[]= {
8489 + /* 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 */
8490 + {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
8491 + {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
8492 + {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
8497 +#ifdef CNS3XXX_NON_NIC_MODE_8021Q
8499 +#define PORT0_PVID 50
8500 +#define PORT1_PVID 60
8501 +#define PORT2_PVID 70
8502 +#define CPU_PVID 80
8504 +#define CONFIG_CNS3XXX_PORT_BASE
8505 +//#define CONFIG_CNS3XXX_VLAN_BASE
8506 +//#define CONFIG_HAVE_VLAN_TAG
8508 +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
8510 +static VLANTableEntry vlan_table_entry[] =
8512 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;C_PORT2_PMAP
8513 + {1, 1, PORT0_PVID, 0, CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8514 + {2, 1, PORT1_PVID, 0, CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8515 + {3, 1, PORT2_PVID, 0, CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8518 +static ARLTableEntry arl_table_entry[] =
8520 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8521 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8522 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8523 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
8527 +// if used 8021Q, use PORT0_NETDEV_INDEX, don't use VID
8528 +static NetDevicePriv net_device_prive[]= {
8529 + {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
8530 + {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
8531 + {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
8537 +#ifdef CNS3XXX_NIC_MODE_8021Q
8539 +#define PORT0_PVID 1
8540 +#define PORT1_PVID 2
8541 +#define PORT2_PVID 9
8544 +#define CONFIG_CNS3XXX_PORT_BASE
8545 +//#define CONFIG_CNS3XXX_VLAN_BASE
8546 +//#define CONFIG_HAVE_VLAN_TAG
8548 +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
8550 +static VLANTableEntry vlan_table_entry[] =
8552 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;C_PORT2_PMAP
8553 + {1, 1, PORT0_PVID, 1, MAC_PORT0_PMAP|CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8554 + {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP|CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8555 + {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP|CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8558 +static ARLTableEntry arl_table_entry[] =
8560 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8561 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8562 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8563 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
8567 +// if used 8021Q, use PORT0_NETDEV_INDEX, don't use VID
8568 +static NetDevicePriv net_device_prive[]= {
8569 + {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
8570 + {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
8571 + {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
8575 +#ifdef CNS3XXX_VLAN_BASE_MODE
8576 +//#error "vlan_base"
8577 +// vlan configuration
8579 +#define PORT0_PVID 1
8580 +#define PORT1_PVID 2
8581 +#define PORT2_PVID 3
8583 +#define CONFIG_CNS3XXX_VLAN_BASE
8584 +#define CONFIG_HAVE_VLAN_TAG
8586 +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
8588 +static VLANTableEntry vlan_table_entry[] =
8590 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;
8591 + {1, 1, PORT0_PVID, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8592 + {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8593 + {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP | CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8596 +static ARLTableEntry arl_table_entry[] =
8598 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8599 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8600 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8601 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
8604 +static NetDevicePriv net_device_prive[]= {
8605 + /* 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 */
8606 + {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
8607 + {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
8608 + {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
8612 +#endif // CONFIG_FPGA
8615 +++ b/drivers/net/cns3xxx/Kconfig
8617 +menu "CNS3XXX Gigabit Switch Support"
8618 + depends on ARCH_CNS3XXX
8621 + tristate "CNS3XXX Gigabit Switch Driver Support"
8623 + CNS3XXX Gigabit Switch.
8625 +config CNS3XXX_SPPE
8626 + bool "CNS3XXX Smart PPE(Packet Processing Engine) Support"
8627 + depends on CNS3XXX_GSW
8629 + PPE(Packet Processing Engine) is a hardware accelerator hook on a port of
8630 + CNS3XXX Gigabit Switch.
8632 + This option is used for Smart PPE hook.
8634 + Say Y if you want to enable Smart PPE function.
8636 +config CNS3XXX_HCIE_TEST
8637 + bool "CNS3XXX HCIE(Hardware Content Inspection Engine) Support"
8638 +# depends on CNS3XXX_GSW
8640 + HCIE is patent-protected layer-7 packet processing engine.
8642 + This option is used for fundamental HCIE functional test .
8643 + Say Y if you want to do HCIE functional test.
8646 +#config CNS3XXX_SHNAT_PCI_FASTPATH
8647 +# bool "FastPath(From PCI to WAN) Support"
8648 +# depends on CNS3XXX_SHNAT
8650 +# Add FastPath Support for Smart HNAT.
8652 +comment "NOTE: 'Validation Board' depends on"
8653 +comment "GPIO_CNS3XXX and SPI_CNS3XXX"
8655 + prompt "CNS3XXX Board"
8656 + depends on CNS3XXX_GSW
8663 + bool "Validation Board"
8665 + MAC0 and MAC1 connect to BCM53115M. It need enable CNS3XXX SPI and CNS3XXX GPIO option.
8666 + MAC2 use ICPLUS IP1001 phy.
8676 +++ b/drivers/net/cns3xxx/Makefile
8678 +################################################################################
8681 +# Copyright (c) 2008 Cavium Networks
8683 +# This program is free software; you can redistribute it and/or modify it
8684 +# under the terms of the GNU General Public License as published by the Free
8685 +# Software Foundation; either version 2 of the License, or (at your option)
8686 +# any later version.
8688 +# This program is distributed in the hope that it will be useful, but WITHOUT
8689 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8690 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
8693 +# You should have received a copy of the GNU General Public License along with
8694 +# this program; if not, write to the Free Software Foundation, Inc., 59
8695 +# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
8697 +# The full GNU General Public License is included in this distribution in the
8698 +# file called LICENSE.
8700 +# Contact Information:
8701 +# Star semiconduction Linux Support <support@starsemi.com>
8703 +################################################################################
8706 +# Makefile for the Star GSW ethernet driver
8712 +obj-$(CONFIG_CNS3XXX_GSW) += cns3xxx.o
8713 +cns3xxx-objs := cns3xxx_phy.o cns3xxx_main.o cns3xxx_ethtool.o
8714 +obj-$(CONFIG_CNS3XXX_SPPE) += cns3xxx_sppe_hook.o
8718 +#include $(TOPDIR)/Rules.make
8720 +++ b/drivers/net/cns3xxx/vb.h
8722 +/*******************************************************************************
8724 + * Copyright (c) 2009 Cavium Networks
8726 + * This program is free software; you can redistribute it and/or modify it
8727 + * under the terms of the GNU General Public License as published by the Free
8728 + * Software Foundation; either version 2 of the License, or (at your option)
8729 + * any later version.
8731 + * This program is distributed in the hope that it will be useful, but WITHOUT
8732 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8733 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
8736 + * You should have received a copy of the GNU General Public License along with
8737 + * this program; if not, write to the Free Software Foundation, Inc., 59
8738 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
8740 + * The full GNU General Public License is included in this distribution in the
8741 + * file called LICENSE.
8743 + ********************************************************************************/
8745 +// This macro or function divide two part,
8746 +// one is initial state, another is in netdev open (ifconfig up) function.
8751 +#include <linux/types.h>
8753 +#include "cns3xxx_config.h"
8754 +#include "cns3xxx_phy.h"
8757 +// init phy or switch chip
8758 +#define INIT_PORT0_PHY cns3xxx_config_VSC8601(0, 0);
8759 +#define INIT_PORT1_PHY cns3xxx_config_VSC8601(1, 1);
8760 +#define INIT_PORT2_PHY
8761 +//#define INIT_PORT1_PHY
8763 +// configure mac0/mac1 register
8764 +#define INIT_PORT0_MAC
8765 +#define INIT_PORT1_MAC
8766 +#define INIT_PORT2_MAC
8767 +//#define INIT_PORT1_MAC
8769 +#define PORT0_LINK_DOWN cns3xxx_std_phy_power_down(0, 1);
8770 +#define PORT0_LINK_UP cns3xxx_std_phy_power_down(0, 0);
8772 +#define PORT1_LINK_DOWN cns3xxx_std_phy_power_down(1, 1);
8773 +#define PORT1_LINK_UP cns3xxx_std_phy_power_down(1, 0);
8775 +#define PORT2_LINK_DOWN
8776 +#define PORT2_LINK_UP
8778 +#define MODEL "CNS3XXX validation board"
8780 +static int rc_port0 = 0; // rc means reference counting, determine port open/close.
8782 +#define PRINT_INFO printk
8786 +static inline void open_port0(void)
8788 + if (rc_port0 == 0) {
8789 + enable_port(0, 1);
8796 +static inline void close_port0(void)
8799 + if (rc_port0 == 0) {
8802 + enable_port(0, 0);
8806 +static inline void open_port1(void)
8809 + enable_port(1, 1);
8814 +static inline void close_port1(void)
8816 + enable_port(1, 0);
8821 +static inline void open_port2(void)
8824 + enable_port(2, 1);
8829 +static inline void close_port2(void)
8831 + enable_port(2, 0);
8836 +#if defined (CONFIG_CNS3XXX_SPPE)
8837 +/* only for PPE PCI-to-WAN fast path */
8838 +static int fp_ref_cnt = 0;
8839 +static inline void open_fp(void)
8841 + if (!fp_ref_cnt) {
8846 +static inline void close_fp(void)
8854 +static u8 my_vlan0_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x00};
8855 +static u8 my_vlan1_mac[] = {0x00, 0x11, 0x22, 0x33, 0x55, 0x11};
8856 +static u8 my_vlan2_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x70};
8857 +static u8 my_vlan3_mac[] = {0x00, 0x11, 0xbb, 0xcc, 0xdd, 0x80};
8862 +// CNS3XXX_NIC_MODE_8021Q, CNS3XXX_NON_NIC_MODE_8021Q, CNS3XXX_VLAN_BASE_MODE and
8863 +// CNS3XXX_PORT_BASE_MODE, only one macro can be defined
8865 +#ifdef CNS3XXX_VLAN_8021Q
8866 + #define CNS3XXX_NIC_MODE_8021Q
8867 + #ifndef CNS3XXX_NIC_MODE_8021Q
8868 + #define CNS3XXX_NON_NIC_MODE_8021Q
8871 + //#define CNS3XXX_VLAN_BASE_MODE
8872 + #define CNS3XXX_PORT_BASE_MODE
8875 +//#define CNS3XXX_PORT_BASE_MODE
8877 +#ifdef CNS3XXX_NON_NIC_MODE_8021Q
8879 +#define PORT0_PVID 50
8880 +#define PORT1_PVID 60
8881 +#define PORT2_PVID 70
8882 +#define CPU_PVID 80
8884 +#define CONFIG_CNS3XXX_PORT_BASE
8886 +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};
8888 +static VLANTableEntry vlan_table_entry[] =
8890 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;
8892 + {1, 1, PORT0_PVID, 0, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8893 + {2, 1, PORT1_PVID, 0, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8894 + {3, 1, PORT2_PVID, 1, 0, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8897 + {1, 1, PORT0_PVID, 0, CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8898 + {2, 1, PORT1_PVID, 0, CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8899 + {3, 1, PORT2_PVID, 0, CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8900 + //{2, 1, 4, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}, // for cpu
8903 +static ARLTableEntry arl_table_entry[] =
8905 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8906 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8907 + //{CPU_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8908 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8909 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
8910 + //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan8_mac, 7, 0, 0},
8911 + //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan9_mac, 7, 0, 0},
8912 + //{CPU_PVID, 0x4, my_vlan2_mac, 7, 1, 0},
8913 + //{CPU_PVID, MAC_PORT2_PMAP, my_vlan2_mac, 7, 1, 0},
8916 +static NetDevicePriv net_device_prive[]= {
8917 + /* 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 */
8918 + {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
8919 + {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
8920 + {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
8921 +#if defined (CONFIG_CNS3XXX_SPPE)
8922 + ,{CPU_PORT_PMAP, 0, 1, FP_NETDEV_INDEX, NULL, fp_port_base,
8923 + open_fp, close_fp, CPU_PORT, my_vlan3_mac, &cpu_vlan_table_entry,
8928 +#endif // CNS3XXX_PORT_BASE_MODE
8930 +#ifdef CNS3XXX_PORT_BASE_MODE
8932 +#define PORT0_PVID 0x1
8933 +#define PORT1_PVID 0x2
8934 +#define PORT2_PVID 3
8937 +#define CONFIG_CNS3XXX_PORT_BASE
8939 +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};
8941 +static VLANTableEntry vlan_table_entry[] =
8943 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;
8944 + //{0, 1, 1, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8945 + {1, 1, PORT0_PVID, 0, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8946 + {2, 1, PORT1_PVID, 0, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8947 + {3, 1, PORT2_PVID, 1, 0, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8948 + //{2, 1, 4, 0, 0, MAC_PORT0_PMAP | MAC_PORT1_PMAP | MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan3_mac}, // for cpu
8951 +static ARLTableEntry arl_table_entry[] =
8953 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8954 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8955 + //{CPU_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8956 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8957 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
8958 + //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan8_mac, 7, 0, 0},
8959 + //{PORT0_PVID, MAC_PORT0_PMAP, my_vlan9_mac, 7, 0, 0},
8960 + //{CPU_PVID, 0x4, my_vlan2_mac, 7, 1, 0},
8961 + //{CPU_PVID, MAC_PORT2_PMAP, my_vlan2_mac, 7, 1, 0},
8964 +static NetDevicePriv net_device_prive[]= {
8965 + /* 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 */
8966 + {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
8967 + {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
8968 + {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
8971 +#endif // CNS3XXX_PORT_BASE_MODE
8973 +#ifdef CNS3XXX_NIC_MODE_8021Q
8975 +#define PORT0_PVID 1
8976 +#define PORT1_PVID 2
8977 +#define PORT2_PVID 9
8980 +#define CONFIG_CNS3XXX_PORT_BASE
8981 +//#define CONFIG_CNS3XXX_VLAN_BASE
8982 +//#define CONFIG_HAVE_VLAN_TAG
8984 +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
8986 +static VLANTableEntry vlan_table_entry[] =
8988 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;C_PORT2_PMAP
8989 + {1, 1, PORT0_PVID, 1, MAC_PORT0_PMAP|CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
8990 + {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP|CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
8991 + {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP|CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
8994 +static ARLTableEntry arl_table_entry[] =
8996 + // vid; pmap; *mac; age_field; vlan_mac ; filter
8997 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
8998 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
8999 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
9003 +// if used 8021Q, use PORT0_NETDEV_INDEX, don't use VID
9004 +static NetDevicePriv net_device_prive[]= {
9005 + {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
9006 + {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
9007 + {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
9009 +#endif // CNS3XXX_NIC_MODE_8021Q
9011 +#ifdef CNS3XXX_VLAN_BASE_MODE
9012 +//#error "vlan_base"
9013 +// vlan configuration
9015 +#define PORT0_PVID 1
9016 +#define PORT1_PVID 2
9017 +#define PORT2_PVID 3
9019 +#define CONFIG_CNS3XXX_VLAN_BASE
9020 +#define CONFIG_HAVE_VLAN_TAG
9022 +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
9024 +static VLANTableEntry vlan_table_entry[] =
9026 + // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;
9027 + {1, 1, PORT0_PVID, 0, MAC_PORT0_PMAP | CPU_PORT_PMAP, MAC_PORT0_PMAP | CPU_PORT_PMAP, my_vlan0_mac},
9028 + {2, 1, PORT1_PVID, 0, MAC_PORT1_PMAP | CPU_PORT_PMAP, MAC_PORT1_PMAP | CPU_PORT_PMAP, my_vlan1_mac},
9029 + {3, 1, PORT2_PVID, 1, MAC_PORT2_PMAP | CPU_PORT_PMAP, MAC_PORT2_PMAP | CPU_PORT_PMAP, my_vlan2_mac},
9032 +static ARLTableEntry arl_table_entry[] =
9034 + // vid; pmap; *mac; age_field; vlan_mac ; filter
9035 + {PORT0_PVID, CPU_PORT_PMAP, my_vlan0_mac, 7, 1, 0},
9036 + {PORT1_PVID, CPU_PORT_PMAP, my_vlan1_mac, 7, 1, 0},
9037 + {PORT2_PVID, CPU_PORT_PMAP, my_vlan2_mac, 7, 1, 0},
9040 +static NetDevicePriv net_device_prive[]= {
9041 + /* 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 */
9042 + {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
9043 + {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
9044 + {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
9046 +#endif // CNS3XXX_VLAN_BASE_MODE
9048 +#endif // CONFIG_VB
9050 --- a/drivers/net/Kconfig
9051 +++ b/drivers/net/Kconfig
9052 @@ -2076,6 +2076,8 @@ menuconfig NETDEV_1000
9056 +source "drivers/net/cns3xxx/Kconfig"
9059 tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
9061 --- a/drivers/net/Makefile
9062 +++ b/drivers/net/Makefile
9063 @@ -6,6 +6,11 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci
9065 obj-$(CONFIG_E1000) += e1000/
9066 obj-$(CONFIG_E1000E) += e1000e/
9067 +obj-$(CONFIG_CNS3XXX_GSW) += cns3xxx/
9068 +ifeq ($(CONFIG_CNS3XXX_GSW),m)
9069 + obj-y += cns3xxx/cns3xxx_sppe_hook.o
9072 obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
9073 obj-$(CONFIG_IGB) += igb/
9074 obj-$(CONFIG_IGBVF) += igbvf/
9076 +++ b/include/linux/cns3xxx/sppe.h
9079 + * PROJECT CODE: CNS3XXX Smart Packet Processing Engine
9080 + * MODULE NAME: sppe.h
9085 + * 1.0.0 25-Dec-2008
9093 +#if defined(CONFIG_CNS3XXX_SPPE)
9096 +/* PPE Table Size Def. */
9097 +#define PPE_TABLE_SIZE_2K (0x0)
9098 +#define PPE_TABLE_SIZE_4K (0x1)
9099 +#define PPE_TABLE_SIZE_8K (0x2)
9100 +#define PPE_TABLE_SIZE_16K (0x3)
9101 +#define PPE_TABLE_SIZE_32K (0x4)
9102 +#define PPE_TABLE_SIZE_64K (0x5)
9103 +#define PPE_TABLE_SIZE_128K (0x6)
9104 +#define PPE_TABLE_SIZE_256K (0x7)
9106 +typedef enum _sppe_cmd {
9107 + SPPE_CMD_INIT = 0,
9111 + SPPE_CMD_FIREWALL,
9112 + SPPE_CMD_RULE_CHECK,
9113 + SPPE_CMD_GRL_CHECK,
9114 + SPPE_CMD_FLOW_CHECK,
9115 + SPPE_CMD_RATE_LIMIT_EN,
9116 + SPPE_CMD_POLICE_EN,
9118 + SPPE_CMD_FC, /* flow control */
9119 + SPPE_CMD_MIRROR_TO_CPU,
9121 + SPPE_CMD_TCP_SNA_TH,
9124 + SPPE_CMD_MAX_LENGTH,
9129 + SPPE_CMD_RULE_PPPOE_RELAY,
9130 + SPPE_CMD_RULE_BRIDGE,
9131 + SPPE_CMD_RULE_ACL,
9132 + SPPE_CMD_RULE_ROUTE,
9134 + SPPE_CMD_RULE_VSERVER,
9136 + SPPE_CMD_RULE_SNAT,
9137 + SPPE_CMD_RULE_DNAT,
9139 + SPPE_CMD_RULE_GRL,
9143 + SPPE_CMD_PPPOE_SID,
9145 + SPPE_CMD_FLOW_BRIDGE_IPV4,
9146 + SPPE_CMD_FLOW_BRIDGE_IPV6,
9147 + SPPE_CMD_FLOW_ROUTE_IPV4,
9148 + SPPE_CMD_FLOW_ROUTE_IPV6,
9149 + SPPE_CMD_FLOW_NAT_IPV4,
9150 + SPPE_CMD_FLOW_NAT_IPV6,
9151 + //SPPE_CMD_FLOW_TWICE_NAT,
9152 + SPPE_CMD_FLOW_MCAST_IPV4,
9153 + SPPE_CMD_FLOW_MCAST_IPV6,
9154 + SPPE_CMD_FLOW_BRIDGE_L2,
9166 + /* accounting group and drop packet count */
9167 + SPPE_CMD_ACCOUNTING_GROUP,
9168 + SPPE_CMD_DROP_IPCS_ERR,
9169 + SPPE_CMD_DROP_RATE_LIMIT,
9170 + SPPE_CMD_DROP_OTHERS,
9172 + SPPE_CMD_PCI_FP_DEV,
9176 +typedef enum _sppe_op {
9180 + SPPE_OP_DELETE_OUTDATED, /* flow only */
9181 + SPPE_OP_UPDATE_COUNTER, /* ACL rule only */
9186 +typedef enum _sppe_boolean {
9187 + SPPE_BOOL_FALSE = 0,
9188 + SPPE_BOOL_TRUE = 1
9192 +typedef enum _sppe_result {
9193 + SPPE_RESULT_SUCCESS = 0,
9195 + SPPE_RESULT_UNSUPPORT_CMD,
9196 + SPPE_RESULT_UNSUPPORT_OP,
9197 + SPPE_RESULT_INVALID_INDEX,
9198 + SPPE_RESULT_INVALID_TYPE,
9199 + SPPE_RESULT_FLOW_NOT_FOUND,
9202 +typedef enum _sppe_prot {
9203 + SPPE_PROT_UDP = 0,
9204 + SPPE_PROT_TCP = 1,
9205 + SPPE_PROT_PPTP_GRE = 2,
9206 + SPPE_PROT_OTHERS = 3,
9210 +typedef enum _sppe_l2_select {
9211 + SPPE_L2S_ARP_TABLE = 0,
9212 + SPPE_L2S_POLICY_ROUTE = 1,
9213 + SPPE_L2S_IN_FLOW = 2,
9214 + SPPE_L2S_RESERVED = 3,
9217 +typedef enum _sppe_dump_type {
9218 + SPPE_DUMP_TYPE_FLOW = 0,
9219 + SPPE_DUMP_TYPE_ARP,
9220 + SPPE_DUMP_TYPE_RULE
9223 +/* Data Structure */
9224 +typedef struct _sppe_pppoe_relay {
9225 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9226 + unsigned int valid:1;
9227 + unsigned int unused:31;
9229 + unsigned int unused:31;
9230 + unsigned int valid:1;
9232 + unsigned short lsid; /* PPPoE session ID in LAN side */
9233 + unsigned short wsid; /* PPPoE session ID in WAN side */
9234 + unsigned char lmac[6]; /* MAC address of PPPoE client */
9235 + unsigned char wmac[6]; /* MAC address of PPPoE server */
9236 +} SPPE_PPPOE_RELAY;
9238 +typedef struct _sppe_bridge {
9239 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9240 + unsigned int valid:1;
9241 + unsigned int wan:1;
9242 + unsigned int ppp:1; /* enable PPPoE sessoion ID comparison*/
9243 + unsigned int psidx:4; /* PPPoE session ID index */
9244 + unsigned int kv:1;
9245 + unsigned int sws:1;
9246 + unsigned int max_len:2; /* Max. length select */
9247 + unsigned int fp:1; /* force VLAN priority */
9248 + unsigned int pri:3;
9249 + unsigned int ag:2;
9250 + unsigned int unused:15;
9252 + unsigned int unused:15;
9253 + unsigned int ag:2;
9254 + unsigned int pri:3;
9255 + unsigned int fp:1; /* force VLAN priority */
9256 + unsigned int max_len:2; /* Max. length select */
9257 + unsigned int sws:1;
9258 + unsigned int kv:1;
9259 + unsigned int psidx:4; /* PPPoE session ID index */
9260 + unsigned int ppp:1; /* enable PPPoE sessoion ID comparison*/
9261 + unsigned int wan:1;
9262 + unsigned int valid:1;
9265 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9266 + unsigned int svid:12;
9267 + unsigned int cvid:12;
9268 + unsigned int loc:8;
9270 + unsigned int loc:8;
9271 + unsigned int cvid:12;
9272 + unsigned int svid:12;
9275 + unsigned char smac[6]; /* source MAC address */
9276 + unsigned char dmac[6]; /* destination MAC address */
9277 + unsigned int pkt_cnt;
9280 +typedef struct _sppe_acl {
9281 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9282 + unsigned int valid:1;
9283 + unsigned int ipv6:1;
9284 + unsigned int wan:1;
9285 + unsigned int tcp:1;
9286 + unsigned int udp:1;
9287 + unsigned int to:4;
9288 + unsigned int from:4;
9289 + unsigned int rr:4;
9290 + unsigned int kv:1;
9291 + unsigned int sws:1;
9292 + unsigned int loc:8;
9293 + unsigned int max_len:2; /* Max. length select */
9294 + unsigned int unused:3;
9296 + unsigned int unused:3;
9297 + unsigned int max_len:2; /* Max. length select */
9298 + unsigned int loc:8;
9299 + unsigned int sws:1;
9300 + unsigned int kv:1;
9301 + unsigned int rr:4;
9302 + unsigned int from:4;
9303 + unsigned int to:4;
9304 + unsigned int udp:1;
9305 + unsigned int tcp:1;
9306 + unsigned int wan:1;
9307 + unsigned int ipv6:1;
9308 + unsigned int valid:1;
9311 + unsigned int sip[4];
9312 + unsigned int dip[4];
9313 + unsigned short sip_mask;
9314 + unsigned short dip_mask;
9316 + unsigned short sport_start;
9317 + unsigned short sport_end;
9318 + unsigned short dport_start;
9319 + unsigned short dport_end;
9320 + unsigned int pkt_cnt;
9323 +typedef struct _sppe_route {
9324 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9325 + unsigned int valid:1;
9326 + unsigned int ipv6:1;
9327 + unsigned int wan:1;
9328 + unsigned int rd:1; /* replace dscp */
9329 + unsigned int dscp:6;
9330 + unsigned int pr:1; /* policy route */
9331 + unsigned int prs:2; /* policy route select */
9332 + unsigned int kv:1;
9333 + unsigned int sws:1;
9334 + unsigned int max_len:2; /* Max. length select */
9335 + unsigned int fp:1; /* force VLAN priority */
9336 + unsigned int pri:3;
9337 + unsigned int pd:1;
9338 + unsigned int pi:1;
9339 + unsigned int psidx:4;
9340 + unsigned int ag:2;
9341 + unsigned int unused:3;
9343 + unsigned int unused:3;
9344 + unsigned int ag:2;
9345 + unsigned int psidx:4;
9346 + unsigned int pi:1;
9347 + unsigned int pd:1;
9348 + unsigned int pri:3;
9349 + unsigned int fp:1; /* force VLAN priority */
9350 + unsigned int max_len:2; /* Max. length select */
9351 + unsigned int sws:1;
9352 + unsigned int kv:1;
9353 + unsigned int prs:2; /* policy route select */
9354 + unsigned int pr:1; /* policy route */
9355 + unsigned int dscp:6;
9356 + unsigned int rd:1; /* replace dscp */
9357 + unsigned int wan:1;
9358 + unsigned int ipv6:1;
9359 + unsigned int valid:1;
9362 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9363 + unsigned int unused_1:24;
9364 + unsigned int loc:8;
9366 + unsigned int loc:8;
9367 + unsigned int unused_1:24;
9370 + unsigned int dip[4];
9371 + unsigned int sip[4];
9372 + unsigned short dip_mask;
9373 + unsigned short sip_mask;
9374 + unsigned int pkt_cnt;
9378 +typedef struct _sppe_vserver {
9379 + unsigned int valid:1;
9380 + unsigned int tcp:1;
9381 + unsigned int udp:1;
9382 + unsigned int dscp_lan:6;
9383 + unsigned int dscp_wan:6;
9384 + unsigned int pri_lan:3;
9385 + unsigned int pri_wan:3;
9386 + unsigned int unused:11;
9388 + unsigned int wanip;
9389 + unsigned int lanip;
9390 + unsigned short port_start;
9391 + unsigned short port_end;
9392 + unsigned int pkt_cnt;
9395 +typedef struct _sppe_snat {
9396 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9397 + unsigned int valid:1;
9398 + unsigned int tcp:1;
9399 + unsigned int udp:1;
9400 + unsigned int rd:1;
9401 + unsigned int dscp:6;
9402 + unsigned int fp:1;
9403 + unsigned int pri:3;
9404 + unsigned int kv:1;
9405 + unsigned int sws:1;
9406 + unsigned int max_len:2;
9407 + unsigned int pd:1;
9408 + unsigned int pi:1;
9409 + unsigned int psidx:4;
9410 + unsigned int pr:1; /* policy route */
9411 + unsigned int prs:2; /* policy route select */
9412 + unsigned int ag:2;
9413 + unsigned int unused:3;
9415 + unsigned int unused:3;
9416 + unsigned int ag:2;
9417 + unsigned int prs:2; /* policy route select */
9418 + unsigned int pr:1; /* policy route */
9419 + unsigned int psidx:4;
9420 + unsigned int pi:1;
9421 + unsigned int pd:1;
9422 + unsigned int max_len:2;
9423 + unsigned int sws:1;
9424 + unsigned int kv:1;
9425 + unsigned int pri:3;
9426 + unsigned int fp:1;
9427 + unsigned int dscp:6;
9428 + unsigned int rd:1;
9429 + unsigned int udp:1;
9430 + unsigned int tcp:1;
9431 + unsigned int valid:1;
9434 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9435 + unsigned int unused_1:24;
9436 + unsigned int loc:8;
9438 + unsigned int loc:8;
9439 + unsigned int unused_1:24;
9442 + unsigned int wanip;
9443 + unsigned int lanip;
9444 + unsigned short port_start;
9445 + unsigned short port_end;
9446 + unsigned int pkt_cnt;
9449 +typedef struct _sppe_dnat {
9450 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9451 + unsigned int valid:1;
9452 + unsigned int tcp:1;
9453 + unsigned int udp:1;
9454 + unsigned int rd:1;
9455 + unsigned int dscp:6;
9456 + unsigned int fp:1;
9457 + unsigned int pri:3;
9458 + unsigned int kv:1;
9459 + unsigned int sws:1;
9460 + unsigned int max_len:2;
9461 + unsigned int pd:1;
9462 + unsigned int pi:1;
9463 + unsigned int psidx:4;
9464 + unsigned int pr:1; /* policy route */
9465 + unsigned int prs:2; /* policy route select */
9466 + unsigned int ag:2;
9467 + unsigned int unused:3;
9469 + unsigned int unused:3;
9470 + unsigned int ag:2;
9471 + unsigned int prs:2; /* policy route select */
9472 + unsigned int pr:1; /* policy route */
9473 + unsigned int psidx:4;
9474 + unsigned int pi:1;
9475 + unsigned int pd:1;
9476 + unsigned int max_len:2;
9477 + unsigned int sws:1;
9478 + unsigned int kv:1;
9479 + unsigned int pri:3;
9480 + unsigned int fp:1;
9481 + unsigned int dscp:6;
9482 + unsigned int rd:1;
9483 + unsigned int udp:1;
9484 + unsigned int tcp:1;
9485 + unsigned int valid:1;
9487 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9488 + unsigned int unused_1:24;
9489 + unsigned int loc:8;
9491 + unsigned int loc:8;
9492 + unsigned int unused_1:24;
9495 + unsigned int wanip;
9496 + unsigned int lanip;
9497 + unsigned short port_start;
9498 + unsigned short port_end;
9499 + unsigned int pkt_cnt;
9502 +typedef struct _sppe_limit {
9503 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9504 + unsigned int drop_red:1;
9505 + unsigned int pass_green:1;
9506 + unsigned int force_color:1;
9507 + unsigned int color_select:2;
9508 + unsigned int time_stamp:21;
9509 + unsigned int reserved:6;
9511 + unsigned int reserved:6;
9512 + unsigned int time_stamp:21;
9513 + unsigned int color_select:2;
9514 + unsigned int force_color:1;
9515 + unsigned int pass_green:1;
9516 + unsigned int drop_red:1;
9518 + unsigned short min_rate;
9519 + unsigned short max_rate;
9522 +typedef struct _sppe_global_rate_limit {
9523 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9524 + unsigned int valid:1;
9525 + unsigned int wan:1;
9526 + unsigned int ipv6:1;
9527 + unsigned int tcp:1;
9528 + unsigned int udp:1;
9529 + unsigned int unused:17;
9531 + unsigned int unused:17;
9532 + unsigned int udp:1;
9533 + unsigned int tcp:1;
9534 + unsigned int ipv6:1;
9535 + unsigned int wan:1;
9536 + unsigned int valid:1;
9539 + unsigned int sip[4];
9540 + unsigned int dip[4];
9541 + unsigned short sip_mask;
9542 + unsigned short dip_mask;
9543 + unsigned short sport_start;
9544 + unsigned short sport_end;
9545 + unsigned short dport_start;
9546 + unsigned short dport_end;
9548 +} SPPE_GLOBAL_RATE_LIMIT;
9551 + * SPPE_CMD_FLOW_BRIDGE_IPV4
9552 + * type = 1 , as = 3
9554 +typedef struct _sppe_flow_bridge_ipv4 {
9555 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9556 + unsigned int fw:1;
9558 + unsigned int sws:1;
9559 + unsigned int ag:2;
9560 + unsigned int rl:1;
9561 + unsigned int l4_prot:2;
9562 + unsigned int l2s:2; /* L2 select */
9563 + unsigned int prs:2;
9564 + unsigned int kv:1;
9565 + unsigned int fp:1;
9566 + unsigned int pri:3;
9567 + unsigned int max_len:2; /* Max. length select */
9568 + unsigned int reserved:13;
9570 + unsigned int reserved:13;
9571 + unsigned int max_len:2; /* Max. length select */
9572 + unsigned int pri:3;
9573 + unsigned int fp:1;
9574 + unsigned int kv:1;
9575 + unsigned int prs:2;
9576 + unsigned int l2s:2; /* L2 select */
9577 + unsigned int l4_prot:2;
9578 + unsigned int rl:1;
9579 + unsigned int ag:2;
9580 + unsigned int sws:1;
9582 + unsigned int fw:1;
9585 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9586 + unsigned int unused:16;
9587 + unsigned int mac4732:16;
9589 + unsigned int mac4732:16;
9590 + unsigned int unused:16;
9593 + unsigned int mac3100;
9594 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9595 + unsigned int lp:1;
9596 + unsigned int fr:1;
9597 + unsigned int pm:4;
9598 + unsigned int sv:1;
9599 + unsigned int svid:12;
9600 + unsigned int cv:1;
9601 + unsigned int cvid:12;
9603 + unsigned int cvid:12;
9604 + unsigned int cv:1;
9605 + unsigned int svid:12;
9606 + unsigned int sv:1;
9607 + unsigned int pm:4;
9608 + unsigned int fr:1;
9609 + unsigned int lp:1;
9616 + unsigned short src;
9617 + unsigned short dst;
9620 + unsigned short call_id;
9623 + unsigned char protocol;
9628 + unsigned int pkt_cnt;
9629 +} SPPE_FLOW_BRIDGE_IPV4;
9632 + * SPPE_CMD_FLOW_BRIDGE_IPV6
9633 + * type = 2 , as = 3
9635 +typedef struct _sppe_flow_bridge_ipv6 {
9636 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9637 + unsigned int fw:1;
9639 + unsigned int sws:1;
9640 + unsigned int ag:2;
9641 + unsigned int rl:1;
9642 + unsigned int l4_prot:2;
9643 + unsigned int l2s:2; /* L2 select */
9644 + unsigned int prs:2;
9645 + unsigned int kv:1;
9646 + unsigned int fp:1;
9647 + unsigned int pri:3;
9648 + unsigned int max_len:2; /* Max. length select */
9649 + unsigned int reserved:13;
9651 + unsigned int reserved:13;
9652 + unsigned int max_len:2; /* Max. length select */
9653 + unsigned int pri:3;
9654 + unsigned int fp:1;
9655 + unsigned int kv:1;
9656 + unsigned int prs:2;
9657 + unsigned int l2s:2; /* L2 select */
9658 + unsigned int l4_prot:2;
9659 + unsigned int rl:1;
9660 + unsigned int ag:2;
9661 + unsigned int sws:1;
9663 + unsigned int fw:1;
9666 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9667 + unsigned int unused:16;
9668 + unsigned int mac4732:16;
9670 + unsigned int mac4732:16;
9671 + unsigned int unused:16;
9674 + unsigned int mac3100;
9675 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9676 + unsigned int lp:1;
9677 + unsigned int fr:1;
9678 + unsigned int pm:4;
9679 + unsigned int sv:1;
9680 + unsigned int svid:12;
9681 + unsigned int cv:1;
9682 + unsigned int cvid:12;
9684 + unsigned int cvid:12;
9685 + unsigned int cv:1;
9686 + unsigned int svid:12;
9687 + unsigned int sv:1;
9688 + unsigned int pm:4;
9689 + unsigned int fr:1;
9690 + unsigned int lp:1;
9692 + unsigned int sip[4];
9693 + unsigned int dip[4];
9696 + unsigned short src;
9697 + unsigned short dst;
9700 + unsigned short call_id;
9703 + unsigned char protocol;
9707 + unsigned int pkt_cnt;
9708 +} SPPE_FLOW_BRIDGE_IPV6;
9711 + * SPPE_CMD_FLOW_ROUTE_IPV4
9712 + * type = 1, as = 0
9714 +typedef struct _sppe_flow_route_ipv4 {
9715 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9716 + unsigned int fw:1;
9718 + unsigned int sws:1;
9719 + unsigned int ag:2;
9720 + unsigned int rl:1;
9721 + unsigned int l4_prot:2;
9722 + unsigned int l2s:2; /* L2 select */
9723 + unsigned int prs:2;
9724 + unsigned int kv:1;
9725 + unsigned int rd:1;
9726 + unsigned int dscp:6;
9727 + unsigned int fp:1;
9728 + unsigned int pri:3;
9729 + unsigned int max_len:2; /* Max. length select */
9730 + unsigned int pd:1;
9731 + unsigned int pi:1;
9732 + unsigned int psidx:4;
9734 + unsigned int psidx:4;
9735 + unsigned int pi:1;
9736 + unsigned int pd:1;
9737 + unsigned int max_len:2; /* Max. length select */
9738 + unsigned int pri:3;
9739 + unsigned int fp:1;
9740 + unsigned int dscp:6;
9741 + unsigned int rd:1;
9742 + unsigned int kv:1;
9743 + unsigned int prs:2;
9744 + unsigned int l2s:2; /* L2 select */
9745 + unsigned int l4_prot:2;
9746 + unsigned int rl:1;
9747 + unsigned int ag:2;
9748 + unsigned int sws:1;
9750 + unsigned int fw:1;
9753 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9754 + unsigned int unused:16;
9755 + unsigned int mac4732:16;
9757 + unsigned int mac4732:16;
9758 + unsigned int unused:16;
9760 + unsigned int mac3100;
9762 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9763 + unsigned int lp:1;
9764 + unsigned int fr:1;
9765 + unsigned int pm:4;
9766 + unsigned int sv:1;
9767 + unsigned int svid:12;
9768 + unsigned int cv:1;
9769 + unsigned int cvid:12;
9771 + unsigned int cvid:12;
9772 + unsigned int cv:1;
9773 + unsigned int svid:12;
9774 + unsigned int sv:1;
9775 + unsigned int pm:4;
9776 + unsigned int fr:1;
9777 + unsigned int lp:1;
9784 + unsigned short src;
9785 + unsigned short dst;
9788 + unsigned short call_id;
9791 + unsigned char protocol;
9795 + unsigned int pkt_cnt;
9796 +} SPPE_FLOW_ROUTE_IPV4;
9799 + * SPPE_CMD_FLOW_ROUTE_IPV6
9800 + * type = 2, as = 0
9802 +typedef struct _sppe_flow_route_ipv6 {
9803 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9804 + unsigned int fw:1;
9806 + unsigned int sws:1;
9807 + unsigned int ag:2;
9808 + unsigned int rl:1;
9809 + unsigned int l4_prot:2;
9810 + unsigned int l2s:2; /* L2 select */
9811 + unsigned int prs:2;
9812 + unsigned int kv:1;
9813 + unsigned int rd:1;
9814 + unsigned int dscp:6;
9815 + unsigned int fp:1;
9816 + unsigned int pri:3;
9817 + unsigned int max_len:2; /* Max. length select */
9818 + unsigned int pd:1;
9819 + unsigned int pi:1;
9820 + unsigned int psidx:4;
9822 + unsigned int psidx:4;
9823 + unsigned int pi:1;
9824 + unsigned int pd:1;
9825 + unsigned int max_len:2; /* Max. length select */
9826 + unsigned int pri:3;
9827 + unsigned int fp:1;
9828 + unsigned int dscp:6;
9829 + unsigned int rd:1;
9830 + unsigned int kv:1;
9831 + unsigned int prs:2;
9832 + unsigned int l2s:2; /* L2 select */
9833 + unsigned int l4_prot:2;
9834 + unsigned int rl:1;
9835 + unsigned int ag:2;
9836 + unsigned int sws:1;
9838 + unsigned int fw:1;
9840 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9841 + unsigned int unused:16;
9842 + unsigned int mac4732:16;
9844 + unsigned int mac4732:16;
9845 + unsigned int unused:16;
9847 + unsigned int mac3100;
9849 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9850 + unsigned int lp:1;
9851 + unsigned int fr:1;
9852 + unsigned int pm:4;
9853 + unsigned int sv:1;
9854 + unsigned int svid:12;
9855 + unsigned int cv:1;
9856 + unsigned int cvid:12;
9858 + unsigned int cvid:12;
9859 + unsigned int cv:1;
9860 + unsigned int svid:12;
9861 + unsigned int sv:1;
9862 + unsigned int pm:4;
9863 + unsigned int fr:1;
9864 + unsigned int lp:1;
9866 + unsigned int sip[4];
9867 + unsigned int dip[4];
9870 + unsigned short src;
9871 + unsigned short dst;
9874 + unsigned short call_id;
9877 + unsigned char protocol;
9881 + unsigned int pkt_cnt;
9882 +} SPPE_FLOW_ROUTE_IPV6;
9885 + * SPPE_CMD_FLOW_NAT_IPV4
9886 + * type = 0, as = 1
9888 +typedef struct _sppe_flow_nat_ipv4 {
9889 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9890 + unsigned int fw:1;
9892 + unsigned int sws:1;
9893 + unsigned int ag:2;
9894 + unsigned int rl:1;
9895 + unsigned int l4_prot:2;
9896 + unsigned int l2s:2; /* L2 select */
9897 + unsigned int prs:2;
9898 + unsigned int kv:1;
9899 + unsigned int rd:1;
9900 + unsigned int dscp:6;
9901 + unsigned int fp:1;
9902 + unsigned int pri:3;
9903 + unsigned int max_len:2; /* Max. length select */
9904 + unsigned int pd:1;
9905 + unsigned int pi:1;
9906 + unsigned int psidx:4;
9908 + unsigned int psidx:4;
9909 + unsigned int pi:1;
9910 + unsigned int pd:1;
9911 + unsigned int max_len:2; /* Max. length select */
9912 + unsigned int pri:3;
9913 + unsigned int fp:1;
9914 + unsigned int dscp:6;
9915 + unsigned int rd:1;
9916 + unsigned int kv:1;
9917 + unsigned int prs:2;
9918 + unsigned int l2s:2; /* L2 select */
9919 + unsigned int l4_prot:2;
9920 + unsigned int rl:1;
9921 + unsigned int ag:2;
9922 + unsigned int sws:1;
9924 + unsigned int fw:1;
9926 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9927 + unsigned int unused:16;
9928 + unsigned int mac4732:16;
9930 + unsigned int mac4732:16;
9931 + unsigned int unused:16;
9934 + unsigned int mac3100;
9936 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9937 + unsigned int lp:1;
9938 + unsigned int fr:1;
9939 + unsigned int pm:4;
9940 + unsigned int sv:1;
9941 + unsigned int svid:12;
9942 + unsigned int cv:1;
9943 + unsigned int cvid:12;
9945 + unsigned int cvid:12;
9946 + unsigned int cv:1;
9947 + unsigned int svid:12;
9948 + unsigned int sv:1;
9949 + unsigned int pm:4;
9950 + unsigned int fr:1;
9951 + unsigned int lp:1;
9958 + unsigned short src;
9959 + unsigned short dst;
9962 + unsigned short call_id;
9963 + unsigned short nat_call_id;
9966 + unsigned char protocol;
9969 + unsigned int nat_ip;
9970 + unsigned short nat_port;
9972 + unsigned int pkt_cnt;
9973 +} SPPE_FLOW_NAT_IPV4;
9976 + * SPPE_CMD_FLOW_NAT_IPV6
9977 + * type = 1, as = 1
9979 +typedef struct _sppe_flow_nat_ipv6 {
9980 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
9981 + unsigned int fw:1;
9983 + unsigned int sws:1;
9984 + unsigned int ag:2;
9985 + unsigned int rl:1;
9986 + unsigned int l4_prot:2;
9987 + unsigned int l2s:2; /* L2 select */
9988 + unsigned int prs:2;
9989 + unsigned int kv:1;
9990 + unsigned int rd:1;
9991 + unsigned int dscp:6;
9992 + unsigned int fp:1;
9993 + unsigned int pri:3;
9994 + unsigned int max_len:2; /* Max. length select */
9995 + unsigned int pd:1;
9996 + unsigned int pi:1;
9997 + unsigned int psidx:4;
9999 + unsigned int psidx:4;
10000 + unsigned int pi:1;
10001 + unsigned int pd:1;
10002 + unsigned int max_len:2; /* Max. length select */
10003 + unsigned int pri:3;
10004 + unsigned int fp:1;
10005 + unsigned int dscp:6;
10006 + unsigned int rd:1;
10007 + unsigned int kv:1;
10008 + unsigned int prs:2;
10009 + unsigned int l2s:2; /* L2 select */
10010 + unsigned int l4_prot:2;
10011 + unsigned int rl:1;
10012 + unsigned int ag:2;
10013 + unsigned int sws:1;
10014 + unsigned int s:1;
10015 + unsigned int fw:1;
10017 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10018 + unsigned int unused:16;
10019 + unsigned int mac4732:16;
10021 + unsigned int mac4732:16;
10022 + unsigned int unused:16;
10024 + unsigned int mac3100;
10025 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10026 + unsigned int lp:1;
10027 + unsigned int fr:1;
10028 + unsigned int pm:4;
10029 + unsigned int sv:1;
10030 + unsigned int svid:12;
10031 + unsigned int cv:1;
10032 + unsigned int cvid:12;
10034 + unsigned int cvid:12;
10035 + unsigned int cv:1;
10036 + unsigned int svid:12;
10037 + unsigned int sv:1;
10038 + unsigned int pm:4;
10039 + unsigned int fr:1;
10040 + unsigned int lp:1;
10042 + unsigned int sip[4];
10043 + unsigned int dip[4];
10046 + unsigned short src;
10047 + unsigned short dst;
10050 + unsigned short call_id;
10051 + unsigned short nat_call_id;
10054 + unsigned char protocol;
10057 + unsigned int nat_ip[4];
10058 + unsigned short nat_port;
10059 + SPPE_LIMIT limit;
10060 + unsigned int pkt_cnt;
10061 +} SPPE_FLOW_NAT_IPV6;
10064 + * SPPE_CMD_FLOW_TWICE_NAT
10065 + * type = 0, as = 2
10067 +typedef struct _sppe_flow_twice_nat {
10068 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10069 + unsigned int fw:1;
10070 + unsigned int s:1;
10071 + unsigned int sws:1;
10072 + unsigned int ag:2;
10073 + unsigned int rl:1;
10074 + unsigned int l4_prot:2;
10075 + unsigned int l2s:2; /* L2 select */
10076 + unsigned int prs:2;
10077 + unsigned int kv:1;
10078 + unsigned int rd:1;
10079 + unsigned int dscp:6;
10080 + unsigned int fp:1;
10081 + unsigned int pri:3;
10082 + unsigned int max_len:2; /* Max. length select */
10083 + unsigned int psidx:4;
10084 + unsigned int reserved:2;
10086 + unsigned int reserved:2;
10087 + unsigned int psidx:4;
10088 + unsigned int max_len:2; /* Max. length select */
10089 + unsigned int pri:3;
10090 + unsigned int fp:1;
10091 + unsigned int dscp:6;
10092 + unsigned int rd:1;
10093 + unsigned int kv:1;
10094 + unsigned int prs:2;
10095 + unsigned int l2s:2; /* L2 select */
10096 + unsigned int l4_prot:2;
10097 + unsigned int rl:1;
10098 + unsigned int ag:2;
10099 + unsigned int sws:1;
10100 + unsigned int s:1;
10101 + unsigned int fw:1;
10104 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10105 + unsigned int unused:16;
10106 + unsigned int mac4732:16;
10108 + unsigned int mac4732:16;
10109 + unsigned int unused:16;
10111 + unsigned int mac3100;
10113 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10114 + unsigned int lp:1;
10115 + unsigned int fr:1;
10116 + unsigned int pm:4;
10117 + unsigned int sv:1;
10118 + unsigned int svid:12;
10119 + unsigned int cv:1;
10120 + unsigned int cvid:12;
10122 + unsigned int cvid:12;
10123 + unsigned int cv:1;
10124 + unsigned int svid:12;
10125 + unsigned int sv:1;
10126 + unsigned int pm:4;
10127 + unsigned int fr:1;
10128 + unsigned int lp:1;
10130 + unsigned int sip;
10131 + unsigned int dip;
10132 + unsigned short sport;
10133 + unsigned short dport;
10134 + unsigned int natsip;
10135 + unsigned int natdip;
10136 + unsigned short natsport;
10137 + unsigned short natdport;
10138 + SPPE_LIMIT limit;
10139 + unsigned int pkt_cnt;
10140 +} SPPE_FLOW_TWICE_NAT;
10143 + * SPPE_CMD_FLOW_MULTICAST_IPV4
10144 + * type = 0, as = 0 or 3
10146 +typedef struct _sppe_flow_multicast_ipv4 {
10147 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10148 + unsigned int fw:1;
10149 + unsigned int s:1;
10150 + unsigned int sws:1;
10151 + unsigned int ag:2;
10152 + unsigned int rl:1;
10153 + unsigned int l2s:2; /* L2 select */
10154 + unsigned int prs:2;
10155 + unsigned int kv:1;
10156 + unsigned int rd:1;
10157 + unsigned int dscp:6;
10158 + unsigned int fp:1;
10159 + unsigned int pri:3;
10160 + unsigned int max_len:2; /* Max. length select */
10161 + unsigned int bridge:1;
10162 + unsigned int reserved:7;
10164 + unsigned int reserved:7;
10165 + unsigned int bridge:1;
10166 + unsigned int max_len:2; /* Max. length select */
10167 + unsigned int pri:3;
10168 + unsigned int fp:1;
10169 + unsigned int dscp:6;
10170 + unsigned int rd:1;
10171 + unsigned int kv:1;
10172 + unsigned int prs:2;
10173 + unsigned int l2s:2; /* L2 select */
10174 + unsigned int rl:1;
10175 + unsigned int ag:2;
10176 + unsigned int sws:1;
10177 + unsigned int s:1;
10178 + unsigned int fw:1;
10180 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10181 + unsigned int unused:16;
10182 + unsigned int mac4732:16;
10184 + unsigned int mac4732:16;
10185 + unsigned int unused:16;
10187 + unsigned int mac3100;
10189 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10190 + unsigned int lp:1;
10191 + unsigned int fr:1;
10192 + unsigned int pm:4;
10193 + unsigned int sv:1;
10194 + unsigned int svid:12;
10195 + unsigned int cv:1;
10196 + unsigned int cvid:12;
10198 + unsigned int cvid:12;
10199 + unsigned int cv:1;
10200 + unsigned int svid:12;
10201 + unsigned int sv:1;
10202 + unsigned int pm:4;
10203 + unsigned int fr:1;
10204 + unsigned int lp:1;
10207 + unsigned int sip;
10208 + unsigned int dip;
10209 + SPPE_LIMIT limit;
10210 + unsigned int pkt_cnt;
10211 +} SPPE_FLOW_MCAST_IPV4;
10214 + * SPPE_CMD_FLOW_MULTICAST_IPV6
10215 + * type = 1, as = 0 or 3
10217 +typedef struct _sppe_flow_multicast_ipv6 {
10218 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10219 + unsigned int fw:1;
10220 + unsigned int s:1;
10221 + unsigned int sws:1;
10222 + unsigned int ag:2;
10223 + unsigned int rl:1;
10224 + unsigned int l2s:2; /* L2 select */
10225 + unsigned int prs:2;
10226 + unsigned int kv:1;
10227 + unsigned int rd:1;
10228 + unsigned int dscp:6;
10229 + unsigned int fp:1;
10230 + unsigned int pri:3;
10231 + unsigned int max_len:2; /* Max. length select */
10232 + unsigned int bridge:1;
10233 + unsigned int reserved:7;
10235 + unsigned int reserved:7;
10236 + unsigned int bridge:1;
10237 + unsigned int max_len:2; /* Max. length select */
10238 + unsigned int pri:3;
10239 + unsigned int fp:1;
10240 + unsigned int dscp:6;
10241 + unsigned int rd:1;
10242 + unsigned int kv:1;
10243 + unsigned int prs:2;
10244 + unsigned int l2s:2; /* L2 select */
10245 + unsigned int rl:1;
10246 + unsigned int ag:2;
10247 + unsigned int sws:1;
10248 + unsigned int s:1;
10249 + unsigned int fw:1;
10252 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10253 + unsigned int unused:16;
10254 + unsigned int mac4732:16;
10256 + unsigned int mac4732:16;
10257 + unsigned int unused:16;
10259 + unsigned int mac3100;
10261 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10262 + unsigned int lp:1;
10263 + unsigned int fr:1;
10264 + unsigned int pm:4;
10265 + unsigned int sv:1;
10266 + unsigned int svid:12;
10267 + unsigned int cv:1;
10268 + unsigned int cvid:12;
10270 + unsigned int cvid:12;
10271 + unsigned int cv:1;
10272 + unsigned int svid:12;
10273 + unsigned int sv:1;
10274 + unsigned int pm:4;
10275 + unsigned int fr:1;
10276 + unsigned int lp:1;
10279 + unsigned int sip[4];
10280 + unsigned int dip[4];
10281 + SPPE_LIMIT limit;
10282 + unsigned int pkt_cnt;
10283 +} SPPE_FLOW_MCAST_IPV6;
10286 + * SPPE_CMD_FLOW_LAYER_TWO
10289 +typedef struct _sppe_flow_bridge_l2 {
10290 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10291 + unsigned int fw:1;
10292 + unsigned int s:1;
10293 + unsigned int sws:1;
10294 + unsigned int ag:2;
10295 + unsigned int rl:1;
10296 + unsigned int l2_prot:2;
10297 + unsigned int kv:1;
10298 + unsigned int fp:1;
10299 + unsigned int pri:3;
10300 + unsigned int psidx:4;
10301 + unsigned int reserved:15;
10303 + unsigned int reserved:15;
10304 + unsigned int psidx:4;
10305 + unsigned int pri:3;
10306 + unsigned int fp:1;
10307 + unsigned int kv:1;
10308 + unsigned int l2_prot:2;
10309 + unsigned int rl:1;
10310 + unsigned int ag:2;
10311 + unsigned int sws:1;
10312 + unsigned int s:1;
10313 + unsigned int fw:1;
10316 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10317 + unsigned int lp:1;
10318 + unsigned int fr:1;
10319 + unsigned int pm:4;
10320 + unsigned int sv:1;
10321 + unsigned int svid:12;
10322 + unsigned int cv:1;
10323 + unsigned int cvid:12;
10325 + unsigned int cvid:12;
10326 + unsigned int cv:1;
10327 + unsigned int svid:12;
10328 + unsigned int sv:1;
10329 + unsigned int pm:4;
10330 + unsigned int fr:1;
10331 + unsigned int lp:1;
10334 + unsigned short smac[3];
10335 + unsigned short dmac[3];
10337 + SPPE_LIMIT limit;
10338 + unsigned int pkt_cnt;
10339 +} SPPE_FLOW_BRIDGE_L2;
10341 +typedef struct _sppe_arl {
10342 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10343 + unsigned int vid:12;
10344 + unsigned int pmap:5;
10345 + unsigned int age:3;
10346 + unsigned int mymac:1;
10347 + unsigned int filter:1;
10348 + unsigned int reserved:10;
10350 + unsigned int reserved:10;
10351 + unsigned int filter:1;
10352 + unsigned int mymac:1;
10353 + unsigned int age:3;
10354 + unsigned int pmap:5;
10355 + unsigned int vid:12;
10357 + unsigned char mac[6];
10360 +typedef struct _sppe_init {
10361 + unsigned int flow_pre_match_paddr;
10362 + unsigned int flow_pre_match_vaddr;
10363 + unsigned int flow_body_paddr;
10364 + unsigned int flow_body_vaddr;
10365 + unsigned int flow_ext_paddr;
10366 + unsigned int flow_ext_vaddr;
10367 + unsigned int flow_size;
10368 + unsigned int arp_pre_match_paddr;
10369 + unsigned int arp_pre_match_vaddr;
10370 + unsigned int arp_body_paddr;
10371 + unsigned int arp_body_vaddr;
10372 + unsigned int arp_size;
10373 + unsigned int ipv6_napt;
10376 +typedef struct _sppe_param_t {
10382 + unsigned char major;
10383 + unsigned char minor;
10384 + unsigned char very_minor;
10385 + unsigned char pre;
10388 + SPPE_BOOL sppe_enable;
10389 + unsigned int sppe_lanip;
10392 + unsigned int index;
10394 + unsigned int session_id;
10398 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10399 + unsigned int index:2;
10400 + unsigned int to:4;
10401 + unsigned int sv:1;
10402 + unsigned int stag_vid:12;
10403 + unsigned int cv:1;
10404 + unsigned int ctag_vid:12;
10406 + unsigned int ctag_vid:12;
10407 + unsigned int cv:1;
10408 + unsigned int stag_vid:12;
10409 + unsigned int sv:1;
10410 + unsigned int to:4;
10411 + unsigned int index:2;
10413 + unsigned char mac[6]; /* MAC address */
10417 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10418 + unsigned int interval:2;
10419 + unsigned int mfactor:1;
10420 + unsigned int ununsed:29;
10422 + unsigned int ununsed:29;
10423 + unsigned int mfactor:1;
10424 + unsigned int interval:2;
10429 + unsigned int index;
10430 + SPPE_PPPOE_RELAY rule;
10431 + } sppe_pppoe_relay;
10434 + unsigned int index;
10435 + SPPE_BRIDGE rule;
10439 + unsigned int index;
10444 + unsigned int index;
10449 + unsigned int index;
10450 + SPPE_VSERVER rule;
10454 + unsigned int index;
10459 + unsigned int index;
10464 + unsigned int index;
10465 + SPPE_GLOBAL_RATE_LIMIT rule;
10469 + unsigned char unit;
10470 + unsigned char arp;
10471 + unsigned char bridge;
10472 + unsigned char tcp;
10473 + unsigned char udp;
10474 + unsigned char pptp;
10475 + unsigned char other;
10479 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10480 + unsigned int index:2;
10481 + unsigned int reserved:20;
10482 + unsigned int max:10;
10484 + unsigned int max:10;
10485 + unsigned int reserved:20;
10486 + unsigned int index:2;
10488 + } sppe_max_length;
10491 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10492 + unsigned int v6:1;
10493 + unsigned int s:1;
10494 + unsigned int r:1;
10495 + unsigned int fr:1;
10496 + unsigned int to:4;
10497 + unsigned int unused:24;
10499 + unsigned int unused:24;
10500 + unsigned int to:4;
10501 + unsigned int fr:1;
10502 + unsigned int r:1;
10503 + unsigned int s:1;
10504 + unsigned int v6:1;
10507 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10508 + unsigned int sv:1;
10509 + unsigned int stag_vid:12;
10510 + unsigned int cv:1;
10511 + unsigned int ctag_vid:12;
10512 + unsigned int unused_1:6;
10514 + unsigned int unused_1:6;
10515 + unsigned int ctag_vid:12;
10516 + unsigned int cv:1;
10517 + unsigned int stag_vid:12;
10518 + unsigned int sv:1;
10520 + unsigned int ip[4];
10521 + unsigned char mac[6];
10524 + SPPE_ARL sppe_arl;
10527 + unsigned int sid;
10528 + unsigned int index;
10529 + } sppe_pppoe_sid;
10531 + SPPE_FLOW_BRIDGE_IPV4 flow_bridge_ipv4;
10532 + SPPE_FLOW_BRIDGE_IPV6 flow_bridge_ipv6;
10533 + SPPE_FLOW_ROUTE_IPV4 flow_route_ipv4;
10534 + SPPE_FLOW_ROUTE_IPV6 flow_route_ipv6;
10535 + SPPE_FLOW_NAT_IPV4 flow_nat_ipv4;
10536 + SPPE_FLOW_NAT_IPV6 flow_nat_ipv6;
10537 + SPPE_FLOW_TWICE_NAT flow_twice_nat;
10538 + SPPE_FLOW_MCAST_IPV4 flow_mcast_ipv4;
10539 + SPPE_FLOW_MCAST_IPV6 flow_mcast_ipv6;
10540 + SPPE_FLOW_BRIDGE_L2 flow_bridge_l2;
10543 + SPPE_DUMP_TYPE type;
10544 + unsigned short key;
10545 + unsigned short way;
10546 + unsigned int raw[23];
10549 + unsigned int sppe_sna_th;
10552 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10553 + unsigned int enable:1;
10554 + unsigned int lan:6;
10555 + unsigned int wan:6;
10556 + unsigned int reserved:19;
10558 + unsigned int reserved:19;
10559 + unsigned int wan:6;
10560 + unsigned int lan:6;
10561 + unsigned int enable:1;
10566 +#ifndef CONFIG_SWITCH_BIG_ENDIAN
10567 + unsigned int enable:1;
10568 + unsigned int lan:3;
10569 + unsigned int wan:3;
10570 + unsigned int reserved:25;
10572 + unsigned int reserved:25;
10573 + unsigned int wan:3;
10574 + unsigned int lan:3;
10575 + unsigned int enable:1;
10586 + unsigned int offset;
10587 + unsigned int data;
10591 + unsigned int offset;
10592 + unsigned int data;
10597 + unsigned int max;
10598 + unsigned int min;
10605 + unsigned int max;
10606 + unsigned int min;
10612 + unsigned int index;
10613 + unsigned short start;
10614 + unsigned short end;
10615 + SPPE_LIMIT limit;
10619 + unsigned int index;
10620 + unsigned int pkt_cnt;
10621 + unsigned int byte_cnt;
10622 + } sppe_accounting_group;
10625 + unsigned int pkt_cnt;
10626 + } sppe_drop_ipcs_err; /* IP checksum error */
10629 + unsigned int pkt_cnt;
10630 + } sppe_drop_rate_limit;
10633 + unsigned int pkt_cnt;
10634 + } sppe_drop_others;
10637 + unsigned int index;
10638 + unsigned char name[16];
10639 + struct net_device *dev;
10640 + unsigned int vid;
10641 + } sppe_pci_fp_dev;
10643 + SPPE_INIT sppe_init;
10648 +extern int sppe_hook_ready;
10649 +extern int (*sppe_func_hook)(SPPE_PARAM *param);
10651 +extern int sppe_pci_fp_ready;
10652 +extern int (*sppe_pci_fp_hook)(SPPE_PARAM *param);
10654 +#endif /* CONFIG_CNS3XXX_SPPE */
10656 +#endif /* _SPPE_H_ */
10658 +++ b/include/linux/cns3xxx/switch_api.h
10660 +/*******************************************************************************
10662 + * Copyright (c) 2008 Cavium Networks
10664 + * This program is free software; you can redistribute it and/or modify it
10665 + * under the terms of the GNU General Public License as published by the Free
10666 + * Software Foundation; either version 2 of the License, or (at your option)
10667 + * any later version.
10669 + * This program is distributed in the hope that it will be useful, but WITHOUT
10670 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10671 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
10674 + * You should have received a copy of the GNU General Public License along with
10675 + * this program; if not, write to the Free Software Foundation, Inc., 59
10676 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
10678 + * The full GNU General Public License is included in this distribution in the
10679 + * file called LICENSE.
10681 + * Contact Information:
10682 + * Technology Support <tech@starsemi.com>
10683 + * Star Semiconductor 4F, No.1, Chin-Shan 8th St, Hsin-Chu,300 Taiwan, R.O.C
10685 + ********************************************************************************/
10687 +#ifndef SWITCH_API_H_K
10688 +#define SWITCH_API_H_K
10691 +#ifndef __KERNEL__
10692 +typedef unsigned int u32;
10693 +typedef unsigned short int u16;
10694 +typedef unsigned char u8;
10698 +#include <linux/types.h>
10704 +#define CAVM_ERR 1
10705 +#define CAVM_NOT_FOUND 2
10706 +#define CAVM_FOUND 3
10707 +#define CAVM_FAIL -1 // use minus
10709 +#define MAC_PORT0 0
10710 +#define MAC_PORT1 1
10711 +#define MAC_PORT2 2
10712 +#define CPU_PORT 3
10718 + CNS3XXX_ARL_TABLE_LOOKUP,
10719 + CNS3XXX_ARL_TABLE_ADD,
10720 + CNS3XXX_ARL_TABLE_DEL,
10721 + CNS3XXX_ARL_TABLE_SEARCH,
10722 + CNS3XXX_ARL_TABLE_SEARCH_AGAIN,
10723 + CNS3XXX_ARL_IS_TABLE_END,
10724 + CNS3XXX_ARL_TABLE_FLUSH,
10726 + CNS3XXX_VLAN_TABLE_LOOKUP,
10727 + CNS3XXX_VLAN_TABLE_ADD,
10728 + CNS3XXX_VLAN_TABLE_DEL,
10729 + CNS3XXX_VLAN_TABLE_READ,
10731 + CNS3XXX_SKEW_SET,
10732 + CNS3XXX_SKEW_GET,
10734 + CNS3XXX_BRIDGE_SET,
10735 + CNS3XXX_BRIDGE_GET,
10737 + CNS3XXX_PORT_NEIGHBOR_SET,
10738 + CNS3XXX_PORT_NEIGHBOR_GET,
10740 + CNS3XXX_HOL_PREVENT_SET,
10741 + CNS3XXX_HOL_PREVENT_GET,
10743 + CNS3XXX_TC_SET, // traffic class, for 1, 2, 4, traffic class
10746 + CNS3XXX_PRI_CTRL_SET,
10747 + CNS3XXX_PRI_CTRL_GET,
10749 + CNS3XXX_DMA_RING_CTRL_SET,
10750 + CNS3XXX_DMA_RING_CTRL_GET,
10752 + CNS3XXX_PRI_IP_DSCP_SET,
10753 + CNS3XXX_PRI_IP_DSCP_GET,
10755 + CNS3XXX_ETYPE_SET,
10756 + CNS3XXX_ETYPE_GET,
10758 + CNS3XXX_UDP_RANGE_SET,
10759 + CNS3XXX_UDP_RANGE_GET,
10761 + CNS3XXX_ARP_REQUEST_SET,
10762 + CNS3XXX_ARP_REQUEST_GET,
10764 + CNS3XXX_RATE_LIMIT_SET,
10765 + CNS3XXX_RATE_LIMIT_GET,
10767 + CNS3XXX_QUEUE_WEIGHT_SET,
10768 + CNS3XXX_QUEUE_WEIGHT_GET,
10770 + CNS3XXX_FC_RLS_SET,
10771 + CNS3XXX_FC_RLS_GET,
10773 + CNS3XXX_FC_SET_SET,
10774 + CNS3XXX_FC_SET_GET,
10776 + CNS3XXX_SARL_RLS_SET,
10777 + CNS3XXX_SARL_RLS_GET,
10779 + CNS3XXX_SARL_SET_SET,
10780 + CNS3XXX_SARL_SET_GET,
10782 + CNS3XXX_SARL_OQ_SET,
10783 + CNS3XXX_SARL_OQ_GET,
10785 + CNS3XXX_SARL_ENABLE_SET,
10786 + CNS3XXX_SARL_ENABLE_GET,
10794 + CNS3XXX_WAN_PORT_SET,
10795 + CNS3XXX_WAN_PORT_GET,
10797 + CNS3XXX_PVID_GET,
10798 + CNS3XXX_PVID_SET,
10800 + CNS3XXX_QA_GET, // queue allocate
10803 + CNS3XXX_PACKET_MAX_LEN_GET, // set maximun frame length.
10804 + CNS3XXX_PACKET_MAX_LEN_SET,
10806 + CNS3XXX_BCM53115M_REG_READ,
10807 + CNS3XXX_BCM53115M_REG_WRITE,
10809 + CNS3XXX_RXRING_STATUS,
10810 + CNS3XXX_TXRING_STATUS,
10812 + CNS3XXX_DUMP_MIB_COUNTER,
10814 + CNS3XXX_REG_READ,
10815 + CNS3XXX_REG_WRITE,
10829 +}VLANTableEntry; // for vlan table function
10840 +}ARLTableEntry; // for arl table function
10845 + CNS3XXXIoctlCmd cmd;
10846 + ARLTableEntry entry;
10847 +}CNS3XXXARLTableEntry; // for ioctl arl ...
10851 + CNS3XXXIoctlCmd cmd;
10852 + VLANTableEntry entry;
10853 +}CNS3XXXVLANTableEntry; // for ioctl VLAN table ...
10857 + CNS3XXXIoctlCmd cmd;
10859 +}CNS3XXXHOLPreventControl;
10864 + CNS3XXXIoctlCmd cmd;
10865 + unsigned char which_port; // 0, 1, 2, 3 (cpu port)
10866 + unsigned char type; // 0: C-Neighbor, 1: S-Neighbor
10867 +}CNS3XXXPortNeighborControl;
10871 + CNS3XXXIoctlCmd cmd;
10872 + unsigned char type; // 0: C-Component, 1: S-Component
10873 +}CNS3XXXBridgeControl;
10877 + CNS3XXXIoctlCmd cmd;
10878 + unsigned char tc; // traffic class, for 1, 2, 4, traffic class
10879 +}CNS3XXXTrafficClassControl;
10883 + CNS3XXXIoctlCmd cmd;
10884 + unsigned char which_port; // 0, 1, 2, 3 (cpu port)
10885 + unsigned int val;
10886 + unsigned char port_pri;
10887 + unsigned char udp_pri_en;
10888 + unsigned char dscp_pri_en;
10889 + unsigned char vlan_pri_en;
10890 + unsigned char ether_pri_en;
10891 +}CNS3XXXPriCtrlControl;
10895 + CNS3XXXIoctlCmd cmd;
10896 + unsigned char ts_double_ring_en;
10897 + unsigned char fs_double_ring_en;
10898 + unsigned char fs_pkt_allocate;
10899 +}CNS3XXXDmaRingCtrlControl;
10903 + CNS3XXXIoctlCmd cmd;
10904 + unsigned int ip_dscp_num; // 0 ~ 63
10905 + unsigned char pri; // 3 bits
10906 +}CNS3XXXPriIpDscpControl;
10910 + CNS3XXXIoctlCmd cmd;
10911 + unsigned int etype_num;
10912 + unsigned int val;
10913 + unsigned int pri;
10914 +}CNS3XXXEtypeControl;
10918 + CNS3XXXIoctlCmd cmd;
10919 + unsigned int udp_range_num;
10920 + unsigned short int port_start;
10921 + unsigned short int port_end;
10922 +}CNS3XXXUdpRangeEtypeControl;
10926 + CNS3XXXIoctlCmd cmd;
10927 + unsigned char val; // 0: boradcast forward, 1: redirect to the CPU
10928 +}CNS3XXXArpRequestControl;
10932 + CNS3XXXIoctlCmd cmd;
10933 + unsigned char which_port; // 0, 1, 2, 3 (port 0 extra dma)
10934 + unsigned char band_width;
10935 + unsigned char base_rate;
10937 +}CNS3XXXRateLimitEntry; // for ioctl arl ...
10941 + CNS3XXXIoctlCmd cmd;
10942 + unsigned char which_port; // 0, 1, 2, 3 (port 0 extra dma)
10943 + unsigned char sch_mode;
10944 + unsigned char q0_w;
10945 + unsigned char q1_w;
10946 + unsigned char q2_w;
10947 + unsigned char q3_w;
10948 +}CNS3XXXQueueWeightEntry; // for ioctl arl ...
10952 + CNS3XXXIoctlCmd cmd;
10953 + unsigned int val;
10954 + unsigned char tc; // 0-3
10955 + unsigned char gyr; // 0 (green), 1(yellow), 2(red)
10956 +}CNS3XXXSARLEntry; // for ioctl arl ...
10960 + CNS3XXXIoctlCmd cmd;
10961 + unsigned char port; // 0, 1, 2, 3 (cpu port)
10962 + unsigned char fc_en; // 0(rx/tx disable), 1(rx enable), 2(tx enable), 3(rx/tx enable)
10963 +}CNS3XXXFCEntry; // for ioctl arl ...
10967 + CNS3XXXIoctlCmd cmd;
10968 + unsigned char enable; // enable: 1 -> IVL, enable: 0 -> SVL
10969 +}CNS3XXXIVLEntry; // for ioctl arl ...
10973 + CNS3XXXIoctlCmd cmd;
10974 + unsigned char wan_port;
10975 +}CNS3XXXWANPortEntry; // for ioctl arl ...
10979 + CNS3XXXIoctlCmd cmd;
10980 + unsigned char which_port;
10981 + unsigned int pvid;
10982 +}CNS3XXXPVIDEntry; // for ioctl arl ...
10986 + CNS3XXXIoctlCmd cmd;
10987 + unsigned char qa; // queue allocate
10988 +}CNS3XXXQAEntry; // for ioctl arl ...
10992 + CNS3XXXIoctlCmd cmd;
10993 + unsigned char max_len; // maximum frame length
10994 +}CNS3XXXMaxLenEntry; // for ioctl arl ...
10998 + CNS3XXXIoctlCmd cmd;
11006 +}CNS3XXXBCM53115M;
11010 + CNS3XXXIoctlCmd cmd;
11013 +}CNS3XXXMIBCounter;
11018 + CNS3XXXIoctlCmd cmd;
11021 +}CNS3XXXRingStatus;
11026 --- a/net/core/dev.c
11027 +++ b/net/core/dev.c
11028 @@ -133,6 +133,10 @@
11030 #include "net-sysfs.h"
11032 +#if defined (CONFIG_CNS3XXX_SPPE)
11033 +#include <linux/cns3xxx/sppe.h>
11036 /* Instead of increasing this, you should create a hash table. */
11037 #define MAX_GRO_SKBS 8
11039 @@ -1944,6 +1948,197 @@ int weight_p __read_mostly = 64;
11041 DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
11043 +#if defined (CONFIG_CNS3XXX_SPPE)
11044 +static struct net_device *tun_netdev = NULL;
11046 +int sppe_pci_fp(struct sk_buff *skb)
11048 + SPPE_PARAM param;
11049 + struct iphdr *iph;
11050 +#if defined (CONFIG_IPV6)
11051 + struct ipv6hdr *ipv6h;
11053 + struct tcphdr *th;
11054 + struct udphdr *uh;
11055 + int pci_dev_index;
11057 + if (!sppe_hook_ready) {
11061 + if (!sppe_pci_fp_ready) {
11065 + /* check device packet comes from, is a registed device? */
11066 + memset(¶m, 0, sizeof(SPPE_PARAM));
11067 + param.cmd = SPPE_CMD_PCI_FP_DEV;
11068 + param.op = SPPE_OP_GET;
11069 + param.data.sppe_pci_fp_dev.dev = skb->dev;
11070 + sppe_pci_fp_hook(¶m);
11072 + pci_dev_index = param.data.sppe_pci_fp_dev.index;
11074 + if ((-1) == pci_dev_index) {
11078 + if (!tun_netdev) {
11079 + tun_netdev = dev_get_by_name(&init_net, "fp");
11081 + if (!tun_netdev) {
11086 + /* check PPE status */
11087 + memset(¶m, 0, sizeof(SPPE_PARAM));
11088 + param.cmd = SPPE_CMD_ENABLE;
11089 + param.op = SPPE_OP_GET;
11091 + if (sppe_func_hook(¶m)) {
11092 + printk("<0><%s> fail to get PPE status!!\n", __FUNCTION__);
11096 + if (!param.data.sppe_enable) {
11100 + memset(¶m, 0, sizeof(SPPE_PARAM));
11102 + switch (htons(skb->protocol)) {
11104 + iph = (struct iphdr *)skb->data;
11106 + if (5 != iph->ihl) { goto NOT_IN_FP; }
11108 + if (iph->frag_off & 0x20) { goto NOT_IN_FP; }
11110 + param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11111 + param.op = SPPE_OP_GET;
11113 + param.data.flow_nat_ipv4.sip = ntohl(iph->saddr);
11114 + param.data.flow_nat_ipv4.dip = ntohl(iph->daddr);
11116 + switch (iph->protocol) {
11117 + case IPPROTO_TCP:
11118 + th = (struct tcphdr *) ((int *)iph + 5); /* IP header length is 20 */
11120 + if ((th->syn) || (th->fin) || (th->rst)) { goto NOT_IN_FP; }
11122 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_TCP;
11123 + param.data.flow_nat_ipv4.l4.port.src = ntohs(th->source);
11124 + param.data.flow_nat_ipv4.l4.port.dst = ntohs(th->dest);
11126 + case IPPROTO_UDP:
11127 + uh = (struct udphdr *) ((int *)iph + 5); /* IP header length is 20 */
11128 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_UDP;
11129 + param.data.flow_nat_ipv4.l4.port.src = ntohs(uh->source);
11130 + param.data.flow_nat_ipv4.l4.port.dst = ntohs(uh->dest);
11136 + if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) {
11139 + struct ethhdr *eth;
11141 + eth = (struct ethhdr *)skb->mac_header;
11143 + memset(¶m, 0, sizeof(SPPE_PARAM));
11144 + param.cmd = SPPE_CMD_ARP;
11145 + param.op = SPPE_OP_SET;
11146 + param.data.sppe_arp.s = 1;
11147 + param.data.sppe_arp.ip[0] = iph->saddr;
11148 + param.data.sppe_arp.mac[0] = eth->h_source[0];
11149 + param.data.sppe_arp.mac[1] = eth->h_source[1];
11150 + param.data.sppe_arp.mac[2] = eth->h_source[2];
11151 + param.data.sppe_arp.mac[3] = eth->h_source[3];
11152 + param.data.sppe_arp.mac[4] = eth->h_source[4];
11153 + param.data.sppe_arp.mac[5] = eth->h_source[5];
11154 + param.data.sppe_arp.unused_1 = pci_dev_index;
11156 + if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) {
11157 + printk("add ARP fail\n");
11160 + param.data.sppe_arp.unused_1 = 0xf;
11161 + param.op = SPPE_OP_GET;
11162 + if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) {
11163 + printk("read ARP fail\n");
11165 + printk("param.data.sppe_arp.unused_1 %d\n", param.data.sppe_arp.unused_1);
11170 + break; /* case ETH_P_IP: */
11171 +#if defined (CONFIG_IPV6)
11173 + ipv6h = (struct ipv6hdr *)skb->data;
11174 + switch (ipv6h->nexthdr) {
11175 + case IPPROTO_TCP:
11176 + th = (struct tcphdr *) ((int *)ipv6h + 10); /* IPv6 header length is 40 bytes */
11178 + if ((th->syn) || (th->fin) || (th->rst)) { goto NOT_IN_FP; }
11180 + param.data.flow_route_ipv6.l4_prot = SPPE_PROT_TCP;
11181 + param.data.flow_route_ipv6.l4.port.src = ntohs(th->source);
11182 + param.data.flow_route_ipv6.l4.port.dst = ntohs(th->dest);
11183 + param.data.flow_route_ipv6.l4_prot = SPPE_PROT_TCP;
11185 + case IPPROTO_UDP:
11186 + uh = (struct udphdr *) ((int *)ipv6h + 10); /* IPv6 header length is 40 byte */
11187 + param.data.flow_route_ipv6.l4_prot = SPPE_PROT_UDP;
11188 + param.data.flow_route_ipv6.l4.port.src = ntohs(uh->source);
11189 + param.data.flow_route_ipv6.l4.port.dst = ntohs(uh->dest);
11195 + param.data.flow_route_ipv6.sip[0] = ntohl(ipv6h->saddr.s6_addr32[0]);
11196 + param.data.flow_route_ipv6.sip[1] = ntohl(ipv6h->saddr.s6_addr32[1]);
11197 + param.data.flow_route_ipv6.sip[2] = ntohl(ipv6h->saddr.s6_addr32[2]);
11198 + param.data.flow_route_ipv6.sip[3] = ntohl(ipv6h->saddr.s6_addr32[3]);
11199 + param.data.flow_route_ipv6.dip[0] = ntohl(ipv6h->daddr.s6_addr32[0]);
11200 + param.data.flow_route_ipv6.dip[1] = ntohl(ipv6h->daddr.s6_addr32[1]);
11201 + param.data.flow_route_ipv6.dip[2] = ntohl(ipv6h->daddr.s6_addr32[2]);
11202 + param.data.flow_route_ipv6.dip[3] = ntohl(ipv6h->daddr.s6_addr32[3]);
11204 + param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11205 + param.op = SPPE_OP_GET;
11207 + if (SPPE_RESULT_SUCCESS != sppe_func_hook(¶m)) {
11211 + break; /* case ETH_P_IPV6: */
11213 + case ETH_P_PPP_SES:
11215 + default: /* unsupport protocol */
11218 + /* Update counter */
11219 + skb->dev = tun_netdev;
11220 + skb->ip_summed = CHECKSUM_NONE;
11221 + skb_push(skb, ETH_HLEN);
11223 + dev_queue_xmit(skb);
11236 * netif_rx - post buffer to the network code
11237 @@ -1965,6 +2160,12 @@ int netif_rx(struct sk_buff *skb)
11238 struct softnet_data *queue;
11239 unsigned long flags;
11241 +#if defined (CONFIG_CNS3XXX_SPPE)
11242 + if (0 == sppe_pci_fp(skb)) {
11243 + return NET_RX_SUCCESS;
11247 /* if netpoll wants it, pretend we never saw it */
11248 if (netpoll_rx(skb))
11249 return NET_RX_DROP;
11250 @@ -2259,6 +2460,12 @@ int netif_receive_skb(struct sk_buff *sk
11251 if (!skb->tstamp.tv64)
11252 net_timestamp(skb);
11254 +#if defined (CONFIG_CNS3XXX_SPPE)
11255 + if (0 == sppe_pci_fp(skb)) {
11256 + return NET_RX_SUCCESS;
11260 if (skb->vlan_tci && vlan_hwaccel_do_receive(skb))
11261 return NET_RX_SUCCESS;
11263 --- a/net/netfilter/nf_conntrack_core.c
11264 +++ b/net/netfilter/nf_conntrack_core.c
11266 #include <net/netfilter/nf_conntrack_ecache.h>
11267 #include <net/netfilter/nf_nat.h>
11268 #include <net/netfilter/nf_nat_core.h>
11269 +#if defined (CONFIG_CNS3XXX_SPPE)
11270 +#include <linux/cns3xxx/sppe.h>
11273 #define NF_CONNTRACK_VERSION "0.5.0"
11275 @@ -275,6 +278,92 @@ void nf_ct_insert_dying_list(struct nf_c
11277 EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
11279 +#if defined (CONFIG_CNS3XXX_SPPE)
11280 +static int sppe_flow_del(struct nf_conn *ct)
11282 + if (sppe_hook_ready) {
11283 + SPPE_PARAM param;
11285 + struct nf_conntrack_tuple *orig, *reply;
11287 + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11288 + reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11290 + if (PF_INET == orig->src.l3num) {
11291 + param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11292 + } else if (PF_INET6 == orig->src.l3num) {
11293 + param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11295 + goto SPPE_FLOW_DEL_FINI;
11298 + if (IPPROTO_TCP == orig->dst.protonum) {
11299 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_TCP;
11300 + } else if (IPPROTO_UDP == orig->dst.protonum) {
11301 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_UDP;
11302 + } else if (IPPROTO_GRE == orig->dst.protonum) {
11303 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_PPTP_GRE;
11305 + goto SPPE_FLOW_DEL_FINI;
11308 + param.op = SPPE_OP_DELETE_OUTDATED;
11310 + param.data.flow_nat_ipv4.fw = 0;
11311 + if (SPPE_CMD_FLOW_ROUTE_IPV6 == param.cmd) {
11312 + param.data.flow_route_ipv6.sip[0] = htonl(orig->src.u3.ip6[0]);
11313 + param.data.flow_route_ipv6.sip[1] = htonl(orig->src.u3.ip6[1]);
11314 + param.data.flow_route_ipv6.sip[2] = htonl(orig->src.u3.ip6[2]);
11315 + param.data.flow_route_ipv6.sip[3] = htonl(orig->src.u3.ip6[3]);
11316 + param.data.flow_route_ipv6.dip[0] = htonl(orig->dst.u3.ip6[0]);
11317 + param.data.flow_route_ipv6.dip[1] = htonl(orig->dst.u3.ip6[1]);
11318 + param.data.flow_route_ipv6.dip[2] = htonl(orig->dst.u3.ip6[2]);
11319 + param.data.flow_route_ipv6.dip[3] = htonl(orig->dst.u3.ip6[3]);
11320 + param.data.flow_route_ipv6.l4.port.src = htons(orig->src.u.tcp.port);
11321 + param.data.flow_route_ipv6.l4.port.dst = htons(orig->dst.u.tcp.port);
11323 + param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip);
11324 + param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip);
11325 + param.data.flow_nat_ipv4.l4.port.src = htons(orig->src.u.tcp.port);
11326 + param.data.flow_nat_ipv4.l4.port.dst = htons(orig->dst.u.tcp.port);
11329 + if (SPPE_RESULT_FAIL == sppe_func_hook(¶m)) {
11333 + param.data.flow_nat_ipv4.fw = 1;
11335 + if (SPPE_CMD_FLOW_ROUTE_IPV6 == param.cmd) {
11336 + param.data.flow_route_ipv6.sip[0] = htonl(reply->src.u3.ip6[0]);
11337 + param.data.flow_route_ipv6.sip[1] = htonl(reply->src.u3.ip6[1]);
11338 + param.data.flow_route_ipv6.sip[2] = htonl(reply->src.u3.ip6[2]);
11339 + param.data.flow_route_ipv6.sip[3] = htonl(reply->src.u3.ip6[3]);
11340 + param.data.flow_route_ipv6.dip[0] = htonl(reply->dst.u3.ip6[0]);
11341 + param.data.flow_route_ipv6.dip[1] = htonl(reply->dst.u3.ip6[1]);
11342 + param.data.flow_route_ipv6.dip[2] = htonl(reply->dst.u3.ip6[2]);
11343 + param.data.flow_route_ipv6.dip[3] = htonl(reply->dst.u3.ip6[3]);
11345 + param.data.flow_route_ipv6.l4.port.src = htons(reply->src.u.tcp.port);
11346 + param.data.flow_route_ipv6.l4.port.dst = htons(reply->dst.u.tcp.port);
11348 + param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip);
11349 + param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip);
11350 + param.data.flow_nat_ipv4.l4.port.src = htons(reply->src.u.tcp.port);
11351 + param.data.flow_nat_ipv4.l4.port.dst = htons(reply->dst.u.tcp.port);
11354 + if (SPPE_RESULT_FAIL == sppe_func_hook(¶m)) {
11359 +SPPE_FLOW_DEL_FINI:
11365 static void death_by_timeout(unsigned long ul_conntrack)
11367 struct nf_conn *ct = (void *)ul_conntrack;
11368 @@ -289,6 +378,16 @@ static void death_by_timeout(unsigned lo
11369 set_bit(IPS_DYING_BIT, &ct->status);
11370 nf_ct_delete_from_lists(ct);
11373 +#if defined (CONFIG_CNS3XXX_SPPE)
11374 + if (sppe_flow_del(ct)) {
11376 + ct->timeout.expires = jiffies + (120*HZ);
11377 + add_timer(&ct->timeout);
11385 --- a/net/netfilter/nf_conntrack_proto_gre.c
11386 +++ b/net/netfilter/nf_conntrack_proto_gre.c
11388 #include <linux/netfilter/nf_conntrack_proto_gre.h>
11389 #include <linux/netfilter/nf_conntrack_pptp.h>
11391 +#if defined (CONFIG_CNS3XXX_SPPE)
11392 +#include <linux/cns3xxx/sppe.h>
11395 #define GRE_TIMEOUT (30 * HZ)
11396 #define GRE_STREAM_TIMEOUT (180 * HZ)
11398 @@ -226,6 +230,57 @@ static int gre_print_conntrack(struct se
11399 (ct->proto.gre.stream_timeout / HZ));
11402 +#if defined (CONFIG_CNS3XXX_SPPE)
11403 +static int sppe_gre_flow_add(struct nf_conn *ct)
11405 + SPPE_PARAM param;
11406 + struct nf_conntrack_tuple *orig, *reply;
11408 + if (0 == sppe_hook_ready) {
11412 + memset(¶m, 0, sizeof(SPPE_PARAM));
11414 + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11415 + reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11417 + param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11418 + param.op = SPPE_OP_SET;
11420 + param.data.flow_nat_ipv4.fw = 0;
11421 + param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip);
11422 + param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip);
11424 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_PPTP_GRE;
11425 + param.data.flow_nat_ipv4.l4.gre.call_id = htons(orig->dst.u.gre.key);
11427 + param.data.flow_nat_ipv4.nat_ip = htonl(reply->dst.u3.ip);
11428 + param.data.flow_nat_ipv4.l4.gre.nat_call_id = htons(reply->src.u.gre.key);
11430 + if (sppe_func_hook(¶m)) {
11431 + printk("<0><%s> fail to add IPv4 from-LAN flow!!\n", __FUNCTION__);
11434 + param.data.flow_nat_ipv4.fw = 1;
11436 + param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip);
11437 + param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip);
11438 + param.data.flow_nat_ipv4.l4.gre.call_id = htons(reply->dst.u.gre.key);
11440 + param.data.flow_nat_ipv4.nat_ip = htonl(orig->src.u3.ip);
11441 + param.data.flow_nat_ipv4.l4.gre.nat_call_id = htons(orig->src.u.gre.key);
11443 + if (sppe_func_hook(¶m)) {
11444 + printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__);
11453 /* Returns verdict for packet, and may modify conntrack */
11454 static int gre_packet(struct nf_conn *ct,
11455 const struct sk_buff *skb,
11456 @@ -242,6 +297,10 @@ static int gre_packet(struct nf_conn *ct
11457 /* Also, more likely to be important, and not a probe. */
11458 set_bit(IPS_ASSURED_BIT, &ct->status);
11459 nf_conntrack_event_cache(IPCT_STATUS, ct);
11460 +#if defined (CONFIG_CNS3XXX_SPPE)
11461 + sppe_gre_flow_add(ct);
11465 nf_ct_refresh_acct(ct, ctinfo, skb,
11466 ct->proto.gre.timeout);
11467 --- a/net/netfilter/nf_conntrack_proto_tcp.c
11468 +++ b/net/netfilter/nf_conntrack_proto_tcp.c
11470 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
11471 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
11473 +#if defined (CONFIG_CNS3XXX_SPPE)
11474 +#include <linux/cns3xxx/sppe.h>
11477 /* "Be conservative in what you do,
11478 be liberal in what you accept from others."
11479 If it's non-zero, we mark only out of window RST segments as INVALID. */
11480 @@ -814,6 +818,141 @@ static int tcp_error(struct net *net,
11484 +#if defined (CONFIG_CNS3XXX_SPPE)
11485 +static int sppe_tcp_flow_add_ipv4(struct nf_conn *ct)
11487 + SPPE_PARAM param;
11488 + struct nf_conntrack_tuple *orig, *reply;
11490 + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11491 + reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11493 +#if defined (CONFIG_NF_CONNTRACK_PPTP)
11494 + if (1723 == htons(orig->dst.u.tcp.port)) {
11495 + /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */
11499 +#if defined (CONFIG_NF_CONNTRACK_FTP)
11500 + if (21 == htons(orig->dst.u.tcp.port)) {
11501 + /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */
11506 + memset(¶m, 0, sizeof(SPPE_PARAM));
11508 + param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11509 + param.op = SPPE_OP_SET;
11511 + param.data.flow_nat_ipv4.fw = 0;
11512 + param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip);
11513 + param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip);
11515 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_TCP;
11516 + param.data.flow_nat_ipv4.l4.port.src = htons(orig->src.u.tcp.port);
11517 + param.data.flow_nat_ipv4.l4.port.dst = htons(orig->dst.u.tcp.port);
11519 + param.data.flow_nat_ipv4.nat_ip = htonl(reply->dst.u3.ip);
11520 + param.data.flow_nat_ipv4.nat_port = htons(reply->dst.u.tcp.port);
11521 + param.data.flow_nat_ipv4.max_len = 0x3;
11523 + if (sppe_func_hook(¶m)) {
11524 + printk("<0><%s> fail to add IPv4 from-LAN flow!!\n", __FUNCTION__);
11527 + param.data.flow_nat_ipv4.fw = 1;
11528 + param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip);
11529 + param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip);
11530 + param.data.flow_nat_ipv4.l4.port.src = htons(reply->src.u.tcp.port);
11531 + param.data.flow_nat_ipv4.l4.port.dst = htons(reply->dst.u.tcp.port);
11533 + param.data.flow_nat_ipv4.nat_ip = htonl(orig->src.u3.ip);
11534 + param.data.flow_nat_ipv4.nat_port = htons(orig->src.u.tcp.port);
11536 + if (sppe_func_hook(¶m)) {
11537 + printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__);
11543 +static int sppe_tcp_flow_add_ipv6(struct nf_conn *ct)
11545 + SPPE_PARAM param;
11546 + struct nf_conntrack_tuple *orig, *reply;
11548 + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11549 + reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11551 + if (1723 == htons(orig->dst.u.tcp.port)) {
11552 + /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */
11556 + memset(¶m, 0, sizeof(SPPE_PARAM));
11558 + param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11559 + param.op = SPPE_OP_SET;
11561 + /* from-LAN flow */
11562 + param.data.flow_route_ipv6.fw = 0;
11563 + param.data.flow_route_ipv6.sip[0] = htonl(orig->src.u3.ip6[0]);
11564 + param.data.flow_route_ipv6.sip[1] = htonl(orig->src.u3.ip6[1]);
11565 + param.data.flow_route_ipv6.sip[2] = htonl(orig->src.u3.ip6[2]);
11566 + param.data.flow_route_ipv6.sip[3] = htonl(orig->src.u3.ip6[3]);
11567 + param.data.flow_route_ipv6.dip[0] = htonl(orig->dst.u3.ip6[0]);
11568 + param.data.flow_route_ipv6.dip[1] = htonl(orig->dst.u3.ip6[1]);
11569 + param.data.flow_route_ipv6.dip[2] = htonl(orig->dst.u3.ip6[2]);
11570 + param.data.flow_route_ipv6.dip[3] = htonl(orig->dst.u3.ip6[3]);
11571 + param.data.flow_route_ipv6.l4_prot = SPPE_PROT_TCP;
11572 + param.data.flow_route_ipv6.l4.port.src = htons(orig->src.u.tcp.port);
11573 + param.data.flow_route_ipv6.l4.port.dst = htons(orig->dst.u.tcp.port);
11574 + param.data.flow_route_ipv6.max_len = 0x3;
11576 + if (sppe_func_hook(¶m)) {
11577 + printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11580 + /* from-WAN flow */
11581 + param.data.flow_route_ipv6.fw = 1;
11582 + param.data.flow_route_ipv6.sip[0] = htonl(reply->src.u3.ip6[0]);
11583 + param.data.flow_route_ipv6.sip[1] = htonl(reply->src.u3.ip6[1]);
11584 + param.data.flow_route_ipv6.sip[2] = htonl(reply->src.u3.ip6[2]);
11585 + param.data.flow_route_ipv6.sip[3] = htonl(reply->src.u3.ip6[3]);
11586 + param.data.flow_route_ipv6.dip[0] = htonl(reply->dst.u3.ip6[0]);
11587 + param.data.flow_route_ipv6.dip[1] = htonl(reply->dst.u3.ip6[1]);
11588 + param.data.flow_route_ipv6.dip[2] = htonl(reply->dst.u3.ip6[2]);
11589 + param.data.flow_route_ipv6.dip[3] = htonl(reply->dst.u3.ip6[3]);
11590 + param.data.flow_route_ipv6.l4.port.src = htons(reply->src.u.tcp.port);
11591 + param.data.flow_route_ipv6.l4.port.dst = htons(reply->dst.u.tcp.port);
11593 + if (sppe_func_hook(¶m)) {
11594 + printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11600 +static int sppe_tcp_flow_add(struct nf_conn *ct)
11602 + if (0 == sppe_hook_ready) {
11606 + if (AF_INET == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11607 + sppe_tcp_flow_add_ipv4(ct);
11609 + } else if (AF_INET6 == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11610 + sppe_tcp_flow_add_ipv6(ct);
11614 + /* return fail */
11619 /* Returns verdict for packet, or -1 for invalid. */
11620 static int tcp_packet(struct nf_conn *ct,
11621 const struct sk_buff *skb,
11622 @@ -961,11 +1100,18 @@ static int tcp_packet(struct nf_conn *ct
11626 +#if defined (CONFIG_CNS3XXX_SPPE)
11627 + if(!(th->rst == 1 || th->fin == 1)) {
11629 if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
11630 skb, dataoff, th, pf)) {
11631 spin_unlock_bh(&ct->lock);
11634 +#if defined (CONFIG_CNS3XXX_SPPE)
11639 /* From now on we have got in-window packets */
11640 ct->proto.tcp.last_index = index;
11641 @@ -1015,6 +1161,10 @@ static int tcp_packet(struct nf_conn *ct
11643 set_bit(IPS_ASSURED_BIT, &ct->status);
11644 nf_conntrack_event_cache(IPCT_STATUS, ct);
11645 +#if defined (CONFIG_CNS3XXX_SPPE)
11646 + /* Add SPPE hardware flow */
11647 + sppe_tcp_flow_add(ct);
11650 nf_ct_refresh_acct(ct, ctinfo, skb, timeout);
11652 --- a/net/netfilter/nf_conntrack_proto_udp.c
11653 +++ b/net/netfilter/nf_conntrack_proto_udp.c
11655 #include <net/netfilter/nf_log.h>
11656 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
11657 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
11658 +#if defined (CONFIG_CNS3XXX_SPPE)
11659 +#include <linux/cns3xxx/sppe.h>
11662 static unsigned int nf_ct_udp_timeout __read_mostly = 30*HZ;
11663 static unsigned int nf_ct_udp_timeout_stream __read_mostly = 180*HZ;
11664 @@ -63,6 +66,122 @@ static int udp_print_tuple(struct seq_fi
11665 ntohs(tuple->dst.u.udp.port));
11668 +#if defined (CONFIG_CNS3XXX_SPPE)
11669 +static int sppe_udp_flow_add_ipv4(struct nf_conn *ct)
11671 + SPPE_PARAM param;
11672 + struct nf_conntrack_tuple *orig, *reply;
11674 + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11675 + reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11677 + memset(¶m, 0, sizeof(SPPE_PARAM));
11679 + param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11680 + param.op = SPPE_OP_SET;
11682 + param.data.flow_nat_ipv4.fw = 0;
11683 + param.data.flow_nat_ipv4.sip = htonl(orig->src.u3.ip);
11684 + param.data.flow_nat_ipv4.dip = htonl(orig->dst.u3.ip);
11685 + param.data.flow_nat_ipv4.l4_prot = SPPE_PROT_UDP;
11687 + param.data.flow_nat_ipv4.l4.port.src = htons(orig->src.u.tcp.port);
11688 + param.data.flow_nat_ipv4.l4.port.dst = htons(orig->dst.u.tcp.port);
11690 + param.data.flow_nat_ipv4.nat_ip = htonl(reply->dst.u3.ip);
11691 + param.data.flow_nat_ipv4.nat_port = htons(reply->dst.u.tcp.port);
11693 + if (sppe_func_hook(¶m)) {
11694 + printk("<0><%s> fail to add IPv4 UDP from-LAN flow!!\n", __FUNCTION__);
11696 + param.data.flow_nat_ipv4.fw = 1;
11697 + param.data.flow_nat_ipv4.sip = htonl(reply->src.u3.ip);
11698 + param.data.flow_nat_ipv4.dip = htonl(reply->dst.u3.ip);
11700 + param.data.flow_nat_ipv4.l4.port.src = htons(reply->src.u.tcp.port);
11701 + param.data.flow_nat_ipv4.l4.port.dst = htons(reply->dst.u.tcp.port);
11703 + param.data.flow_nat_ipv4.nat_ip = htonl(orig->src.u3.ip);
11704 + param.data.flow_nat_ipv4.nat_port = htons(orig->src.u.tcp.port);
11706 + if (sppe_func_hook(¶m)) {
11707 + printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__);
11713 +static int sppe_udp_flow_add_ipv6(struct nf_conn *ct)
11715 + SPPE_PARAM param;
11716 + struct nf_conntrack_tuple *orig, *reply;
11718 + orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11719 + reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11721 + memset(¶m, 0, sizeof(SPPE_PARAM));
11723 + param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11724 + param.op = SPPE_OP_SET;
11726 + /* from-LAN flow */
11727 + param.data.flow_route_ipv6.fw = 0;
11728 + param.data.flow_route_ipv6.sip[0] = htonl(orig->src.u3.ip6[0]);
11729 + param.data.flow_route_ipv6.sip[1] = htonl(orig->src.u3.ip6[1]);
11730 + param.data.flow_route_ipv6.sip[2] = htonl(orig->src.u3.ip6[2]);
11731 + param.data.flow_route_ipv6.sip[3] = htonl(orig->src.u3.ip6[3]);
11732 + param.data.flow_route_ipv6.dip[0] = htonl(orig->dst.u3.ip6[0]);
11733 + param.data.flow_route_ipv6.dip[1] = htonl(orig->dst.u3.ip6[1]);
11734 + param.data.flow_route_ipv6.dip[2] = htonl(orig->dst.u3.ip6[2]);
11735 + param.data.flow_route_ipv6.dip[3] = htonl(orig->dst.u3.ip6[3]);
11736 + param.data.flow_route_ipv6.l4_prot = SPPE_PROT_UDP;
11737 + param.data.flow_route_ipv6.l4.port.src = htons(orig->src.u.udp.port);
11738 + param.data.flow_route_ipv6.l4.port.dst = htons(orig->dst.u.udp.port);
11740 + if (sppe_func_hook(¶m)) {
11741 + printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11744 + /* from-WAN flow */
11745 + param.data.flow_route_ipv6.fw = 1;
11746 + param.data.flow_route_ipv6.sip[0] = htonl(reply->src.u3.ip6[0]);
11747 + param.data.flow_route_ipv6.sip[1] = htonl(reply->src.u3.ip6[1]);
11748 + param.data.flow_route_ipv6.sip[2] = htonl(reply->src.u3.ip6[2]);
11749 + param.data.flow_route_ipv6.sip[3] = htonl(reply->src.u3.ip6[3]);
11750 + param.data.flow_route_ipv6.dip[0] = htonl(reply->dst.u3.ip6[0]);
11751 + param.data.flow_route_ipv6.dip[1] = htonl(reply->dst.u3.ip6[1]);
11752 + param.data.flow_route_ipv6.dip[2] = htonl(reply->dst.u3.ip6[2]);
11753 + param.data.flow_route_ipv6.dip[3] = htonl(reply->dst.u3.ip6[3]);
11754 + param.data.flow_route_ipv6.l4.port.src = htons(reply->src.u.udp.port);
11755 + param.data.flow_route_ipv6.l4.port.dst = htons(reply->dst.u.udp.port);
11757 + if (sppe_func_hook(¶m)) {
11758 + printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11764 +static int sppe_udp_flow_add(struct nf_conn *ct)
11766 + if (0 == sppe_hook_ready) {
11770 + if (AF_INET == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11771 + sppe_udp_flow_add_ipv4(ct);
11773 + } else if (AF_INET6 == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11774 + sppe_udp_flow_add_ipv6(ct);
11778 + /* return fail */
11784 /* Returns verdict for packet, and may modify conntracktype */
11785 static int udp_packet(struct nf_conn *ct,
11786 const struct sk_buff *skb,
11787 @@ -77,7 +196,15 @@ static int udp_packet(struct nf_conn *ct
11788 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream);
11789 /* Also, more likely to be important, and not a probe */
11790 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
11791 +#if defined (CONFIG_CNS3XXX_SPPE)
11794 nf_conntrack_event_cache(IPCT_STATUS, ct);
11795 +#if defined (CONFIG_CNS3XXX_SPPE)
11796 + /* Add SPPE hardware flow */
11797 + sppe_udp_flow_add(ct);
11801 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);