Root/target/linux/cns3xxx/patches-2.6.31/205-cns3xxx_net_device_support.patch

1--- /dev/null
2+++ b/drivers/net/cns3xxx/cns3xxx_config.h
3@@ -0,0 +1,136 @@
4+/*******************************************************************************
5+ *
6+ * Copyright (c) 2009 Cavium Networks
7+ *
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.
12+ *
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
16+ * more details.
17+ *
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.
21+ *
22+ * The full GNU General Public License is included in this distribution in the
23+ * file called LICENSE.
24+ *
25+ ********************************************************************************/
26+
27+#include <linux/version.h>
28+
29+#ifndef CNS3XXX_CONFIG_H
30+#define CNS3XXX_CONFIG_H
31+
32+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,27)
33+#define LINUX2627 1
34+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31)
35+#define LINUX2631 1
36+#endif
37+
38+
39+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
40+#define CNS3XXX_VLAN_8021Q
41+#endif
42+
43+#ifdef CNS3XXX_VLAN_8021Q
44+//#define CNS3XXX_NIC_MODE_8021Q // use NIC mode to support 8021Q
45+
46+#endif
47+
48+#define CONFIG_CNS3XXX_JUMBO_FRAME
49+
50+#ifdef CONFIG_CNS3XXX_JUMBO_FRAME
51+#define MAX_PACKET_LEN 9600
52+#else
53+#define MAX_PACKET_LEN 1536
54+#endif
55+
56+//#define CONFIG_SWITCH_BIG_ENDIAN
57+
58+//#define CONFIG_FPGA_FORCE
59+
60+//#define CNS3XXX_GIGA_MODE
61+
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
70+//#define QOS_TEST
71+//#define ACCEPT_CRC_BAD_PKT
72+//#define CONFIG_FAST_BRIDGE
73+//#define CONFIG_HOLP_TEST
74+
75+
76+#define CONFIG_CNS3XXX_NAPI
77+#ifdef CONFIG_CNS3XXX_NAPI
78+#define CNS3XXX_NAPI_WEIGHT 64
79+#endif
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
86+
87+
88+#define CNS3XXX_FSQF_RING0_ISR
89+//#define CNS3XXX_TSTC_RING0_ISR
90+//#define CNS3XXX_TSTC_RING1_ISR
91+
92+//#define CNS3XXX_COMPARE_PACKET
93+//#define CONFIG_FPGA_10
94+//#define CNS3XXX_CONFIG_SIM_MODE
95+
96+#define CNS3XXX_8021Q_HW_TX
97+
98+
99+#ifndef CONFIG_CNS3XXX_SPPE
100+#define IVL // if no define, use SVL
101+#endif
102+//#define CNS3XXX_4N // if don't define it, use 4N+2
103+
104+//#define NCNB_TEST
105+//#define CNS3XXX_TEST_D_CACHE
106+#define CNS3XXX_FREE_TX_IN_RX_PATH
107+
108+
109+//#define DEBUG_RX
110+//#define DEBUG_TX
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
117+
118+
119+//#define DOUBLE_RING_TEST
120+
121+//#define CNS3XXX_DOUBLE_RX_RING
122+//#define CNS3XXX_DOUBLE_TX_RING
123+#define CNS3XXX_USE_MASK
124+
125+#define CNS3XXX_CONFIG_CHANGE_TX_RING
126+
127+#ifdef CNS3XXX_DOUBLE_RX_RING
128+#define CNS3XXX_FSQF_RING1_ISR
129+#endif
130+
131+//#define CNS3XXX_DELAYED_INTERRUPT
132+
133+#ifdef CNS3XXX_DELAYED_INTERRUPT
134+#define MAX_PEND_INT_CNT 0x06
135+#define MAX_PEND_TIME 0x20
136+#endif
137+
138+//#define CNS3XXX_ENABLE_RINT1
139+#endif
140--- /dev/null
141+++ b/drivers/net/cns3xxx/cns3xxx_ethtool.c
142@@ -0,0 +1,436 @@
143+/*******************************************************************************
144+ *
145+ *
146+ * Copyright (c) 2009 Cavium Networks
147+ *
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.
152+ *
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
156+ * more details.
157+ *
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.
161+ *
162+ * The full GNU General Public License is included in this distribution in the
163+ * file called LICENSE.
164+ *
165+ ********************************************************************************/
166+
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"
174+
175+// ethtool support reference e100.c and e1000_ethtool.c .
176+static void cns3xxx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
177+{
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");
182+}
183+
184+static void cns3xxx_get_ringparam(struct net_device *netdev,
185+ struct ethtool_ringparam *ring)
186+{
187+ CNS3XXXPrivate *priv = netdev_priv(netdev);
188+
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;
193+#if 0
194+ struct nic *nic = netdev_priv(netdev);
195+ struct param_range *rfds = &nic->params.rfds;
196+ struct param_range *cbs = &nic->params.cbs;
197+
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;
206+#endif
207+}
208+
209+
210+
211+static int cns3xxx_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
212+{
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[];
218+
219+ CNS3XXXPrivate *priv = netdev_priv(netdev);
220+
221+ int i=0;
222+
223+#if 0
224+ struct nic *nic = netdev_priv(netdev);
225+ struct param_range *rfds = &nic->params.rfds;
226+ struct param_range *cbs = &nic->params.cbs;
227+
228+ if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
229+ return -EINVAL;
230+
231+ if(netif_running(netdev))
232+ e100_down(nic);
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))
240+ e100_up(nic);
241+
242+#endif
243+ //ring->rx_max_pending = RX_DESC_SIZE;
244+ //ring->tx_max_pending = TX_DESC_SIZE;
245+
246+#if 0
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);
251+#endif
252+
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]);
257+ }
258+ }
259+
260+ //cns3xxx_down();
261+
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);
264+
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]);
269+ }
270+ }
271+ //cns3xxx_up();
272+
273+ return 0;
274+}
275+
276+static uint32_t cns3xxx_get_tx_csum(struct net_device *netdev)
277+{
278+ //return (netdev->features & NETIF_F_HW_CSUM) != 0;
279+ return (netdev->features & NETIF_F_IP_CSUM) != 0;
280+}
281+
282+static int cns3xxx_set_tx_csum(struct net_device *netdev, uint32_t data)
283+{
284+ if (data)
285+ netdev->features |= NETIF_F_IP_CSUM;
286+ else
287+ netdev->features &= ~NETIF_F_IP_CSUM;
288+ return 0;
289+}
290+
291+static uint32_t cns3xxx_get_rx_csum(struct net_device *netdev)
292+{
293+ //struct e1000_adapter *adapter = netdev_priv(netdev);
294+ //return adapter->rx_csum;
295+ return 1;
296+}
297+
298+static int cns3xxx_set_rx_csum(struct net_device *netdev, uint32_t data)
299+{
300+ return 0;
301+}
302+
303+u32 cns3xxx_get_sg(struct net_device *dev)
304+{
305+#ifdef NETIF_F_SG
306+ return (dev->features & NETIF_F_SG) != 0;
307+#else
308+ return 0;
309+#endif
310+}
311+
312+int cns3xxx_set_sg(struct net_device *dev, u32 data)
313+{
314+#ifdef NETIF_F_SG
315+ if (data)
316+ dev->features |= NETIF_F_SG;
317+ else
318+ dev->features &= ~NETIF_F_SG;
319+#endif
320+
321+ return 0;
322+}
323+
324+static void cns3xxx_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
325+{
326+ u32 mac_port_config = 0;
327+ CNS3XXXPrivate *priv = netdev_priv(netdev);
328+
329+ switch (priv->net_device_priv->which_port)
330+ {
331+ case MAC_PORT0:
332+ {
333+ mac_port_config = MAC0_CFG_REG;
334+ break;
335+ }
336+ case MAC_PORT1:
337+ {
338+ mac_port_config = MAC1_CFG_REG;
339+ break;
340+ }
341+ case MAC_PORT2:
342+ {
343+ mac_port_config = MAC2_CFG_REG;
344+ break;
345+ }
346+ }
347+
348+
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;
352+}
353+
354+static int cns3xxx_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)
355+{
356+ u32 mac_port_config = 0;
357+ CNS3XXXPrivate *priv = netdev_priv(netdev);
358+
359+ switch (priv->net_device_priv->which_port)
360+ {
361+ case MAC_PORT0:
362+ {
363+ mac_port_config = MAC0_CFG_REG;
364+ break;
365+ }
366+ case MAC_PORT1:
367+ {
368+ mac_port_config = MAC1_CFG_REG;
369+ break;
370+ }
371+ case MAC_PORT2:
372+ {
373+ mac_port_config = MAC2_CFG_REG;
374+ break;
375+ }
376+ }
377+
378+
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
382+
383+ mac_port_config |= ( (pause->autoneg << 7) | (pause->rx_pause << 11) | (pause->tx_pause << 12) );
384+
385+
386+ switch (priv->net_device_priv->which_port)
387+ {
388+ case MAC_PORT0:
389+ {
390+ MAC0_CFG_REG = mac_port_config;
391+ break;
392+ }
393+ case MAC_PORT1:
394+ {
395+ MAC1_CFG_REG = mac_port_config;
396+ break;
397+ }
398+ case MAC_PORT2:
399+ {
400+ MAC2_CFG_REG = mac_port_config;
401+ break;
402+ }
403+ }
404+ return 0;
405+}
406+
407+u32 cns3xxx_get_link(struct net_device *netdev)
408+{
409+ u32 mac_port_config = 0;
410+ CNS3XXXPrivate *priv = netdev_priv(netdev);
411+
412+ switch (priv->net_device_priv->which_port)
413+ {
414+ case MAC_PORT0:
415+ {
416+ mac_port_config = MAC0_CFG_REG;
417+ break;
418+ }
419+ case MAC_PORT1:
420+ {
421+ mac_port_config = MAC1_CFG_REG;
422+ break;
423+ }
424+ case MAC_PORT2:
425+ {
426+ mac_port_config = MAC2_CFG_REG;
427+ break;
428+ }
429+ }
430+
431+ return (mac_port_config & 1 ) ? 1 : 0;
432+ //return netif_carrier_ok(dev) ? 1 : 0;
433+}
434+
435+
436+static int cns3xxx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
437+{
438+ u8 value;
439+ u32 mac_port_config = 0;
440+ CNS3XXXPrivate *priv = netdev_priv(netdev);
441+
442+
443+ if (priv->net_device_priv->nic_setting == 0) { // connect to switch chip
444+
445+ GET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config)
446+
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);
448+
449+ ecmd->duplex = ((mac_port_config >> 4) & 0x1) ? DUPLEX_FULL : DUPLEX_HALF ;
450+
451+ value = ((mac_port_config >> 2) & 0x3);
452+ switch (value)
453+ {
454+ case 0:
455+ ecmd->speed = SPEED_10;
456+ break;
457+ case 1:
458+ ecmd->speed = SPEED_100;
459+ break;
460+ case 2:
461+ ecmd->speed = SPEED_1000;
462+ break;
463+ }
464+
465+ ecmd->autoneg = ((mac_port_config >> 7) & 1) ? AUTONEG_ENABLE : AUTONEG_DISABLE;
466+
467+
468+
469+ } else { // connect to PHY chip
470+
471+ }
472+
473+ return 0;
474+}
475+
476+// set speed and duplex
477+int cns3xxx_set_spd_dplx(struct net_device *netdev, u16 spddplx)
478+{
479+ u32 mac_port_config = 0;
480+ CNS3XXXPrivate *priv = netdev_priv(netdev);
481+
482+ GET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config)
483+
484+ //printk("mac_port_config: %x\n", mac_port_config);
485+
486+ mac_port_config &= ~(0x3 << 8); // clear speed
487+ mac_port_config &= ~(0x1 << 10); // clear duplex
488+ mac_port_config &= ~(0x1 << 7); // disable AN
489+
490+ switch (spddplx) {
491+ case AUTONEG_ENABLE:
492+ mac_port_config |= (0x1 << 7); // enable AN
493+ break;
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);
499+ break;
500+ case SPEED_10 + DUPLEX_FULL:
501+ mac_port_config |= (0 << 8); // set speed
502+ mac_port_config |= (1 << 10); // set duplex
503+ break;
504+ case SPEED_100 + DUPLEX_HALF:
505+ mac_port_config |= (1 << 8); // set speed
506+ mac_port_config |= (0 << 10); // set duplex
507+ break;
508+ case SPEED_100 + DUPLEX_FULL:
509+ mac_port_config |= (1 << 8); // set speed
510+ mac_port_config |= (1 << 10); // set duplex
511+ break;
512+ case SPEED_1000 + DUPLEX_HALF:
513+ mac_port_config |= (2 << 8); // set speed
514+ mac_port_config |= (0 << 10); // set duplex
515+ break;
516+ case SPEED_1000 + DUPLEX_FULL:
517+ mac_port_config |= (2 << 8); // set speed
518+ mac_port_config |= (1 << 10); // set duplex
519+ break;
520+ default:
521+ //printk("Unsupported Speed/Duplex configuration\n");
522+ return -EINVAL;
523+ }
524+
525+ SET_MAC_PORT_CFG(priv->net_device_priv->which_port, mac_port_config)
526+
527+ return 0;
528+}
529+
530+static int cns3xxx_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
531+{
532+ u8 value = 0;
533+ CNS3XXXPrivate *priv = netdev_priv(netdev);
534+
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) {
539+ return -EINVAL;
540+ }
541+ } else {
542+ printk("no autoneg\n");
543+ if ((value=cns3xxx_set_spd_dplx(netdev, ecmd->speed + ecmd->duplex)) != 0) {
544+ return -EINVAL;
545+ }
546+
547+
548+ }
549+
550+ } else { // connect to PHY chip
551+
552+ }
553+
554+ // down then up
555+ return 0;
556+}
557+
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,
573+};
574+
575+void cns3xxx_set_ethtool_ops(struct net_device *netdev)
576+{
577+ SET_ETHTOOL_OPS(netdev, &cns3xxx_ethtool_ops);
578+}
579--- /dev/null
580+++ b/drivers/net/cns3xxx/cns3xxx.h
581@@ -0,0 +1,452 @@
582+/*******************************************************************************
583+ *
584+ * Copyright (c) 2009 Cavium Networks
585+ *
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.
590+ *
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
594+ * more details.
595+ *
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.
599+ *
600+ * The full GNU General Public License is included in this distribution in the
601+ * file called LICENSE.
602+ *
603+ ********************************************************************************/
604+
605+#ifndef CNS3XXX_H
606+#define CNS3XXX_H
607+
608+#include "cns3xxx_symbol.h"
609+#include "cns3xxx_config.h"
610+#include <linux/cns3xxx/switch_api.h>
611+
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>
629+#include <asm/io.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>
644+
645+
646+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
647+#include <linux/if_vlan.h>
648+#endif
649+
650+//#define VERSION "1.0"
651+
652+
653+typedef struct
654+{
655+ int32_t sdp; // segment data pointer
656+
657+#ifdef CONFIG_SWITCH_BIG_ENDIAN
658+ u32 cown:1;
659+ u32 eor:1;
660+ u32 fsd:1;
661+ u32 lsd:1;
662+ u32 interrupt:1;
663+ u32 fr:1;
664+ u32 fp:1; // force priority
665+ u32 pri:3;
666+ u32 rsv_1:3; // reserve
667+ u32 ico:1;
668+ u32 uco:1;
669+ u32 tco:1;
670+ u32 sdl:16; // segment data length
671+
672+#else
673+ u32 sdl:16; // segment data length
674+ u32 tco:1;
675+ u32 uco:1;
676+ u32 ico:1;
677+ u32 rsv_1:3; // reserve
678+ u32 pri:3;
679+ u32 fp:1; // force priority
680+ u32 fr:1;
681+ u32 interrupt:1;
682+ u32 lsd:1;
683+ u32 fsd:1;
684+ u32 eor:1;
685+ u32 cown:1;
686+#endif
687+
688+#ifdef CONFIG_SWITCH_BIG_ENDIAN
689+ u32 rsv_3:5;
690+ u32 fewan:1;
691+ u32 ewan:1;
692+ u32 mark:3;
693+ u32 pmap:5;
694+ u32 rsv_2:9;
695+ u32 dels:1;
696+ u32 inss:1;
697+ u32 sid:4;
698+ u32 stv:1;
699+ u32 ctv:1;
700+#else
701+ u32 ctv:1;
702+ u32 stv:1;
703+ u32 sid:4;
704+ u32 inss:1;
705+ u32 dels:1;
706+ u32 rsv_2:9;
707+ u32 pmap:5;
708+ u32 mark:3;
709+ u32 ewan:1;
710+ u32 fewan:1;
711+ u32 rsv_3:5;
712+#endif
713+
714+#ifdef CONFIG_SWITCH_BIG_ENDIAN
715+ u32 s_pri:3;
716+ u32 s_dei:1;
717+ u32 s_vid:12;
718+ u32 c_pri:3;
719+ u32 c_cfs:1;
720+ u32 c_vid:12;
721+#else
722+ u32 c_vid:12;
723+ u32 c_cfs:1;
724+ u32 c_pri:3;
725+ u32 s_vid:12;
726+ u32 s_dei:1;
727+ u32 s_pri:3;
728+#endif
729+
730+ u8 alignment[16]; // for alignment 32 byte
731+
732+} __attribute__((packed)) TXDesc;
733+
734+typedef struct
735+{
736+ u32 sdp;
737+
738+#ifdef CONFIG_SWITCH_BIG_ENDIAN
739+ u32 cown:1;
740+ u32 eor:1;
741+ u32 fsd:1;
742+ u32 lsd:1;
743+ u32 hr :6;
744+ u32 prot:4;
745+ u32 ipf:1;
746+ u32 l4f:1;
747+ u32 sdl:16;
748+#else
749+ u32 sdl:16;
750+ u32 l4f:1;
751+ u32 ipf:1;
752+ u32 prot:4;
753+ u32 hr :6;
754+ u32 lsd:1;
755+ u32 fsd:1;
756+ u32 eor:1;
757+ u32 cown:1;
758+#endif
759+
760+#ifdef CONFIG_SWITCH_BIG_ENDIAN
761+ u32 rsv_3:11;
762+ u32 ip_offset:5;
763+ u32 rsv_2:1;
764+ u32 tc:2;
765+ u32 un_eth:1;
766+ u32 crc_err:1;
767+ u32 sp:3;
768+ u32 rsv_1:2;
769+ u32 e_wan:1;
770+ u32 exdv:1;
771+ u32 iwan:1;
772+ u32 unv:1;
773+ u32 stv:1;
774+ u32 ctv:1;
775+#else
776+ u32 ctv:1;
777+ u32 stv:1;
778+ u32 unv:1;
779+ u32 iwan:1;
780+ u32 exdv:1;
781+ u32 e_wan:1;
782+ u32 rsv_1:2;
783+ u32 sp:3;
784+ u32 crc_err:1;
785+ u32 un_eth:1;
786+ u32 tc:2;
787+ u32 rsv_2:1;
788+ u32 ip_offset:5;
789+ u32 rsv_3:11;
790+#endif
791+
792+#ifdef CONFIG_SWITCH_BIG_ENDIAN
793+ u32 s_pri:3;
794+ u32 s_dei:1;
795+ u32 s_vid:12;
796+ u32 c_pri:3;
797+ u32 c_cfs:1;
798+ u32 c_vid:12;
799+#else
800+ u32 c_vid:12;
801+ u32 c_cfs:1;
802+ u32 c_pri:3;
803+ u32 s_vid:12;
804+ u32 s_dei:1;
805+ u32 s_pri:3;
806+#endif
807+
808+ u8 alignment[16]; // for alignment 32 byte
809+
810+} __attribute__((packed)) RXDesc;
811+
812+typedef struct {
813+ TXDesc *tx_desc;
814+ struct sk_buff *skb; // for free skb
815+ u32 pri;
816+ unsigned long j;
817+ unsigned long tx_index;
818+}TXBuffer;
819+
820+typedef struct {
821+ RXDesc *rx_desc;
822+ struct sk_buff *skb; // rx path need to fill some skb field, ex: length ...
823+#ifdef NCNB_TEST
824+ u32 ncnb_index;
825+#endif
826+}RXBuffer;
827+
828+
829+typedef struct {
830+ TXBuffer *head;
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;
837+ u32 ring_size;
838+ u32 max_ring_size;
839+}TXRing;
840+
841+
842+typedef struct {
843+ RXBuffer *head;
844+ RXDesc *rx_desc_head_vir_addr;
845+ dma_addr_t rx_desc_head_phy_addr;
846+ u32 cur_index;
847+ u32 ring_size;
848+ u32 max_ring_size;
849+}RXRing;
850+
851+#if 0
852+typedef struct
853+{
854+ CNS3XXXIoctlCmd cmd;
855+ TXRing *tx_ring;
856+ RXRing *rx_ring;
857+}CNS3XXXRingStatus;
858+#endif
859+
860+
861+#define RX_RING0(priv) (priv->rx_ring[0])
862+#define TX_RING0(priv) (priv->tx_ring[0])
863+
864+
865+static inline u32 get_rx_ring_size(const RXRing *ring)
866+{
867+ //printk("rx ring->ring_size: %d\n", ring->ring_size);
868+ return ring->ring_size;
869+}
870+
871+static inline u32 get_tx_ring_size(TXRing *ring)
872+{
873+ //printk("tx ring->ring_size: %d\n", ring->ring_size);
874+ return ring->ring_size;
875+}
876+
877+static inline RXBuffer *get_rx_ring_head(const RXRing *rx_ring)
878+{
879+ return rx_ring->head;
880+}
881+
882+static inline TXBuffer *get_tx_ring_head(TXRing *tx_ring)
883+{
884+ return tx_ring->head;
885+}
886+
887+static inline RXBuffer *get_cur_rx_buffer(RXRing *rx_ring)
888+{
889+ return rx_ring->head + rx_ring->cur_index;
890+}
891+
892+static inline TXBuffer *get_cur_tx_buffer(TXRing *tx_ring)
893+{
894+ return tx_ring->head + tx_ring->cur_index;
895+}
896+
897+static inline u32 get_rx_head_phy_addr(RXRing *rx_ring)
898+{
899+ return rx_ring->rx_desc_head_phy_addr;
900+}
901+
902+static inline u32 get_tx_ring_head_phy_addr(TXRing *tx_ring)
903+{
904+ return tx_ring->tx_desc_head_phy_addr;
905+}
906+
907+
908+static inline u32 get_rx_cur_index(RXRing *rx_ring)
909+{
910+ return rx_ring->cur_index;
911+}
912+
913+static inline u32 get_tx_cur_index(TXRing *tx_ring)
914+{
915+ return tx_ring->cur_index;
916+}
917+
918+static inline u32 get_tx_cur_phy_addr(u8 ring_num)
919+{
920+ if (ring_num == 0)
921+ return TS_DESC_PTR0_REG;
922+ if (ring_num == 1)
923+ return TS_DESC_PTR1_REG;
924+ return 0; // fail
925+}
926+
927+static inline void rx_index_next(RXRing *ring)
928+{
929+ ring->cur_index = ((ring->cur_index + 1) % ring->ring_size);
930+}
931+static inline void tx_index_next(TXRing *ring)
932+{
933+ ring->cur_index = ((ring->cur_index + 1) % ring->ring_size);
934+}
935+
936+
937+
938+struct CNS3XXXPrivate_;
939+
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);
944+
945+
946+// for ethtool set operate
947+typedef struct{
948+
949+}NICSetting;
950+
951+typedef struct{
952+ int pmap; // for port base, force route
953+ int is_wan; // mean the net device is WAN side.
954+ //u16 gid;
955+ u16 s_tag;
956+ //u8 mac_type; // VLAN base, or port base;
957+ u16 vlan_tag;
958+
959+ // do port base mode and vlan base mode work
960+ RXFuncPtr rx_func;
961+ TXFuncPtr tx_func;
962+ OpenPtr open;
963+ ClosePtr close;
964+ u8 which_port;
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
971+}NetDevicePriv;
972+
973+typedef struct
974+{
975+ u8 num_rx_queues;
976+ u8 num_tx_queues;
977+ TXRing *tx_ring;
978+ RXRing *rx_ring;
979+}RingInfo;
980+
981+
982+/* store this information for the driver.. */
983+typedef struct CNS3XXXPrivate_
984+{
985+ u8 num_rx_queues;
986+ u8 num_tx_queues;
987+ TXRing *tx_ring;
988+ RXRing *rx_ring;
989+ struct net_device_stats stats;
990+ spinlock_t lock;
991+ int pmap;
992+ int is_wan; // mean the net device is WAN side.
993+ u16 gid;
994+ u8 mac_type; // VLAN base, or port base;
995+ u16 vlan_tag;
996+ struct napi_struct napi;
997+ struct work_struct reset_task;
998+
999+ u8 which_port;
1000+ //NICSetting *nic_setting;
1001+ char name[IFNAMSIZ]; // 16 bytes, reference include/linux/netdevice.h IFNAMSIZ
1002+
1003+
1004+ NetDevicePriv *net_device_priv;
1005+ u8 ring_index;
1006+
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
1011+#endif
1012+
1013+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
1014+ struct vlan_group *vlgrp;
1015+#endif
1016+}CNS3XXXPrivate;
1017+
1018+
1019+
1020+
1021+int rx_port_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv);
1022+
1023+int rx_vlan_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv);
1024+
1025+int tx_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb);
1026+
1027+
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);
1031+#endif
1032+#endif
1033+
1034--- /dev/null
1035+++ b/drivers/net/cns3xxx/cns3xxx_main.c
1036@@ -0,0 +1,3949 @@
1037+/*******************************************************************************
1038+ *
1039+ * Copyright (c) 2009 Cavium Networks
1040+ *
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.
1045+ *
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
1049+ * more details.
1050+ *
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.
1054+ *
1055+ * The full GNU General Public License is included in this distribution in the
1056+ * file called LICENSE.
1057+ *
1058+ ********************************************************************************/
1059+
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"
1066+
1067+#if defined (CONFIG_CNS3XXX_SPPE)
1068+#include <linux/cns3xxx/sppe.h>
1069+#define PACKET_REASON_TO_CPU (0x2C)
1070+#endif
1071+
1072+#define RX_SDP_ALIGN 64
1073+
1074+#ifdef CONFIG_FPGA
1075+#include "fpga.h"
1076+#endif
1077+
1078+#ifdef CONFIG_VB
1079+#include "vb.h"
1080+#endif
1081+
1082+#define CPU_CACHE_BYTES 64
1083+#define CPU_CACHE_ALIGN(X) (((X) + (CPU_CACHE_BYTES-1)) & ~(CPU_CACHE_BYTES-1))
1084+
1085+
1086+#define QUEUE_WEIGHT_SET(port, ctl) \
1087+{ \
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); \
1094+}
1095+
1096+#define QUEUE_WEIGHT_GET(port, ctl) \
1097+{ \
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); \
1103+}
1104+
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;
1113+u8 show_rx_proc=0;
1114+u8 show_tx_proc=0;
1115+
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);
1119+
1120+u8 ring_index=0; // 0 or 1
1121+
1122+#ifdef CNS3XXX_DELAYED_INTERRUPT
1123+static u32 max_pend_int_cnt=MAX_PEND_INT_CNT, max_pend_time=MAX_PEND_TIME;
1124+#endif
1125+
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
1130+ #endif
1131+#endif
1132+
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;
1138+
1139+//RXRing *rx_ring;
1140+//TXRing *tx_ring;
1141+
1142+// only for debug (proc)
1143+RingInfo g_ring_info;
1144+
1145+int MSG_LEVEL = NORMAL_MSG;
1146+
1147+#ifdef CNS3XXX_STATUS_ISR
1148+const char *cns3xxx_gsw_status_tbl[] = {
1149+ "\nMAC0_Q_FULL\n",
1150+ "\nMAC1_Q_FULL\n",
1151+ "\nCPU_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",
1158+ "\n", // 9
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",
1181+};
1182+#endif
1183+
1184+#define MIN_PACKET_LEN 14
1185+
1186+void cns3xxx_write_pri_mask(u8 pri_mask);
1187+
1188+static int cns3xxx_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr);
1189+
1190+static struct notifier_block cns3xxx_notifier_reboot = {
1191+ .notifier_call = cns3xxx_notify_reboot,
1192+ .next = NULL,
1193+ .priority = 0
1194+};
1195+
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);
1199+#endif
1200+
1201+void take_off_vlan_header(struct sk_buff *skb)
1202+{
1203+ // take off VLAN header
1204+ memmove(skb->data + 4, skb->data, 12);
1205+#if 0
1206+ //skb_ptr->data += 4;
1207+ skb_reserve(skb, 4);
1208+#else
1209+ skb->data += 4;
1210+#endif
1211+ skb->len -= 4; // minus 4 byte vlan tag
1212+}
1213+
1214+int rx_port_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv)
1215+{
1216+ if (skb->data[12] == 0x81 && skb->data[13] == 0x00) // VLAN header
1217+ {
1218+ take_off_vlan_header(skb);
1219+ print_packet(skb->data, skb->len);
1220+ }
1221+ return 0;
1222+}
1223+
1224+int rx_vlan_base(struct sk_buff *skb, RXDesc *rx_desc_ptr, const struct CNS3XXXPrivate_ *priv)
1225+{
1226+ return 0;
1227+}
1228+
1229+int tx_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb)
1230+{
1231+#if defined(CNS3XXX_VLAN_8021Q) && defined (CNS3XXX_8021Q_HW_TX)
1232+ if (skb && priv->vlgrp != NULL && vlan_tx_tag_present(skb))
1233+ {
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;
1237+
1238+ }
1239+ else
1240+#endif
1241+ {
1242+ tx_desc_ptr->ctv = 0;
1243+ tx_desc_ptr->pmap = priv->net_device_priv->pmap;
1244+ tx_desc_ptr->fr = 1;
1245+ }
1246+
1247+ return 0;
1248+}
1249+
1250+
1251+int tx_vlan_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb)
1252+{
1253+#if defined(CNS3XXX_VLAN_8021Q)
1254+
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));
1257+ }
1258+#else
1259+ tx_desc_ptr->c_vid = priv->net_device_priv->vlan_tag;
1260+
1261+#endif
1262+ tx_desc_ptr->ctv=1;
1263+ tx_desc_ptr->fr = 0;
1264+
1265+ return 0;
1266+}
1267+
1268+#if defined (CONFIG_CNS3XXX_SPPE)
1269+int fp_port_base(TXDesc *tx_desc_ptr, const struct CNS3XXXPrivate_ *priv, struct sk_buff *skb)
1270+{
1271+#if 1
1272+ tx_desc_ptr->fr = 1;
1273+ tx_desc_ptr->pmap = 0x8;
1274+#else
1275+ tx_desc_ptr->fr = 0;
1276+ tx_desc_ptr->ctv = 1;
1277+ tx_desc_ptr->c_vid = 80;
1278+#endif
1279+ return 0;
1280+}
1281+#endif
1282+
1283+static inline struct sk_buff *cns3xxx_alloc_skb(void)
1284+{
1285+ struct sk_buff *skb;
1286+ u32 align_64;
1287+
1288+ skb = dev_alloc_skb(MAX_PACKET_LEN + 2 + RX_SDP_ALIGN);
1289+
1290+ if (unlikely(!skb)) {
1291+ return NULL;
1292+ }
1293+ pci_dma_sync_single_for_device(NULL, virt_to_phys(skb->data), MAX_PACKET_LEN+2+RX_SDP_ALIGN, PCI_DMA_FROMDEVICE);
1294+
1295+ align_64=CPU_CACHE_ALIGN((u32)skb->data);
1296+ skb_reserve(skb, align_64-(u32)skb->data); /* 16 bytes alignment */
1297+
1298+#ifndef CNS3XXX_4N
1299+ skb_reserve(skb, NET_IP_ALIGN); /* 16 bytes alignment */
1300+#endif
1301+
1302+
1303+
1304+ return skb;
1305+}
1306+
1307+static int free_rx_skb(RXRing *rx_ring)
1308+{
1309+ int i=0;
1310+ RXBuffer *rx_buffer = rx_ring->head;
1311+ //RXDesc *rx_desc = rx_ring.rx_desc_head_vir_addr;
1312+
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);
1316+ rx_buffer->skb=0;
1317+ }
1318+ }
1319+ return 0;
1320+}
1321+
1322+int cns3xxx_setup_all_rx_resources(RXRing *rx_ring, u8 ring_num)
1323+{
1324+ int i=0;
1325+ RXBuffer *rx_buffer = 0;
1326+ RXDesc *rx_desc = 0;
1327+
1328+#ifdef NCNB_TEST
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);
1331+
1332+#endif
1333+
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) {
1337+ return -ENOMEM;
1338+ }
1339+
1340+ memset(rx_ring->rx_desc_head_vir_addr, 0, sizeof(RXDesc) * get_rx_ring_size(rx_ring));
1341+
1342+ // alloc RXBuffer array
1343+ rx_ring->head = kmalloc(sizeof(RXBuffer) * get_rx_ring_size(rx_ring), GFP_KERNEL);
1344+
1345+ if (!rx_ring->head) {
1346+ return -ENOMEM;
1347+ }
1348+
1349+ rx_buffer = rx_ring->head;
1350+ for (i=0 ; i < get_rx_ring_size(rx_ring) ; ++i) {
1351+ rx_buffer->skb=0;
1352+ ++rx_buffer;
1353+ }
1354+
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();
1360+
1361+ if (!rx_buffer->skb) {
1362+
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);
1366+ return -ENOMEM;
1367+ }
1368+
1369+#ifdef CONFIG_SWITCH_BIG_ENDIAN
1370+ {
1371+ RXDesc tmp_rx_desc;
1372+
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;
1378+ }
1379+ tmp_rx_desc.fsd = 1;
1380+ tmp_rx_desc.lsd = 1;
1381+ swap_rx_desc(&tmp_rx_desc, rx_buffer->rx_desc);
1382+ }
1383+
1384+#else
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;
1389+ }
1390+ rx_buffer->rx_desc->fsd = 1;
1391+ rx_buffer->rx_desc->lsd = 1;
1392+#endif
1393+
1394+ }
1395+ rx_ring->cur_index = 0 ;
1396+
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;
1400+
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;
1404+ }
1405+
1406+ return CAVM_OK;
1407+}
1408+
1409+static int cns3xxx_setup_all_tx_resources(TXRing *tx_ring, u8 ring_num)
1410+{
1411+ int i=0;
1412+ TXBuffer *tx_buffer = 0;
1413+ TXDesc *tx_desc = 0;
1414+
1415+
1416+ spin_lock_init(&(tx_ring->tx_lock));
1417+
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) {
1420+ return -ENOMEM;
1421+ }
1422+
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);
1425+
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;
1430+
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;
1435+ }
1436+#ifdef CONFIG_SWITCH_BIG_ENDIAN
1437+ swap_tx_desc(tx_buffer->tx_desc, tx_buffer->tx_desc);
1438+#endif
1439+
1440+ }
1441+
1442+ tx_ring->cur_index = 0 ;
1443+
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;
1450+ }
1451+ return CAVM_OK;
1452+}
1453+
1454+int cns3xxx_free_all_rx_resources(RXRing *rx_ring)
1455+{
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);
1459+ return 0;
1460+}
1461+
1462+static int free_tx_skb(TXRing *tx_ring)
1463+{
1464+ int i=0;
1465+ TXBuffer *tx_buffer = tx_ring->head;
1466+
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;
1471+ }
1472+ }
1473+ return 0;
1474+}
1475+
1476+int cns3xxx_free_all_tx_resources(TXRing *tx_ring)
1477+{
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);
1481+ return 0;
1482+}
1483+
1484+static int cns3xxx_free_rx_tx_res(CNS3XXXPrivate *priv)
1485+{
1486+ int i=0;
1487+
1488+ --rc_setup_rx_tx;
1489+ if (rc_setup_rx_tx == 0) {
1490+ enable_port(3, 0); // disable cpu port
1491+
1492+ // stop RX/TX ring0 dma
1493+ enable_rx_dma(0, 0);
1494+ enable_tx_dma(0, 0);
1495+
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));
1499+ }
1500+
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));
1504+ }
1505+
1506+ }
1507+ return 0;
1508+}
1509+
1510+
1511+static int cns3xxx_setup_rx_tx_res(CNS3XXXPrivate *priv)
1512+{
1513+ int i=0;
1514+
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;
1525+
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)
1531+ return CAVM_ERR;
1532+ }
1533+
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)
1538+ return CAVM_ERR;
1539+
1540+ }
1541+ clear_fs_dma_state(0);
1542+ }
1543+ ++rc_setup_rx_tx;
1544+ return CAVM_OK;
1545+}
1546+
1547+int free_tx_desc_skb(TXRing *tx_ring, u8 ring_num)
1548+{
1549+#if 1
1550+ int i=0;
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;
1556+
1557+ tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index);
1558+
1559+
1560+ //while (1)
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);
1564+ tx_buffer->skb=0;
1565+ //tx_buffer->tx_desc->cown == 1;
1566+ } else {
1567+ break;
1568+ }
1569+ // --tx_desc_pair_ptr
1570+ --cur_index;
1571+ tx_buffer = get_tx_buffer_by_index(tx_ring, cur_index);
1572+
1573+ }
1574+#endif
1575+ return 0;
1576+}
1577+
1578+void do_arl_lookup(void)
1579+{
1580+}
1581+
1582+inline void assign_netdev(RXBuffer volatile *rx_buffer)
1583+{
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);
1589+#else
1590+ rx_desc = rx_buffer->rx_desc;
1591+#endif
1592+
1593+
1594+#if defined(CONFIG_CNS3XXX_PORT_BASE) || defined(CNS3XXX_VLAN_8021Q)
1595+ // sp:
1596+ // 0 - mac port 0
1597+ // 1 - mac port 1
1598+ // 4 - mac port 2
1599+
1600+ switch (rx_desc->sp)
1601+ {
1602+ case 0:
1603+ {
1604+ rx_buffer->skb->dev = PORT0_NETDEV;
1605+ break;
1606+ }
1607+ case 1:
1608+ {
1609+ rx_buffer->skb->dev = PORT1_NETDEV;
1610+ break;
1611+ }
1612+ case 4:
1613+ {
1614+ rx_buffer->skb->dev = PORT2_NETDEV;
1615+ break;
1616+ }
1617+
1618+ }
1619+#endif
1620+
1621+#ifdef CONFIG_CNS3XXX_VLAN_BASE
1622+{
1623+ u16 vlan_tag;
1624+
1625+ vlan_tag = rx_desc->c_vid;
1626+ rx_buffer->skb->dev = net_dev_array[vlan_tag];
1627+
1628+}
1629+#endif
1630+
1631+}
1632+
1633+#if defined(CNS3XXX_VLAN_8021Q)
1634+static int cns3xxx_vlan_rx(CNS3XXXPrivate *priv, struct sk_buff *skb, u16 vlan_tag)
1635+{
1636+ return vlan_hwaccel_receive_skb(skb, priv->vlgrp, vlan_tag);
1637+}
1638+#endif
1639+
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)
1642+{
1643+ CNS3XXXPrivate *priv=0;
1644+ //RXDesc volatile *rxdesc_ptr = rx_buffer->rx_desc;
1645+ struct sk_buff *skb;
1646+ //unsigned char *data;
1647+ u32 len;
1648+ RXDesc *rx_desc;
1649+
1650+#ifdef CONFIG_SWITCH_BIG_ENDIAN
1651+
1652+ RXDesc tmp_rx_desc;
1653+
1654+ rx_desc = &tmp_rx_desc;
1655+ swap_rx_desc(rx_buffer->rx_desc, rx_desc);
1656+
1657+#else
1658+ rx_desc = rx_buffer->rx_desc;
1659+#endif
1660+
1661+ //rxdesc_ptr = rxring.vir_addr + index;
1662+ skb = rx_buffer->skb;
1663+ len = rx_desc->sdl;
1664+
1665+
1666+#ifdef DEBUG_RX
1667+ if (MSG_LEVEL == DUMP_RX_PKT_INFO) {
1668+ print_packet(skb->data, len);
1669+ }
1670+
1671+#endif
1672+
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) {
1677+ SPPE_PARAM param;
1678+ int pci_dev_index;
1679+ struct iphdr *iph;
1680+
1681+ skb_put(skb, len);
1682+ iph = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
1683+
1684+ memset(&param, 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(&param)) {
1689+ goto NOT_IN_PCI_FP;
1690+ } else {
1691+ pci_dev_index = param.data.sppe_arp.unused_1;
1692+ }
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(&param)) {
1698+ goto NOT_IN_PCI_FP;
1699+ } else {
1700+ skb->dev = param.data.sppe_pci_fp_dev.dev;
1701+ }
1702+ #if 1
1703+ dev_queue_xmit(skb);
1704+ #else
1705+ skb->dev->hard_start_xmit(skb, skb->dev);
1706+ #endif
1707+
1708+ return 0;
1709+ }
1710+ }
1711+NOT_IN_PCI_FP:
1712+#endif
1713+
1714+#ifdef CNS3XXX_NON_NIC_MODE_8021Q
1715+ if (cns3xxx_is_untag_packet(rx_desc) == 1)
1716+ take_off_vlan_header(skb);
1717+#endif
1718+
1719+#ifdef CONFIG_CNS3XXX_PORT_BASE
1720+ assign_netdev(rx_buffer);
1721+
1722+ if (rx_buffer->skb->dev) // if skb->dev is 0, means VLAN base
1723+ goto determine_dev_ok;
1724+
1725+#endif /* CONFIG_CNS3XXX_PORT_BASE */
1726+
1727+
1728+#ifdef CONFIG_CNS3XXX_VLAN_BASE
1729+
1730+#ifdef CONFIG_HAVE_VLAN_TAG
1731+
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)
1737+ {
1738+ assign_netdev(rx_buffer);
1739+
1740+ take_off_vlan_header(skb);
1741+ if (MSG_LEVEL == 5)
1742+ print_packet(skb->data, 32);
1743+
1744+ if ( rx_buffer->skb->dev == 0){
1745+ goto freepacket;
1746+ }
1747+ }
1748+
1749+#endif // CNS3XXX_VLAN_8021Q
1750+
1751+#else /* CONFIG_HAVE_VLAN_TAG */
1752+
1753+#ifdef CNS3XXX_RX_DESC_VLAN_INFO
1754+// get VLAN information by RX descriptor field
1755+
1756+#endif
1757+
1758+#endif // CONFIG_HAVE_VLAN_TAG
1759+
1760+#endif // CONFIG_CNS3XXX_VLAN_BASE
1761+
1762+
1763+#ifdef CONFIG_CNS3XXX_PORT_BASE
1764+determine_dev_ok:
1765+#endif
1766+
1767+ skb_put(skb, len);
1768+
1769+ if (skb->dev) {
1770+ priv = netdev_priv(skb->dev);
1771+ }
1772+ else{
1773+ DEBUG_MSG(WARNING_MSG, "skb_ptr->dev==NULL\n");
1774+ goto freepacket;
1775+ }
1776+
1777+#ifdef CNS3XXX_RX_HW_CHECKSUM
1778+ switch (rx_desc->prot)
1779+ {
1780+ case 1 :
1781+ case 2 :
1782+ case 5 :
1783+ case 6 :
1784+ {
1785+ if ( rx_desc->l4f == 0) { // tcp/udp checksum is correct
1786+ skb->ip_summed = CHECKSUM_UNNECESSARY;
1787+ } else {
1788+ skb->ip_summed = CHECKSUM_NONE;
1789+ }
1790+ break;
1791+ }
1792+ default:
1793+ {
1794+ skb->ip_summed = CHECKSUM_NONE;
1795+ break;
1796+ }
1797+ }
1798+#else
1799+ skb->ip_summed = CHECKSUM_NONE;
1800+#endif // CNS3XXX_RX_HW_CHECKSUM
1801+
1802+
1803+ // this line must, if no, packet will not send to network layer
1804+#ifdef CONFIG_FAST_BRIDGE
1805+ if (fast_bridge_en == 0)
1806+#endif
1807+ skb->protocol = eth_type_trans(skb, skb->dev);
1808+
1809+ skb->dev->last_rx = jiffies;
1810+ priv->stats.rx_packets++;
1811+ priv->stats.rx_bytes += len;
1812+
1813+#ifdef CONFIG_FAST_BRIDGE
1814+ if (fast_bridge_en == 1) {
1815+
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;
1821+ }
1822+ //skb->dev->hard_start_xmit(skb, skb->dev);
1823+ cns3xxx_send_packet(skb, skb->dev);
1824+ } else {
1825+#endif // #ifdef CONFIG_FAST_BRIDGE
1826+
1827+
1828+//#if defined(CNS3XXX_VLAN_8021Q)
1829+#if 0
1830+ if (priv->vlgrp != NULL)
1831+ {
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)) );
1835+ }
1836+ else
1837+#else
1838+ #ifdef CONFIG_CNS3XXX_NAPI
1839+ netif_receive_skb(skb);
1840+ #else
1841+ netif_rx(skb);
1842+ #endif
1843+#endif
1844+
1845+#ifdef CONFIG_FAST_BRIDGE
1846+ }
1847+#endif
1848+
1849+ //vlan_hwaccel_receive_skb(skb, priv->vlgrp, 1);
1850+
1851+ return 0;
1852+
1853+freepacket:
1854+ //DEBUG_MSG(NORMAL_MSG, "freepacket\n");
1855+ dev_kfree_skb_any(skb);
1856+ return 0;
1857+}
1858+
1859+// index from 1
1860+inline u32 get_rx_hw_index(CNS3XXXPrivate *priv)
1861+{
1862+ return ((FS_DESC_PTR0_REG - get_rx_head_phy_addr(&RX_RING0(priv))) / sizeof(RXDesc) );
1863+}
1864+
1865+inline int get_rx_hw_index_by_reg(u8 ring_num)
1866+{
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) );
1871+ }
1872+
1873+ return CAVM_FAIL;
1874+}
1875+
1876+void dump_rxring(void)
1877+{
1878+ int j=0;
1879+ RXBuffer *rx_buffer = 0;
1880+
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);
1884+ }
1885+}
1886+
1887+#ifdef CONFIG_CNS3XXX_NAPI
1888+void cns3xxx_receive_packet(CNS3XXXPrivate *priv, int mode, int *work_done, int work_to_do)
1889+#else
1890+void cns3xxx_receive_packet(CNS3XXXPrivate *priv, int mode)
1891+#endif
1892+{
1893+ int fssd_index;
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
1900+#endif
1901+ int i, rxcount = 0;
1902+ u8 queue_index = priv->ring_index;
1903+
1904+#ifdef CONFIG_SWITCH_BIG_ENDIAN
1905+ RXDesc tmp_rx_desc;
1906+#endif
1907+
1908+ rx_buffer = get_cur_rx_buffer(&(priv->rx_ring[queue_index]));
1909+
1910+#ifdef CONFIG_SWITCH_BIG_ENDIAN
1911+ rx_desc = &tmp_rx_desc;
1912+ swap_rx_desc(rx_buffer->rx_desc, rx_desc);
1913+#else
1914+ rx_desc = rx_buffer->rx_desc;
1915+#endif
1916+
1917+ fssd_index = get_rx_hw_index_by_reg(queue_index);
1918+
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;
1927+ } else {
1928+ // Queue Full
1929+#ifndef CONFIG_CNS3XXX_NAPI
1930+ fsqf = 1;
1931+#endif
1932+ rxcount = get_rx_ring_size(&priv->rx_ring[queue_index]);
1933+ }
1934+ }
1935+#ifndef CONFIG_CNS3XXX_NAPI
1936+ if (mode == 1) {
1937+ fsqf = 1;
1938+ rxcount = get_rx_ring_size(&priv->rx_ring[queue_index]);
1939+ }
1940+#endif
1941+
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);
1946+#endif
1947+#endif
1948+
1949+ for (i = 0; i < rxcount; i++) {
1950+
1951+ if (rx_desc->cown != 0) { // start to get packet
1952+ // Alloc New skb_buff
1953+ skb = cns3xxx_alloc_skb();
1954+ // Check skb_buff
1955+ if (skb) {
1956+ cns3xxx_get_rfd_buff(rx_buffer, priv);
1957+ rx_buffer->skb = skb;
1958+#ifndef NCNB_TEST
1959+ rx_desc->sdp = (u32)virt_to_phys(skb->data);
1960+#endif
1961+ rx_desc->sdl = MAX_PACKET_LEN;
1962+ rx_desc->fsd = 1;
1963+ rx_desc->lsd = 1;
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);
1967+#endif
1968+
1969+#ifdef CONFIG_CNS3XXX_NAPI
1970+ ++(*work_done);
1971+ if (*work_done >= work_to_do) {
1972+
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;
1976+ break;
1977+ }
1978+#endif
1979+
1980+ } else {
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);
1986+#endif
1987+
1988+ return;
1989+ }
1990+ } else { // cown is 0, no packets
1991+ //*work_done = 0;
1992+ return;
1993+ }
1994+
1995+
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;
1999+
2000+ } // end for (i = 0; i < rxcount; i++)
2001+
2002+
2003+#ifndef CONFIG_CNS3XXX_NAPI
2004+ if (fsqf) {
2005+ priv->rx_ring[queue_index].cur_index = fssd_index;
2006+ mb();
2007+ enable_rx_dma(0, 1);
2008+ }
2009+#endif
2010+
2011+
2012+ //spin_unlock(&rx_lock);
2013+receive_packet_exit:
2014+ return;
2015+}
2016+
2017+irqreturn_t cns3xxx_fsrc_ring0_isr(int irq, void *dev_id)
2018+{
2019+ struct net_device *netdev = dev_id;
2020+ CNS3XXXPrivate *priv = netdev_priv(netdev);
2021+
2022+ priv->ring_index=0;
2023+
2024+#ifdef CONFIG_CNS3XXX_NAPI
2025+{
2026+ CNS3XXXPrivate *priv = netdev_priv(napi_dev);
2027+ priv->ring_index=0;
2028+
2029+#ifdef CNS3XXX_USE_MASK
2030+ cns3xxx_write_pri_mask(0xb0);
2031+#else
2032+ cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID);
2033+#endif
2034+
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);
2039+ } else {
2040+#ifdef CNS3XXX_USE_MASK
2041+ cns3xxx_write_pri_mask(0xf0);
2042+#else
2043+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
2044+#endif
2045+ }
2046+}
2047+#else // !CONFIG_CNS3XXX_NAPI
2048+
2049+#ifdef CNS3XXX_USE_MASK
2050+ cns3xxx_write_pri_mask(0xb0);
2051+#else
2052+ cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID);
2053+ cns3xxx_disable_irq(FSQF_RING0_INTERRUPT_ID);
2054+#endif
2055+
2056+ cns3xxx_receive_packet(priv, 0); // Receive Once
2057+
2058+#ifdef CNS3XXX_USE_MASK
2059+ cns3xxx_write_pri_mask(0xf0);
2060+#else
2061+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
2062+ cns3xxx_enable_irq(FSQF_RING0_INTERRUPT_ID);
2063+#endif
2064+ enable_rx_dma(0, 1);
2065+#endif
2066+
2067+ return IRQ_HANDLED;
2068+}
2069+
2070+
2071+#if defined(CNS3XXX_DOUBLE_RX_RING)
2072+irqreturn_t cns3xxx_fsrc_ring1_isr(int irq, void *dev_id)
2073+{
2074+ struct net_device *netdev = dev_id;
2075+ CNS3XXXPrivate *priv = netdev_priv(netdev);
2076+ priv->ring_index=1;
2077+
2078+
2079+#if defined(CONFIG_CNS3XXX_NAPI) && defined(CNS3XXX_DOUBLE_RX_RING)
2080+{
2081+ CNS3XXXPrivate *priv = netdev_priv(r1_napi_dev);
2082+ priv->ring_index=1;
2083+
2084+ cns3xxx_disable_irq(FSRC_RING1_INTERRUPT_ID);
2085+
2086+ if (likely(napi_schedule_prep(&priv->napi))) {
2087+ __napi_schedule(&priv->napi);
2088+ } else {
2089+ cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID);
2090+ }
2091+}
2092+#else
2093+
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);
2098+
2099+ cns3xxx_enable_irq(CNS3XXX_FSRC_RING1_INTERRUPT_ID);
2100+ cns3xxx_enable_irq(CNS3XXX_FSQF_RING1_INTERRUPT_ID);
2101+#endif
2102+
2103+ return IRQ_HANDLED;
2104+}
2105+#endif
2106+
2107+int cns3xxx_check_enough_tx_descriptor(TXRing *tx_ring, int need_free_tx_desc)
2108+{
2109+#if 1
2110+ int i=0;
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);
2114+
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);
2119+#else
2120+ tx_desc = tx_buffer->tx_desc;
2121+#endif
2122+
2123+
2124+ for (i=0 ; i < need_free_tx_desc ; ++i) {
2125+ if ( tx_desc->cown == 0 ) {
2126+ return 0; // no free TX descriptor
2127+ }
2128+ tx_buffer = get_tx_buffer_by_index(tx_ring, ++cur_index);
2129+ }
2130+#endif
2131+ return 1;
2132+}
2133+
2134+// if return CAVM_ERR, means pad is fail, the packet cannot send by switch.
2135+
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)
2137+{
2138+ //TXDesc *tx_desc_ptr = tx_buffer->tx_desc;
2139+ static int tt=0;
2140+
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);
2146+#else
2147+ tx_desc_ptr = tx_buffer->tx_desc;
2148+#endif
2149+
2150+
2151+
2152+ if (tx_buffer->skb) {
2153+ dev_kfree_skb_any(tx_buffer->skb);
2154+ tx_buffer->skb = 0 ;
2155+ } else {
2156+ //++tx_ring.non_free_tx_skb;
2157+ }
2158+
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);
2163+ ++tt;
2164+
2165+#if 0
2166+ {
2167+ static u16 previous_sn_num=10;
2168+ u16 sn_num=0;
2169+ u16 e_type=0;
2170+
2171+ memcpy(&e_type, skb->data + 12, 2);
2172+ e_type = be16_to_cpu(e_type);
2173+
2174+ if (e_type == 0x0800) {
2175+ memcpy(&sn_num, skb->data + 0x28, 2);
2176+ sn_num = be16_to_cpu(sn_num);
2177+
2178+ if ( previous_sn_num == sn_num)
2179+ printk("dup\n");
2180+
2181+ previous_sn_num = sn_num;
2182+ }
2183+
2184+ }
2185+#endif
2186+
2187+
2188+#ifdef CNS3XXX_TX_HW_CHECKSUM
2189+ tx_desc_ptr->ico = 1;
2190+ tx_desc_ptr->uco = 1;
2191+ tx_desc_ptr->tco = 1;
2192+#else
2193+ tx_desc_ptr->ico = 0;
2194+ tx_desc_ptr->uco = 0;
2195+ tx_desc_ptr->tco = 0;
2196+#endif
2197+ // Wake interrupt
2198+#ifdef CNS3XXX_TSTC_RING0_ISR
2199+ tx_desc_ptr->interrupt = 1;
2200+#else
2201+ tx_desc_ptr->interrupt = 0;
2202+#endif
2203+
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))
2208+ return CAVM_ERR;
2209+
2210+ //memset(skb->data + len, 0, MIN_PACKET_LEN - len);
2211+ //skb->len = MIN_PACKET_LEN;
2212+ tx_desc_ptr->sdl = MIN_PACKET_LEN;
2213+ } else {
2214+ tx_desc_ptr->sdl = len;
2215+ }
2216+
2217+ dma_cache_maint(data, tx_desc_ptr->sdl, PCI_DMA_TODEVICE);
2218+
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;
2224+
2225+ /* NOT SG packet */
2226+ if( fsd == 1 && lsd == 1)
2227+ tx_desc_ptr->cown = 0;
2228+
2229+#ifdef CONFIG_SWITCH_BIG_ENDIAN
2230+ swap_tx_desc(tx_desc_ptr, tx_buffer->tx_desc);
2231+#endif
2232+
2233+ return CAVM_OK;
2234+}
2235+
2236+int cns3xxx_send_packet(struct sk_buff *skb, struct net_device *netdev)
2237+{
2238+
2239+ CNS3XXXPrivate *priv = netdev_priv(netdev);
2240+ TXBuffer *tx_buffer = 0;
2241+ unsigned long flags;
2242+ int nr_frags =skb_shinfo(skb)->nr_frags;
2243+
2244+ TXDesc *tx_desc[10]; // FIXME: ensure to maximum sg size
2245+ int tx_desc_count=0;
2246+ int i=0;
2247+
2248+#ifdef DEBUG_TX
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);
2252+ }
2253+#endif
2254+
2255+ spin_lock_irqsave(&tx_lock, flags);
2256+
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;
2262+ }
2263+
2264+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2265+
2266+ if (nr_frags == 0) { // non scatter/gather I/O
2267+
2268+ fill_a_skb_to_tx_desc(tx_buffer, skb->data, skb->len, skb, priv, 0, 1, 1);
2269+
2270+ tx_index_next(priv->tx_ring + ring_index);
2271+
2272+ } else { // scatter/gather I/O
2273+ struct skb_frag_struct *frag = 0;
2274+
2275+
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);
2280+
2281+ for (i=0 ; i < nr_frags-1 ; ++i) {
2282+ frag = &skb_shinfo(skb)->frags[i];
2283+
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;
2286+
2287+ tx_index_next(priv->tx_ring + ring_index);
2288+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2289+ }
2290+ frag = &skb_shinfo(skb)->frags[nr_frags-1];
2291+
2292+ // last fragment
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;
2295+
2296+ tx_index_next(priv->tx_ring + ring_index);
2297+ tx_buffer = get_cur_tx_buffer(priv->tx_ring + ring_index);
2298+ }
2299+
2300+
2301+ if( nr_frags != 0) {
2302+
2303+ for (i = 0; i < tx_desc_count ; i++ )
2304+ tx_desc[i]->cown = 0 ;
2305+ }
2306+
2307+ mb();
2308+ enable_tx_dma(ring_index, 1);
2309+
2310+ priv->stats.tx_packets++;
2311+ priv->stats.tx_bytes += skb->len;
2312+ netdev->trans_start = jiffies;
2313+
2314+ spin_unlock_irqrestore(&tx_lock, flags);
2315+ return NETDEV_TX_OK;
2316+}
2317+
2318+
2319+#ifdef CNS3XXX_FSQF_RING0_ISR
2320+irqreturn_t cns3xxx_fsqf_ring0_isr(int irq, void *dev_id)
2321+{
2322+#ifndef CONFIG_CNS3XXX_NAPI
2323+ struct net_device *netdev = dev_id;
2324+ CNS3XXXPrivate *priv = netdev_priv(netdev);
2325+#endif
2326+
2327+#ifdef CONFIG_CNS3XXX_NAPI
2328+{
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);
2333+}
2334+#else
2335+#ifdef CNS3XXX_USE_MASK
2336+ cns3xxx_write_pri_mask(0xb0);
2337+#else
2338+ cns3xxx_disable_irq(FSRC_RING0_INTERRUPT_ID);
2339+ cns3xxx_disable_irq(FSQF_RING0_INTERRUPT_ID);
2340+#endif
2341+
2342+
2343+ cns3xxx_receive_packet(priv, 1); // Receive at Queue Full Mode
2344+
2345+#ifdef CNS3XXX_USE_MASK
2346+ cns3xxx_write_pri_mask(0xf0);
2347+#else
2348+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
2349+ cns3xxx_enable_irq(FSQF_RING0_INTERRUPT_ID);
2350+#endif
2351+
2352+ enable_rx_dma(0, 1);
2353+#endif // CONFIG_CNS3XXX_NAPI
2354+
2355+ return IRQ_HANDLED;
2356+}
2357+#endif
2358+
2359+
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)
2363+{
2364+ struct net_device *netdev = dev_id;
2365+ CNS3XXXPrivate *priv = netdev_priv(netdev);
2366+ //INTC_CLEAR_EDGE_TRIGGER_INTERRUPT(INTC_GSW_FSQF_BIT_INDEX);
2367+
2368+#ifdef CONFIG_CNS3XXX_NAPI
2369+{
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);
2374+}
2375+#else
2376+ cns3xxx_disable_irq(FSRC_RING1_INTERRUPT_ID);
2377+ cns3xxx_disable_irq(FSQF_RING1_INTERRUPT_ID);
2378+
2379+ cns3xxx_receive_packet(priv, 1); // Receive at Queue Full Mode
2380+ enable_rx_dma(1, 1);
2381+
2382+ cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID);
2383+ cns3xxx_enable_irq(FSQF_RING1_INTERRUPT_ID);
2384+#endif
2385+ return IRQ_HANDLED;
2386+}
2387+#endif
2388+#endif //#if defined(CNS3XXX_DOUBLE_RX_RING)
2389+
2390+
2391+#ifdef CNS3XXX_STATUS_ISR
2392+irqreturn_t cns3xxx_status_isr(int irq, void *dev_id)
2393+{
2394+ u32 int_status = INTR_STAT_REG;
2395+ u32 i=0;
2396+
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]);
2401+ }
2402+ }
2403+ INTR_STAT_REG = 0xffffffff; // write 1 for clear.
2404+ cns3xxx_enable_irq(STATUS_INTERRUPT_ID);
2405+ return IRQ_HANDLED;
2406+}
2407+#endif
2408+
2409+
2410+#ifdef CNS3XXX_TSTC_RING0_ISR
2411+irqreturn_t cns3xxx_tstc_ring0_isr(int irq, void *dev_id)
2412+{
2413+ return IRQ_HANDLED;
2414+}
2415+#endif
2416+
2417+
2418+static int cns3xxx_install_isr(struct net_device *dev)
2419+{
2420+ int retval;
2421+ CNS3XXXPrivate *priv = netdev_priv(dev);
2422+
2423+ if (install_isr_rc == 0) {
2424+
2425+ retval = request_irq(FSRC_RING0_INTERRUPT_ID, cns3xxx_fsrc_ring0_isr, IRQF_SHARED, "FSRC_RING0", intr_netdev);
2426+
2427+ if (retval) {
2428+ return 1;
2429+ }
2430+
2431+#ifdef CNS3XXX_FSQF_RING0_ISR
2432+ retval = request_irq(FSQF_RING0_INTERRUPT_ID, cns3xxx_fsqf_ring0_isr, IRQF_SHARED, "FSQF_RING0", intr_netdev);
2433+
2434+ if (retval) {
2435+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "FSQF_RING0", FSQF_RING0_INTERRUPT_ID, retval);
2436+ return 2;
2437+ }
2438+#endif
2439+
2440+#ifdef CNS3XXX_TSTC_RING0_ISR
2441+ retval = request_irq(TSTC_RING0_INTERRUPT_ID, cns3xxx_tstc_ring0_isr, IRQF_SHARED, "TSTC_RING0", intr_netdev);
2442+
2443+ if (retval) {
2444+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "TSTC_RING0", FSQF_RING0_INTERRUPT_ID, retval);
2445+ return 3;
2446+ }
2447+
2448+#endif
2449+
2450+
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);
2454+
2455+ if (retval) {
2456+ return 1;
2457+ }
2458+
2459+#ifdef CNS3XXX_FSQF_RING1_ISR
2460+ retval = request_irq(FSQF_RING1_INTERRUPT_ID, cns3xxx_fsqf_ring1_isr, IRQF_SHARED, "FSQF_RING1", intr_netdev);
2461+
2462+ if (retval) {
2463+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "FSQF_RING1", FSQF_RING1_INTERRUPT_ID, retval);
2464+ return 2;
2465+ }
2466+#endif
2467+
2468+#endif
2469+ }
2470+
2471+#ifdef CNS3XXX_STATUS_ISR
2472+ retval = request_irq(STATUS_INTERRUPT_ID, cns3xxx_status_isr, IRQF_SHARED, "GSW_STATUS", intr_netdev);
2473+
2474+ if (retval) {
2475+ PRINT_INFO("%s: unable to get IRQ %d (irqval=%d).\n", "GSW STATUS INT", STATUS_INTERRUPT_ID, retval);
2476+ return 3;
2477+ }
2478+ INTR_MASK_REG = 0;
2479+#endif
2480+
2481+
2482+
2483+
2484+
2485+
2486+#ifdef CONFIG_CNS3XXX_NAPI
2487+{
2488+ CNS3XXXPrivate *sp = netdev_priv(napi_dev);
2489+ napi_enable(&sp->napi);
2490+ netif_start_queue(napi_dev);
2491+
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);
2496+#endif
2497+}
2498+#endif
2499+ // enable cpu port
2500+ enable_port(3, 1);
2501+
2502+ } // end if (install_isr_rc == 0)
2503+
2504+ ++install_isr_rc;
2505+
2506+ return 0;
2507+}
2508+
2509+
2510+int cns3xxx_open(struct net_device *dev)
2511+{
2512+ CNS3XXXPrivate *priv = netdev_priv(dev);
2513+ //static int init_state=0;
2514+
2515+ if (cns3xxx_setup_rx_tx_res(priv) != CAVM_OK) {
2516+ return -1;
2517+ }
2518+
2519+ netif_start_queue(dev);
2520+ priv->net_device_priv->open();
2521+
2522+ cns3xxx_install_isr(dev);
2523+
2524+ enable_rx_dma(0, 1);
2525+
2526+ if (priv->num_rx_queues == 2)
2527+ enable_rx_dma(1, 1);
2528+
2529+ netif_carrier_on(dev);
2530+
2531+ return 0;
2532+}
2533+
2534+static int cns3xxx_uninstall_isr(struct net_device *dev)
2535+{
2536+ CNS3XXXPrivate *priv = netdev_priv(dev);
2537+ --install_isr_rc;
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);
2543+#endif
2544+
2545+#ifdef CNS3XXX_FSQF_RING0_ISR
2546+ free_irq(FSQF_RING0_INTERRUPT_ID, intr_netdev);
2547+#endif
2548+
2549+#ifdef CNS3XXX_TSTC_RING0_ISR
2550+ free_irq(TSTC_RING0_INTERRUPT_ID, intr_netdev);
2551+#endif
2552+
2553+ if (priv->num_rx_queues == 2) {
2554+ free_irq(FSRC_RING1_INTERRUPT_ID, intr_netdev);
2555+
2556+#ifdef CNS3XXX_FSQF_RING1_ISR
2557+ free_irq(FSQF_RING1_INTERRUPT_ID, intr_netdev);
2558+#endif
2559+ }
2560+
2561+
2562+
2563+#ifdef CONFIG_CNS3XXX_NAPI
2564+{
2565+ CNS3XXXPrivate *sp = netdev_priv(napi_dev);
2566+
2567+ napi_disable(&sp->napi);
2568+ netif_stop_queue(napi_dev);
2569+#ifdef CNS3XXX_DOUBLE_RX_RING
2570+ sp = netdev_priv(r1_napi_dev);
2571+
2572+ napi_disable(&sp->napi);
2573+ netif_stop_queue(r1_napi_dev);
2574+#endif
2575+}
2576+#endif
2577+
2578+
2579+ }
2580+
2581+ return 0;
2582+}
2583+
2584+int cns3xxx_close(struct net_device *dev)
2585+{
2586+ CNS3XXXPrivate *priv = netdev_priv(dev);
2587+
2588+ enable_rx_dma(0, 0);
2589+ enable_tx_dma(0, 0);
2590+
2591+ if (priv->num_rx_queues == 2)
2592+ enable_tx_dma(1, 0);
2593+
2594+ if (priv->num_tx_queues == 2)
2595+ enable_rx_dma(1, 0);
2596+
2597+ netif_stop_queue(dev);
2598+
2599+ priv->net_device_priv->close();
2600+ cns3xxx_uninstall_isr(dev);
2601+ cns3xxx_free_rx_tx_res(priv);
2602+ netif_carrier_off(dev);
2603+ return 0;
2604+}
2605+
2606+
2607+
2608+//#define MAC_PORT(p) MAC##p##_CFG_REG
2609+
2610+void broadcast_storm_cfg(u8 port, u8 boradcast, u8 multicast, u8 unknown)
2611+{
2612+ switch (port)
2613+ {
2614+ case 0:
2615+ {
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))) ;
2619+ break;
2620+ }
2621+ case 1:
2622+ {
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))) ;
2626+ break;
2627+ }
2628+ case 2:
2629+ {
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))) ;
2633+ break;
2634+ }
2635+ }
2636+}
2637+
2638+void broadcast_storm_rate(u8 rate)
2639+{
2640+ TC_CTRL_REG &= (~(0xf << 24));
2641+ TC_CTRL_REG |= (rate << 24);
2642+}
2643+
2644+// port: 0, 1, 2 ; port0, port1 and port2
2645+// config general mac port configuration
2646+void cns3xxx_general_mac_cfg(u8 port)
2647+{
2648+ u32 cfg=0;
2649+
2650+ switch (port)
2651+ {
2652+ case 0:
2653+ {
2654+ cfg = MAC0_CFG_REG;
2655+ break;
2656+ }
2657+ case 1:
2658+ {
2659+ cfg = MAC1_CFG_REG;
2660+ break;
2661+ }
2662+ case 2:
2663+ {
2664+ cfg = MAC2_CFG_REG;
2665+ break;
2666+ }
2667+ }
2668+
2669+
2670+ // txc_check_en: 1
2671+ cfg |= (1 << 13);
2672+
2673+ // bp_en: 1
2674+ cfg |= (1 << 17);
2675+
2676+#ifdef CNS3XXX_LEARN_ENABLE
2677+ // learn_dis: 0
2678+ cfg &= (~(1 << 19));
2679+#else
2680+ // learn disable
2681+ cfg |= (1 << 19);
2682+#endif
2683+
2684+ // blocking_state: 0
2685+ cfg &= (~(1 << 20));
2686+
2687+ // block_mode: 0
2688+ cfg &= (~(1 << 21));
2689+
2690+#ifdef CNS3XXX_AGE_ENABLE
2691+ // age_en: 1
2692+ cfg |= (1 << 22);
2693+
2694+#else
2695+ // age disable
2696+ cfg &= (~(1 << 22));
2697+#endif
2698+
2699+ // SA_secured: 0
2700+ cfg &= (~(1 << 23));
2701+
2702+ switch (port)
2703+ {
2704+ case 0:
2705+ {
2706+ MAC0_CFG_REG = cfg;
2707+ break;
2708+ }
2709+ case 1:
2710+ {
2711+ MAC1_CFG_REG = cfg;
2712+ break;
2713+ }
2714+ case 2:
2715+ {
2716+ MAC2_CFG_REG = cfg;
2717+ break;
2718+ }
2719+ }
2720+
2721+}
2722+
2723+void cns3xxx_configu_cpu_port(void)
2724+{
2725+ // Set CPU port to general configuration
2726+
2727+#ifdef CNS3XXX_LEARN_ENABLE
2728+ CPU_CFG_REG &= (~(1 << 19));
2729+#else
2730+ // learn_dis: 1
2731+ CPU_CFG_REG |= (1 << 19);
2732+#endif
2733+
2734+#ifdef CNS3XXX_AGE_ENABLE
2735+ // age_en: 1
2736+ CPU_CFG_REG |= (1 << 22);
2737+#else
2738+ // age disable
2739+ CPU_CFG_REG &= (~(1 << 22));
2740+#endif
2741+
2742+ // SA_secured: 0
2743+ CPU_CFG_REG &= (~(1 << 23));
2744+
2745+ // go to hnat:1
2746+ CPU_CFG_REG |= (1 << 29);
2747+
2748+ //offset 4N +2
2749+ CPU_CFG_REG &= (~(1 << 30));
2750+#ifdef CNS3XXX_4N
2751+ CPU_CFG_REG |= (1 << 30);
2752+#endif
2753+
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);
2759+#endif
2760+
2761+}
2762+
2763+static void __init cns3xxx_gsw_hw_init(void)
2764+{
2765+ //u32 mac_port_config;
2766+ int i;
2767+ //u32 cfg_reg = 0;
2768+ u32 reg_config = 0;
2769+
2770+#ifdef CONFIG_SILICON
2771+
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
2776+
2777+ cns3xxx_gsw_power_enable();
2778+ cns3xxx_gsw_software_reset();
2779+#endif
2780+
2781+#ifdef CNS3XXX_CONFIG_SIM_MODE
2782+ SLK_SKEW_CTRL_REG |= (1 << 31);
2783+#endif
2784+
2785+
2786+#if 1
2787+ while (((SRAM_TEST_REG >> 20) & 1) == 0);
2788+#endif
2789+
2790+ clear_fs_dma_state(1);
2791+
2792+
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);
2798+
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);
2804+
2805+ INTR_STAT_REG = 0xffffffff; // write 1 for clear.
2806+
2807+#ifdef CNS3XXX_DELAYED_INTERRUPT
2808+ DELAY_INTR_CFG_REG = (1 << 16) | (max_pend_int_cnt << 8) | (max_pend_time);
2809+#endif
2810+
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
2815+#else
2816+ reg_config |= (2 << 30); // maximum frame length: 1536 bytes
2817+#endif
2818+
2819+ PHY_AUTO_ADDR_REG = reg_config;
2820+
2821+
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;
2826+
2827+
2828+ // bkoff_mode: 111 follow standard
2829+ MAC_GLOB_CFG_REG &= (~(0x7 << 9));
2830+ MAC_GLOB_CFG_REG |= (0x7 << 9);
2831+
2832+ // jam_no: 1010:
2833+ MAC_GLOB_CFG_REG &= (~(0xf << 12));
2834+ MAC_GLOB_CFG_REG |= (0xa << 12);
2835+
2836+ // bp_mode: 10:
2837+ MAC_GLOB_CFG_REG &= (~(0x3 << 16));
2838+ MAC_GLOB_CFG_REG |= (0x2 << 16);
2839+
2840+ // res_mc_flt: 0
2841+ MAC_GLOB_CFG_REG &= (~(0x1 << 28));
2842+
2843+ // col_mode: 11
2844+ MAC_GLOB_CFG_REG &= (~(0x3 << 18));
2845+ MAC_GLOB_CFG_REG |= (0x3 << 18);
2846+
2847+ // crc_stripping: 1
2848+ MAC_GLOB_CFG_REG |= (0x1 << 20);
2849+
2850+
2851+ // ACCEPT_CRC_BAD_PKT : 0
2852+ MAC_GLOB_CFG_REG &= (~(0x1 << 21));
2853+
2854+#ifdef ACCEPT_CRC_BAD_PKT
2855+ MAC_GLOB_CFG_REG |= (0x1 << 21);
2856+#endif
2857+
2858+ // SVL
2859+ MAC_GLOB_CFG_REG &= (~(0x1 << 7));
2860+
2861+#ifdef IVL
2862+ // IVL: 1 (IVL), 0 (SVL)
2863+ MAC_GLOB_CFG_REG |= (0x1 << 7);
2864+#endif
2865+
2866+
2867+ // HNAT_en: 0
2868+ MAC_GLOB_CFG_REG &= (~(0x1 << 26));
2869+
2870+ // Firewall_mode: 0
2871+ MAC_GLOB_CFG_REG &= (~(0x1 << 27));
2872+
2873+
2874+
2875+ cns3xxx_general_mac_cfg(0);
2876+ cns3xxx_general_mac_cfg(1);
2877+ cns3xxx_general_mac_cfg(2);
2878+ cns3xxx_configu_cpu_port();
2879+
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]);
2885+
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);
2890+
2891+#ifdef CNS3XXX_SET_ARL_TABLE
2892+ // set arl table
2893+ cns3xxx_arl_table_flush();
2894+#endif
2895+}
2896+
2897+static int cns3xxx_set_mac_addr(struct net_device *dev, void *p)
2898+{
2899+ //struct sockaddr *sock_addr = addr;
2900+ CNS3XXXPrivate *priv = netdev_priv(dev);
2901+
2902+ struct sockaddr *addr= p;
2903+
2904+
2905+ spin_lock_irq(&priv->lock);
2906+
2907+
2908+ if (!is_valid_ether_addr(addr->sa_data))
2909+ return -EADDRNOTAVAIL;
2910+
2911+ // 1. delete old arl mac entry
2912+ // 2. add new arl mac entry
2913+ // 3. copy new mac to netdev field
2914+
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);
2920+ }
2921+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
2922+
2923+ spin_unlock_irq(&priv->lock);
2924+ return 0;
2925+}
2926+
2927+
2928+int set_fc_rls(struct ifreq *ifr)
2929+{
2930+ CNS3XXXSARLEntry ctl;
2931+
2932+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2933+ return -EFAULT;
2934+ FC_GLOB_THRS_REG &= (~(0x1ff << 16));
2935+ FC_GLOB_THRS_REG |= (ctl.val << 16);
2936+ return CAVM_OK;
2937+}
2938+
2939+int get_fc_rls(struct ifreq *ifr)
2940+{
2941+ CNS3XXXSARLEntry ctl;
2942+
2943+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2944+ return -EFAULT;
2945+
2946+ ctl.val = ((FC_GLOB_THRS_REG >> 16) & 0x1ff);
2947+
2948+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
2949+ return -EFAULT;
2950+ return CAVM_OK;
2951+}
2952+
2953+int set_fc_set(struct ifreq *ifr)
2954+{
2955+ CNS3XXXSARLEntry ctl;
2956+
2957+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2958+ return -EFAULT;
2959+ FC_GLOB_THRS_REG &= (~0x1ff);
2960+ FC_GLOB_THRS_REG |= ctl.val;
2961+ return CAVM_OK;
2962+}
2963+
2964+int get_fc_set(struct ifreq *ifr)
2965+{
2966+ CNS3XXXSARLEntry ctl;
2967+
2968+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2969+ return -EFAULT;
2970+
2971+ ctl.val = ((FC_GLOB_THRS_REG) & 0x1ff);
2972+
2973+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
2974+ return -EFAULT;
2975+ return CAVM_OK;
2976+}
2977+
2978+
2979+int set_sarl_rls(struct ifreq *ifr)
2980+{
2981+ CNS3XXXSARLEntry ctl;
2982+
2983+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2984+ return -EFAULT;
2985+ SARL_CTRL_REG &= (~(0x1ff << 12));
2986+ SARL_CTRL_REG |= (ctl.val << 12);
2987+ return CAVM_OK;
2988+}
2989+
2990+int get_sarl_rls(struct ifreq *ifr)
2991+{
2992+ CNS3XXXSARLEntry ctl;
2993+
2994+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
2995+ return -EFAULT;
2996+
2997+ ctl.val = ((SARL_CTRL_REG >> 12) & 0x1ff);
2998+
2999+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3000+ return -EFAULT;
3001+ return CAVM_OK;
3002+}
3003+
3004+int set_sarl_enable(struct ifreq *ifr)
3005+{
3006+ CNS3XXXSARLEntry ctl;
3007+
3008+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3009+ return -EFAULT;
3010+ SARL_CTRL_REG &= (~(0x1 << 31));
3011+ SARL_CTRL_REG |= (ctl.val << 31);
3012+ return CAVM_OK;
3013+}
3014+
3015+int get_sarl_enable(struct ifreq *ifr)
3016+{
3017+ CNS3XXXSARLEntry ctl;
3018+
3019+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3020+ return -EFAULT;
3021+ ctl.val = ((SARL_CTRL_REG >> 31 ) & 0x1);
3022+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3023+ return -EFAULT;
3024+ return CAVM_OK;
3025+}
3026+int set_sarl_set(struct ifreq *ifr)
3027+{
3028+ CNS3XXXSARLEntry ctl;
3029+
3030+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3031+ return -EFAULT;
3032+ SARL_CTRL_REG &= (~0x1ff);
3033+ SARL_CTRL_REG |= ctl.val;
3034+ return CAVM_OK;
3035+}
3036+
3037+int get_sarl_set(struct ifreq *ifr)
3038+{
3039+ CNS3XXXSARLEntry ctl;
3040+
3041+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3042+ return -EFAULT;
3043+
3044+ ctl.val = ((SARL_CTRL_REG) & 0x1ff);
3045+
3046+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3047+ return -EFAULT;
3048+ return CAVM_OK;
3049+}
3050+
3051+int set_sarl_oq(struct ifreq *ifr)
3052+{
3053+ CNS3XXXSARLEntry ctl;
3054+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3055+ return -EFAULT;
3056+
3057+ switch (ctl.gyr)
3058+ {
3059+ case 0: // green
3060+ {
3061+ SARL_OQ_GTH_REG &= (~(0xff << ctl.tc*8));
3062+ SARL_OQ_GTH_REG |= (ctl.val << ctl.tc*8);
3063+ break;
3064+ }
3065+ case 1: // yellow
3066+ {
3067+ SARL_OQ_YTH_REG &= (~(0xff << ctl.tc*8));
3068+ SARL_OQ_YTH_REG |= (ctl.val << ctl.tc*8);
3069+ break;
3070+ }
3071+ case 2: // red
3072+ {
3073+ SARL_OQ_RTH_REG &= (~(0xff << ctl.tc*8));
3074+ SARL_OQ_RTH_REG |= (ctl.val << ctl.tc*8);
3075+ break;
3076+ }
3077+ }
3078+ return CAVM_OK;
3079+}
3080+
3081+int get_sarl_oq(struct ifreq *ifr)
3082+{
3083+ CNS3XXXSARLEntry ctl;
3084+
3085+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXSARLEntry)) )
3086+ return -EFAULT;
3087+
3088+ switch (ctl.gyr)
3089+ {
3090+ case 0: // green
3091+ {
3092+ ctl.val = ((SARL_OQ_GTH_REG >> ctl.tc*8) & 0xff);
3093+ break;
3094+ }
3095+ case 1: // yellow
3096+ {
3097+ ctl.val = ((SARL_OQ_YTH_REG >> ctl.tc*8) & 0xff);
3098+ break;
3099+ }
3100+ case 2: // red
3101+ {
3102+ ctl.val = ((SARL_OQ_RTH_REG >> ctl.tc*8) & 0xff);
3103+ break;
3104+ }
3105+ }
3106+
3107+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXSARLEntry)) )
3108+ return -EFAULT;
3109+ return CAVM_OK;
3110+}
3111+
3112+int set_queue_weight(struct ifreq *ifr)
3113+{
3114+ CNS3XXXQueueWeightEntry ctl;
3115+
3116+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQueueWeightEntry)) )
3117+ return -EFAULT;
3118+ switch (ctl.which_port)
3119+ {
3120+ case 0:
3121+ {
3122+ QUEUE_WEIGHT_SET(0, ctl)
3123+ return 0;
3124+ }
3125+ case 1:
3126+ {
3127+ QUEUE_WEIGHT_SET(1, ctl)
3128+ return 0;
3129+ }
3130+ case 2:
3131+ {
3132+ QUEUE_WEIGHT_SET(2, ctl)
3133+ return 0;
3134+ }
3135+ case 3: // cpu port
3136+ {
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);
3143+ return 0;
3144+ }
3145+ case 4: // PPE port
3146+ {
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);
3153+ return 0;
3154+ }
3155+ default:
3156+ {
3157+ return -EFAULT;
3158+ }
3159+ }
3160+}
3161+
3162+int get_queue_weight(struct ifreq *ifr)
3163+{
3164+ CNS3XXXQueueWeightEntry ctl;
3165+
3166+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQueueWeightEntry)) )
3167+ return -EFAULT;
3168+
3169+ switch (ctl.which_port)
3170+ {
3171+ case 0:
3172+ {
3173+ QUEUE_WEIGHT_GET(0, ctl)
3174+ break;
3175+ }
3176+ case 1:
3177+ {
3178+ QUEUE_WEIGHT_GET(1, ctl)
3179+ break;
3180+ }
3181+ case 2:
3182+ {
3183+ QUEUE_WEIGHT_GET(2, ctl)
3184+ break;
3185+ }
3186+ case 3:
3187+ {
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);
3193+ break;
3194+ }
3195+ case 4:
3196+ {
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);
3202+ break;
3203+ }
3204+ }
3205+
3206+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXQueueWeightEntry)) )
3207+ return -EFAULT;
3208+
3209+ return CAVM_OK;
3210+}
3211+
3212+int set_rate_limit(struct ifreq *ifr)
3213+{
3214+ CNS3XXXRateLimitEntry ctl;
3215+
3216+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXRateLimitEntry)) )
3217+ return -EFAULT;
3218+ switch (ctl.which_port)
3219+ {
3220+ case 0:
3221+ {
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;
3226+ return 0;
3227+ }
3228+ case 1:
3229+ {
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);
3234+ return 0;
3235+ }
3236+ case 2:
3237+ {
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);
3242+ return 0;
3243+ }
3244+ case 3: // port 0 extra dma
3245+ {
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);
3250+ return 0;
3251+ }
3252+ default:
3253+ {
3254+ return -EFAULT;
3255+ }
3256+ }
3257+}
3258+
3259+int get_rate_limit(struct ifreq *ifr)
3260+{
3261+ CNS3XXXRateLimitEntry ctl;
3262+
3263+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXRateLimitEntry)) )
3264+ return -EFAULT;
3265+ switch (ctl.which_port)
3266+ {
3267+ case 0:
3268+ {
3269+ ctl.band_width = (RATE_CTRL_REG >> 8) & 0x7f;
3270+ ctl.base_rate = RATE_CTRL_REG & 0x3;
3271+ break;
3272+ }
3273+ case 1:
3274+ {
3275+ ctl.band_width = (RATE_CTRL_REG >> 16) & 0x7f;
3276+ ctl.base_rate = (RATE_CTRL_REG >> 2) & 0x3;
3277+ break;
3278+ }
3279+ case 2:
3280+ {
3281+ ctl.band_width = (RATE_CTRL_REG >> 24) & 0x7f;
3282+ ctl.base_rate = (RATE_CTRL_REG >> 4) & 0x3;
3283+ break;
3284+ }
3285+ case 3: // port 0 extra dma
3286+ {
3287+ ctl.band_width = (TC_CTRL_REG) & 0x7f;
3288+ ctl.base_rate = (RATE_CTRL_REG >> 6) & 0x3;
3289+ break;
3290+ }
3291+ default:
3292+ {
3293+ return -EFAULT;
3294+ }
3295+ }
3296+
3297+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXRateLimitEntry)) )
3298+ return -EFAULT;
3299+
3300+ return CAVM_OK;
3301+}
3302+
3303+int set_fc(struct ifreq *ifr)
3304+{
3305+ CNS3XXXFCEntry ctl;
3306+ u32 port_offset[]={0x0c, 0x10, 0x18, 0x14}; // 0x14 is cpu port offset
3307+ u32 val=0;
3308+
3309+
3310+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXFCEntry)) )
3311+ return -EFAULT;
3312+
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));
3316+ if (ctl.fc_en)
3317+ val |= (1 << 31);
3318+ } else {
3319+ val &= (~(1 << 11)); // disable rx fc
3320+ val &= (~(1 << 12)); // disable tx fc
3321+ val |= (ctl.fc_en << 11);
3322+ }
3323+
3324+ SWITCH_REG_VALUE(port_offset[ctl.port]) = val;
3325+ return CAVM_OK;
3326+}
3327+
3328+int get_fc(struct ifreq *ifr)
3329+{
3330+ CNS3XXXFCEntry ctl;
3331+ u32 port_offset[]={0x0c, 0x10, 0x18, 0x14}; // 0x14 is cpu port offset
3332+ u32 val=0;
3333+
3334+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXFCEntry)) )
3335+ return -EFAULT;
3336+
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);
3340+ } else {
3341+ ctl.fc_en = ((val >> 11) & 3);
3342+
3343+ }
3344+
3345+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXFCEntry)) )
3346+ return -EFAULT;
3347+
3348+ return CAVM_OK;
3349+}
3350+
3351+int set_ivl(struct ifreq *ifr)
3352+{
3353+ CNS3XXXIVLEntry ctl;
3354+
3355+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXIVLEntry)) )
3356+ return -EFAULT;
3357+
3358+ cns3xxx_ivl(ctl.enable);
3359+
3360+ return CAVM_OK;
3361+}
3362+
3363+int get_ivl(struct ifreq *ifr)
3364+{
3365+ CNS3XXXIVLEntry ctl;
3366+
3367+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXIVLEntry)) )
3368+ return -EFAULT;
3369+
3370+ ctl.enable = ((MAC_GLOB_CFG_REG >> 7) & 0x1);
3371+
3372+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXIVLEntry)) )
3373+ return -EFAULT;
3374+
3375+ return CAVM_OK;
3376+}
3377+
3378+int set_wan_port(struct ifreq *ifr)
3379+{
3380+ CNS3XXXWANPortEntry ctl;
3381+
3382+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXWANPortEntry)) )
3383+ return -EFAULT;
3384+ VLAN_CFG &= (~(0x1f << 8));
3385+ VLAN_CFG |= (ctl.wan_port << 8);
3386+
3387+ return CAVM_OK;
3388+}
3389+int get_wan_port(struct ifreq *ifr)
3390+{
3391+ CNS3XXXWANPortEntry ctl;
3392+
3393+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXWANPortEntry)) )
3394+ return -EFAULT;
3395+
3396+ ctl.wan_port = ((VLAN_CFG >> 8) & 0x1f);
3397+
3398+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXWANPortEntry)) )
3399+ return -EFAULT;
3400+
3401+ return CAVM_OK;
3402+}
3403+
3404+int set_pvid(struct ifreq *ifr)
3405+{
3406+ CNS3XXXPVIDEntry ctl;
3407+
3408+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPVIDEntry)) )
3409+ return -EFAULT;
3410+ cns3xxx_set_pvid(ctl.which_port, ctl.pvid);
3411+
3412+ return CAVM_OK;
3413+}
3414+
3415+int get_pvid(struct ifreq *ifr)
3416+{
3417+ CNS3XXXPVIDEntry ctl;
3418+
3419+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPVIDEntry)) )
3420+ return -EFAULT;
3421+
3422+ ctl.pvid = cns3xxx_get_pvid(ctl.which_port);
3423+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPVIDEntry)) )
3424+ return -EFAULT;
3425+ return CAVM_OK;
3426+}
3427+
3428+int set_qa(struct ifreq *ifr)
3429+{
3430+ CNS3XXXQAEntry ctl;
3431+
3432+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQAEntry)) )
3433+ return -EFAULT;
3434+
3435+ MAC_GLOB_CFG_EXT_REG &= ~(0x7 << 27);
3436+ MAC_GLOB_CFG_EXT_REG |= (ctl.qa << 27);
3437+
3438+ return CAVM_OK;
3439+}
3440+
3441+int get_qa(struct ifreq *ifr)
3442+{
3443+ CNS3XXXQAEntry ctl;
3444+
3445+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXQAEntry)) )
3446+ return -EFAULT;
3447+
3448+ ctl.qa = (MAC_GLOB_CFG_EXT_REG >> 27) & 0x7;
3449+
3450+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXQAEntry)) )
3451+ return -EFAULT;
3452+ return CAVM_OK;
3453+}
3454+
3455+int get_packet_max_len(struct ifreq *ifr)
3456+{
3457+ CNS3XXXMaxLenEntry ctl;
3458+
3459+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXMaxLenEntry)) )
3460+ return -EFAULT;
3461+
3462+ ctl.max_len = (PHY_AUTO_ADDR_REG >> 30) & 0x3;
3463+
3464+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXMaxLenEntry)) )
3465+ return -EFAULT;
3466+ return CAVM_OK;
3467+}
3468+
3469+int set_packet_max_len(struct ifreq *ifr)
3470+{
3471+ CNS3XXXMaxLenEntry ctl;
3472+
3473+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXMaxLenEntry)) )
3474+ return -EFAULT;
3475+
3476+ PHY_AUTO_ADDR_REG &= (~(3 << 30));
3477+ PHY_AUTO_ADDR_REG |= (ctl.max_len << 30);
3478+
3479+ return CAVM_OK;
3480+}
3481+
3482+int set_udp_range(struct ifreq *ifr)
3483+{
3484+ CNS3XXXUdpRangeEtypeControl conf;
3485+
3486+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXUdpRangeEtypeControl)) )
3487+ return -EFAULT;
3488+
3489+ switch (conf.udp_range_num)
3490+ {
3491+ case 0:
3492+ {
3493+ UDP_RANGE0_REG = 0;
3494+ UDP_RANGE0_REG |= conf.port_start;
3495+ UDP_RANGE0_REG |= (conf.port_end << 16);
3496+ break;
3497+ }
3498+ case 1:
3499+ {
3500+ UDP_RANGE1_REG = 0;
3501+ UDP_RANGE1_REG |= conf.port_start;
3502+ UDP_RANGE1_REG |= (conf.port_end << 16);
3503+ break;
3504+ }
3505+ case 2:
3506+ {
3507+ UDP_RANGE2_REG = 0;
3508+ UDP_RANGE2_REG |= conf.port_start;
3509+ UDP_RANGE2_REG |= (conf.port_end << 16);
3510+ break;
3511+ }
3512+ case 3:
3513+ {
3514+ UDP_RANGE3_REG = 0;
3515+ UDP_RANGE3_REG |= conf.port_start;
3516+ UDP_RANGE3_REG |= (conf.port_end << 16);
3517+ break;
3518+ }
3519+ }
3520+
3521+ return CAVM_OK;
3522+}
3523+
3524+int get_udp_range(struct ifreq *ifr)
3525+{
3526+ CNS3XXXUdpRangeEtypeControl conf;
3527+
3528+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXUdpRangeEtypeControl)) )
3529+ return -EFAULT;
3530+
3531+ switch (conf.udp_range_num)
3532+ {
3533+ case 0:
3534+ {
3535+ conf.port_start = (UDP_RANGE0_REG & 0xffff);
3536+ conf.port_end = ((UDP_RANGE0_REG >> 16 )& 0xffff);
3537+ break;
3538+ }
3539+ case 1:
3540+ {
3541+ conf.port_start = (UDP_RANGE1_REG & 0xffff);
3542+ conf.port_end = ((UDP_RANGE1_REG >> 16 )& 0xffff);
3543+ break;
3544+ }
3545+ case 2:
3546+ {
3547+ conf.port_start = (UDP_RANGE2_REG & 0xffff);
3548+ conf.port_end = ((UDP_RANGE2_REG >> 16 )& 0xffff);
3549+ break;
3550+ }
3551+ case 3:
3552+ {
3553+ conf.port_start = (UDP_RANGE3_REG & 0xffff);
3554+ conf.port_end = ((UDP_RANGE3_REG >> 16 )& 0xffff);
3555+ break;
3556+ }
3557+ }
3558+
3559+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXEtypeControl)) )
3560+ return -EFAULT;
3561+
3562+ return CAVM_OK;
3563+}
3564+
3565+int get_etype(struct ifreq *ifr)
3566+{
3567+ CNS3XXXEtypeControl conf;
3568+
3569+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXEtypeControl)) )
3570+ return -EFAULT;
3571+ switch (conf.etype_num)
3572+ {
3573+ case 0:
3574+ {
3575+ conf.val = (ETYPE1_ETYPE0_REG & 0xffff);
3576+ conf.pri = (PRIO_ETYPE_UDP_REG & 0x7);
3577+ break;
3578+ }
3579+ case 1:
3580+ {
3581+ conf.val = ((ETYPE1_ETYPE0_REG >> 16 )& 0xffff);
3582+ conf.pri = ((PRIO_ETYPE_UDP_REG >> 4) & 0x7);
3583+ break;
3584+ }
3585+ case 2:
3586+ {
3587+ conf.val = (ETYPE3_ETYPE2_REG & 0xffff);
3588+ conf.pri = ((PRIO_ETYPE_UDP_REG >> 8) & 0x7);
3589+ break;
3590+ }
3591+ case 3:
3592+ {
3593+ conf.val = ((ETYPE3_ETYPE2_REG >> 16 )& 0xffff);
3594+ conf.pri = ((PRIO_ETYPE_UDP_REG >> 12) & 0x7);
3595+ break;
3596+ }
3597+ }
3598+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXEtypeControl)) )
3599+ return -EFAULT;
3600+
3601+ return CAVM_OK;
3602+}
3603+
3604+int set_etype(struct ifreq *ifr)
3605+{
3606+ CNS3XXXEtypeControl conf;
3607+
3608+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXEtypeControl)) )
3609+ return -EFAULT;
3610+ switch (conf.etype_num)
3611+ {
3612+ case 0:
3613+ {
3614+ ETYPE1_ETYPE0_REG &= (~0xffff);
3615+ ETYPE1_ETYPE0_REG |= conf.val;
3616+
3617+ PRIO_ETYPE_UDP_REG &= (~7);
3618+ PRIO_ETYPE_UDP_REG |= (conf.pri);
3619+ break;
3620+ }
3621+ case 1:
3622+ {
3623+ ETYPE1_ETYPE0_REG &= (~(0xffff << 16));
3624+ ETYPE1_ETYPE0_REG |= (conf.val << 16);
3625+
3626+ PRIO_ETYPE_UDP_REG &= (~(7 << 4));
3627+ PRIO_ETYPE_UDP_REG |= (conf.pri << 4);
3628+ break;
3629+ }
3630+ case 2:
3631+ {
3632+ ETYPE3_ETYPE2_REG &= (~0xffff);
3633+ ETYPE3_ETYPE2_REG |= conf.val;
3634+
3635+ PRIO_ETYPE_UDP_REG &= (~(7 << 8));
3636+ PRIO_ETYPE_UDP_REG |= (conf.pri << 8);
3637+ break;
3638+ }
3639+ case 3:
3640+ {
3641+ ETYPE3_ETYPE2_REG &= (~(0xffff << 16));
3642+ ETYPE3_ETYPE2_REG |= (conf.val << 16);
3643+
3644+ PRIO_ETYPE_UDP_REG &= (~(7 << 12));
3645+ PRIO_ETYPE_UDP_REG |= (conf.pri << 12);
3646+ break;
3647+ }
3648+ }
3649+ return CAVM_OK;
3650+}
3651+
3652+int get_pri_ip_dscp(struct ifreq *ifr)
3653+{
3654+ CNS3XXXPriIpDscpControl conf;
3655+
3656+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXPriIpDscpControl)) )
3657+ return -EFAULT;
3658+
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);
3675+ } else {
3676+ return CAVM_ERR;
3677+ }
3678+
3679+
3680+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXPriIpDscpControl)) )
3681+ return -EFAULT;
3682+ return CAVM_OK;
3683+}
3684+
3685+
3686+int set_pri_ip_dscp(struct ifreq *ifr)
3687+{
3688+ CNS3XXXPriIpDscpControl conf;
3689+
3690+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXPriIpDscpControl)) )
3691+ return -EFAULT;
3692+
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));
3702+
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));
3706+
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));
3710+
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));
3720+ } else {
3721+ return CAVM_ERR;
3722+ }
3723+ return CAVM_OK;
3724+}
3725+
3726+
3727+int bcm53115M_reg_read_ioctl(struct ifreq *ifr)
3728+{
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);
3732+
3733+
3734+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXBCM53115M)) )
3735+ return -EFAULT;
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)
3740+ {
3741+ case 1:
3742+ {
3743+ bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u8_val, 1);
3744+ printk("conf.u8_val: %x\n", conf.u8_val);
3745+ break;
3746+ }
3747+ case 2:
3748+ {
3749+ bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u16_val, 2);
3750+ printk("conf.u16_val: %x\n", conf.u16_val);
3751+ break;
3752+ }
3753+ case 4:
3754+ {
3755+ bcm53115M_reg_read(conf.page, conf.offset, (u8 *)&conf.u32_val, 4);
3756+ printk("conf.u32_val: %x\n", conf.u32_val);
3757+ break;
3758+ }
3759+ default:
3760+ {
3761+ printk("[kernel mode]: don't support date length: %d\n", conf.data_len);
3762+ }
3763+ }
3764+
3765+
3766+
3767+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXBCM53115M)) )
3768+ return -EFAULT;
3769+ return CAVM_OK;
3770+}
3771+
3772+int bcm53115M_reg_write_ioctl(struct ifreq *ifr)
3773+{
3774+ int bcm53115M_reg_write(int page, int offset, u8 *buf, int len);
3775+ CNS3XXXBCM53115M conf;
3776+
3777+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXBCM53115M)) )
3778+ return -EFAULT;
3779+
3780+ switch (conf.data_len)
3781+ {
3782+ case 1:
3783+ {
3784+ bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u8_val, 1);
3785+ break;
3786+ }
3787+ case 2:
3788+ {
3789+ bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u16_val, 2);
3790+ break;
3791+ }
3792+ case 4:
3793+ {
3794+ bcm53115M_reg_write(conf.page, conf.offset, (u8 *)&conf.u32_val, 4);
3795+ break;
3796+ }
3797+ default:
3798+ {
3799+ printk("[kernel mode]: don't support date length: %d\n", conf.data_len);
3800+ }
3801+ }
3802+ return CAVM_OK;
3803+}
3804+
3805+#if 0
3806+int get_rxring(struct ifreq *ifr)
3807+{
3808+ CNS3XXXRingStatus conf;
3809+
3810+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXRingStatus)) )
3811+ return -EFAULT;
3812+ conf.rx_ring=g_ring_info.rx_ring;
3813+ conf.tx_ring=0;
3814+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXRingStatus)) )
3815+ return -EFAULT;
3816+}
3817+#endif
3818+
3819+int dump_mib_counter(struct ifreq *ifr)
3820+{
3821+ CNS3XXXMIBCounter conf;
3822+ int addr=0,i=0;
3823+
3824+ if (copy_from_user(&conf, ifr->ifr_data, sizeof(CNS3XXXMIBCounter)) )
3825+ return -EFAULT;
3826+
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);
3836+ conf.mib_len=i;
3837+ if (copy_to_user(ifr->ifr_data, &conf, sizeof(CNS3XXXMIBCounter)) )
3838+ return -EFAULT;
3839+ return 0;
3840+}
3841+
3842+// reference e100.c
3843+int cns3xxx_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
3844+{
3845+ CNS3XXXIoctlCmd ioctl_cmd;
3846+
3847+ //printk("cns3xxx_do_ioctl begin\n");
3848+
3849+ if (cmd != SIOCDEVPRIVATE) {
3850+ return -EOPNOTSUPP;
3851+ }
3852+ if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(CNS3XXXIoctlCmd)))
3853+ return -EFAULT;
3854+
3855+ //printk("ioctl_cmd: %d\n", ioctl_cmd);
3856+ switch (ioctl_cmd) {
3857+ case CNS3XXX_ARP_REQUEST_SET:
3858+ {
3859+ CNS3XXXArpRequestControl ctl;
3860+
3861+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXArpRequestControl)) )
3862+ return -EFAULT;
3863+
3864+ (ctl.val==0) ? (MAC_GLOB_CFG_REG &= (~(1 << 23)) ): (MAC_GLOB_CFG_REG |= (1 << 23) );
3865+
3866+ }
3867+
3868+ case CNS3XXX_ARP_REQUEST_GET:
3869+ {
3870+ CNS3XXXArpRequestControl ctl;
3871+
3872+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXArpRequestControl)) )
3873+ return -EFAULT;
3874+
3875+ ctl.val = ((MAC_GLOB_CFG_REG >> 23) & 1);
3876+
3877+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXArpRequestControl)) )
3878+ return -EFAULT;
3879+ return CAVM_OK;
3880+ }
3881+
3882+ case CNS3XXX_HOL_PREVENT_SET:
3883+ {
3884+ CNS3XXXHOLPreventControl ctl;
3885+
3886+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXHOLPreventControl)) )
3887+ return -EFAULT;
3888+ (ctl.enable == 1) ? (TC_CTRL_REG |= (1 << 29)) : (TC_CTRL_REG &= (~(1 << 29))) ;
3889+
3890+ return CAVM_OK;
3891+ }
3892+ case CNS3XXX_HOL_PREVENT_GET:
3893+ {
3894+ CNS3XXXHOLPreventControl ctl;
3895+
3896+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXHOLPreventControl)) )
3897+ return -EFAULT;
3898+
3899+ ctl.enable = ((TC_CTRL_REG >> 29) & 0x1);
3900+
3901+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXHOLPreventControl)) )
3902+ return -EFAULT;
3903+ return CAVM_OK;
3904+ }
3905+
3906+ // for S component or C conponent
3907+ case CNS3XXX_BRIDGE_SET:
3908+ {
3909+ CNS3XXXBridgeControl ctl;
3910+
3911+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXBridgeControl)) )
3912+ return -EFAULT;
3913+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 1)) : (VLAN_CFG &= (~(1 << 1))) ;
3914+
3915+
3916+ }
3917+ case CNS3XXX_BRIDGE_GET:
3918+ {
3919+ CNS3XXXBridgeControl ctl;
3920+
3921+ ctl.type = ((VLAN_CFG >> 1) & 0x1);
3922+ printk("[kernel mode] ctl.type: %d\n", ctl.type);
3923+
3924+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXBridgeControl)) )
3925+ return -EFAULT;
3926+
3927+ return CAVM_OK;
3928+ }
3929+
3930+ case CNS3XXX_PORT_NEIGHBOR_SET:
3931+ {
3932+ CNS3XXXPortNeighborControl ctl;
3933+
3934+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPortNeighborControl)) )
3935+ return -EFAULT;
3936+ switch (ctl.which_port)
3937+ {
3938+ case 0:
3939+ {
3940+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 4)) : (VLAN_CFG &= (~(1 << 4))) ;
3941+ return 0;
3942+ }
3943+ case 1:
3944+ {
3945+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 5)) : (VLAN_CFG &= (~(1 << 5))) ;
3946+ return 0;
3947+ }
3948+ case 2:
3949+ {
3950+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 7)) : (VLAN_CFG &= (~(1 << 7))) ;
3951+ return 0;
3952+ }
3953+ case 3: // cpu port
3954+ {
3955+ (ctl.type == 1) ? (VLAN_CFG |= (1 << 6)) : (VLAN_CFG &= (~(1 << 6))) ;
3956+ return 0;
3957+ }
3958+ default:
3959+ return -EFAULT;
3960+ }
3961+
3962+ }
3963+
3964+ case CNS3XXX_PORT_NEIGHBOR_GET:
3965+ {
3966+ CNS3XXXPortNeighborControl ctl;
3967+
3968+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPortNeighborControl)) )
3969+ return -EFAULT;
3970+ switch (ctl.which_port)
3971+ {
3972+ case 0:
3973+ {
3974+ ctl.type = ((VLAN_CFG >> 4 ) & 0x1);
3975+ break;
3976+ }
3977+ case 1:
3978+ {
3979+ ctl.type = ((VLAN_CFG >> 5 ) & 0x1);
3980+ break;
3981+ }
3982+ case 2:
3983+ {
3984+ ctl.type = ((VLAN_CFG >> 7 ) & 0x1);
3985+ break;
3986+ }
3987+ case 3: // cpu port
3988+ {
3989+ ctl.type = ((VLAN_CFG >> 6 ) & 0x1);
3990+ break;
3991+ }
3992+ }
3993+
3994+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPortNeighborControl)) )
3995+ return -EFAULT;
3996+
3997+ return CAVM_OK;
3998+ }
3999+
4000+ case CNS3XXX_VLAN_TABLE_LOOKUP:
4001+ {
4002+ CNS3XXXVLANTableEntry ctl;
4003+
4004+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) )
4005+ return -EFAULT;
4006+ if (cns3xxx_vlan_table_lookup(&ctl.entry) == CAVM_NOT_FOUND) {
4007+ return CAVM_NOT_FOUND;
4008+ }
4009+
4010+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry)))
4011+ return -EFAULT;
4012+
4013+ return CAVM_FOUND;
4014+ }
4015+ case CNS3XXX_VLAN_TABLE_READ:
4016+ {
4017+ CNS3XXXVLANTableEntry ctl;
4018+
4019+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) )
4020+ {
4021+ return -EFAULT;
4022+ }
4023+ cns3xxx_vlan_table_read(&ctl.entry);
4024+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry)))
4025+ return -EFAULT;
4026+
4027+ return 0;
4028+ }
4029+ case CNS3XXX_VLAN_TABLE_ADD:
4030+ {
4031+ CNS3XXXVLANTableEntry ctl;
4032+
4033+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXVLANTableEntry)) )
4034+ return -EFAULT;
4035+ cns3xxx_vlan_table_add(&ctl.entry);
4036+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXVLANTableEntry)))
4037+ return -EFAULT;
4038+
4039+ return 0;
4040+ }
4041+
4042+ case CNS3XXX_ARL_TABLE_ADD:
4043+ {
4044+ CNS3XXXARLTableEntry ctl;
4045+
4046+ printk("[kernel mode] CNS3XXX_ARL_TABLE_ADD\n");
4047+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4048+ return -EFAULT;
4049+ cns3xxx_arl_table_add(&ctl.entry);
4050+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4051+ return -EFAULT;
4052+
4053+ return 0;
4054+ }
4055+
4056+
4057+ case CNS3XXX_ARL_TABLE_DEL:
4058+ {
4059+ CNS3XXXARLTableEntry ctl;
4060+
4061+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4062+ return -EFAULT;
4063+ cns3xxx_arl_table_invalid(&ctl.entry);
4064+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4065+ return -EFAULT;
4066+
4067+ return 0;
4068+ }
4069+ case CNS3XXX_VLAN_TABLE_DEL:
4070+ {
4071+ CNS3XXXARLTableEntry ctl;
4072+
4073+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4074+ return -EFAULT;
4075+ cns3xxx_arl_table_invalid(&ctl.entry);
4076+
4077+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4078+ return -EFAULT;
4079+
4080+ return CAVM_FOUND;
4081+ }
4082+
4083+ case CNS3XXX_ARL_TABLE_SEARCH:
4084+ {
4085+ CNS3XXXARLTableEntry ctl;
4086+
4087+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4088+ return -EFAULT;
4089+ if (cns3xxx_arl_table_search(&ctl.entry) == CAVM_NOT_FOUND){
4090+ printk("[kernel mode] not found\n");
4091+ return CAVM_NOT_FOUND;
4092+ }
4093+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4094+ return -EFAULT;
4095+
4096+ return CAVM_FOUND;
4097+ }
4098+ case CNS3XXX_ARL_IS_TABLE_END:
4099+ {
4100+ CNS3XXXARLTableEntry ctl;
4101+
4102+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4103+ return -EFAULT;
4104+ if (cns3xxx_is_arl_table_end() == CAVM_ERR)
4105+ return CAVM_ERR;
4106+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4107+ return -EFAULT;
4108+
4109+ return CAVM_OK;
4110+ }
4111+
4112+ case CNS3XXX_ARL_TABLE_SEARCH_AGAIN:
4113+ {
4114+ CNS3XXXARLTableEntry ctl;
4115+
4116+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4117+ return -EFAULT;
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)))
4121+ return -EFAULT;
4122+
4123+ return CAVM_FOUND;
4124+ }
4125+
4126+ case CNS3XXX_ARL_TABLE_FLUSH:
4127+ {
4128+ CNS3XXXARLTableEntry ctl;
4129+
4130+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4131+ return -EFAULT;
4132+
4133+ cns3xxx_arl_table_flush();
4134+
4135+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXARLTableEntry)))
4136+ return -EFAULT;
4137+
4138+ return CAVM_FOUND;
4139+ }
4140+
4141+
4142+
4143+ case CNS3XXX_ARL_TABLE_LOOKUP:
4144+ {
4145+ CNS3XXXARLTableEntry ctl;
4146+
4147+
4148+ printk("[kernel mode] in CNS3XXX_ARL_TABLE_LOOKUP\n");
4149+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXARLTableEntry)) )
4150+ return -EFAULT;
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)))
4154+ return -EFAULT;
4155+
4156+ return CAVM_FOUND;
4157+ }
4158+
4159+ case CNS3XXX_TC_SET:
4160+ {
4161+ CNS3XXXTrafficClassControl ctl;
4162+
4163+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXTrafficClassControl)) )
4164+ return -EFAULT;
4165+ TC_CTRL_REG &= (~(0x3 << 30));
4166+ TC_CTRL_REG |= (ctl.tc << 30);
4167+ return CAVM_OK;
4168+ }
4169+ case CNS3XXX_TC_GET:
4170+ {
4171+ CNS3XXXTrafficClassControl ctl;
4172+
4173+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXTrafficClassControl)) )
4174+ return -EFAULT;
4175+
4176+ ctl.tc = ((TC_CTRL_REG >> 30) & 0x3);
4177+
4178+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXTrafficClassControl)) )
4179+ return -EFAULT;
4180+
4181+ return CAVM_OK;
4182+ }
4183+
4184+ case CNS3XXX_PRI_CTRL_SET:
4185+ {
4186+ CNS3XXXPriCtrlControl ctl;
4187+
4188+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPriCtrlControl)) )
4189+ return -EFAULT;
4190+
4191+ switch (ctl.which_port)
4192+ {
4193+ case 0:
4194+ {
4195+ MAC0_PRI_CTRL_REG &= (~(0x7 << 24));
4196+ MAC0_PRI_CTRL_REG &= (~(0xf << 18));
4197+
4198+ MAC0_PRI_CTRL_REG |= (ctl.port_pri << 24);
4199+
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);
4204+ break;
4205+ }
4206+ case 1:
4207+ {
4208+ MAC1_PRI_CTRL_REG &= (~(0x7 << 24));
4209+ MAC1_PRI_CTRL_REG &= (~(0xf << 18));
4210+
4211+ MAC1_PRI_CTRL_REG |= (ctl.port_pri << 24);
4212+
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);
4217+ break;
4218+ }
4219+ case 2:
4220+ {
4221+ MAC2_PRI_CTRL_REG &= (~(0x7 << 24));
4222+ MAC2_PRI_CTRL_REG &= (~(0xf << 18));
4223+
4224+ MAC2_PRI_CTRL_REG |= (ctl.port_pri << 24);
4225+
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);
4230+ break;
4231+ }
4232+ case 3: // cpu
4233+ {
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));
4237+
4238+ CPU_PRI_CTRL_REG |= (ctl.port_pri << 24);
4239+
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);
4244+ break;
4245+ }
4246+ }
4247+
4248+ return CAVM_OK;
4249+ }
4250+
4251+ case CNS3XXX_PRI_CTRL_GET:
4252+ {
4253+ CNS3XXXPriCtrlControl ctl;
4254+
4255+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXPriCtrlControl)) )
4256+ return -EFAULT;
4257+
4258+
4259+ if (copy_to_user(ifr->ifr_data, &ctl, sizeof(CNS3XXXPriCtrlControl)) )
4260+ return -EFAULT;
4261+
4262+ return CAVM_OK;
4263+ }
4264+
4265+ case CNS3XXX_DMA_RING_CTRL_SET:
4266+ {
4267+ CNS3XXXDmaRingCtrlControl ctl;
4268+
4269+ if (copy_from_user(&ctl, ifr->ifr_data, sizeof(CNS3XXXDmaRingCtrlControl)) )
4270+ return -EFAULT;
4271+
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));
4275+ }
4276+
4277+ case CNS3XXX_PRI_IP_DSCP_SET:
4278+ {
4279+ return set_pri_ip_dscp(ifr);
4280+ }
4281+ case CNS3XXX_PRI_IP_DSCP_GET:
4282+ {
4283+ return get_pri_ip_dscp(ifr);
4284+ }
4285+
4286+ case CNS3XXX_ETYPE_SET:
4287+ {
4288+ return set_etype(ifr);
4289+ }
4290+ case CNS3XXX_ETYPE_GET:
4291+ {
4292+ return get_etype(ifr);
4293+ }
4294+
4295+ case CNS3XXX_UDP_RANGE_SET:
4296+ {
4297+ return set_udp_range(ifr);
4298+ }
4299+ case CNS3XXX_UDP_RANGE_GET:
4300+ {
4301+ return get_udp_range(ifr);
4302+ }
4303+
4304+ case CNS3XXX_RATE_LIMIT_SET:
4305+ {
4306+ return set_rate_limit(ifr);
4307+ }
4308+ case CNS3XXX_RATE_LIMIT_GET:
4309+ {
4310+ return get_rate_limit(ifr);
4311+ }
4312+ case CNS3XXX_QUEUE_WEIGHT_SET:
4313+ {
4314+ return set_queue_weight(ifr);
4315+ }
4316+ case CNS3XXX_QUEUE_WEIGHT_GET:
4317+ {
4318+ return get_queue_weight(ifr);
4319+ }
4320+
4321+ case CNS3XXX_FC_RLS_SET:
4322+ {
4323+ return set_fc_rls(ifr);
4324+ }
4325+ case CNS3XXX_FC_RLS_GET:
4326+ {
4327+ return get_fc_rls(ifr);
4328+ }
4329+
4330+ case CNS3XXX_FC_SET_SET:
4331+ {
4332+ return set_fc_set(ifr);
4333+ }
4334+ case CNS3XXX_FC_SET_GET:
4335+ {
4336+ return get_fc_set(ifr);
4337+ }
4338+
4339+ case CNS3XXX_SARL_RLS_SET:
4340+ {
4341+ return set_sarl_rls(ifr);
4342+ }
4343+ case CNS3XXX_SARL_RLS_GET:
4344+ {
4345+ return get_sarl_rls(ifr);
4346+ }
4347+
4348+ case CNS3XXX_SARL_SET_SET:
4349+ {
4350+ return set_sarl_set(ifr);
4351+ }
4352+ case CNS3XXX_SARL_SET_GET:
4353+ {
4354+ return get_sarl_set(ifr);
4355+ }
4356+
4357+ case CNS3XXX_SARL_OQ_SET:
4358+ {
4359+ return set_sarl_oq(ifr);
4360+ }
4361+ case CNS3XXX_SARL_OQ_GET:
4362+ {
4363+ return get_sarl_oq(ifr);
4364+ }
4365+
4366+ case CNS3XXX_SARL_ENABLE_SET:
4367+ {
4368+ return set_sarl_enable(ifr);
4369+ }
4370+ case CNS3XXX_SARL_ENABLE_GET:
4371+ {
4372+ return get_sarl_enable(ifr);
4373+ }
4374+
4375+ case CNS3XXX_FC_SET:
4376+ {
4377+ return set_fc(ifr);
4378+ }
4379+ case CNS3XXX_FC_GET:
4380+ {
4381+ return get_fc(ifr);
4382+ }
4383+
4384+ case CNS3XXX_IVL_SET:
4385+ {
4386+ return set_ivl(ifr);
4387+ }
4388+ case CNS3XXX_IVL_GET:
4389+ {
4390+ return get_ivl(ifr);
4391+ }
4392+
4393+ case CNS3XXX_WAN_PORT_SET:
4394+ {
4395+ return set_wan_port(ifr);
4396+ }
4397+ case CNS3XXX_WAN_PORT_GET:
4398+ {
4399+ return get_wan_port(ifr);
4400+ }
4401+
4402+ case CNS3XXX_PVID_SET:
4403+ {
4404+ return set_pvid(ifr);
4405+ }
4406+ case CNS3XXX_PVID_GET:
4407+ {
4408+ return get_pvid(ifr);
4409+ }
4410+
4411+ case CNS3XXX_QA_GET:
4412+ {
4413+ return get_qa(ifr);
4414+ }
4415+ case CNS3XXX_QA_SET:
4416+ {
4417+ return set_qa(ifr);
4418+ }
4419+
4420+ case CNS3XXX_PACKET_MAX_LEN_GET:
4421+ {
4422+ return get_packet_max_len(ifr);
4423+ }
4424+ case CNS3XXX_PACKET_MAX_LEN_SET:
4425+ {
4426+ return set_packet_max_len(ifr);
4427+ }
4428+
4429+ case CNS3XXX_BCM53115M_REG_READ:
4430+ {
4431+ return bcm53115M_reg_read_ioctl(ifr);
4432+ }
4433+ case CNS3XXX_BCM53115M_REG_WRITE:
4434+ {
4435+ return bcm53115M_reg_write_ioctl(ifr);
4436+ }
4437+
4438+#if 0
4439+ case CNS3XXX_RXRING_STATUS:
4440+ {
4441+ return get_rxring(ifr);
4442+ }
4443+#endif
4444+ case CNS3XXX_DUMP_MIB_COUNTER:
4445+ {
4446+ return dump_mib_counter(ifr);
4447+ }
4448+
4449+
4450+ default:
4451+ {
4452+ printk("[kernel mode] don't match any command\n");
4453+ break;
4454+ }
4455+
4456+ } // end switch (ioctl_cmd)
4457+ return 0;
4458+}
4459+
4460+#ifdef CONFIG_CNS3XXX_NAPI
4461+static int cns3xxx_poll(struct napi_struct *napi, int budget)
4462+{
4463+
4464+ CNS3XXXPrivate *sp = container_of(napi, CNS3XXXPrivate, napi);
4465+ int work_done = 0;
4466+ int work_to_do = budget; // define minima value
4467+
4468+ cns3xxx_receive_packet(sp, 0, &work_done, work_to_do);
4469+
4470+ budget -= work_done;
4471+
4472+ if (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);
4476+ return 1;
4477+ }
4478+ } else {
4479+ //netif_rx_complete(napi_dev, &sp->napi);
4480+ napi_complete(napi);
4481+#ifdef CNS3XXX_USE_MASK
4482+ cns3xxx_write_pri_mask(0xf0);
4483+#else
4484+ if (sp->ring_index == 0)
4485+ cns3xxx_enable_irq(FSRC_RING0_INTERRUPT_ID);
4486+ else
4487+ cns3xxx_enable_irq(FSRC_RING1_INTERRUPT_ID);
4488+#endif
4489+ return 0;
4490+ }
4491+
4492+ return 1;
4493+}
4494+#endif
4495+
4496+static struct net_device_stats *cns3xxx_get_stats(struct net_device *dev)
4497+{
4498+ CNS3XXXPrivate *priv = netdev_priv(dev);
4499+
4500+ return &priv->stats;
4501+}
4502+
4503+static int cns3xxx_change_mtu(struct net_device *dev, int new_mtu)
4504+{
4505+ if (new_mtu < cns3xxx_min_mtu() || new_mtu > cns3xxx_max_mtu())
4506+ return -EINVAL;
4507+
4508+ dev->mtu = new_mtu;
4509+
4510+ return 0;
4511+}
4512+
4513+static void cns3xxx_timeout(struct net_device *dev)
4514+{
4515+ //star_gsw_enable(dev);
4516+ netif_wake_queue(dev);
4517+ dev->trans_start = jiffies;
4518+}
4519+
4520+#ifdef LINUX2631
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,
4532+
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,
4537+#endif
4538+
4539+#ifdef CONFIG_NET_POLL_CONTROLLER
4540+ .ndo_poll_controller = cns3xxx_netpoll,
4541+#endif
4542+};
4543+#endif // LINUX2631
4544+
4545+static int __init cns3xxx_probe(RingInfo ring_info)
4546+{
4547+ void cns3xxx_set_ethtool_ops(struct net_device *netdev);
4548+
4549+ int netdev_size = sizeof(net_device_prive)/sizeof(NetDevicePriv);
4550+ int i=0, err=0;
4551+ struct net_device *netdev=0;
4552+ CNS3XXXPrivate *priv=0;
4553+ struct sockaddr sock_addr;
4554+
4555+ for (i=0 ; i < netdev_size ; ++i) {
4556+ if (init_port & (1 << i)) {
4557+
4558+ netdev = alloc_etherdev(sizeof(CNS3XXXPrivate));
4559+ if (!netdev) {
4560+ err = -ENOMEM;
4561+ goto err_alloc_etherdev;
4562+ }
4563+ if (net_device_prive[i].name)
4564+ strcpy(netdev->name, net_device_prive[i].name);
4565+
4566+
4567+ net_dev_array[net_device_prive[i].vlan_tag] = netdev;
4568+ if (intr_netdev==0)
4569+ intr_netdev = netdev;
4570+
4571+ SET_NETDEV_DEV(netdev, NULL);
4572+ priv = netdev_priv(netdev);
4573+ spin_lock_init(&priv->lock);
4574+ memset(priv, 0, sizeof(CNS3XXXPrivate));
4575+
4576+#if 1
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;
4581+#endif
4582+
4583+ priv->net_device_priv = &net_device_prive[i];
4584+
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);
4588+
4589+#ifdef LINUX2631
4590+ netdev->netdev_ops = &cns3xxx_netdev_ops;
4591+#endif
4592+
4593+ cns3xxx_set_ethtool_ops(netdev);
4594+#ifdef LINUX2627
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;
4603+
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;
4608+#endif
4609+
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);
4613+#endif
4614+
4615+
4616+#ifdef CONFIG_CNS3XXX_NAPI
4617+ //netif_napi_add(netdev, &priv->napi, cns3xxx_poll, CNS3XXX_NAPI_WEIGHT);
4618+#endif
4619+
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;
4628+#else
4629+ netdev->features |= NETIF_F_HW_VLAN_RX; // remove NETIF_F_HW_VLAN_TX flag that 8021Q module to insert vlan tag.
4630+#endif
4631+
4632+ //netdev->vlan_rx_register = cns3xxx_vlan_rx_register;
4633+ //netdev->vlan_rx_kill_vid = cns3xxx_vlan_rx_kill_vid;
4634+#endif
4635+
4636+
4637+ err = register_netdev(netdev);
4638+ if (err) {
4639+ goto err_register_netdev;
4640+ }
4641+
4642+ netif_carrier_off(netdev);
4643+ netdev = 0;
4644+ }
4645+ } // for (i=0 ; i < netdev_size ; ++i)
4646+
4647+ return 0;
4648+
4649+
4650+err_register_netdev:
4651+ free_netdev(netdev);
4652+
4653+err_alloc_etherdev:
4654+ return err;
4655+}
4656+
4657+int cns3xxx_gsw_config_mac_port0(void)
4658+{
4659+ INIT_PORT0_PHY
4660+ INIT_PORT0_MAC
4661+ PORT0_LINK_DOWN
4662+ return 0;
4663+}
4664+
4665+int cns3xxx_gsw_config_mac_port1(void)
4666+{
4667+ INIT_PORT1_PHY
4668+ INIT_PORT1_MAC
4669+ PORT1_LINK_DOWN
4670+ return 0;
4671+}
4672+
4673+int cns3xxx_gsw_config_mac_port2(void)
4674+{
4675+ INIT_PORT2_PHY
4676+ INIT_PORT2_MAC
4677+ PORT2_LINK_DOWN
4678+ return 0;
4679+}
4680+
4681+static int cns3xxx_notify_reboot(struct notifier_block *nb, unsigned long event, void *ptr)
4682+{
4683+ // stop the DMA
4684+ enable_rx_dma(0, 0);
4685+ enable_tx_dma(0, 0);
4686+ enable_rx_dma(1, 0);
4687+ enable_tx_dma(1, 0);
4688+
4689+ // disable Port 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;
4695+}
4696+
4697+#ifdef CONFIG_CNS3XXX_NAPI
4698+static struct net_device *init_napi_dev(struct net_device *ndev, const RingInfo *ring_info)
4699+{
4700+ CNS3XXXPrivate *priv;
4701+
4702+ ndev = alloc_etherdev(sizeof(CNS3XXXPrivate));
4703+ if (!ndev) {
4704+ BUG();
4705+ }
4706+ priv = netdev_priv(ndev);
4707+ memset(priv, 0, sizeof(CNS3XXXPrivate));
4708+
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
4715+
4716+ netif_napi_add(ndev, &priv->napi , cns3xxx_poll, CNS3XXX_NAPI_WEIGHT);
4717+ dev_hold(ndev);
4718+ set_bit(__LINK_STATE_START, &ndev->state);
4719+
4720+ return ndev;
4721+}
4722+#endif
4723+
4724+
4725+void cns3xxx_config_intr(void)
4726+{
4727+ u32 v=0xffffffff;
4728+
4729+ get_interrupt_type(FSRC_RING0_INTERRUPT_ID, &v);
4730+#if 1
4731+ set_interrupt_type(FSRC_RING0_INTERRUPT_ID, RISING_EDGE);
4732+ get_interrupt_type(FSRC_RING0_INTERRUPT_ID, &v);
4733+
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);
4737+
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);
4741+
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);
4745+
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);
4750+
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);
4754+
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);
4758+
4759+ #ifndef CONFIG_CNS3XXX_NAPI
4760+ set_interrupt_pri(FSQF_RING0_INTERRUPT_ID, 0xc);
4761+ #endif
4762+
4763+
4764+ #endif // CNS3XXX_USE_MASK
4765+#endif
4766+}
4767+
4768+static int __devinit cns3xxx_init(struct platform_device *pdev)
4769+{
4770+ // when tx_ring/rx_ring alloc memory,
4771+ // don't free them until cns3xxx_exit_module
4772+
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);
4778+#endif
4779+
4780+ RingInfo ring_info;
4781+ int i=0;
4782+ //spin_lock_init(&star_gsw_send_lock);
4783+
4784+
4785+#ifdef CNS3XXX_DOUBLE_RX_RING
4786+ ring_info.num_rx_queues = 2;
4787+#else
4788+ ring_info.num_rx_queues = 1;
4789+#endif
4790+
4791+#ifdef CNS3XXX_DOUBLE_TX_RING
4792+ ring_info.num_tx_queues = 2;
4793+#else
4794+ ring_info.num_tx_queues = 1;
4795+#endif
4796+
4797+ ring_info.rx_ring = kcalloc(ring_info.num_rx_queues, sizeof(RXRing), GFP_KERNEL);
4798+ if (!ring_info.rx_ring)
4799+ return -ENOMEM;
4800+
4801+ for (i=0 ; i < ring_info.num_rx_queues ; ++i) {
4802+ memset(ring_info.rx_ring + i, 0, sizeof(RXRing));
4803+ }
4804+
4805+
4806+ ring_info.tx_ring = kcalloc(ring_info.num_tx_queues, sizeof(TXRing), GFP_KERNEL);
4807+
4808+
4809+ if (!ring_info.tx_ring)
4810+ return -ENOMEM;
4811+
4812+ for (i=0 ; i < ring_info.num_tx_queues ; ++i) {
4813+ memset(ring_info.tx_ring + i, 0, sizeof(TXRing));
4814+ }
4815+
4816+
4817+ g_ring_info = ring_info;
4818+
4819+ cns3xxx_gsw_hw_init();
4820+
4821+#ifdef CONFIG_FPGA
4822+ // GIGA mode disable
4823+ MAC0_CFG_REG &= (~(1<<16));
4824+ MAC1_CFG_REG &= (~(1<<16));
4825+ MAC2_CFG_REG &= (~(1<<16));
4826+#endif
4827+
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();
4833+ }
4834+
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();
4840+ }
4841+
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();
4847+ }
4848+
4849+ cns3xxx_probe(ring_info);
4850+ cns3xxx_config_intr();
4851+
4852+#ifdef CNS3XXX_VLAN_8021Q
4853+#ifdef CNS3XXX_NIC_MODE_8021Q
4854+ cns3xxx_nic_mode(1);
4855+#endif
4856+#endif
4857+ spin_lock_init(&tx_lock);
4858+ spin_lock_init(&rx_lock);
4859+
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);
4864+ #endif
4865+#endif
4866+
4867+ register_reboot_notifier(&cns3xxx_notifier_reboot);
4868+ clear_fs_dma_state(0);
4869+
4870+ if (ring_info.num_rx_queues == 2) {
4871+ // enable RX dobule ring
4872+ DMA_RING_CTRL_REG |= 1;
4873+ }
4874+
4875+ if (ring_info.num_tx_queues == 2 ) {
4876+ // enable TX dobule ring
4877+ DMA_RING_CTRL_REG |= (1 << 16);
4878+ }
4879+
4880+
4881+ return 0;
4882+}
4883+
4884+static int __devexit cns3xxx_remove(struct platform_device *pdev)
4885+{
4886+ int i=0;
4887+
4888+#if 1
4889+ for (i=0 ; i < NETDEV_SIZE ; ++i) {
4890+ CNS3XXXPrivate *priv = 0;
4891+
4892+ if (net_dev_array[i]){
4893+ priv = netdev_priv(net_dev_array[i]);
4894+
4895+ kfree(priv->tx_ring);
4896+ priv->tx_ring = 0;
4897+
4898+ kfree(priv->rx_ring);
4899+ priv->rx_ring = 0;
4900+
4901+ unregister_netdev(net_dev_array[i]);
4902+ free_netdev(net_dev_array[i]);
4903+ }
4904+
4905+
4906+#if 0
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.
4911+ #if 1
4912+ if (netdev) {
4913+ unregister_netdev(netdev);
4914+ free_netdev(netdev);
4915+ }
4916+#endif
4917+ #endif
4918+ }
4919+#endif
4920+
4921+#ifdef CONFIG_CNS3XXX_NAPI
4922+ free_netdev(napi_dev);
4923+ #ifdef CNS3XXX_DOUBLE_RX_RING
4924+ free_netdev(r1_napi_dev);
4925+ #endif
4926+#endif
4927+
4928+
4929+#if 0
4930+ //star_gsw_buffer_free();
4931+#endif
4932+ unregister_reboot_notifier(&cns3xxx_notifier_reboot);
4933+}
4934+
4935+
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)
4939+{
4940+ CNS3XXXPrivate *priv = netdev_priv(dev);
4941+ unsigned long flags;
4942+
4943+ spin_lock_irqsave(&priv->lock, flags);
4944+ priv->vlgrp = grp;
4945+ spin_unlock_irqrestore(&priv->lock, flags);
4946+}
4947+
4948+void cns3xxx_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
4949+{
4950+ CNS3XXXPrivate *priv = netdev_priv(dev);
4951+ unsigned long flags;
4952+
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);
4958+}
4959+
4960+#endif
4961+
4962+static struct platform_driver drv = {
4963+ .driver.name = "cns3xxx-net",
4964+ .probe = cns3xxx_init,
4965+ .remove = cns3xxx_remove,
4966+};
4967+
4968+static int __init cns3xxx_init_module(void)
4969+{
4970+ return platform_driver_register(&drv);
4971+}
4972+
4973+static void __exit cns3xxx_exit_module(void)
4974+{
4975+ platform_driver_unregister(&drv);
4976+}
4977+
4978+MODULE_AUTHOR("Cavium Networks, <tech@XXXX.com>");
4979+MODULE_DESCRIPTION("CNS3XXX Switch Driver");
4980+MODULE_LICENSE("GPL");
4981+MODULE_VERSION(DRV_VERSION);
4982+
4983+module_init(cns3xxx_init_module);
4984+module_exit(cns3xxx_exit_module);
4985+
4986--- /dev/null
4987+++ b/drivers/net/cns3xxx/cns3xxx_phy.c
4988@@ -0,0 +1,1968 @@
4989+/*******************************************************************************
4990+ *
4991+ *
4992+ * Copyright (c) 2009 Cavium Networks
4993+ *
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.
4998+ *
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
5002+ * more details.
5003+ *
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.
5007+ *
5008+ * The full GNU General Public License is included in this distribution in the
5009+ * file called LICENSE.
5010+ *
5011+ ********************************************************************************/
5012+
5013+#include "cns3xxx_phy.h"
5014+#include "cns3xxx_symbol.h"
5015+
5016+
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"
5022+#else // u-boot
5023+#include <common.h>
5024+#include "cns3xxx_switch_type.h"
5025+#define printk printf
5026+#endif
5027+
5028+int cns3xxx_phy_reset(u8 phy_addr)
5029+{
5030+ u16 phy_data=0;
5031+
5032+ if (cns3xxx_read_phy(phy_addr, 0, &phy_data) != CAVM_OK)
5033+ return CAVM_ERR;
5034+ phy_data |= (0x1 << 15);
5035+ if (cns3xxx_write_phy(phy_addr, 0, phy_data) != CAVM_OK)
5036+ return CAVM_ERR;
5037+
5038+ return CAVM_OK;
5039+}
5040+
5041+// mac_port: 0, 1, 2
5042+int cns3xxx_enable_mac_clock(u8 mac_port, u8 en)
5043+{
5044+ switch (mac_port)
5045+ {
5046+ case 0:
5047+ {
5048+ (en==1)?(PHY_AUTO_ADDR_REG |= 1 << 7) :(PHY_AUTO_ADDR_REG &= (~(1 << 7)) );
5049+ break;
5050+ }
5051+ case 1:
5052+ {
5053+ (en==1)?(PHY_AUTO_ADDR_REG |= (1 << 15)) :(PHY_AUTO_ADDR_REG &= (~(1 << 15)) );
5054+ break;
5055+ }
5056+ case 2:
5057+ {
5058+ (en==1)?(PHY_AUTO_ADDR_REG |= (1 << 23)) :(PHY_AUTO_ADDR_REG &= (~(1 << 23)) );
5059+ break;
5060+ }
5061+ }
5062+
5063+ return CAVM_OK;
5064+}
5065+
5066+// dis: 1 disable
5067+// dis: 0 enable
5068+int cns3xxx_phy_auto_polling_enable(u8 port, u8 en)
5069+{
5070+ u8 phy_addr[]={5, 13, 21};
5071+
5072+ PHY_AUTO_ADDR_REG &= (~(1 << phy_addr[port]));
5073+ if (en) {
5074+ PHY_AUTO_ADDR_REG |= (1 << phy_addr[port]);
5075+ }
5076+ return CAVM_OK;
5077+}
5078+
5079+// dis: 1 disable
5080+// dis: 0 enable
5081+int cns3xxx_mdc_mdio_disable(u8 dis)
5082+{
5083+
5084+ PHY_CTRL_REG &= (~(1 << 7));
5085+ if (dis) {
5086+ PHY_CTRL_REG |= (1 << 7);
5087+ }
5088+ return CAVM_OK;
5089+}
5090+
5091+
5092+static int cns3xxx_phy_auto_polling_conf(int mac_port, u8 phy_addr)
5093+{
5094+ if ( (mac_port < 0) || (mac_port > 2) ) {
5095+ return CAVM_ERR;
5096+ }
5097+
5098+ switch (mac_port)
5099+ {
5100+ case 0:
5101+ {
5102+ PHY_AUTO_ADDR_REG &= (~0x1f);
5103+ PHY_AUTO_ADDR_REG |= phy_addr;
5104+ break;
5105+ }
5106+ case 1:
5107+ {
5108+ PHY_AUTO_ADDR_REG &= (~(0x1f << 8));
5109+ PHY_AUTO_ADDR_REG |= (phy_addr << 8);
5110+ break;
5111+ }
5112+ case 2:
5113+ {
5114+ PHY_AUTO_ADDR_REG &= (~(0x1f << 16));
5115+ PHY_AUTO_ADDR_REG |= (phy_addr << 16);
5116+ break;
5117+ }
5118+ }
5119+ cns3xxx_phy_auto_polling_enable(mac_port, 1);
5120+ return CAVM_OK;
5121+}
5122+
5123+
5124+
5125+int cns3xxx_read_phy(u8 phy_addr, u8 phy_reg, u16 *read_data)
5126+{
5127+ int delay=0;
5128+ u32 volatile tmp = PHY_CTRL_REG;
5129+
5130+ PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit
5131+ // delay
5132+ for (delay=0; delay<10; delay++);
5133+ tmp &= (~0x1f);
5134+ tmp |= phy_addr;
5135+
5136+ tmp &= (~(0x1f << 8));
5137+ tmp |= (phy_reg << 8);
5138+
5139+ tmp |= (1 << 14); // read command
5140+
5141+ PHY_CTRL_REG = tmp;
5142+
5143+ // wait command complete
5144+ while ( ((PHY_CTRL_REG >> 15) & 1) == 0);
5145+
5146+ *read_data = (PHY_CTRL_REG >> 16);
5147+
5148+ PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit
5149+
5150+ return CAVM_OK;
5151+}
5152+
5153+int cns3xxx_write_phy(u8 phy_addr, u8 phy_reg, u16 write_data)
5154+{
5155+ int delay=0;
5156+ u32 tmp = PHY_CTRL_REG;
5157+
5158+ PHY_CTRL_REG |= (1 << 15); // clear "command completed" bit
5159+ // delay
5160+ for (delay=0; delay<10; delay++);
5161+
5162+ tmp &= (~(0xffff << 16));
5163+ tmp |= (write_data << 16);
5164+
5165+ tmp &= (~0x1f);
5166+ tmp |= phy_addr;
5167+
5168+ tmp &= (~(0x1f << 8));
5169+ tmp |= (phy_reg << 8);
5170+
5171+ tmp |= (1 << 13); // write command
5172+
5173+ PHY_CTRL_REG = tmp;
5174+
5175+ // wait command complete
5176+ while ( ((PHY_CTRL_REG >> 15) & 1) == 0);
5177+
5178+ return CAVM_OK;
5179+}
5180+
5181+// port 0,1,2
5182+void cns3xxx_rxc_dly(u8 port, u8 val)
5183+{
5184+ switch (port)
5185+ {
5186+ case 0:
5187+ {
5188+ SLK_SKEW_CTRL_REG &= (~(0x3 << 4));
5189+ SLK_SKEW_CTRL_REG |= (val << 4);
5190+ break;
5191+ }
5192+ case 1:
5193+ {
5194+ SLK_SKEW_CTRL_REG &= (~(0x3 << 12));
5195+ SLK_SKEW_CTRL_REG |= (val << 12);
5196+ break;
5197+ }
5198+ case 2:
5199+ {
5200+ SLK_SKEW_CTRL_REG &= (~(0x3 << 20));
5201+ SLK_SKEW_CTRL_REG |= (val << 20);
5202+ break;
5203+ }
5204+ }
5205+}
5206+
5207+// port 0,1,2
5208+void cns3xxx_txc_dly(u8 port, u8 val)
5209+{
5210+ switch (port)
5211+ {
5212+ case 0:
5213+ {
5214+ SLK_SKEW_CTRL_REG &= (~(0x3 << 6));
5215+ SLK_SKEW_CTRL_REG |= (val << 6);
5216+ break;
5217+ }
5218+ case 1:
5219+ {
5220+ SLK_SKEW_CTRL_REG &= (~(0x3 << 14));
5221+ SLK_SKEW_CTRL_REG |= (val << 14);
5222+ break;
5223+ }
5224+ case 2:
5225+ {
5226+ SLK_SKEW_CTRL_REG &= (~(0x3 << 22));
5227+ SLK_SKEW_CTRL_REG |= (val << 22);
5228+ break;
5229+ }
5230+ }
5231+}
5232+
5233+void cns3xxx_mac2_gtxd_dly(u8 val)
5234+{
5235+ SLK_SKEW_CTRL_REG &= (~(0x3 << 24));
5236+ SLK_SKEW_CTRL_REG |= (val << 24);
5237+}
5238+
5239+// VITESSE suggest use isolate bit.
5240+int vsc8601_power_down(int phy_addr, int y)
5241+{
5242+ u16 phy_data = 0;
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);
5250+
5251+ return 0;
5252+}
5253+
5254+
5255+// port : 0 => port0 ; port : 1 => port1
5256+// y = 1 ; disable AN
5257+void disable_AN(int port, int y)
5258+{
5259+ u32 mac_port_config=0;
5260+
5261+ switch (port)
5262+ {
5263+ case 0:
5264+ {
5265+ mac_port_config = MAC0_CFG_REG;
5266+ break;
5267+ }
5268+ case 1:
5269+ {
5270+ mac_port_config = MAC1_CFG_REG;
5271+ break;
5272+ }
5273+ case 2:
5274+ {
5275+ mac_port_config = MAC2_CFG_REG;
5276+ break;
5277+ }
5278+ }
5279+
5280+
5281+ // disable PHY's AN
5282+ if (y==1)
5283+ {
5284+ mac_port_config &= ~(0x1 << 7);
5285+ }
5286+
5287+ // enable PHY's AN
5288+ if (y==0)
5289+ {
5290+ mac_port_config |= (0x1 << 7);
5291+ }
5292+
5293+ switch (port)
5294+ {
5295+ case 0:
5296+ {
5297+ MAC0_CFG_REG = mac_port_config;
5298+ break;
5299+ }
5300+ case 1:
5301+ {
5302+ MAC1_CFG_REG = mac_port_config;
5303+ break;
5304+ }
5305+ case 2:
5306+ {
5307+ MAC2_CFG_REG = mac_port_config;
5308+ break;
5309+ }
5310+ }
5311+}
5312+
5313+int cns3xxx_std_phy_power_down(int phy_addr, int y)
5314+{
5315+ u16 phy_data = 0;
5316+ // power-down or up the PHY
5317+ cns3xxx_read_phy(phy_addr, 0, &phy_data);
5318+ if (y==1) // down
5319+ phy_data |= (0x1 << 11);
5320+ if (y==0) // up
5321+ phy_data &= (~(0x1 << 11));
5322+ cns3xxx_write_phy(phy_addr, 0, phy_data);
5323+
5324+ phy_data=0;
5325+ cns3xxx_read_phy(phy_addr, 0, &phy_data);
5326+
5327+ return 0;
5328+}
5329+
5330+
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)
5333+{
5334+ u8 cns3xxx_spi_tx_rx(u8 tx_channel, u8 tx_eof, u32 tx_data, u32 * rx_data);
5335+
5336+ return cns3xxx_spi_tx_rx(tx_channel, tx_eof_flag, tx_data, rx_data);
5337+}
5338+
5339+int bcm53115M_reg_read(int page, int offset, u8 *buf, int len)
5340+{
5341+ u32 ch = BCM53115_SPI_CHANNEL;
5342+ u8 cmd_byte;
5343+ u32 dumy_word;
5344+ u32 spi_status;
5345+ int i;
5346+
5347+ /*
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)
5351+ *
5352+ */
5353+
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 */
5357+ do
5358+ {
5359+ cmd_byte = 0x60;
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);
5363+ udelay(100);
5364+ }while ((spi_status >> ROBO_SPIF_BIT) & 1) ; // wait SPI bit to 0
5365+
5366+ /* 2. Issue a normal write command(0x61) to write the register page value
5367+ into the SPI page register(0xFF) */
5368+ cmd_byte = 0x61;
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);
5372+
5373+ /* 3. Issue a normal read command(0x60) to setup the required RobiSwitch register
5374+ address */
5375+ cmd_byte = 0x60;
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);
5379+
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 */
5382+ do
5383+ {
5384+ cmd_byte = 0x60;
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);
5388+ udelay(100);
5389+ }while (((spi_status >> ROBO_RACK_BIT) & 1) == 0); // wait RACK bit to 1
5390+
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) */
5393+ cmd_byte = 0x60;
5394+ cns3xxx_spi_tx_rx_n(cmd_byte, &dumy_word, ch, 0);
5395+ cns3xxx_spi_tx_rx_n(0xF0, &dumy_word, ch, 0);
5396+ // read content
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;
5400+ }
5401+
5402+ return 0;
5403+
5404+}
5405+
5406+int bcm53115M_reg_write(int page, int offset, u8 *buf, int len)
5407+{
5408+ u32 ch = BCM53115_SPI_CHANNEL;
5409+ u8 cmd_byte;
5410+ u32 dumy_word;
5411+ u32 spi_status;
5412+ int i;
5413+
5414+ /*
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)
5418+ *
5419+ */
5420+
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 */
5424+
5425+ do
5426+ {
5427+ cmd_byte = 0x60;
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
5432+
5433+ /* 2. Issue a normal write command(0x61) to write the register page value
5434+ into the SPI page register(0xFF) */
5435+ cmd_byte = 0x61;
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);
5439+
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 */
5442+ cmd_byte = 0x61;
5443+ cns3xxx_spi_tx_rx_n((u32)cmd_byte, &dumy_word, ch, 0);
5444+ cns3xxx_spi_tx_rx_n(offset, &dumy_word, ch, 0);
5445+ // write content
5446+ for (i=0; i<len; i++) {
5447+ cns3xxx_spi_tx_rx_n((u32)buf[i], &dumy_word, ch, ((i==(len-1)) ? 1 : 0));
5448+ }
5449+
5450+ return 0;
5451+}
5452+
5453+int __init_or_module gpio_direction_output(unsigned int pin, unsigned int state);
5454+
5455+void bcm53115M_init_mac(u8 mac_port, u16 phy_addr)
5456+{
5457+ u32 mac_port_config = 0;
5458+ u8 mac_addr[]={0x0c, 0x10, 0x18};
5459+
5460+ cns3xxx_enable_mac_clock(mac_port, 1);
5461+ cns3xxx_phy_auto_polling_enable(mac_port, 0);
5462+
5463+ mac_port_config = SWITCH_REG_VALUE(mac_addr[mac_port]);
5464+
5465+ // enable GMII, MII, reverse MII
5466+ mac_port_config &= (~(1 << 15));
5467+
5468+ // enable RGMII
5469+ mac_port_config |= (1 << 15);
5470+
5471+ // disable GIGA mode
5472+ mac_port_config &= (~(1<<16));
5473+
5474+ // enable GIGA mode
5475+ mac_port_config |= (1<<16);
5476+
5477+ // disable PHY's AN
5478+ mac_port_config &= (~(0x1 << 7));
5479+
5480+ // force 1000Mbps
5481+ mac_port_config &= (~(0x3 << 8));
5482+ mac_port_config |= (0x2 << 8);
5483+
5484+ // force duplex
5485+ mac_port_config |= (0x1 << 10);
5486+
5487+ // TX flow control on
5488+ mac_port_config |= (0x1 << 12);
5489+
5490+ // RX flow control on
5491+ mac_port_config |= (0x1 << 11);
5492+
5493+ // Turn off GSW_PORT_TX_CHECK_EN_BIT
5494+ mac_port_config &= (~(0x1 << 13));
5495+
5496+ // Turn on GSW_PORT_TX_CHECK_EN_BIT
5497+ mac_port_config |= (0x1 << 13);
5498+
5499+ SWITCH_REG_VALUE(mac_addr[mac_port]) = mac_port_config;
5500+}
5501+
5502+typedef struct bcm53115M_vlan_entry_t
5503+{
5504+ u16 vid;
5505+ u16 forward_map;
5506+ u16 untag_map;
5507+}bcm53115M_vlan_entry;
5508+
5509+
5510+
5511+int bcm53115M_write_vlan(bcm53115M_vlan_entry *v)
5512+{
5513+ u8 bval;
5514+ u16 wval;
5515+ u32 dwval;
5516+
5517+ // fill vid
5518+ wval = (u16)v->vid;
5519+ bcm53115M_reg_write(0x05, 0x81, (u8*)&wval, 2);
5520+
5521+ // fill table content
5522+ dwval = 0;
5523+ dwval |= (v->forward_map & 0x1FF);
5524+ dwval |= ((v->untag_map& 0x1FF) << 9);
5525+ bcm53115M_reg_write(0x05, 0x83, (u8*)&wval, 4);
5526+
5527+ // write cmd
5528+ bval = VLAN_WRITE_CMD;
5529+ bval |= (1 << VLAN_START_BIT);
5530+ bcm53115M_reg_write(0x05, 0x80, (u8*)&bval, 1);
5531+
5532+ // wait cmd complete
5533+ while(1) {
5534+ bcm53115M_reg_read(0x05, 0x80, (u8*)&bval, 1);
5535+ if (((bval >> VLAN_START_BIT) & 1) == 0) break;
5536+ }
5537+
5538+ return CAVM_OK;
5539+}
5540+
5541+typedef struct bcm_port_cfg_t
5542+{
5543+ u8 link;
5544+ u8 fdx;
5545+ BCM_PORT_SPEED speed;
5546+ u8 rx_flw_ctrl;
5547+ u8 tx_flw_ctrl;
5548+ u8 ow;
5549+}bcm_port_cfg;
5550+
5551+
5552+
5553+int bcm53115M_mac_port_config(int port, bcm_port_cfg *cfg)
5554+{
5555+ u8 bval = 0;
5556+ int page, addr;
5557+
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);
5563+
5564+ if (port == BCM_PORT_IMP) {
5565+ bval |= (1<<7); // Use content of this register
5566+ page = 0x00;
5567+ addr = 0x0E;
5568+ }else {
5569+ page = 0x00;
5570+ addr = 0x58+port;
5571+ }
5572+
5573+ bcm53115M_reg_write(page, addr, &bval, 1);
5574+
5575+ return 0;
5576+}
5577+
5578+int bcm53115M_init_internal_phy(void)
5579+{
5580+ int p, page;
5581+ u16 wval;
5582+
5583+ for (p=BCM_PORT_0; p<=BCM_PORT_4; p++) {
5584+ page = 0x10+p;
5585+
5586+ // reset phy
5587+ bcm53115M_reg_read(page, 0x00, (u8*)&wval, 2);
5588+ wval |= 0x8000;
5589+ bcm53115M_reg_write(page, 0x00, (u8*)&wval, 2);
5590+
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);
5595+
5596+ bcm53115M_reg_read(page, 0x08, (u8*)&wval, 2);
5597+ wval |= 0x1E0; // advertisement all
5598+ bcm53115M_reg_write(page, 0x08, (u8*)&wval, 2);
5599+
5600+ // 1000BASE-T
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);
5605+ }
5606+
5607+ return 0;
5608+}
5609+
5610+int bcm53115M_led_init(void)
5611+{
5612+ u16 led_func, bval, wval;
5613+
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);
5618+
5619+ /* LED map enable */
5620+ wval = 0x1F; // port0~4
5621+ bcm53115M_reg_write(0x00, 0x16, (u8*)&wval, 2);
5622+
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);
5627+
5628+ /* LED enable */
5629+ bcm53115M_reg_read(0x00, 0x0F, (u8*)&bval, 1);
5630+ bval |= 0x80;
5631+ bcm53115M_reg_write(0x00, 0x0F, (u8*)&bval, 1);
5632+
5633+ return 0;
5634+}
5635+
5636+//#define BCM53115M_DUMMY_SWITCH
5637+#define BCM53115M_DISABLE_LEARNING
5638+
5639+int bcm53115M_init(u8 mac_port, u16 phy_addr)
5640+{
5641+ u32 u32_val=0;
5642+ u16 u16_val=0;
5643+ u8 bval=0;
5644+ int i=0;
5645+ bcm53115M_vlan_entry v_ent;
5646+ bcm_port_cfg pc;
5647+ u8 page=0, offset=0;
5648+
5649+ printk("bcm53115M init\n");
5650+
5651+ memset(&v_ent, 0, sizeof(bcm53115M_vlan_entry));
5652+
5653+ // gpio B pin 18
5654+ gpio_direction_output(50, 0);
5655+ bcm53115M_init_mac(0, 0);
5656+ bcm53115M_init_mac(1, 1);
5657+
5658+ // read device id
5659+ bcm53115M_reg_read(0x02, 0x30, (u8*)&u32_val, 4);
5660+ printk("bcm53115M device id:(0x%x)\r\n", u32_val);
5661+
5662+ if (u32_val != 0x53115) {
5663+ printk("bad device id(0x%x)\r\n", u32_val);
5664+ return -1;
5665+ }
5666+
5667+ u16_val=0;
5668+ // read phy id
5669+ bcm53115M_reg_read(0x10, 0x04, (u8 *)&u16_val, 2);
5670+ printk("bcm53115M phy id_1:(0x%x)\r\n", u16_val);
5671+
5672+ if (u16_val != 0x143) {
5673+ printk("bad phy id1(0x%x)\r\n", u16_val);
5674+ return CAVM_ERR;
5675+ }
5676+
5677+ u16_val=0;
5678+ // read phy id2
5679+ bcm53115M_reg_read(0x10, 0x06, (u8 *)&u16_val, 2);
5680+ printk("bcm53115M phy id_2:(0x%x)\r\n", u16_val);
5681+
5682+#ifdef BCM53115M_DUMMY_SWITCH
5683+ bval=0;
5684+ bcm53115M_reg_read(0x00, 0x0e, (u8 *)&bval, 1);
5685+ printk("bcm53115M page:0 addr:0x0e ## %x\n", bval);
5686+ bval |= (1 << 7);
5687+ bval |= 1;
5688+
5689+ bval = 0x8b;
5690+ bval |= (1 << 5);
5691+ bval |= (1 << 4);
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);
5696+
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);
5704+
5705+ page=0x0;
5706+ offset=0x5d; // port 5
5707+ bval=0x7b;
5708+ bcm53115M_reg_write(page, offset, (u8 *)&bval, 1);
5709+ bcm53115M_reg_read(page, offset, (u8 *)&bval, 1);
5710+
5711+ printk("bcm53115M page:%x addr:%x ## %x\n", page, offset, bval);
5712+
5713+ page=0x0;
5714+ offset=0x58; // port 0
5715+ bval=0x7b;
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);
5719+
5720+#ifdef CONFIG_CNS3XXX_JUMBO_FRAME
5721+ printk("enable BCM53115 jumbo frame\n");
5722+
5723+ page=0x40;
5724+ offset=0x01;
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);
5729+
5730+#if 0
5731+ page=0x40;
5732+ offset=0x05;
5733+ u16_val=0;
5734+ bcm53115M_reg_write(page, offset, (u8 *)&u16_val, 2);
5735+#endif
5736+
5737+#endif
5738+
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);
5744+
5745+
5746+ /* VLAN forwarding mask */
5747+ // Bit8 IMP port, Bits[5:0] correspond to ports[5:0]
5748+ // port 0 <-> port IMP
5749+ u16_val = 0x103;
5750+ bcm53115M_reg_write(0x31, 0x0, (u8 *)&u16_val, 2); // port 0
5751+ u16_val = 0x103;
5752+ bcm53115M_reg_write(0x31, 0x10, (u8 *)&u16_val, 2); // IMP
5753+
5754+
5755+ // port 4 <-> port 5
5756+ u16_val = 0x3c;
5757+ bcm53115M_reg_write(0x31, 0x08, (u8 *)&u16_val, 2); // port 4
5758+ u16_val = 0x3c;
5759+ bcm53115M_reg_write(0x31, 0x0A, (u8 *)&u16_val, 2); // port 5
5760+
5761+
5762+ // others <-> none
5763+ u16_val = 0x00;
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
5767+
5768+ // port 1 <-> port IMP
5769+ u16_val = 0x103;
5770+ bcm53115M_reg_write(0x31, 0x2, (u8 *)&u16_val, 2); // port 1
5771+
5772+ // port 2 <-> port 5
5773+ u16_val = 0x3c;
5774+ bcm53115M_reg_write(0x31, 0x4, (u8 *)&u16_val, 2); // port 2
5775+
5776+ // port 3 <-> port 5
5777+ u16_val = 0x3c;
5778+ bcm53115M_reg_write(0x31, 0x6, (u8 *)&u16_val, 2); // port 3
5779+
5780+ /* Create VLAN1 for default port pvid */
5781+#if 0
5782+ v_ent.vid = 1;
5783+ v_ent.forward_map = 0x13F; // all ports
5784+ robo_write_vlan(&v_ent);
5785+#endif
5786+
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);
5791+
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);
5796+
5797+ offset=0x5d; // port 5
5798+ bval=0x7b;
5799+ bcm53115M_reg_write(page, offset, (u8 *)&bval, 1);
5800+ bcm53115M_reg_read(page, offset, (u8 *)&bval, 1);
5801+
5802+ // Speed, dulplex......etc
5803+ // setting in Gsw_Configure_Gsw_Hardware()
5804+
5805+ // Mgmt configuration, Page 02h, Address 00h
5806+ bval = 0;
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);
5811+
5812+ /* Init front ports, port0-4 */
5813+ // MAC
5814+ pc.speed = BCM_PORT_1G;
5815+ pc.link = 0; // link detect by robo_port_update()
5816+ pc.ow = 0;
5817+ for (i=BCM_PORT_0; i<=BCM_PORT_4; i++)
5818+ bcm53115M_mac_port_config(i, &pc);
5819+ // Internal Phy
5820+ bcm53115M_init_internal_phy();
5821+
5822+ /* Enable all port, STP_STATE=No spanning tree, TX/RX enable */
5823+ // Page 00h, Address 00h-05h
5824+ bval = 0x0;
5825+ for (i=0; i<=5; i++)
5826+ bcm53115M_reg_write(0x0, i, &bval, 1);
5827+
5828+ // Disable broadcast storm control due to h/w strap pin BC_SUPP_EN
5829+ // Page 41h, Address 10h-13h, bit28&22
5830+
5831+ // for port 0 ~ 5
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);
5836+ }
5837+
5838+ // for IMP port
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);
5842+
5843+ /* Misc */
5844+ // led
5845+ bcm53115M_led_init();
5846+ // multicast fwd rule, Page 00h, Address 2Fh
5847+ bval = 0;
5848+ bcm53115M_reg_write(0x00, 0x2F, &bval, 1);
5849+
5850+#ifdef BCM53115M_DISABLE_LEARNING
5851+ // disable learning
5852+ page=0x00;
5853+ offset=0x3c;
5854+ u16_val=0x13f;
5855+ bcm53115M_reg_write(page, offset, (u8 *)&u16_val, 2);
5856+ bcm53115M_reg_read(page, offset, (u8 *)&u16_val, 2);
5857+
5858+ page=0x02;
5859+ offset=0x06;
5860+ u32_val=4;
5861+ bcm53115M_reg_write(page, offset, (u8 *)&u32_val, 4);
5862+#endif
5863+#endif
5864+ return CAVM_OK;
5865+}
5866+#endif // defined(LINUX_KERNEL)
5867+
5868+//#define MAC2_RGMII
5869+#define CNS3XXX_MAC2_IP1001_GIGA_MODE
5870+
5871+void icp_ip1001_init_mac(u8 mac_port, u16 phy_addr)
5872+{
5873+ u32 mac_port_config = 0;
5874+ u8 mac_addr[]={0x0c, 0x10, 0x18};
5875+
5876+ cns3xxx_enable_mac_clock(mac_port, 1);
5877+
5878+ mac_port_config = SWITCH_REG_VALUE(mac_addr[mac_port]);
5879+
5880+ //cns3xxx_txc_dly(mac_port, 2);
5881+ //cns3xxx_rxc_dly(mac_port, 2);
5882+ //SLK_SKEW_CTRL_REG
5883+#if 1
5884+
5885+ // enable GMII, MII, reverse MII
5886+ mac_port_config &= (~(1 << 15));
5887+
5888+#ifdef MAC2_RGMII
5889+ mac_port_config |= (1 << 15);
5890+#endif
5891+
5892+ // TXC check disable
5893+ //mac_port_config &= (~(1 << 13));
5894+
5895+ // disable GIGA mode
5896+ mac_port_config &= (~(1<<16));
5897+
5898+#ifdef CNS3XXX_MAC2_IP1001_GIGA_MODE
5899+ // enable GIGA mode
5900+ mac_port_config |= (1<<16);
5901+
5902+ //mac_port_config |= (1<<19);
5903+#endif
5904+
5905+ // disable PHY's AN
5906+ mac_port_config &= (~(0x1 << 7));
5907+
5908+ // enable PHY's AN
5909+ mac_port_config |= (0x1 << 7);
5910+#else
5911+ // disable PHY's AN
5912+ mac_port_config &= (~(0x1 << 7));
5913+ // disable GIGA mode
5914+ mac_port_config &= (~(1<<16));
5915+
5916+ // force 100Mbps
5917+ mac_port_config &= (~(0x3 << 8));
5918+ mac_port_config |= (0x1 << 8);
5919+
5920+ // force duplex
5921+ mac_port_config |= (0x1 << 10);
5922+
5923+ // TX flow control off
5924+ mac_port_config &= (~(0x1 << 12));
5925+
5926+ // RX flow control off
5927+ mac_port_config &= (~(0x1 << 11));
5928+
5929+#if 0
5930+ // TX flow control on
5931+ mac_port_config |= (0x1 << 12);
5932+
5933+ // RX flow control on
5934+ mac_port_config |= (0x1 << 11);
5935+#endif
5936+
5937+ // enable GMII, MII, reverse MII
5938+ mac_port_config &= (~(1 << 15));
5939+#endif
5940+ SWITCH_REG_VALUE(mac_addr[mac_port]) = mac_port_config;
5941+
5942+ // If mac port AN turns on, auto polling needs to turn on.
5943+ cns3xxx_phy_auto_polling_conf(mac_port, phy_addr);
5944+
5945+}
5946+
5947+int icp_ip1001_init(u8 mac_port, u8 phy_addr)
5948+{
5949+ u16 phy_data = 0;
5950+
5951+ printk("mac_port: %d ## phy_addr: %d\n", mac_port, phy_addr);
5952+ cns3xxx_mdc_mdio_disable(0);
5953+
5954+#if 0
5955+ // GMII2 high speed drive strength
5956+ IOCDA_REG &= ((~3 << 10));
5957+ IOCDA_REG |= (1 << 10);
5958+#endif
5959+ IOCDA_REG = 0x55555800;
5960+
5961+ phy_data = get_phy_id(phy_addr); // should be 0x243
5962+
5963+ printk("ICPLUS IP 1001 phy id : %x\n", phy_data);
5964+
5965+ if (phy_data != 0x0243) {
5966+ printk("wrong phy id!!\n");
5967+ return CAVM_ERR;
5968+ }
5969+
5970+
5971+ cns3xxx_phy_reset(phy_addr);
5972+
5973+ icp_ip1001_init_mac(mac_port, phy_addr);
5974+
5975+ // read advertisement register
5976+ cns3xxx_read_phy(phy_addr, 0x4, &phy_data);
5977+
5978+ // enable PAUSE frame capability
5979+ phy_data |= (0x1 << 10);
5980+
5981+ phy_data &= (~(0x1 << 5));
5982+ phy_data &= (~(0x1 << 6));
5983+ phy_data &= (~(0x1 << 7));
5984+ phy_data &= (~(0x1 << 8));
5985+
5986+#if 1
5987+ phy_data |= (0x1 << 5);
5988+ phy_data |= (0x1 << 6);
5989+ phy_data |= (0x1 << 7);
5990+ phy_data |= (0x1 << 8);
5991+#endif
5992+
5993+ cns3xxx_write_phy(phy_addr, 0x4, phy_data);
5994+
5995+ cns3xxx_read_phy(phy_addr, 9, &phy_data);
5996+
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
6002+#endif
6003+ cns3xxx_write_phy(phy_addr, 9, phy_data);
6004+
6005+ cns3xxx_read_phy(phy_addr, 9, &phy_data);
6006+
6007+ cns3xxx_read_phy(phy_addr, 0, &phy_data);
6008+ // AN enable
6009+ phy_data |= (0x1 << 12);
6010+ cns3xxx_write_phy(phy_addr, 0, phy_data);
6011+
6012+ cns3xxx_read_phy(phy_addr, 0, &phy_data);
6013+ // restart AN
6014+ phy_data |= (0x1 << 9);
6015+ cns3xxx_write_phy(phy_addr, 0, phy_data);
6016+ return 0;
6017+}
6018+
6019+#define PHY_CONTROL_REG_ADDR 0x00
6020+#define PHY_AN_ADVERTISEMENT_REG_ADDR 0x04
6021+
6022+int icp_101a_init_mac(u8 port, u8 phy_addr)
6023+{
6024+ u32 mac_port_config = 0;
6025+
6026+ cns3xxx_enable_mac_clock(port, 1);
6027+
6028+ switch (port)
6029+ {
6030+ case 0:
6031+ {
6032+ mac_port_config = MAC0_CFG_REG;
6033+ break;
6034+ }
6035+ case 1:
6036+ {
6037+ mac_port_config = MAC1_CFG_REG;
6038+ break;
6039+ }
6040+ case 2:
6041+ {
6042+ mac_port_config = MAC2_CFG_REG;
6043+ break;
6044+ }
6045+ }
6046+
6047+ // enable GMII, MII, reverse MII
6048+ mac_port_config &= (~(1 << 15));
6049+
6050+ // disable PHY's AN, use force mode
6051+ mac_port_config &= (~(0x1 << 7));
6052+#ifdef CONFIG_FPGA_FORCE
6053+
6054+ // force 100Mbps
6055+ mac_port_config &= (~(0x3 << 8));
6056+ mac_port_config |= (0x1 << 8);
6057+
6058+ // force duplex
6059+ mac_port_config |= (0x1 << 10);
6060+
6061+ // TX flow control on
6062+ mac_port_config |= (0x1 << 12);
6063+
6064+ // RX flow control on
6065+ mac_port_config |= (0x1 << 11);
6066+
6067+ // Turn off GSW_PORT_TX_CHECK_EN_BIT
6068+ mac_port_config &= (~(0x1 << 13));
6069+#else
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);
6074+#endif
6075+ // normal MII
6076+ mac_port_config &= (~(1 << 14));
6077+
6078+
6079+ switch (port)
6080+ {
6081+ case 0:
6082+ {
6083+ MAC0_CFG_REG = mac_port_config;
6084+ break;
6085+ }
6086+ case 1:
6087+ {
6088+ MAC1_CFG_REG = mac_port_config;
6089+ break;
6090+ }
6091+ case 2:
6092+ {
6093+ MAC2_CFG_REG = mac_port_config;
6094+ break;
6095+ }
6096+ }
6097+
6098+
6099+ return CAVM_OK;
6100+}
6101+
6102+int icp_101a_init(u8 mac_port, u8 phy_addr)
6103+{
6104+ u32 mac_port_config=0;
6105+ u16 phy_data = 0;
6106+
6107+ cns3xxx_mdc_mdio_disable(0);
6108+ cns3xxx_phy_reset(phy_addr);
6109+
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);
6113+ return CAVM_ERR;
6114+ }
6115+ printk("phy id : %x\n", phy_data);
6116+ printk("init IC+101A\n");
6117+
6118+ icp_101a_init_mac(mac_port, phy_addr);
6119+
6120+ // read advertisement register
6121+ cns3xxx_read_phy(phy_addr, 0x4, &phy_data);
6122+
6123+ // enable PAUSE frame capability
6124+ phy_data |= (0x1 << 10);
6125+
6126+ cns3xxx_write_phy(phy_addr, 0x4, phy_data);
6127+
6128+#ifndef CONFIG_FPGA_FORCE
6129+
6130+ switch (mac_port)
6131+ {
6132+ case 0:
6133+ {
6134+ mac_port_config = MAC0_CFG_REG;
6135+ break;
6136+ }
6137+ case 1:
6138+ {
6139+ mac_port_config = MAC1_CFG_REG;
6140+ break;
6141+ }
6142+ case 2:
6143+ {
6144+ mac_port_config = MAC2_CFG_REG;
6145+ break;
6146+ }
6147+ }
6148+
6149+#if 0
6150+ if (!(mac_port_config & (0x1 << 5))) {
6151+ if (cns3xxx_read_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, &phy_data) == CAVM_ERR)
6152+ {
6153+ //PDEBUG("\n PORT%d, enable local flow control capability Fail\n", port);
6154+ return CAVM_ERR;
6155+ }
6156+ else
6157+ {
6158+ // enable PAUSE frame capability
6159+ phy_data |= (0x1 << 10);
6160+
6161+ if (cns3xxx_write_phy (port, PHY_AN_ADVERTISEMENT_REG_ADDR, phy_data) == CAVM_ERR)
6162+ {
6163+ //PDEBUG("\nPORT%d, enable PAUSE frame capability Fail\n", port);
6164+ return CAVM_ERR;
6165+ }
6166+ }
6167+ }
6168+#endif
6169+
6170+ cns3xxx_read_phy(phy_addr, 0, &phy_data);
6171+ // an enable
6172+ phy_data |= (0x1 << 12);
6173+
6174+ // restart AN
6175+ phy_data |= (0x1 << 9);
6176+ cns3xxx_write_phy(phy_addr, 0, phy_data);
6177+
6178+ while (1)
6179+ {
6180+ //PDEBUG ("\n Polling PHY%d AN \n", port);
6181+ cns3xxx_read_phy (phy_data, 0, &phy_data);
6182+
6183+ if (phy_data & (0x1 << 9)) {
6184+ continue;
6185+ } else {
6186+ //PDEBUG ("\n PHY%d AN restart is complete \n", port);
6187+ break;
6188+ }
6189+ }
6190+
6191+#endif
6192+
6193+ return CAVM_OK;
6194+}
6195+
6196+int cns3xxx_config_VSC8601_mac(u8 port)
6197+{
6198+ u32 mac_port_config = 0;
6199+
6200+ switch (port)
6201+ {
6202+ case 0:
6203+ {
6204+ mac_port_config = MAC0_CFG_REG;
6205+ break;
6206+ }
6207+ case 1:
6208+ {
6209+ mac_port_config = MAC1_CFG_REG;
6210+ break;
6211+ }
6212+ case 2:
6213+ {
6214+ mac_port_config = MAC2_CFG_REG;
6215+ break;
6216+ }
6217+ }
6218+
6219+ switch (port)
6220+ {
6221+ case 0:
6222+ {
6223+ MAC0_CFG_REG = mac_port_config;
6224+ break;
6225+ }
6226+ case 1:
6227+ {
6228+ MAC1_CFG_REG = mac_port_config;
6229+ break;
6230+ }
6231+ case 2:
6232+ {
6233+ MAC2_CFG_REG = mac_port_config;
6234+ break;
6235+ }
6236+ }
6237+ return CAVM_OK;
6238+}
6239+
6240+u16 get_phy_id(u8 phy_addr)
6241+{
6242+ u16 read_data;
6243+
6244+ cns3xxx_read_phy(phy_addr, 2, &read_data);
6245+
6246+ return read_data;
6247+}
6248+
6249+u32 get_vsc8601_recv_err_counter(u8 phy_addr)
6250+{
6251+ u16 read_data=0;
6252+ cns3xxx_read_phy(phy_addr, 19, &read_data);
6253+ return read_data;
6254+}
6255+
6256+u32 get_crc_good_counter(u8 phy_addr)
6257+{
6258+ u16 read_data=0;
6259+
6260+ // enter extended register mode
6261+ cns3xxx_write_phy(phy_addr, 31, 0x0001);
6262+
6263+ cns3xxx_read_phy(phy_addr, 18, &read_data);
6264+
6265+ // back to normal register mode
6266+ cns3xxx_write_phy(phy_addr, 31, 0x0000);
6267+
6268+ return read_data;
6269+}
6270+
6271+int cns3xxx_config_VSC8601(u8 mac_port, u8 phy_addr)
6272+{
6273+ u16 phy_data=0;
6274+ u32 mac_port_config=0;
6275+ //u8 tx_skew=1, rx_skew=1;
6276+ u16 phy_id=0;
6277+
6278+ cns3xxx_mdc_mdio_disable(0);
6279+
6280+ cns3xxx_read_phy(phy_addr, 0, &phy_data);
6281+ // software reset
6282+ phy_data |= (0x1 << 15);
6283+ cns3xxx_write_phy(phy_addr, 0, phy_data);
6284+ udelay(10);
6285+
6286+ phy_id = get_phy_id(phy_addr);
6287+ if (phy_id != 0x143) {
6288+ return CAVM_ERR;
6289+ }
6290+
6291+ switch (mac_port)
6292+ {
6293+ case 0:
6294+ {
6295+ mac_port_config = MAC0_CFG_REG;
6296+ break;
6297+ }
6298+ case 1:
6299+ {
6300+ mac_port_config = MAC1_CFG_REG;
6301+ break;
6302+ }
6303+ case 2:
6304+ {
6305+ mac_port_config = MAC2_CFG_REG;
6306+ break;
6307+ }
6308+ }
6309+
6310+ cns3xxx_enable_mac_clock(mac_port, 1);
6311+ //phy_auto_polling(mac_port, phy_addr);
6312+
6313+ // enable RGMII-PHY mode
6314+ mac_port_config |= (0x1 << 15);
6315+
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);
6320+
6321+ // enable GSW MAC port 0
6322+ mac_port_config &= ~(0x1 << 18);
6323+
6324+ // normal MII
6325+ mac_port_config &= (~(1 << 14));
6326+
6327+ switch (mac_port)
6328+ {
6329+ case 0:
6330+ {
6331+ MAC0_CFG_REG = mac_port_config;
6332+ printk("8601 MAC0_CFG_REG: %x\n", MAC0_CFG_REG);
6333+ break;
6334+ }
6335+ case 1:
6336+ {
6337+ MAC1_CFG_REG = mac_port_config;
6338+ printk("8601 MAC1_CFG_REG: %x\n", MAC1_CFG_REG);
6339+ break;
6340+ }
6341+ case 2:
6342+ {
6343+ MAC2_CFG_REG = mac_port_config;
6344+ break;
6345+ }
6346+ }
6347+
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);
6357+
6358+ return CAVM_OK;
6359+}
6360+
6361+
6362+
6363+#ifdef CONFIG_LIBRA
6364+void icp_175c_all_phy_power_down(int y)
6365+{
6366+ int i=0;
6367+
6368+ for (i=0 ; i < 5 ; ++i)
6369+ std_phy_power_down(i, y);
6370+
6371+}
6372+
6373+static int star_gsw_config_icplus_175c_phy4(void)
6374+{
6375+ u16 phy_data = 0, phy_data2 = 0;
6376+ u32 volatile ii, jj;
6377+ u8 phy_speed_dup = 0, phy_flowctrl = 0;
6378+ u32 volatile reg;
6379+ u8 gsw_mac_0_phy_addr = 0;
6380+ u8 gsw_mac_1_phy_addr = 1;
6381+
6382+
6383+ printk("config IC+175C\n");
6384+ /*
6385+ * Configure MAC port 0
6386+ * For IP175C Switch setting
6387+ * Force 100Mbps, and full-duplex, and flow control on
6388+ */
6389+ reg = GSW_MAC_PORT_0_CONFIG_REG;
6390+
6391+ // disable PHY's AN
6392+ reg &= ~(0x1 << 7);
6393+
6394+ // disable RGMII-PHY mode
6395+ reg &= ~(0x1 << 15);
6396+
6397+ // force speed = 100Mbps
6398+ reg &= ~(0x3 << 8);
6399+ reg |= (0x1 << 8);
6400+
6401+ // force full-duplex
6402+ reg |= (0x1 << 10);
6403+
6404+ // force Tx/Rx flow-control on
6405+ reg |= (0x1 << 11) | (0x1 << 12);
6406+
6407+ GSW_MAC_PORT_0_CONFIG_REG = reg;
6408+
6409+
6410+ for (ii = 0; ii < 0x2000; ii++)
6411+ {
6412+ reg = GSW_MAC_PORT_0_CONFIG_REG;
6413+
6414+ if ((reg & 0x1) && !(reg & 0x2))
6415+ {
6416+ /*
6417+ * enable MAC port 0
6418+ */
6419+ reg &= ~(0x1 << 18);
6420+
6421+
6422+ /*
6423+ * enable the forwarding of unknown, multicast and broadcast packets to CPU
6424+ */
6425+ reg &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
6426+
6427+ /*
6428+ * include unknown, multicast and broadcast packets into broadcast storm
6429+ */
6430+ reg |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31));
6431+
6432+ GSW_MAC_PORT_0_CONFIG_REG = reg;
6433+
6434+ break;
6435+ }
6436+ else
6437+ {
6438+ for (jj = 0; jj < 0x1000; jj++);
6439+
6440+
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 : \\");
6449+ }
6450+ }
6451+
6452+
6453+ if (!(reg & 0x1) || (reg & 0x2))
6454+ {
6455+ /*
6456+ * Port 0 PHY link down or no TXC in Port 0
6457+ */
6458+ printk("\rCheck MAC/PHY 0 Link Status : DOWN!\n");
6459+
6460+ return -1;
6461+ }
6462+ else
6463+ {
6464+ printk("\rCheck MAC/PHY 0 Link Status : UP!\n");
6465+ }
6466+
6467+
6468+
6469+ /*
6470+ * Configure MAC port 1
6471+ */
6472+ reg = GSW_MAC_PORT_0_CONFIG_REG;
6473+
6474+ // disable MAC's AN
6475+ reg &= ~(0x1 << 7);
6476+
6477+ GSW_MAC_PORT_0_CONFIG_REG = reg;
6478+
6479+
6480+ /* enable flow control on (PAUSE frame) */
6481+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x4, &phy_data);
6482+
6483+ phy_data |= (0x1 << 10);
6484+
6485+ star_gsw_write_phy(gsw_mac_1_phy_addr, 0x4, phy_data);
6486+
6487+#if 1
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.
6493+ */
6494+ phy_data = 0x1001;
6495+ star_gsw_write_phy(30, 9, phy_data);
6496+#endif
6497+ /* restart PHY auto neg. */
6498+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x0, &phy_data);
6499+
6500+ phy_data |= (0x1 << 9) | (0x1 << 12);
6501+
6502+ star_gsw_write_phy(gsw_mac_1_phy_addr, 0x0, phy_data);
6503+
6504+
6505+
6506+ /* wait for PHY auto neg. complete */
6507+ for (ii = 0; ii < 0x20; ii++)
6508+ {
6509+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x1, &phy_data);
6510+
6511+ if ((phy_data & (0x1 << 2)) && (phy_data & (0x1 << 5)))
6512+ {
6513+ break;
6514+ }
6515+ else
6516+ {
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 : \\");
6525+ }
6526+ }
6527+
6528+
6529+ if (ii >= 0x20)
6530+ {
6531+ printk("\rCheck MAC/PHY 1 Link Status : DOWN!\n");
6532+
6533+ return -1;
6534+ }
6535+ else
6536+ {
6537+ printk("\rCheck MAC/PHY 1 Link Status : UP!\n");
6538+ }
6539+
6540+
6541+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x4, &phy_data);
6542+
6543+ star_gsw_read_phy(gsw_mac_1_phy_addr, 0x5, &phy_data2);
6544+
6545+
6546+ if (phy_data & 0x0400) //FC on
6547+ {
6548+ //printk("<FC ON>");
6549+ phy_flowctrl = 1;
6550+ }
6551+ else
6552+ {
6553+ // printk("<FC OFF>");
6554+ phy_flowctrl = 0;
6555+ }
6556+
6557+
6558+ phy_speed_dup = 0;
6559+
6560+ if ((phy_data & 0x0100) && (phy_data2 & 0x0100)) //100F
6561+ {
6562+ // printk("<100F>");
6563+ phy_speed_dup |= (0x1 << 3); //set bit3 for 100F
6564+ }
6565+ else if ((phy_data & 0x0080) && (phy_data2 & 0x0080)) //100F
6566+ {
6567+ // printk("<100H>");
6568+ phy_speed_dup |= (0x1 << 2);
6569+ }
6570+ else if ((phy_data & 0x0040) && (phy_data2 & 0x0040)) //100F
6571+ {
6572+ // printk("<10F>");
6573+ phy_speed_dup |= (0x1 << 1);
6574+ }
6575+ else if ((phy_data & 0x0020) && (phy_data2 & 0x0020)) //100F
6576+ {
6577+ // printk("<10H>");
6578+ phy_speed_dup |= 0x1;
6579+ }
6580+
6581+
6582+ /*
6583+ * Configure MAC port 1 in forced setting subject to the current PHY status
6584+ */
6585+ reg = GSW_MAC_PORT_1_CONFIG_REG;
6586+
6587+ reg &= ~(0x1 << 7); //AN off
6588+
6589+ reg &= ~(0x3 << 8);
6590+
6591+ if (phy_speed_dup & 0x0C) //100
6592+ {
6593+ //printk("<set 100>");
6594+ reg |= (0x01 << 8);
6595+ }
6596+ else if (phy_speed_dup & 0x03) //10
6597+ {
6598+ //printk("<set 10>");
6599+ reg |= (0x00 << 8);
6600+ }
6601+
6602+ reg &= ~(0x1 << 11);
6603+
6604+ if (phy_flowctrl) //FC on
6605+ {
6606+ //printk("<set FC on>");
6607+ reg |= (0x1 << 11);
6608+ }
6609+ else
6610+ {
6611+ //printk("<set FC off>");
6612+ reg |= (0x0 << 11);
6613+ }
6614+
6615+ reg &= ~(0x1 << 10);
6616+
6617+ if ((phy_speed_dup & 0x2) || (phy_speed_dup & 0x8)) //FullDup
6618+ {
6619+ //printk("<set full>");
6620+ reg |= (0x1 << 10);
6621+ }
6622+ else //HalfDup
6623+ {
6624+ //printk("<set half>");
6625+ reg |= (0x0 << 10); //Half
6626+ }
6627+
6628+ GSW_MAC_PORT_1_CONFIG_REG = reg;
6629+
6630+
6631+ /*
6632+ * Check MAC port 1 link status
6633+ */
6634+ for (ii = 0; ii < 0x1000; ii++)
6635+ {
6636+ reg = GSW_MAC_PORT_1_CONFIG_REG;
6637+
6638+ if ((reg & 0x1) && !(reg & 0x2))
6639+ {
6640+ /*
6641+ * enable MAC port 1
6642+ */
6643+ reg &= ~(0x1 << 18);
6644+
6645+ /*
6646+ * enable the forwarding of unknown, multicast and broadcast packets to CPU
6647+ */
6648+ reg &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
6649+
6650+ /*
6651+ * include unknown, multicast and broadcast packets into broadcast storm
6652+ */
6653+ reg |= ((0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31));
6654+
6655+ GSW_MAC_PORT_1_CONFIG_REG = reg;
6656+
6657+ return 0;
6658+ }
6659+ }
6660+
6661+
6662+ if (ii > 0x1000)
6663+ {
6664+ /*
6665+ * Port 1 PHY link down or no TXC in Port 1
6666+ */
6667+ printk("\rCheck MAC/PHY 1 Link Status : DOWN!\n");
6668+
6669+ return -1;
6670+ }
6671+ return 0;
6672+}
6673+#endif
6674+
6675+#if 0
6676+static int star_gsw_config_VSC8201(u8 mac_port, u8 phy_addr) // include cicada 8201
6677+{
6678+ //u32 mac_port_base = 0;
6679+ u32 mac_port_config=0;
6680+ u16 phy_reg;
6681+ int i;
6682+
6683+ printk("\nconfigure VSC8201\n");
6684+ //PDEBUG("mac port : %d phy addr : %d\n", mac_port, phy_addr);
6685+ /*
6686+ * Configure MAC port 0
6687+ * For Cicada CIS8201 single PHY
6688+ */
6689+ if (mac_port == 0) {
6690+ //PDEBUG("port 0\n");
6691+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6692+ }
6693+ if (mac_port == 1) {
6694+ //PDEBUG("port 1\n");
6695+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6696+ }
6697+
6698+ star_gsw_set_phy_addr(mac_port, phy_addr);
6699+ //star_gsw_set_phy_addr(1, 1);
6700+
6701+ //mac_port_config = __REG(mac_port_base);
6702+
6703+ // enable PHY's AN
6704+ mac_port_config |= (0x1 << 7);
6705+
6706+ // enable RGMII-PHY mode
6707+ mac_port_config |= (0x1 << 15);
6708+
6709+ // enable GSW MAC port 0
6710+ mac_port_config &= ~(0x1 << 18);
6711+
6712+ if (mac_port == 0) {
6713+ //PDEBUG("port 0\n");
6714+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6715+ }
6716+ if (mac_port == 1) {
6717+ //PDEBUG("port 1\n");
6718+ GSW_MAC_PORT_1_CONFIG_REG = mac_port_config;
6719+ }
6720+
6721+ /*
6722+ * Configure Cicada's CIS8201 single PHY
6723+ */
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);
6729+#endif
6730+
6731+ star_gsw_read_phy(phy_addr, 0x1C, &phy_reg);
6732+
6733+ // configure SMI registers have higher priority over MODE/FRC_DPLX, and ANEG_DIS pins
6734+ phy_reg |= (0x1 << 2);
6735+
6736+ star_gsw_write_phy(phy_addr, 0x1C, phy_reg);
6737+
6738+ star_gsw_read_phy(phy_addr, 0x17, &phy_reg);
6739+
6740+ // enable RGMII MAC interface mode
6741+ phy_reg &= ~(0xF << 12);
6742+ phy_reg |= (0x1 << 12);
6743+
6744+ // enable RGMII I/O pins operating from 2.5V supply
6745+ phy_reg &= ~(0x7 << 9);
6746+ phy_reg |= (0x1 << 9);
6747+
6748+ star_gsw_write_phy(phy_addr, 0x17, phy_reg);
6749+
6750+ star_gsw_read_phy(phy_addr, 0x4, &phy_reg);
6751+
6752+ // Enable symmetric Pause capable
6753+ phy_reg |= (0x1 << 10);
6754+
6755+ star_gsw_write_phy(phy_addr, 0x4, phy_reg);
6756+
6757+
6758+
6759+ if (mac_port == 0) {
6760+ //PDEBUG("port 0\n");
6761+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6762+ }
6763+ if (mac_port == 1) {
6764+ //PDEBUG("port 1\n");
6765+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6766+ }
6767+
6768+
6769+
6770+
6771+
6772+
6773+
6774+ // enable PHY's AN
6775+ mac_port_config |= (0x1 << 7);
6776+
6777+ if (mac_port == 0) {
6778+ //PDEBUG("port 0\n");
6779+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6780+ }
6781+ if (mac_port == 1) {
6782+ //PDEBUG("port 1\n");
6783+ GSW_MAC_PORT_1_CONFIG_REG = mac_port_config;
6784+ }
6785+
6786+ /*
6787+ * Enable PHY1 AN restart bit to restart PHY1 AN
6788+ */
6789+ star_gsw_read_phy(phy_addr, 0x0, &phy_reg);
6790+
6791+ phy_reg |= (0x1 << 9) | (0x1 << 12);
6792+
6793+ star_gsw_write_phy(phy_addr, 0x0, phy_reg);
6794+
6795+ /*
6796+ * Polling until PHY0 AN restart is complete
6797+ */
6798+ for (i = 0; i < 0x1000; i++) {
6799+ star_gsw_read_phy(phy_addr, 0x1, &phy_reg);
6800+
6801+ if ((phy_reg & (0x1 << 5)) && (phy_reg & (0x1 << 2))) {
6802+ printk("0x1 phy reg: %x\n", phy_reg);
6803+ break;
6804+ } else {
6805+ udelay(100);
6806+ }
6807+ }
6808+
6809+ if (mac_port == 0) {
6810+ //PDEBUG("port 0\n");
6811+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6812+ }
6813+ if (mac_port == 1) {
6814+ //PDEBUG("port 1\n");
6815+ mac_port_config = GSW_MAC_PORT_1_CONFIG_REG;
6816+ }
6817+
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"));
6820+ } else {
6821+ printk("Check MAC/PHY%s Link Status : UP!\n", (mac_port == 0 ? "0" : "1"));
6822+ /*
6823+ * There is a bug for CIS8201 PHY operating at 10H mode, and we use the following
6824+ * code segment to work-around
6825+ */
6826+ star_gsw_read_phy(phy_addr, 0x05, &phy_reg);
6827+
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);
6830+
6831+ if ((!(phy_reg & (0x1 << 10))) && (!(phy_reg & (0x1 << 11)))) { /* 1000F/1000H off */
6832+ star_gsw_read_phy(phy_addr, 0x16, &phy_reg);
6833+
6834+ phy_reg |= (0x1 << 13) | (0x1 << 15); // disable "Link integrity check(B13)" & "Echo mode(B15)"
6835+
6836+ star_gsw_write_phy(phy_addr, 0x16, phy_reg);
6837+ }
6838+ }
6839+ }
6840+
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));
6845+ }
6846+
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));
6851+ }
6852+
6853+ return 0;
6854+}
6855+
6856+
6857+
6858+
6859+static void star_gsw_config_VSC8X01()
6860+{
6861+ u16 phy_id = 0;
6862+
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);
6869+ else
6870+ star_gsw_config_VSC8601(1,1);
6871+#else
6872+#ifdef CONFIG_LEO
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);
6878+ else
6879+ star_gsw_config_VSC8601(0,0);
6880+#endif
6881+#endif
6882+}
6883+#endif
6884+
6885+#if defined(CONFIG_DORADO) || defined(CONFIG_DORADO2)
6886+static int star_gsw_config_port0_VSC7385(void)
6887+{
6888+ u32 mac_port_config=0;
6889+ int i;
6890+
6891+ printk("config VSC7385\n");
6892+
6893+ mac_port_config = GSW_MAC_PORT_0_CONFIG_REG;
6894+
6895+ // disable PHY's AN
6896+ mac_port_config &= ~(0x1 << 7);
6897+
6898+ // enable RGMII-PHY mode
6899+ mac_port_config |= (0x1 << 15);
6900+
6901+ // force speed = 1000Mbps
6902+ mac_port_config &= ~(0x3 << 8);
6903+ mac_port_config |= (0x2 << 8);
6904+
6905+ // force full-duplex
6906+ mac_port_config |= (0x1 << 10);
6907+
6908+ // force Tx/Rx flow-control on
6909+ mac_port_config |= (0x1 << 11) | (0x1 << 12);
6910+
6911+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6912+
6913+ udelay(1000);
6914+
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)) {
6918+ break;
6919+ } else {
6920+ udelay(100);
6921+ }
6922+ }
6923+
6924+ if (!(mac_port_config & 0x1) || (mac_port_config & 0x2)) {
6925+ printk("MAC0 PHY Link Status : DOWN!\n");
6926+ return -1;
6927+ } else {
6928+ printk("MAC0 PHY Link Status : UP!\n");
6929+ }
6930+
6931+ // enable MAC port 0
6932+ mac_port_config &= ~(0x1 << 18);
6933+
6934+ // disable SA learning
6935+ mac_port_config |= (0x1 << 19);
6936+
6937+ // forward unknown, multicast and broadcast packets to CPU
6938+ mac_port_config &= ~((0x1 << 25) | (0x1 << 26) | (0x1 << 27));
6939+
6940+ // storm rate control for unknown, multicast and broadcast packets
6941+ mac_port_config |= (0x1 << 29) | (0x1 << 30) | ((u32)0x1 << 31);
6942+
6943+ GSW_MAC_PORT_0_CONFIG_REG = mac_port_config;
6944+
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;
6949+
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));
6953+
6954+ return 0;
6955+}
6956+#endif
6957--- /dev/null
6958+++ b/drivers/net/cns3xxx/cns3xxx_phy.h
6959@@ -0,0 +1,82 @@
6960+/*******************************************************************************
6961+ *
6962+ *
6963+ * Copyright (c) 2009 Cavium Networks
6964+ *
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.
6969+ *
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
6973+ * more details.
6974+ *
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.
6978+ *
6979+ * The full GNU General Public License is included in this distribution in the
6980+ * file called LICENSE.
6981+ *
6982+ ********************************************************************************/
6983+
6984+#ifndef CNS3XXX_PHY_H
6985+#define CNS3XXX_PHY_H
6986+
6987+#define LINUX_KERNEL // if don't define LINUX_KERNEL, mean u-boot
6988+
6989+#if defined(LINUX_KERNEL)
6990+#include <linux/version.h>
6991+#include <linux/types.h>
6992+#else // u-boot
6993+#define __init_or_module
6994+#include "cns3xxx_symbol.h"
6995+#endif
6996+
6997+void disable_AN(int port, int y);
6998+
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);
7008+
7009+int cns3xxx_phy_auto_polling_enable(u8 port, u8 en);
7010+
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);
7013+
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);
7016+
7017+// for bcm53115M
7018+#define ROBO_SPIF_BIT 7
7019+#define BCM53115_SPI_CHANNEL 1
7020+#define ROBO_RACK_BIT 5
7021+
7022+#define VLAN_START_BIT 7
7023+#define VLAN_WRITE_CMD 0
7024+
7025+//#define BCM_PORT_1G 2
7026+typedef enum
7027+{
7028+ BCM_PORT_10M = 0,
7029+ BCM_PORT_100M,
7030+ BCM_PORT_1G,
7031+}BCM_PORT_SPEED;
7032+
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
7040+
7041+#endif // end #ifndef CNS3XXX_PHY_H
7042--- /dev/null
7043+++ b/drivers/net/cns3xxx/cns3xxx_sppe_hook.c
7044@@ -0,0 +1,39 @@
7045+/******************************************************************************
7046+ *
7047+ * Copyright (c) 2008 Cavium Networks
7048+ *
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.
7052+ *
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.
7057+ *
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/.
7062+ *
7063+ * This file may also be available under a different license from Cavium.
7064+ * Contact Cavium Networks for more information
7065+ *
7066+ ******************************************************************************/
7067+
7068+#if defined(CONFIG_CNS3XXX_SPPE)
7069+#include <linux/module.h>
7070+#include <linux/cns3xxx/sppe.h>
7071+
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;
7076+
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);
7081+
7082+#endif //#if defined(CONFIG_CNS3XXX_SPPE)
7083+
7084--- /dev/null
7085+++ b/drivers/net/cns3xxx/cns3xxx_symbol.h
7086@@ -0,0 +1,317 @@
7087+/*******************************************************************************
7088+ *
7089+ * Copyright (c) 2009 Cavium Networks
7090+ *
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.
7095+ *
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
7099+ * more details.
7100+ *
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.
7104+ *
7105+ * The full GNU General Public License is included in this distribution in the
7106+ * file called LICENSE.
7107+ *
7108+ ********************************************************************************/
7109+
7110+// the symbol define memory map register.
7111+
7112+#ifndef CNS3XXX_SYMBOL_H
7113+#define CNS3XXX_SYMBOL_H
7114+
7115+#define DRV_VERSION "Cavium CNS3XXX Switch Driver-0.0.1"
7116+
7117+
7118+#define LINUX_KERNEL // if don't define LINUX_KERNEL, mean u-boot
7119+
7120+#if defined(LINUX_KERNEL)
7121+// linux kernel
7122+#include <mach/board.h>
7123+
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)))
7127+
7128+
7129+#define NETDEV_SIZE 4097+3
7130+
7131+#define PORT0_NETDEV_INDEX NETDEV_SIZE-3
7132+#define PORT1_NETDEV_INDEX NETDEV_SIZE-2
7133+#define PORT2_NETDEV_INDEX NETDEV_SIZE-1
7134+
7135+#if defined (CONFIG_CNS3XXX_SPPE)
7136+#define FP_NETDEV_INDEX NETDEV_SIZE-4
7137+#endif
7138+
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]
7142+
7143+#if defined (CONFIG_CNS3XXX_SPPE)
7144+#define FP_NETDEV net_dev_array[FP_NETDEV_INDEX]
7145+#endif
7146+
7147+#else // u-boot
7148+#include <malloc.h> // for u8, u32
7149+
7150+#include "cns3000.h"
7151+#define CAVM_OK 0
7152+#define CAVM_ERR 1
7153+#define CAVM_NOT_FOUND 2
7154+#define CAVM_FOUND 3
7155+#define CAVM_FAIL -1 // use minus
7156+
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)))
7160+
7161+#endif
7162+
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)
7168+
7169+
7170+
7171+// memory map register definition
7172+
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)
7176+
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)
7183+
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)
7189+
7190+#define MAC0_PRI_CTRL_EXT_REG SWITCH_REG_VALUE(0x30)
7191+
7192+#define ETYPE1_ETYPE0_REG SWITCH_REG_VALUE(0x34)
7193+#define ETYPE3_ETYPE2_REG SWITCH_REG_VALUE(0x38)
7194+
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)
7199+
7200+
7201+#define PRIO_ETYPE_UDP_REG SWITCH_REG_VALUE(0x4c)
7202+
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)
7211+
7212+#define TC_CTRL_REG SWITCH_REG_VALUE(0x70)
7213+#define RATE_CTRL_REG SWITCH_REG_VALUE(0x74)
7214+
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)
7219+
7220+#define ARL_VLAN_CMD_REG SWITCH_REG_VALUE(0x88)
7221+
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)
7225+
7226+#define VLAN_CFG SWITCH_REG_VALUE(0x098)
7227+
7228+#define MAC1_MAC0_PVID_REG SWITCH_REG_VALUE(0x9c)
7229+#define MAC2_CPU_PVID_REG SWITCH_REG_VALUE(0xa0)
7230+
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)
7234+
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)
7243+
7244+#define INTR_STAT_REG SWITCH_REG_VALUE(0xd0)
7245+#define INTR_MASK_REG SWITCH_REG_VALUE(0xd4)
7246+
7247+#define SRAM_TEST_REG SWITCH_REG_VALUE(0xd8)
7248+
7249+#define MEM_QUEUE_REG SWITCH_REG_VALUE(0xdc)
7250+
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)
7255+
7256+#define SLK_SKEW_CTRL_REG SWITCH_REG_VALUE(0xf0)
7257+
7258+#define DMA_RING_CTRL_REG SWITCH_REG_VALUE(0x100)
7259+
7260+#define DMA_AUTO_POLL_CFG_REG SWITCH_REG_VALUE(0x104)
7261+
7262+#define DELAY_INTR_CFG_REG SWITCH_REG_VALUE(0x108)
7263+
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)
7267+
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)
7271+
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)
7275+
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)
7279+
7280+#define TS_DMA_STA_REG SWITCH_REG_VALUE(0x150)
7281+#define FS_DMA_STA_REG SWITCH_REG_VALUE(0x154)
7282+
7283+#define TS_MRD_CMD_CNT_REG SWITCH_REG_VALUE(0x158)
7284+#define TS_MWT_CMD_CNT_REG SWITCH_REG_VALUE(0x15c)
7285+
7286+#define FS_MRD_CMD_CNT_REG SWITCH_REG_VALUE(0x160)
7287+#define FS_MWT_CMD_CNT_REG SWITCH_REG_VALUE(0x164)
7288+
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)
7300+
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)
7304+
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)
7316+
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)
7320+
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)
7330+
7331+#define C_FSOKPKT_CPU_REG SWITCH_REG_VALUE(0x524)
7332+#define C_FSOKBYTE_CPU_REG SWITCH_REG_VALUE(0x528)
7333+
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)
7345+
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)
7349+
7350+#define C_TXOKPKT_MAC0_EXT_REG SWITCH_REG_VALUE(0x72c)
7351+#define C_TXOKBYTE_MAC0_EXT_REG SWITCH_REG_VALUE(0x730)
7352+
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)
7356+
7357+#define GPIOB_PIN_EN_REG MISC_REG_VALUE(0x18)
7358+#define IOCDA_REG MISC_REG_VALUE(0x1c)
7359+
7360+#define LEVEL_HIGH 0
7361+#define RISING_EDGE 1
7362+
7363+#ifdef CONFIG_SILICON
7364+
7365+#define STATUS_INTERRUPT_ID 49
7366+
7367+#define FSRC_RING0_INTERRUPT_ID 51
7368+#define FSQF_RING0_INTERRUPT_ID 53
7369+
7370+#define FSRC_RING1_INTERRUPT_ID 55
7371+#define FSQF_RING1_INTERRUPT_ID 57
7372+
7373+#define TSTC_RING0_INTERRUPT_ID 50
7374+
7375+#define TSTC_RING1_INTERRUPT_ID 54
7376+
7377+#define HNAT_INTERRUPT_ID 58
7378+
7379+#else
7380+
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
7385+
7386+#define TSQE_RING0_INTERRUPT_ID 52
7387+
7388+//#define FSQF_RING0_INTERRUPT_ID 53
7389+#define FSQF_RING0_INTERRUPT_ID 42
7390+
7391+#define FSQF_RING1_INTERRUPT_ID 46
7392+#define FSRC_RING1_INTERRUPT_ID 44
7393+
7394+//#define FSRC_RING1_INTERRUPT_ID 55
7395+
7396+#define TSTC_RING0_INTERRUPT_ID 39
7397+#define TSTC_RING1_INTERRUPT_ID 43
7398+
7399+#define TSQE_RING1_INTERRUPT_ID 56
7400+#define HNAT_INTERRUPT_ID 58
7401+#endif // #ifdef CONFIG_SILICON
7402+
7403+#endif
7404--- /dev/null
7405+++ b/drivers/net/cns3xxx/cns3xxx_tool.h
7406@@ -0,0 +1,898 @@
7407+/*******************************************************************************
7408+ *
7409+ *
7410+ * Copyright (c) 2009 Cavium Networks
7411+ *
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.
7416+ *
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
7420+ * more details.
7421+ *
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.
7425+ *
7426+ * The full GNU General Public License is included in this distribution in the
7427+ * file called LICENSE.
7428+ *
7429+ ********************************************************************************/
7430+
7431+#ifndef CNS3XXX_TOOL_H
7432+#define CNS3XXX_TOOL_H
7433+
7434+#define PRINT_INFO printk
7435+
7436+#if defined(__KERNEL__)
7437+
7438+#include "cns3xxx.h"
7439+#include <linux/kernel.h> // for printk
7440+
7441+#else // u-boot
7442+
7443+#endif
7444+
7445+#define SHOW_DEBUG_MESSAGE
7446+#ifdef SHOW_DEBUG_MESSAGE
7447+
7448+extern int MSG_LEVEL;
7449+
7450+#define NO_MSG 0
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)
7456+
7457+#define DEBUG_MSG(msg_level, fmt, args...)\
7458+{ \
7459+ int i=0; \
7460+\
7461+ for(i=0 ; i < 3 ; ++i) { \
7462+ if ((MSG_LEVEL & msg_level) >> i) \
7463+ printk(KERN_INFO "*cns3xxx gsw debug* " fmt, ## args); \
7464+ } \
7465+}
7466+
7467+#endif
7468+
7469+#define GET_MAC_PORT_CFG(port, cfg) \
7470+{ \
7471+ switch (port) \
7472+ { \
7473+ case MAC_PORT0: \
7474+ { \
7475+ cfg = MAC0_CFG_REG; \
7476+ break; \
7477+ } \
7478+ case MAC_PORT1: \
7479+ { \
7480+ cfg = MAC1_CFG_REG; \
7481+ break; \
7482+ } \
7483+ case MAC_PORT2: \
7484+ { \
7485+ cfg = MAC2_CFG_REG; \
7486+ break; \
7487+ } \
7488+ } \
7489+}
7490+
7491+#define SET_MAC_PORT_CFG(port, cfg) \
7492+{ \
7493+ switch (port) \
7494+ { \
7495+ case MAC_PORT0: \
7496+ { \
7497+ MAC0_CFG_REG = cfg; \
7498+ break; \
7499+ } \
7500+ case MAC_PORT1: \
7501+ { \
7502+ MAC1_CFG_REG = cfg; \
7503+ break; \
7504+ } \
7505+ case MAC_PORT2: \
7506+ { \
7507+ MAC2_CFG_REG = cfg; \
7508+ break; \
7509+ } \
7510+ } \
7511+}
7512+
7513+#define between(x, start, end) ((x)>=(start) && (x)<=(end))
7514+static inline void print_packet(unsigned char *data, int len)
7515+{
7516+ int i,j;
7517+
7518+ printk("packet length: %d%s:\n", len, len>128?"(only show the first 128 bytes)":"");
7519+#if 0
7520+ if(len > 128) {
7521+ len = 128;
7522+ }
7523+#endif
7524+ for(i=0;len;) {
7525+ if(len >=16 ) {
7526+ for(j=0;j<16;j++) {
7527+ printk("%02x ", data[i++]);
7528+ }
7529+ printk("| ");
7530+
7531+ i -= 16;
7532+ for(j=0;j<16;j++) {
7533+ if( between(data[i], 0x21, 0x7e) ) {
7534+ printk("%c", data[i++]);
7535+ }
7536+ else {
7537+ printk(".");
7538+ i++;
7539+ }
7540+ }
7541+ printk("\n");
7542+
7543+ len -= 16;
7544+ }
7545+ else {
7546+ /* last line */
7547+
7548+ for(j=0; j<len; j++) {
7549+ printk("%02x ", data[i++]);
7550+ }
7551+ for(;j<16;j++) {
7552+ printk(" ");
7553+ }
7554+ printk("| ");
7555+
7556+ i -= len;
7557+ for(j=0;j<len;j++) {
7558+ if( between(data[i], 0x21, 0x7e) ) {
7559+ printk("%c", data[i++]);
7560+ }
7561+ else {
7562+ printk(".");
7563+ i++;
7564+ }
7565+ }
7566+ for(;j<16;j++) {
7567+ printk(" ");
7568+ }
7569+ printk("\n");
7570+
7571+ len = 0;
7572+ }
7573+ }
7574+ return;
7575+
7576+}
7577+
7578+static inline void cns3xxx_gsw_power_enable(void)
7579+{
7580+ PLL_HM_PD_CTRL_REG &= (~(1 << 2)); // power up PLL_RGMII (for MAC)
7581+ CLK_GATE_REG |= (1 << 11); // enable switch clock
7582+}
7583+
7584+static inline void cns3xxx_gsw_software_reset(void)
7585+{
7586+ SOFT_RST_REG &= (~(1 << 11));
7587+ SOFT_RST_REG |= (1 << 11);
7588+}
7589+
7590+
7591+
7592+
7593+// port:
7594+// 0 : mac port0
7595+// 1 : mac port1
7596+// 2 : mac port2
7597+// 3 : cpu port
7598+static inline void enable_port(u8 port, u8 enable)
7599+{
7600+ switch (port)
7601+ {
7602+ case 0:
7603+ {
7604+ (enable==1) ? (MAC0_CFG_REG &= (~(1 << 18)) ) : (MAC0_CFG_REG |= (1 << 18)) ;
7605+
7606+ break;
7607+ }
7608+ case 1:
7609+ {
7610+ (enable==1) ? (MAC1_CFG_REG &= (~(1 << 18)) ) : (MAC1_CFG_REG |= (1 << 18)) ;
7611+ break;
7612+ }
7613+ case 2:
7614+ {
7615+ (enable==1) ? (MAC2_CFG_REG &= (~(1 << 18)) ) : (MAC2_CFG_REG |= (1 << 18)) ;
7616+ break;
7617+ }
7618+ case 3:
7619+ {
7620+ (enable==1) ? (CPU_CFG_REG &= (~(1 << 18)) ) : (CPU_CFG_REG |= (1 << 18)) ;
7621+ break;
7622+ }
7623+ }
7624+}
7625+
7626+static inline int cns3xxx_vlan_table_lookup(VLANTableEntry *entry)
7627+{
7628+ VLAN_CTRL2_REG |= entry->vid;
7629+ ARL_VLAN_CMD_REG |= (1 << 8); // look up vlan table command
7630+
7631+ // wait for vlan command complete
7632+ while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ;
7633+
7634+ if (!((ARL_VLAN_CMD_REG >> 10) & 1)) {
7635+ // not found any entry
7636+ return CAVM_NOT_FOUND;
7637+ }
7638+
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);
7644+
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);
7649+
7650+ entry->my_mac[4] = ((VLAN_CTRL2_REG >> 24) & 0xff);
7651+ entry->my_mac[5] = ((VLAN_CTRL2_REG >> 16) & 0xff);
7652+
7653+ return CAVM_FOUND;
7654+}
7655+
7656+static inline int cns3xxx_vlan_table_read(VLANTableEntry *entry)
7657+{
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);
7663+
7664+ // wait for vlan command complete
7665+ while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ;
7666+
7667+ //printf("ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG);
7668+ //printf("VLAN_CTRL0_REG: %x\n", VLAN_CTRL0_REG);
7669+
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);
7675+
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);
7680+
7681+ entry->my_mac[4] = ((VLAN_CTRL2_REG >> 24) & 0xff);
7682+ entry->my_mac[5] = ((VLAN_CTRL2_REG >> 16) & 0xff);
7683+
7684+ return CAVM_OK;
7685+
7686+}
7687+
7688+
7689+// add a entry in the vlan table
7690+static inline int cns3xxx_vlan_table_add(VLANTableEntry *entry)
7691+{
7692+ VLAN_CTRL0_REG = 0;
7693+ VLAN_CTRL1_REG = 0;
7694+ VLAN_CTRL2_REG = 0;
7695+
7696+#if 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);
7700+#endif
7701+
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);
7714+
7715+ //printf("vlan index: %d ## add VLAN_CTRL0_REG: %x\n", entry->vlan_index, VLAN_CTRL0_REG);
7716+
7717+
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]);
7722+
7723+ VLAN_CTRL2_REG |= (entry->my_mac[4] << 24);
7724+ VLAN_CTRL2_REG |= (entry->my_mac[5] << 16);
7725+ VLAN_CTRL2_REG |= entry->vid;
7726+
7727+#if 0
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);
7731+#endif
7732+
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
7736+
7737+
7738+ //printf("after write ARL_VLAN_CMD_REG: %x\n", ARL_VLAN_CMD_REG);
7739+
7740+ // wait for vlan command complete
7741+ while(( (ARL_VLAN_CMD_REG >> 9) & 1) == 0) ;
7742+
7743+ return CAVM_OK;
7744+}
7745+
7746+static inline void print_arl_table_entry(ARLTableEntry *entry)
7747+{
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]);
7754+
7755+}
7756+
7757+
7758+static inline int cns3xxx_arl_table_lookup(ARLTableEntry *entry)
7759+{
7760+ ARL_CTRL0_REG = 0;
7761+ ARL_CTRL1_REG = 0;
7762+ ARL_CTRL2_REG = 0;
7763+
7764+ ARL_CTRL0_REG |= (entry->vid << 16);
7765+
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];
7770+
7771+ ARL_CTRL2_REG |= (entry->mac[4] << 24);
7772+ ARL_CTRL2_REG |= (entry->mac[5] << 16);
7773+
7774+ ARL_VLAN_CMD_REG |= (1 << 18); // arl table lookup command
7775+
7776+ // wait arl command complete
7777+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7778+
7779+ if (( (ARL_VLAN_CMD_REG >> 23) & 1)) {
7780+ // found
7781+
7782+ entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff);
7783+ entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f);
7784+
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);
7788+ } else {
7789+ // not found
7790+ return CAVM_NOT_FOUND;
7791+ }
7792+#if 0
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);
7797+#endif
7798+
7799+ return CAVM_FOUND;
7800+}
7801+
7802+static inline int cns3xxx_arl_table_search_again(ARLTableEntry *entry)
7803+{
7804+ ARL_CTRL0_REG = 0;
7805+ ARL_CTRL1_REG = 0;
7806+ ARL_CTRL2_REG = 0;
7807+
7808+ ARL_VLAN_CMD_REG |= (1 << 17); // arl table search again command
7809+
7810+ // wait arl command complete
7811+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7812+
7813+ if ((ARL_VLAN_CMD_REG >> 23) & 1) {
7814+
7815+ // found
7816+ #if 0
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);
7821+ #endif
7822+ entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff);
7823+ entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f);
7824+
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);
7828+
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;
7833+
7834+ entry->mac[4] = (ARL_CTRL2_REG >> 24);
7835+ entry->mac[5] = (ARL_CTRL2_REG >> 16);
7836+
7837+ return CAVM_FOUND;
7838+ } else {
7839+ // not found
7840+ return CAVM_NOT_FOUND;
7841+ }
7842+}
7843+
7844+static inline int cns3xxx_is_arl_table_end(void)
7845+{
7846+ ARL_CTRL0_REG = 0;
7847+ ARL_CTRL1_REG = 0;
7848+ ARL_CTRL2_REG = 0;
7849+
7850+ if (( (ARL_VLAN_CMD_REG >> 22) & 1)) { // search to table end
7851+ return CAVM_OK;
7852+ } else {
7853+ return CAVM_ERR;
7854+ }
7855+}
7856+
7857+static inline int cns3xxx_arl_table_search(ARLTableEntry *entry)
7858+{
7859+ ARL_CTRL0_REG = 0;
7860+ ARL_CTRL1_REG = 0;
7861+ ARL_CTRL2_REG = 0;
7862+
7863+#if 0
7864+ ARL_CTRL0_REG |= (entry->vid << 16);
7865+
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];
7870+
7871+ ARL_CTRL2_REG |= (entry->mac[4] << 24);
7872+ ARL_CTRL2_REG |= (entry->mac[5] << 16);
7873+#endif
7874+ ARL_VLAN_CMD_REG |= (1 << 16); // arl table search start command
7875+
7876+ // wait arl command complete
7877+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7878+
7879+ if (((ARL_VLAN_CMD_REG >> 23) & 1)) {
7880+ // found
7881+ #if 0
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);
7886+ #endif
7887+ entry->vid = ((ARL_CTRL0_REG >> 16) & 0xfff);
7888+ entry->pmap = ((ARL_CTRL0_REG >> 9) & 0x1f);
7889+
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);
7893+
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;
7898+
7899+ entry->mac[4] = (ARL_CTRL2_REG >> 24);
7900+ entry->mac[5] = (ARL_CTRL2_REG >> 16);
7901+
7902+ return CAVM_FOUND;
7903+ } else {
7904+ // not found
7905+ return CAVM_NOT_FOUND;
7906+ }
7907+}
7908+
7909+
7910+// flush all age out entries except static entries
7911+static inline int cns3xxx_arl_table_flush(void)
7912+{
7913+ ARL_VLAN_CMD_REG |= (1 << 20); // flush arl table command
7914+
7915+ // wait arl command complete
7916+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7917+
7918+
7919+ return CAVM_OK;
7920+}
7921+
7922+
7923+// add a entry in the arl table
7924+static inline int cns3xxx_arl_table_add(ARLTableEntry *entry)
7925+{
7926+ ARL_CTRL0_REG = 0;
7927+ ARL_CTRL1_REG = 0;
7928+ ARL_CTRL2_REG = 0;
7929+
7930+ entry->age_field = 7; // static entry
7931+ ARL_CTRL0_REG |= (entry->vid << 16);
7932+ ARL_CTRL0_REG |= (entry->pmap << 9);
7933+
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];
7938+
7939+ ARL_CTRL2_REG |= (entry->mac[4] << 24);
7940+ ARL_CTRL2_REG |= (entry->mac[5] << 16);
7941+
7942+ ARL_CTRL2_REG |= (entry->age_field << 4);
7943+ ARL_CTRL2_REG |= (entry->vlan_mac << 1);
7944+ ARL_CTRL2_REG |= (entry->filter);
7945+
7946+ //printk("entry->age_field: %d\n", entry->age_field);
7947+ //printk("ARL_CTRL2_REG: %x\n", ARL_CTRL2_REG);
7948+
7949+ ARL_VLAN_CMD_REG |= (1 << 19); // arl table write command
7950+
7951+ // wait arl command complete
7952+ while(( (ARL_VLAN_CMD_REG >> 21) & 1) == 0);
7953+
7954+ return CAVM_OK;
7955+}
7956+
7957+// invalid a entry in the arl table
7958+static inline int cns3xxx_arl_table_invalid(ARLTableEntry *entry)
7959+{
7960+ entry->age_field = 0; // invalid
7961+ return cns3xxx_arl_table_add(entry);
7962+}
7963+
7964+// port:
7965+// 0 : mac port0
7966+// 1 : mac port1
7967+// 2 : mac port2
7968+// 3 : cpu port
7969+static inline void cns3xxx_set_pvid(u8 port, u16 pvid)
7970+{
7971+ switch (port)
7972+ {
7973+ case 0:
7974+ {
7975+ MAC1_MAC0_PVID_REG &= (~0x0fff);
7976+ MAC1_MAC0_PVID_REG |= pvid;
7977+ break;
7978+ }
7979+ case 1:
7980+ {
7981+ MAC1_MAC0_PVID_REG &= (~(0x0fff << 16));
7982+ MAC1_MAC0_PVID_REG |= (pvid << 16);
7983+ break;
7984+ }
7985+ case 2:
7986+ {
7987+ MAC2_CPU_PVID_REG &= (~(0x0fff << 16));
7988+ MAC2_CPU_PVID_REG |= (pvid << 16);
7989+ break;
7990+ }
7991+ case 3: // cpu port
7992+ {
7993+ MAC2_CPU_PVID_REG &= (~0x0fff);
7994+ MAC2_CPU_PVID_REG |= pvid;
7995+ break;
7996+ }
7997+ }
7998+
7999+
8000+}
8001+
8002+static inline u16 cns3xxx_get_pvid(u8 port)
8003+{
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};
8008+
8009+ return ((SWITCH_REG_VALUE(port_offset[port]) >> port_shift[port]) & 0xfff);
8010+}
8011+
8012+// which : 0 or 1
8013+// enable: 0 or 1
8014+static inline int enable_rx_dma(u8 which, u8 enable)
8015+{
8016+ if (which == 0 ) {
8017+ FS_DMA_CTRL0_REG = enable;
8018+ } else if (which == 1 ) {
8019+ FS_DMA_CTRL1_REG = enable;
8020+ } else {
8021+ return CAVM_ERR;
8022+ }
8023+ return CAVM_OK;
8024+}
8025+
8026+
8027+// which : 0 or 1
8028+// enable: 0 or 1
8029+static inline int enable_tx_dma(u8 which, u8 enable)
8030+{
8031+ if (which == 0 ) {
8032+ TS_DMA_CTRL0_REG = enable;
8033+ } else if (which == 1 ) {
8034+ TS_DMA_CTRL1_REG = enable;
8035+ } else {
8036+ return CAVM_ERR;
8037+ }
8038+ return CAVM_OK;
8039+}
8040+
8041+#define DUMP_TX_DESC_PROC(tx_desc, page, num) \
8042+{ \
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); \
8056+ \
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); \
8066+ \
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); \
8073+}
8074+
8075+static inline void dump_tx_desc(TXDesc volatile *tx_desc)
8076+{
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);
8090+
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);
8100+
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);
8107+}
8108+
8109+static inline void dump_rx_desc(RXDesc volatile *rx_desc)
8110+{
8111+
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) );
8115+#if 0
8116+ int i=0;
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);
8120+ }
8121+#endif
8122+
8123+ printk("sdp: %x\n", rx_desc->sdp);
8124+
8125+ printk("sdl: %d\n", rx_desc->sdl);
8126+#if 1
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);
8134+#endif
8135+ printk("cown: %d\n", rx_desc->cown);
8136+
8137+#if 1
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);
8148+
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);
8155+#endif
8156+}
8157+
8158+static inline void dump_all_rx_ring(const RXRing *rx_ring, u8 r_index)
8159+{
8160+ int i=0;
8161+
8162+ RXBuffer volatile *rx_buf = get_rx_ring_head(rx_ring);
8163+
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);
8168+ ++rx_buf;
8169+ }
8170+}
8171+
8172+static inline void rx_dma_suspend(u8 enable)
8173+{
8174+#if 1
8175+ DMA_AUTO_POLL_CFG_REG &= (~0x00000001);
8176+ if (enable == 1)
8177+ DMA_AUTO_POLL_CFG_REG |= 1;
8178+#endif
8179+}
8180+
8181+
8182+// clear: 0 normal
8183+// clear: 1 clear
8184+static inline void clear_fs_dma_state(u8 clear)
8185+{
8186+ DMA_RING_CTRL_REG &= (~(1 << 31));
8187+ if (clear==1) {
8188+ DMA_RING_CTRL_REG |= (1 << 31);
8189+ }
8190+}
8191+
8192+// enable: 1 -> IVL
8193+// enable: 0 -> SVL
8194+static inline void cns3xxx_ivl(u8 enable)
8195+{
8196+ // SVL
8197+ MAC_GLOB_CFG_REG &= (~(0x1 << 7));
8198+ if (enable == 1)
8199+ MAC_GLOB_CFG_REG |= (0x1 << 7);
8200+}
8201+
8202+static inline void cns3xxx_nic_mode(u8 enable)
8203+{
8204+ VLAN_CFG &= (~(1<<15));
8205+ if (enable == 1)
8206+ VLAN_CFG |= (1<<15);
8207+}
8208+
8209+
8210+void gic_mask_irq(unsigned int irq);
8211+void gic_unmask_irq(unsigned int irq);
8212+extern void __iomem *gic_cpu_base_addr;
8213+
8214+
8215+static inline void cns3xxx_disable_irq(u32 irq)
8216+{
8217+#ifdef CONFIG_SMP
8218+ disable_irq_nosync(irq);
8219+#else
8220+ disable_irq(irq);
8221+#endif
8222+ //gic_mask_irq(irq);
8223+}
8224+
8225+static inline void cns3xxx_enable_irq(u32 irq)
8226+{
8227+ enable_irq(irq);
8228+ //gic_unmask_irq(irq);
8229+}
8230+
8231+static inline int cns3xxx_get_tx_hw_index(u8 ring_index)
8232+{
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);
8237+ } else {
8238+ return CAVM_ERR;
8239+ }
8240+}
8241+
8242+static inline TXBuffer* get_tx_buffer_by_index(TXRing *tx_ring, int i)
8243+{
8244+ int index = i;
8245+
8246+ index = ((index + get_tx_ring_size(tx_ring) )% get_tx_ring_size(tx_ring));
8247+
8248+ return tx_ring->head + index;
8249+}
8250+
8251+static inline int cns3xxx_is_untag_packet(const RXDesc *rx_desc)
8252+{
8253+ return rx_desc->crc_err;
8254+}
8255+
8256+
8257+#ifdef CONFIG_SWITCH_BIG_ENDIAN
8258+static inline void swap_rx_desc(RXDesc *org_desc, RXDesc *new_desc)
8259+{
8260+ int i=0;
8261+ void *org_p = org_desc;
8262+ void *new_p = new_desc;
8263+
8264+ for (i=0; i < 16 ; i+=4) {
8265+ u32 rx_desc_data = 0;
8266+ u32 swab_rx_desc_data = 0;
8267+
8268+ rx_desc_data = *((volatile u32 *)(org_p+i));
8269+ swab_rx_desc_data = ___swab32(rx_desc_data);
8270+
8271+ *((volatile u32 *)(new_p+i)) = swab_rx_desc_data;
8272+ }
8273+}
8274+
8275+static inline void swap_tx_desc(TXDesc *org_desc, TXDesc *new_desc)
8276+{
8277+ int i=0;
8278+ void *org_p = org_desc;
8279+ void *new_p = new_desc;
8280+
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);
8284+
8285+ *((volatile u32 *)(new_p+i)) = swab_desc_data;
8286+ }
8287+}
8288+
8289+#endif
8290+
8291+
8292+static inline int cns3xxx_min_mtu(void)
8293+{
8294+ return 64;
8295+}
8296+
8297+static inline int cns3xxx_max_mtu(void)
8298+{
8299+ int max_len[]={1518, 1522, 1536, 9600};
8300+
8301+ return max_len[((PHY_AUTO_ADDR_REG >> 30) & 0x3)];
8302+}
8303+
8304+#endif // CNS3XXX_TOOL_H
8305--- /dev/null
8306+++ b/drivers/net/cns3xxx/fpga.h
8307@@ -0,0 +1,306 @@
8308+/*******************************************************************************
8309+ *
8310+ * Copyright (c) 2009 Cavium Networks
8311+ *
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.
8316+ *
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
8320+ * more details.
8321+ *
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.
8325+ *
8326+ * The full GNU General Public License is included in this distribution in the
8327+ * file called LICENSE.
8328+ *
8329+ ********************************************************************************/
8330+
8331+// This macro or function divide two part,
8332+// one is initial state, another is in netdev open (ifconfig up) function.
8333+
8334+#ifndef FPGA_H
8335+#define FPGA_H
8336+
8337+#include <linux/types.h>
8338+
8339+#include "cns3xxx_config.h"
8340+#include "cns3xxx_phy.h"
8341+
8342+//#define FGPA
8343+
8344+
8345+#ifdef CONFIG_FPGA
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
8351+
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
8357+
8358+#define PORT0_LINK_DOWN vsc8601_power_down(0, 1);
8359+#define PORT0_LINK_UP vsc8601_power_down(0, 0);
8360+
8361+#define PORT1_LINK_DOWN vsc8601_power_down(1, 1);
8362+#define PORT1_LINK_UP vsc8601_power_down(1, 0);
8363+
8364+#define PORT2_LINK_DOWN cns3xxx_std_phy_power_down(2, 1);
8365+#define PORT2_LINK_UP cns3xxx_std_phy_power_down(2, 0);
8366+
8367+
8368+
8369+#define MODEL "VEGA FPGA"
8370+
8371+static int rc_port0 = 0; // rc means reference counting, determine port open/close.
8372+
8373+
8374+// enable port
8375+// link down
8376+static inline void open_port0(void)
8377+{
8378+ if (rc_port0 == 0) {
8379+ enable_port(0, 1);
8380+ PRINT_INFO("open mac port 0\n");
8381+ // link up
8382+ PORT0_LINK_UP
8383+ } else {
8384+ PRINT_INFO("port 0 already open\n");\
8385+ }
8386+ ++rc_port0;
8387+}
8388+
8389+static inline void close_port0(void)
8390+{
8391+ --rc_port0;
8392+ if (rc_port0 == 0) {
8393+ // link down
8394+ PORT0_LINK_DOWN
8395+ enable_port(0, 0);
8396+ PRINT_INFO("close mac port 0\n");\
8397+ }
8398+}
8399+
8400+static inline void open_port1(void)
8401+{
8402+
8403+ enable_port(1, 1);
8404+ PRINT_INFO("open mac port 1\n");
8405+ // link up
8406+ PORT1_LINK_UP
8407+}
8408+
8409+static inline void close_port1(void)
8410+{
8411+ enable_port(1, 0);
8412+ PRINT_INFO("close mac port 1\n");
8413+ // link down
8414+ PORT1_LINK_DOWN
8415+}
8416+
8417+static inline void open_port2(void)
8418+{
8419+
8420+ enable_port(2, 1);
8421+ PRINT_INFO("open mac port 2\n");
8422+ // link up
8423+ PORT2_LINK_UP
8424+}
8425+
8426+static inline void close_port2(void)
8427+{
8428+ enable_port(2, 0);
8429+ PRINT_INFO("close mac port 2\n");
8430+ // link down
8431+ PORT2_LINK_DOWN
8432+}
8433+
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};
8438+
8439+
8440+
8441+
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
8444+
8445+#ifdef CNS3XXX_VLAN_8021Q
8446+ #ifndef CNS3XXX_NIC_MODE_8021Q
8447+ #define CNS3XXX_NON_NIC_MODE_8021Q
8448+ #endif
8449+#else
8450+ //#define CNS3XXX_VLAN_BASE_MODE
8451+ #define CNS3XXX_PORT_BASE_MODE
8452+#endif
8453+
8454+#ifdef CNS3XXX_PORT_BASE_MODE
8455+
8456+#define PORT0_PVID 0x1
8457+#define PORT1_PVID 0x2
8458+#define PORT2_PVID 3
8459+#define CPU_PVID 5
8460+
8461+#define CONFIG_CNS3XXX_PORT_BASE
8462+
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};
8464+
8465+static VLANTableEntry vlan_table_entry[] =
8466+{
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
8473+};
8474+
8475+static ARLTableEntry arl_table_entry[] =
8476+{
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},
8486+};
8487+
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
8493+ };
8494+
8495+#endif
8496+
8497+#ifdef CNS3XXX_NON_NIC_MODE_8021Q
8498+//#error "8021Q"
8499+#define PORT0_PVID 50
8500+#define PORT1_PVID 60
8501+#define PORT2_PVID 70
8502+#define CPU_PVID 80
8503+
8504+#define CONFIG_CNS3XXX_PORT_BASE
8505+//#define CONFIG_CNS3XXX_VLAN_BASE
8506+//#define CONFIG_HAVE_VLAN_TAG
8507+
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
8509+
8510+static VLANTableEntry vlan_table_entry[] =
8511+{
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},
8516+};
8517+
8518+static ARLTableEntry arl_table_entry[] =
8519+{
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},
8524+};
8525+
8526+
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
8532+ };
8533+#endif
8534+
8535+
8536+
8537+#ifdef CNS3XXX_NIC_MODE_8021Q
8538+//#error "8021Q"
8539+#define PORT0_PVID 1
8540+#define PORT1_PVID 2
8541+#define PORT2_PVID 9
8542+#define CPU_PVID 5
8543+
8544+#define CONFIG_CNS3XXX_PORT_BASE
8545+//#define CONFIG_CNS3XXX_VLAN_BASE
8546+//#define CONFIG_HAVE_VLAN_TAG
8547+
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
8549+
8550+static VLANTableEntry vlan_table_entry[] =
8551+{
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},
8556+};
8557+
8558+static ARLTableEntry arl_table_entry[] =
8559+{
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},
8564+};
8565+
8566+
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
8572+ };
8573+#endif
8574+
8575+#ifdef CNS3XXX_VLAN_BASE_MODE
8576+//#error "vlan_base"
8577+// vlan configuration
8578+
8579+#define PORT0_PVID 1
8580+#define PORT1_PVID 2
8581+#define PORT2_PVID 3
8582+#define CPU_PVID 5
8583+#define CONFIG_CNS3XXX_VLAN_BASE
8584+#define CONFIG_HAVE_VLAN_TAG
8585+
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
8587+
8588+static VLANTableEntry vlan_table_entry[] =
8589+{
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},
8594+};
8595+
8596+static ARLTableEntry arl_table_entry[] =
8597+{
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},
8602+};
8603+
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
8609+ };
8610+#endif
8611+
8612+#endif // CONFIG_FPGA
8613+#endif // FPGA_H
8614--- /dev/null
8615+++ b/drivers/net/cns3xxx/Kconfig
8616@@ -0,0 +1,58 @@
8617+menu "CNS3XXX Gigabit Switch Support"
8618+ depends on ARCH_CNS3XXX
8619+
8620+config CNS3XXX_GSW
8621+ tristate "CNS3XXX Gigabit Switch Driver Support"
8622+ help
8623+ CNS3XXX Gigabit Switch.
8624+
8625+config CNS3XXX_SPPE
8626+ bool "CNS3XXX Smart PPE(Packet Processing Engine) Support"
8627+ depends on CNS3XXX_GSW
8628+ help
8629+ PPE(Packet Processing Engine) is a hardware accelerator hook on a port of
8630+ CNS3XXX Gigabit Switch.
8631+
8632+ This option is used for Smart PPE hook.
8633+
8634+ Say Y if you want to enable Smart PPE function.
8635+
8636+config CNS3XXX_HCIE_TEST
8637+ bool "CNS3XXX HCIE(Hardware Content Inspection Engine) Support"
8638+# depends on CNS3XXX_GSW
8639+ help
8640+ HCIE is patent-protected layer-7 packet processing engine.
8641+
8642+ This option is used for fundamental HCIE functional test .
8643+ Say Y if you want to do HCIE functional test.
8644+
8645+
8646+#config CNS3XXX_SHNAT_PCI_FASTPATH
8647+# bool "FastPath(From PCI to WAN) Support"
8648+# depends on CNS3XXX_SHNAT
8649+# help
8650+# Add FastPath Support for Smart HNAT.
8651+
8652+comment "NOTE: 'Validation Board' depends on"
8653+comment "GPIO_CNS3XXX and SPI_CNS3XXX"
8654+choice
8655+ prompt "CNS3XXX Board"
8656+ depends on CNS3XXX_GSW
8657+ default FPGA
8658+
8659+config FPGA
8660+ bool "Fpga"
8661+
8662+config VB
8663+ bool "Validation Board"
8664+ help
8665+ MAC0 and MAC1 connect to BCM53115M. It need enable CNS3XXX SPI and CNS3XXX GPIO option.
8666+ MAC2 use ICPLUS IP1001 phy.
8667+
8668+#config LEO
8669+# bool "Leo"
8670+
8671+endchoice
8672+
8673+endmenu
8674+
8675--- /dev/null
8676+++ b/drivers/net/cns3xxx/Makefile
8677@@ -0,0 +1,41 @@
8678+################################################################################
8679+#
8680+#
8681+# Copyright (c) 2008 Cavium Networks
8682+#
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.
8687+#
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
8691+# more details.
8692+#
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.
8696+#
8697+# The full GNU General Public License is included in this distribution in the
8698+# file called LICENSE.
8699+#
8700+# Contact Information:
8701+# Star semiconduction Linux Support <support@starsemi.com>
8702+#
8703+################################################################################
8704+
8705+#
8706+# Makefile for the Star GSW ethernet driver
8707+#
8708+
8709+#obj-y :=
8710+#obj-m :=
8711+
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
8715+#endif
8716+#vega_main.o
8717+
8718+#include $(TOPDIR)/Rules.make
8719--- /dev/null
8720+++ b/drivers/net/cns3xxx/vb.h
8721@@ -0,0 +1,328 @@
8722+/*******************************************************************************
8723+ *
8724+ * Copyright (c) 2009 Cavium Networks
8725+ *
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.
8730+ *
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
8734+ * more details.
8735+ *
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.
8739+ *
8740+ * The full GNU General Public License is included in this distribution in the
8741+ * file called LICENSE.
8742+ *
8743+ ********************************************************************************/
8744+
8745+// This macro or function divide two part,
8746+// one is initial state, another is in netdev open (ifconfig up) function.
8747+
8748+#ifndef VB_H
8749+#define VB_H
8750+
8751+#include <linux/types.h>
8752+
8753+#include "cns3xxx_config.h"
8754+#include "cns3xxx_phy.h"
8755+
8756+#ifdef CONFIG_VB
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
8762+
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
8768+
8769+#define PORT0_LINK_DOWN cns3xxx_std_phy_power_down(0, 1);
8770+#define PORT0_LINK_UP cns3xxx_std_phy_power_down(0, 0);
8771+
8772+#define PORT1_LINK_DOWN cns3xxx_std_phy_power_down(1, 1);
8773+#define PORT1_LINK_UP cns3xxx_std_phy_power_down(1, 0);
8774+
8775+#define PORT2_LINK_DOWN
8776+#define PORT2_LINK_UP
8777+
8778+#define MODEL "CNS3XXX validation board"
8779+
8780+static int rc_port0 = 0; // rc means reference counting, determine port open/close.
8781+
8782+#define PRINT_INFO printk
8783+
8784+// enable port
8785+// link down
8786+static inline void open_port0(void)
8787+{
8788+ if (rc_port0 == 0) {
8789+ enable_port(0, 1);
8790+ // link up
8791+ PORT0_LINK_UP
8792+ }
8793+ ++rc_port0;
8794+}
8795+
8796+static inline void close_port0(void)
8797+{
8798+ --rc_port0;
8799+ if (rc_port0 == 0) {
8800+ // link down
8801+ PORT0_LINK_DOWN
8802+ enable_port(0, 0);
8803+ }
8804+}
8805+
8806+static inline void open_port1(void)
8807+{
8808+
8809+ enable_port(1, 1);
8810+ // link up
8811+ PORT1_LINK_UP
8812+}
8813+
8814+static inline void close_port1(void)
8815+{
8816+ enable_port(1, 0);
8817+ // link down
8818+ PORT1_LINK_DOWN
8819+}
8820+
8821+static inline void open_port2(void)
8822+{
8823+
8824+ enable_port(2, 1);
8825+ // link up
8826+ PORT2_LINK_UP
8827+}
8828+
8829+static inline void close_port2(void)
8830+{
8831+ enable_port(2, 0);
8832+ // link down
8833+ PORT2_LINK_DOWN
8834+}
8835+
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)
8840+{
8841+ if (!fp_ref_cnt) {
8842+ fp_ref_cnt++;
8843+ }
8844+}
8845+
8846+static inline void close_fp(void)
8847+{
8848+ if (fp_ref_cnt) {
8849+ fp_ref_cnt--;
8850+ }
8851+}
8852+#endif
8853+
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};
8858+
8859+
8860+
8861+
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
8864+
8865+#ifdef CNS3XXX_VLAN_8021Q
8866+ #define CNS3XXX_NIC_MODE_8021Q
8867+ #ifndef CNS3XXX_NIC_MODE_8021Q
8868+ #define CNS3XXX_NON_NIC_MODE_8021Q
8869+ #endif
8870+#else
8871+ //#define CNS3XXX_VLAN_BASE_MODE
8872+ #define CNS3XXX_PORT_BASE_MODE
8873+#endif
8874+
8875+//#define CNS3XXX_PORT_BASE_MODE
8876+//
8877+#ifdef CNS3XXX_NON_NIC_MODE_8021Q
8878+
8879+#define PORT0_PVID 50
8880+#define PORT1_PVID 60
8881+#define PORT2_PVID 70
8882+#define CPU_PVID 80
8883+
8884+#define CONFIG_CNS3XXX_PORT_BASE
8885+
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};
8887+
8888+static VLANTableEntry vlan_table_entry[] =
8889+{
8890+ // vlan_index; valid; vid; wan_side; etag_pmap; mb_pmap; *my_mac;
8891+ #if 0
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},
8895+ #endif
8896+
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
8901+};
8902+
8903+static ARLTableEntry arl_table_entry[] =
8904+{
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},
8914+};
8915+
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,
8924+ 0, 0, "fp"}
8925+#endif
8926+ };
8927+
8928+#endif // CNS3XXX_PORT_BASE_MODE
8929+
8930+#ifdef CNS3XXX_PORT_BASE_MODE
8931+
8932+#define PORT0_PVID 0x1
8933+#define PORT1_PVID 0x2
8934+#define PORT2_PVID 3
8935+#define CPU_PVID 5
8936+
8937+#define CONFIG_CNS3XXX_PORT_BASE
8938+
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};
8940+
8941+static VLANTableEntry vlan_table_entry[] =
8942+{
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
8949+};
8950+
8951+static ARLTableEntry arl_table_entry[] =
8952+{
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},
8962+};
8963+
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
8969+ };
8970+
8971+#endif // CNS3XXX_PORT_BASE_MODE
8972+
8973+#ifdef CNS3XXX_NIC_MODE_8021Q
8974+//#error "8021Q"
8975+#define PORT0_PVID 1
8976+#define PORT1_PVID 2
8977+#define PORT2_PVID 9
8978+#define CPU_PVID 5
8979+
8980+#define CONFIG_CNS3XXX_PORT_BASE
8981+//#define CONFIG_CNS3XXX_VLAN_BASE
8982+//#define CONFIG_HAVE_VLAN_TAG
8983+
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
8985+
8986+static VLANTableEntry vlan_table_entry[] =
8987+{
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},
8992+};
8993+
8994+static ARLTableEntry arl_table_entry[] =
8995+{
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},
9000+};
9001+
9002+
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
9008+ };
9009+#endif // CNS3XXX_NIC_MODE_8021Q
9010+
9011+#ifdef CNS3XXX_VLAN_BASE_MODE
9012+//#error "vlan_base"
9013+// vlan configuration
9014+
9015+#define PORT0_PVID 1
9016+#define PORT1_PVID 2
9017+#define PORT2_PVID 3
9018+#define CPU_PVID 5
9019+#define CONFIG_CNS3XXX_VLAN_BASE
9020+#define CONFIG_HAVE_VLAN_TAG
9021+
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
9023+
9024+static VLANTableEntry vlan_table_entry[] =
9025+{
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},
9030+};
9031+
9032+static ARLTableEntry arl_table_entry[] =
9033+{
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},
9038+};
9039+
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
9045+ };
9046+#endif // CNS3XXX_VLAN_BASE_MODE
9047+
9048+#endif // CONFIG_VB
9049+#endif // VB_H
9050--- a/drivers/net/Kconfig
9051+++ b/drivers/net/Kconfig
9052@@ -2076,6 +2076,8 @@ menuconfig NETDEV_1000
9053 
9054 if NETDEV_1000
9055 
9056+source "drivers/net/cns3xxx/Kconfig"
9057+
9058 config ACENIC
9059     tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
9060     depends on PCI
9061--- a/drivers/net/Makefile
9062+++ b/drivers/net/Makefile
9063@@ -6,6 +6,11 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci
9064 
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
9070+endif
9071+
9072 obj-$(CONFIG_IBM_NEW_EMAC) += ibm_newemac/
9073 obj-$(CONFIG_IGB) += igb/
9074 obj-$(CONFIG_IGBVF) += igbvf/
9075--- /dev/null
9076+++ b/include/linux/cns3xxx/sppe.h
9077@@ -0,0 +1,1579 @@
9078+/*
9079+ * PROJECT CODE: CNS3XXX Smart Packet Processing Engine
9080+ * MODULE NAME: sppe.h
9081+ * DESCRIPTION:
9082+ *
9083+ * Change Log
9084+ *
9085+ * 1.0.0 25-Dec-2008
9086+ * o
9087+ *
9088+ */
9089+
9090+#ifndef _SPPE_H_
9091+#define _SPPE_H_
9092+
9093+#if defined(CONFIG_CNS3XXX_SPPE)
9094+
9095+
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)
9105+
9106+typedef enum _sppe_cmd {
9107+ SPPE_CMD_INIT = 0,
9108+ SPPE_CMD_VERSION,
9109+
9110+ SPPE_CMD_ENABLE,
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,
9117+ SPPE_CMD_RLCFG,
9118+ SPPE_CMD_FC, /* flow control */
9119+ SPPE_CMD_MIRROR_TO_CPU,
9120+
9121+ SPPE_CMD_TCP_SNA_TH,
9122+ SPPE_CMD_PRDA,
9123+ SPPE_CMD_AGING,
9124+ SPPE_CMD_MAX_LENGTH,
9125+
9126+ SPPE_CMD_LANIPV4,
9127+ SPPE_CMD_WANIPV4,
9128+
9129+ SPPE_CMD_RULE_PPPOE_RELAY,
9130+ SPPE_CMD_RULE_BRIDGE,
9131+ SPPE_CMD_RULE_ACL,
9132+ SPPE_CMD_RULE_ROUTE,
9133+#if 0
9134+ SPPE_CMD_RULE_VSERVER,
9135+#else
9136+ SPPE_CMD_RULE_SNAT,
9137+ SPPE_CMD_RULE_DNAT,
9138+#endif
9139+ SPPE_CMD_RULE_GRL,
9140+
9141+ SPPE_CMD_ARP,
9142+ SPPE_CMD_ARL,
9143+ SPPE_CMD_PPPOE_SID,
9144+
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,
9155+
9156+ SPPE_CMD_CHGDSCP,
9157+ SPPE_CMD_CHGPRI,
9158+ SPPE_CMD_RL_FLOW,
9159+ SPPE_CMD_RL_RULE,
9160+
9161+ SPPE_CMD_DEBUG,
9162+ SPPE_CMD_REG,
9163+ SPPE_CMD_SRAM,
9164+ SPPE_CMD_DUMP,
9165+
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,
9171+
9172+ SPPE_CMD_PCI_FP_DEV,
9173+
9174+} SPPE_CMD;
9175+
9176+typedef enum _sppe_op {
9177+ SPPE_OP_GET = 0,
9178+ SPPE_OP_SET,
9179+ SPPE_OP_DELETE,
9180+ SPPE_OP_DELETE_OUTDATED, /* flow only */
9181+ SPPE_OP_UPDATE_COUNTER, /* ACL rule only */
9182+ SPPE_OP_CLEAN,
9183+ SPPE_OP_UNKNOWN
9184+} SPPE_OP;
9185+
9186+typedef enum _sppe_boolean {
9187+ SPPE_BOOL_FALSE = 0,
9188+ SPPE_BOOL_TRUE = 1
9189+} SPPE_BOOL;
9190+
9191+
9192+typedef enum _sppe_result {
9193+ SPPE_RESULT_SUCCESS = 0,
9194+ SPPE_RESULT_FAIL,
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,
9200+} SPPE_RESULT;
9201+
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,
9207+} SPPE_PROT;
9208+
9209+
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,
9215+} SPPE_L2_SELECT;
9216+
9217+typedef enum _sppe_dump_type {
9218+ SPPE_DUMP_TYPE_FLOW = 0,
9219+ SPPE_DUMP_TYPE_ARP,
9220+ SPPE_DUMP_TYPE_RULE
9221+} SPPE_DUMP_TYPE;
9222+
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;
9228+#else
9229+ unsigned int unused:31;
9230+ unsigned int valid:1;
9231+#endif
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;
9237+
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;
9251+#else
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;
9263+#endif
9264+
9265+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9266+ unsigned int svid:12;
9267+ unsigned int cvid:12;
9268+ unsigned int loc:8;
9269+#else
9270+ unsigned int loc:8;
9271+ unsigned int cvid:12;
9272+ unsigned int svid:12;
9273+#endif
9274+
9275+ unsigned char smac[6]; /* source MAC address */
9276+ unsigned char dmac[6]; /* destination MAC address */
9277+ unsigned int pkt_cnt;
9278+} SPPE_BRIDGE;
9279+
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;
9295+#else
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;
9309+#endif
9310+
9311+ unsigned int sip[4];
9312+ unsigned int dip[4];
9313+ unsigned short sip_mask;
9314+ unsigned short dip_mask;
9315+
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;
9321+} SPPE_ACL;
9322+
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;
9342+#else
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;
9360+#endif
9361+
9362+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9363+ unsigned int unused_1:24;
9364+ unsigned int loc:8;
9365+#else
9366+ unsigned int loc:8;
9367+ unsigned int unused_1:24;
9368+#endif
9369+
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;
9375+} SPPE_ROUTE;
9376+
9377+#if 0
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;
9387+
9388+ unsigned int wanip;
9389+ unsigned int lanip;
9390+ unsigned short port_start;
9391+ unsigned short port_end;
9392+ unsigned int pkt_cnt;
9393+} SPPE_VSERVER;
9394+#else
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;
9414+#else
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;
9432+#endif
9433+
9434+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9435+ unsigned int unused_1:24;
9436+ unsigned int loc:8;
9437+#else
9438+ unsigned int loc:8;
9439+ unsigned int unused_1:24;
9440+#endif
9441+
9442+ unsigned int wanip;
9443+ unsigned int lanip;
9444+ unsigned short port_start;
9445+ unsigned short port_end;
9446+ unsigned int pkt_cnt;
9447+} SPPE_SNAT;
9448+
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;
9468+#else
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;
9486+#endif
9487+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9488+ unsigned int unused_1:24;
9489+ unsigned int loc:8;
9490+#else
9491+ unsigned int loc:8;
9492+ unsigned int unused_1:24;
9493+#endif
9494+
9495+ unsigned int wanip;
9496+ unsigned int lanip;
9497+ unsigned short port_start;
9498+ unsigned short port_end;
9499+ unsigned int pkt_cnt;
9500+} SPPE_DNAT;
9501+#endif
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;
9510+#else
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;
9517+#endif
9518+ unsigned short min_rate;
9519+ unsigned short max_rate;
9520+} SPPE_LIMIT;
9521+
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;
9530+#else
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;
9537+#endif
9538+
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;
9547+ SPPE_LIMIT limit;
9548+} SPPE_GLOBAL_RATE_LIMIT;
9549+
9550+/*
9551+ * SPPE_CMD_FLOW_BRIDGE_IPV4
9552+ * type = 1 , as = 3
9553+ */
9554+typedef struct _sppe_flow_bridge_ipv4 {
9555+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9556+ unsigned int fw:1;
9557+ unsigned int s: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;
9569+#else
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;
9581+ unsigned int s:1;
9582+ unsigned int fw:1;
9583+#endif
9584+
9585+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9586+ unsigned int unused:16;
9587+ unsigned int mac4732:16;
9588+#else
9589+ unsigned int mac4732:16;
9590+ unsigned int unused:16;
9591+#endif
9592+
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;
9602+#else
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;
9610+#endif
9611+ unsigned int sip;
9612+ unsigned int dip;
9613+
9614+ union {
9615+ struct {
9616+ unsigned short src;
9617+ unsigned short dst;
9618+ } port;
9619+ struct {
9620+ unsigned short call_id;
9621+ } gre;
9622+ struct {
9623+ unsigned char protocol;
9624+ } others;
9625+ } l4;
9626+
9627+ SPPE_LIMIT limit;
9628+ unsigned int pkt_cnt;
9629+} SPPE_FLOW_BRIDGE_IPV4;
9630+
9631+/*
9632+ * SPPE_CMD_FLOW_BRIDGE_IPV6
9633+ * type = 2 , as = 3
9634+ */
9635+typedef struct _sppe_flow_bridge_ipv6 {
9636+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9637+ unsigned int fw:1;
9638+ unsigned int s: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;
9650+#else
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;
9662+ unsigned int s:1;
9663+ unsigned int fw:1;
9664+#endif
9665+
9666+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9667+ unsigned int unused:16;
9668+ unsigned int mac4732:16;
9669+#else
9670+ unsigned int mac4732:16;
9671+ unsigned int unused:16;
9672+#endif
9673+
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;
9683+#else
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;
9691+#endif
9692+ unsigned int sip[4];
9693+ unsigned int dip[4];
9694+ union {
9695+ struct {
9696+ unsigned short src;
9697+ unsigned short dst;
9698+ } port;
9699+ struct {
9700+ unsigned short call_id;
9701+ } gre;
9702+ struct {
9703+ unsigned char protocol;
9704+ } others;
9705+ } l4;
9706+ SPPE_LIMIT limit;
9707+ unsigned int pkt_cnt;
9708+} SPPE_FLOW_BRIDGE_IPV6;
9709+
9710+/*
9711+ * SPPE_CMD_FLOW_ROUTE_IPV4
9712+ * type = 1, as = 0
9713+ */
9714+typedef struct _sppe_flow_route_ipv4 {
9715+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9716+ unsigned int fw:1;
9717+ unsigned int s: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;
9733+#else
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;
9749+ unsigned int s:1;
9750+ unsigned int fw:1;
9751+#endif
9752+
9753+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9754+ unsigned int unused:16;
9755+ unsigned int mac4732:16;
9756+#else
9757+ unsigned int mac4732:16;
9758+ unsigned int unused:16;
9759+#endif
9760+ unsigned int mac3100;
9761+
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;
9770+#else
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;
9778+#endif
9779+
9780+ unsigned int sip;
9781+ unsigned int dip;
9782+ union {
9783+ struct {
9784+ unsigned short src;
9785+ unsigned short dst;
9786+ } port;
9787+ struct {
9788+ unsigned short call_id;
9789+ } gre;
9790+ struct {
9791+ unsigned char protocol;
9792+ } others;
9793+ } l4;
9794+ SPPE_LIMIT limit;
9795+ unsigned int pkt_cnt;
9796+} SPPE_FLOW_ROUTE_IPV4;
9797+
9798+/*
9799+ * SPPE_CMD_FLOW_ROUTE_IPV6
9800+ * type = 2, as = 0
9801+ */
9802+typedef struct _sppe_flow_route_ipv6 {
9803+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9804+ unsigned int fw:1;
9805+ unsigned int s: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;
9821+#else
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;
9837+ unsigned int s:1;
9838+ unsigned int fw:1;
9839+#endif
9840+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9841+ unsigned int unused:16;
9842+ unsigned int mac4732:16;
9843+#else
9844+ unsigned int mac4732:16;
9845+ unsigned int unused:16;
9846+#endif
9847+ unsigned int mac3100;
9848+
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;
9857+#else
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;
9865+#endif
9866+ unsigned int sip[4];
9867+ unsigned int dip[4];
9868+ union {
9869+ struct {
9870+ unsigned short src;
9871+ unsigned short dst;
9872+ } port;
9873+ struct {
9874+ unsigned short call_id;
9875+ } gre;
9876+ struct {
9877+ unsigned char protocol;
9878+ } others;
9879+ } l4;
9880+ SPPE_LIMIT limit;
9881+ unsigned int pkt_cnt;
9882+} SPPE_FLOW_ROUTE_IPV6;
9883+
9884+/*
9885+ * SPPE_CMD_FLOW_NAT_IPV4
9886+ * type = 0, as = 1
9887+ */
9888+typedef struct _sppe_flow_nat_ipv4 {
9889+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9890+ unsigned int fw:1;
9891+ unsigned int s: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;
9907+#else
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;
9923+ unsigned int s:1;
9924+ unsigned int fw:1;
9925+#endif
9926+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9927+ unsigned int unused:16;
9928+ unsigned int mac4732:16;
9929+#else
9930+ unsigned int mac4732:16;
9931+ unsigned int unused:16;
9932+#endif
9933+
9934+ unsigned int mac3100;
9935+
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;
9944+#else
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;
9952+#endif
9953+
9954+ unsigned int sip;
9955+ unsigned int dip;
9956+ union {
9957+ struct {
9958+ unsigned short src;
9959+ unsigned short dst;
9960+ } port;
9961+ struct {
9962+ unsigned short call_id;
9963+ unsigned short nat_call_id;
9964+ } gre;
9965+ struct {
9966+ unsigned char protocol;
9967+ } others;
9968+ } l4;
9969+ unsigned int nat_ip;
9970+ unsigned short nat_port;
9971+ SPPE_LIMIT limit;
9972+ unsigned int pkt_cnt;
9973+} SPPE_FLOW_NAT_IPV4;
9974+
9975+/*
9976+ * SPPE_CMD_FLOW_NAT_IPV6
9977+ * type = 1, as = 1
9978+ */
9979+typedef struct _sppe_flow_nat_ipv6 {
9980+#ifndef CONFIG_SWITCH_BIG_ENDIAN
9981+ unsigned int fw:1;
9982+ unsigned int s: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;
9998+#else
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;
10016+#endif
10017+#ifndef CONFIG_SWITCH_BIG_ENDIAN
10018+ unsigned int unused:16;
10019+ unsigned int mac4732:16;
10020+#else
10021+ unsigned int mac4732:16;
10022+ unsigned int unused:16;
10023+#endif
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;
10033+#else
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;
10041+#endif
10042+ unsigned int sip[4];
10043+ unsigned int dip[4];
10044+ union {
10045+ struct {
10046+ unsigned short src;
10047+ unsigned short dst;
10048+ } port;
10049+ struct {
10050+ unsigned short call_id;
10051+ unsigned short nat_call_id;
10052+ } gre;
10053+ struct {
10054+ unsigned char protocol;
10055+ } others;
10056+ } l4;
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;
10062+
10063+/*
10064+ * SPPE_CMD_FLOW_TWICE_NAT
10065+ * type = 0, as = 2
10066+ */
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;
10085+#else
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;
10102+#endif
10103+
10104+#ifndef CONFIG_SWITCH_BIG_ENDIAN
10105+ unsigned int unused:16;
10106+ unsigned int mac4732:16;
10107+#else
10108+ unsigned int mac4732:16;
10109+ unsigned int unused:16;
10110+#endif
10111+ unsigned int mac3100;
10112+
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;
10121+#else
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;
10129+#endif
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;
10141+
10142+/*
10143+ * SPPE_CMD_FLOW_MULTICAST_IPV4
10144+ * type = 0, as = 0 or 3
10145+ */
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;
10163+#else
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;
10179+#endif
10180+#ifndef CONFIG_SWITCH_BIG_ENDIAN
10181+ unsigned int unused:16;
10182+ unsigned int mac4732:16;
10183+#else
10184+ unsigned int mac4732:16;
10185+ unsigned int unused:16;
10186+#endif
10187+ unsigned int mac3100;
10188+
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;
10197+#else
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;
10205+#endif
10206+
10207+ unsigned int sip;
10208+ unsigned int dip;
10209+ SPPE_LIMIT limit;
10210+ unsigned int pkt_cnt;
10211+} SPPE_FLOW_MCAST_IPV4;
10212+
10213+/*
10214+ * SPPE_CMD_FLOW_MULTICAST_IPV6
10215+ * type = 1, as = 0 or 3
10216+ */
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;
10234+#else
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;
10250+#endif
10251+
10252+#ifndef CONFIG_SWITCH_BIG_ENDIAN
10253+ unsigned int unused:16;
10254+ unsigned int mac4732:16;
10255+#else
10256+ unsigned int mac4732:16;
10257+ unsigned int unused:16;
10258+#endif
10259+ unsigned int mac3100;
10260+
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;
10269+#else
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;
10277+#endif
10278+
10279+ unsigned int sip[4];
10280+ unsigned int dip[4];
10281+ SPPE_LIMIT limit;
10282+ unsigned int pkt_cnt;
10283+} SPPE_FLOW_MCAST_IPV6;
10284+
10285+/*
10286+ * SPPE_CMD_FLOW_LAYER_TWO
10287+ * type = 2
10288+ */
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;
10302+#else
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;
10314+#endif
10315+
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;
10324+#else
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;
10332+#endif
10333+
10334+ unsigned short smac[3];
10335+ unsigned short dmac[3];
10336+
10337+ SPPE_LIMIT limit;
10338+ unsigned int pkt_cnt;
10339+} SPPE_FLOW_BRIDGE_L2;
10340+
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;
10349+#else
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;
10356+#endif
10357+ unsigned char mac[6];
10358+} SPPE_ARL;
10359+
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;
10374+} SPPE_INIT;
10375+
10376+typedef struct _sppe_param_t {
10377+ SPPE_CMD cmd;
10378+ SPPE_OP op;
10379+
10380+ union {
10381+ struct {
10382+ unsigned char major;
10383+ unsigned char minor;
10384+ unsigned char very_minor;
10385+ unsigned char pre;
10386+ } sppe_version;
10387+
10388+ SPPE_BOOL sppe_enable;
10389+ unsigned int sppe_lanip;
10390+
10391+ struct {
10392+ unsigned int index;
10393+ unsigned int ip;
10394+ unsigned int session_id;
10395+ } sppe_wanip;
10396+
10397+ struct {
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;
10405+#else
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;
10412+#endif
10413+ unsigned char mac[6]; /* MAC address */
10414+ } sppe_prda;
10415+
10416+ struct {
10417+#ifndef CONFIG_SWITCH_BIG_ENDIAN
10418+ unsigned int interval:2;
10419+ unsigned int mfactor:1;
10420+ unsigned int ununsed:29;
10421+#else
10422+ unsigned int ununsed:29;
10423+ unsigned int mfactor:1;
10424+ unsigned int interval:2;
10425+#endif
10426+ } sppe_rlcfg;
10427+
10428+ struct {
10429+ unsigned int index;
10430+ SPPE_PPPOE_RELAY rule;
10431+ } sppe_pppoe_relay;
10432+
10433+ struct {
10434+ unsigned int index;
10435+ SPPE_BRIDGE rule;
10436+ } sppe_bridge;
10437+
10438+ struct {
10439+ unsigned int index;
10440+ SPPE_ACL rule;
10441+ } sppe_acl;
10442+
10443+ struct {
10444+ unsigned int index;
10445+ SPPE_ROUTE rule;
10446+ } sppe_route;
10447+#if 0
10448+ struct {
10449+ unsigned int index;
10450+ SPPE_VSERVER rule;
10451+ } sppe_vserver;
10452+#else
10453+ struct {
10454+ unsigned int index;
10455+ SPPE_SNAT rule;
10456+ } sppe_snat;
10457+
10458+ struct {
10459+ unsigned int index;
10460+ SPPE_DNAT rule;
10461+ } sppe_dnat;
10462+#endif
10463+ struct {
10464+ unsigned int index;
10465+ SPPE_GLOBAL_RATE_LIMIT rule;
10466+ } sppe_grl;
10467+
10468+ struct {
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;
10476+ } sppe_agingout;
10477+
10478+ struct {
10479+#ifndef CONFIG_SWITCH_BIG_ENDIAN
10480+ unsigned int index:2;
10481+ unsigned int reserved:20;
10482+ unsigned int max:10;
10483+#else
10484+ unsigned int max:10;
10485+ unsigned int reserved:20;
10486+ unsigned int index:2;
10487+#endif
10488+ } sppe_max_length;
10489+
10490+ struct {
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;
10498+#else
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;
10505+#endif
10506+
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;
10513+#else
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;
10519+#endif
10520+ unsigned int ip[4];
10521+ unsigned char mac[6];
10522+ } sppe_arp;
10523+
10524+ SPPE_ARL sppe_arl;
10525+
10526+ struct {
10527+ unsigned int sid;
10528+ unsigned int index;
10529+ } sppe_pppoe_sid;
10530+
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;
10541+
10542+ struct {
10543+ SPPE_DUMP_TYPE type;
10544+ unsigned short key;
10545+ unsigned short way;
10546+ unsigned int raw[23];
10547+ } sppe_dump;
10548+
10549+ unsigned int sppe_sna_th;
10550+
10551+ struct {
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;
10557+#else
10558+ unsigned int reserved:19;
10559+ unsigned int wan:6;
10560+ unsigned int lan:6;
10561+ unsigned int enable:1;
10562+#endif
10563+ } sppe_chgdscp;
10564+
10565+ struct {
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;
10571+#else
10572+ unsigned int reserved:25;
10573+ unsigned int wan:3;
10574+ unsigned int lan:3;
10575+ unsigned int enable:1;
10576+#endif
10577+ } sppe_chgpri;
10578+
10579+ struct {
10580+ int enable;
10581+ int module;
10582+ int level;
10583+ } sppe_debug;
10584+
10585+ struct {
10586+ unsigned int offset;
10587+ unsigned int data;
10588+ } sppe_reg;
10589+
10590+ struct {
10591+ unsigned int offset;
10592+ unsigned int data;
10593+ } sppe_sram;
10594+
10595+ struct {
10596+ char enable;
10597+ unsigned int max;
10598+ unsigned int min;
10599+ char drop_red;
10600+ char pass_green;
10601+ } sppe_rl_flow;
10602+
10603+ struct {
10604+ char enable;
10605+ unsigned int max;
10606+ unsigned int min;
10607+ char drop_red;
10608+ char pass_green;
10609+ } sppe_rl_rule;
10610+
10611+ struct {
10612+ unsigned int index;
10613+ unsigned short start;
10614+ unsigned short end;
10615+ SPPE_LIMIT limit;
10616+ } sppe_bm_flow;
10617+
10618+ struct {
10619+ unsigned int index;
10620+ unsigned int pkt_cnt;
10621+ unsigned int byte_cnt;
10622+ } sppe_accounting_group;
10623+
10624+ struct {
10625+ unsigned int pkt_cnt;
10626+ } sppe_drop_ipcs_err; /* IP checksum error */
10627+
10628+ struct {
10629+ unsigned int pkt_cnt;
10630+ } sppe_drop_rate_limit;
10631+
10632+ struct {
10633+ unsigned int pkt_cnt;
10634+ } sppe_drop_others;
10635+
10636+ struct {
10637+ unsigned int index;
10638+ unsigned char name[16];
10639+ struct net_device *dev;
10640+ unsigned int vid;
10641+ } sppe_pci_fp_dev;
10642+
10643+ SPPE_INIT sppe_init;
10644+
10645+ } data;
10646+} SPPE_PARAM;
10647+
10648+extern int sppe_hook_ready;
10649+extern int (*sppe_func_hook)(SPPE_PARAM *param);
10650+
10651+extern int sppe_pci_fp_ready;
10652+extern int (*sppe_pci_fp_hook)(SPPE_PARAM *param);
10653+
10654+#endif /* CONFIG_CNS3XXX_SPPE */
10655+
10656+#endif /* _SPPE_H_ */
10657--- /dev/null
10658+++ b/include/linux/cns3xxx/switch_api.h
10659@@ -0,0 +1,366 @@
10660+/*******************************************************************************
10661+ *
10662+ * Copyright (c) 2008 Cavium Networks
10663+ *
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.
10668+ *
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
10672+ * more details.
10673+ *
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.
10677+ *
10678+ * The full GNU General Public License is included in this distribution in the
10679+ * file called LICENSE.
10680+ *
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
10684+ *
10685+ ********************************************************************************/
10686+
10687+#ifndef SWITCH_API_H_K
10688+#define SWITCH_API_H_K
10689+
10690+
10691+#ifndef __KERNEL__
10692+typedef unsigned int u32;
10693+typedef unsigned short int u16;
10694+typedef unsigned char u8;
10695+typedef int s32;
10696+#else
10697+
10698+#include <linux/types.h>
10699+
10700+#endif
10701+
10702+
10703+#define CAVM_OK 0
10704+#define CAVM_ERR 1
10705+#define CAVM_NOT_FOUND 2
10706+#define CAVM_FOUND 3
10707+#define CAVM_FAIL -1 // use minus
10708+
10709+#define MAC_PORT0 0
10710+#define MAC_PORT1 1
10711+#define MAC_PORT2 2
10712+#define CPU_PORT 3
10713+
10714+typedef enum
10715+{
10716+
10717+
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,
10725+
10726+ CNS3XXX_VLAN_TABLE_LOOKUP,
10727+ CNS3XXX_VLAN_TABLE_ADD,
10728+ CNS3XXX_VLAN_TABLE_DEL,
10729+ CNS3XXX_VLAN_TABLE_READ,
10730+
10731+ CNS3XXX_SKEW_SET,
10732+ CNS3XXX_SKEW_GET,
10733+
10734+ CNS3XXX_BRIDGE_SET,
10735+ CNS3XXX_BRIDGE_GET,
10736+
10737+ CNS3XXX_PORT_NEIGHBOR_SET,
10738+ CNS3XXX_PORT_NEIGHBOR_GET,
10739+
10740+ CNS3XXX_HOL_PREVENT_SET,
10741+ CNS3XXX_HOL_PREVENT_GET,
10742+
10743+ CNS3XXX_TC_SET, // traffic class, for 1, 2, 4, traffic class
10744+ CNS3XXX_TC_GET,
10745+
10746+ CNS3XXX_PRI_CTRL_SET,
10747+ CNS3XXX_PRI_CTRL_GET,
10748+
10749+ CNS3XXX_DMA_RING_CTRL_SET,
10750+ CNS3XXX_DMA_RING_CTRL_GET,
10751+
10752+ CNS3XXX_PRI_IP_DSCP_SET,
10753+ CNS3XXX_PRI_IP_DSCP_GET,
10754+
10755+ CNS3XXX_ETYPE_SET,
10756+ CNS3XXX_ETYPE_GET,
10757+
10758+ CNS3XXX_UDP_RANGE_SET,
10759+ CNS3XXX_UDP_RANGE_GET,
10760+
10761+ CNS3XXX_ARP_REQUEST_SET,
10762+ CNS3XXX_ARP_REQUEST_GET,
10763+
10764+ CNS3XXX_RATE_LIMIT_SET,
10765+ CNS3XXX_RATE_LIMIT_GET,
10766+
10767+ CNS3XXX_QUEUE_WEIGHT_SET,
10768+ CNS3XXX_QUEUE_WEIGHT_GET,
10769+
10770+ CNS3XXX_FC_RLS_SET,
10771+ CNS3XXX_FC_RLS_GET,
10772+
10773+ CNS3XXX_FC_SET_SET,
10774+ CNS3XXX_FC_SET_GET,
10775+
10776+ CNS3XXX_SARL_RLS_SET,
10777+ CNS3XXX_SARL_RLS_GET,
10778+
10779+ CNS3XXX_SARL_SET_SET,
10780+ CNS3XXX_SARL_SET_GET,
10781+
10782+ CNS3XXX_SARL_OQ_SET,
10783+ CNS3XXX_SARL_OQ_GET,
10784+
10785+ CNS3XXX_SARL_ENABLE_SET,
10786+ CNS3XXX_SARL_ENABLE_GET,
10787+
10788+ CNS3XXX_FC_SET,
10789+ CNS3XXX_FC_GET,
10790+
10791+ CNS3XXX_IVL_SET,
10792+ CNS3XXX_IVL_GET,
10793+
10794+ CNS3XXX_WAN_PORT_SET,
10795+ CNS3XXX_WAN_PORT_GET,
10796+
10797+ CNS3XXX_PVID_GET,
10798+ CNS3XXX_PVID_SET,
10799+
10800+ CNS3XXX_QA_GET, // queue allocate
10801+ CNS3XXX_QA_SET,
10802+
10803+ CNS3XXX_PACKET_MAX_LEN_GET, // set maximun frame length.
10804+ CNS3XXX_PACKET_MAX_LEN_SET,
10805+
10806+ CNS3XXX_BCM53115M_REG_READ,
10807+ CNS3XXX_BCM53115M_REG_WRITE,
10808+
10809+ CNS3XXX_RXRING_STATUS,
10810+ CNS3XXX_TXRING_STATUS,
10811+
10812+ CNS3XXX_DUMP_MIB_COUNTER,
10813+
10814+ CNS3XXX_REG_READ,
10815+ CNS3XXX_REG_WRITE,
10816+
10817+}CNS3XXXIoctlCmd;
10818+
10819+typedef struct
10820+{
10821+ u8 vlan_index;
10822+ u8 valid;
10823+ u16 vid;
10824+ u8 wan_side;
10825+ u8 etag_pmap;
10826+ u8 mb_pmap;
10827+ //u8 my_mac[6];
10828+ u8 *my_mac;
10829+}VLANTableEntry; // for vlan table function
10830+
10831+typedef struct
10832+{
10833+ u16 vid;
10834+ u8 pmap;
10835+ //u8 mac[6];
10836+ u8 *mac;
10837+ u8 age_field;
10838+ u8 vlan_mac;
10839+ u8 filter;
10840+}ARLTableEntry; // for arl table function
10841+
10842+
10843+typedef struct
10844+{
10845+ CNS3XXXIoctlCmd cmd;
10846+ ARLTableEntry entry;
10847+}CNS3XXXARLTableEntry; // for ioctl arl ...
10848+
10849+typedef struct
10850+{
10851+ CNS3XXXIoctlCmd cmd;
10852+ VLANTableEntry entry;
10853+}CNS3XXXVLANTableEntry; // for ioctl VLAN table ...
10854+
10855+typedef struct
10856+{
10857+ CNS3XXXIoctlCmd cmd;
10858+ u8 enable;
10859+}CNS3XXXHOLPreventControl;
10860+
10861+
10862+typedef struct
10863+{
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;
10868+
10869+typedef struct
10870+{
10871+ CNS3XXXIoctlCmd cmd;
10872+ unsigned char type; // 0: C-Component, 1: S-Component
10873+}CNS3XXXBridgeControl;
10874+
10875+typedef struct
10876+{
10877+ CNS3XXXIoctlCmd cmd;
10878+ unsigned char tc; // traffic class, for 1, 2, 4, traffic class
10879+}CNS3XXXTrafficClassControl;
10880+
10881+typedef struct
10882+{
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;
10892+
10893+typedef struct
10894+{
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;
10900+
10901+typedef struct
10902+{
10903+ CNS3XXXIoctlCmd cmd;
10904+ unsigned int ip_dscp_num; // 0 ~ 63
10905+ unsigned char pri; // 3 bits
10906+}CNS3XXXPriIpDscpControl;
10907+
10908+typedef struct
10909+{
10910+ CNS3XXXIoctlCmd cmd;
10911+ unsigned int etype_num;
10912+ unsigned int val;
10913+ unsigned int pri;
10914+}CNS3XXXEtypeControl;
10915+
10916+typedef struct
10917+{
10918+ CNS3XXXIoctlCmd cmd;
10919+ unsigned int udp_range_num;
10920+ unsigned short int port_start;
10921+ unsigned short int port_end;
10922+}CNS3XXXUdpRangeEtypeControl;
10923+
10924+typedef struct
10925+{
10926+ CNS3XXXIoctlCmd cmd;
10927+ unsigned char val; // 0: boradcast forward, 1: redirect to the CPU
10928+}CNS3XXXArpRequestControl;
10929+
10930+typedef struct
10931+{
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;
10936+
10937+}CNS3XXXRateLimitEntry; // for ioctl arl ...
10938+
10939+typedef struct
10940+{
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 ...
10949+
10950+typedef struct
10951+{
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 ...
10957+
10958+typedef struct
10959+{
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 ...
10964+
10965+typedef struct
10966+{
10967+ CNS3XXXIoctlCmd cmd;
10968+ unsigned char enable; // enable: 1 -> IVL, enable: 0 -> SVL
10969+}CNS3XXXIVLEntry; // for ioctl arl ...
10970+
10971+typedef struct
10972+{
10973+ CNS3XXXIoctlCmd cmd;
10974+ unsigned char wan_port;
10975+}CNS3XXXWANPortEntry; // for ioctl arl ...
10976+
10977+typedef struct
10978+{
10979+ CNS3XXXIoctlCmd cmd;
10980+ unsigned char which_port;
10981+ unsigned int pvid;
10982+}CNS3XXXPVIDEntry; // for ioctl arl ...
10983+
10984+typedef struct
10985+{
10986+ CNS3XXXIoctlCmd cmd;
10987+ unsigned char qa; // queue allocate
10988+}CNS3XXXQAEntry; // for ioctl arl ...
10989+
10990+typedef struct
10991+{
10992+ CNS3XXXIoctlCmd cmd;
10993+ unsigned char max_len; // maximum frame length
10994+}CNS3XXXMaxLenEntry; // for ioctl arl ...
10995+
10996+typedef struct
10997+{
10998+ CNS3XXXIoctlCmd cmd;
10999+ u8 page;
11000+ u8 offset;
11001+ u32 u32_val;
11002+ u16 u16_val;
11003+ u8 u8_val;
11004+ u8 data_len;
11005+
11006+}CNS3XXXBCM53115M;
11007+
11008+typedef struct
11009+{
11010+ CNS3XXXIoctlCmd cmd;
11011+ u32 mib[52];
11012+ u16 mib_len;
11013+}CNS3XXXMIBCounter;
11014+
11015+#if 0
11016+typedef struct
11017+{
11018+ CNS3XXXIoctlCmd cmd;
11019+ TXRing *tx_ring;
11020+ RXRing *rx_ring;
11021+}CNS3XXXRingStatus;
11022+#endif
11023+
11024+
11025+#endif
11026--- a/net/core/dev.c
11027+++ b/net/core/dev.c
11028@@ -133,6 +133,10 @@
11029 
11030 #include "net-sysfs.h"
11031 
11032+#if defined (CONFIG_CNS3XXX_SPPE)
11033+#include <linux/cns3xxx/sppe.h>
11034+#endif
11035+
11036 /* Instead of increasing this, you should create a hash table. */
11037 #define MAX_GRO_SKBS 8
11038 
11039@@ -1944,6 +1948,197 @@ int weight_p __read_mostly = 64;
11040 
11041 DEFINE_PER_CPU(struct netif_rx_stats, netdev_rx_stat) = { 0, };
11042 
11043+#if defined (CONFIG_CNS3XXX_SPPE)
11044+static struct net_device *tun_netdev = NULL;
11045+
11046+int sppe_pci_fp(struct sk_buff *skb)
11047+{
11048+ SPPE_PARAM param;
11049+ struct iphdr *iph;
11050+#if defined (CONFIG_IPV6)
11051+ struct ipv6hdr *ipv6h;
11052+#endif
11053+ struct tcphdr *th;
11054+ struct udphdr *uh;
11055+ int pci_dev_index;
11056+
11057+ if (!sppe_hook_ready) {
11058+ goto NOT_IN_FP;
11059+ }
11060+
11061+ if (!sppe_pci_fp_ready) {
11062+ goto NOT_IN_FP;
11063+ }
11064+
11065+ /* check device packet comes from, is a registed device? */
11066+ memset(&param, 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(&param);
11071+
11072+ pci_dev_index = param.data.sppe_pci_fp_dev.index;
11073+
11074+ if ((-1) == pci_dev_index) {
11075+ goto NOT_IN_FP;
11076+ }
11077+
11078+ if (!tun_netdev) {
11079+ tun_netdev = dev_get_by_name(&init_net, "fp");
11080+
11081+ if (!tun_netdev) {
11082+ goto NOT_IN_FP;
11083+ }
11084+ }
11085+
11086+ /* check PPE status */
11087+ memset(&param, 0, sizeof(SPPE_PARAM));
11088+ param.cmd = SPPE_CMD_ENABLE;
11089+ param.op = SPPE_OP_GET;
11090+
11091+ if (sppe_func_hook(&param)) {
11092+ printk("<0><%s> fail to get PPE status!!\n", __FUNCTION__);
11093+ goto NOT_IN_FP;
11094+ }
11095+
11096+ if (!param.data.sppe_enable) {
11097+ goto NOT_IN_FP;
11098+ }
11099+
11100+ memset(&param, 0, sizeof(SPPE_PARAM));
11101+
11102+ switch (htons(skb->protocol)) {
11103+ case ETH_P_IP:
11104+ iph = (struct iphdr *)skb->data;
11105+
11106+ if (5 != iph->ihl) { goto NOT_IN_FP; }
11107+
11108+ if (iph->frag_off & 0x20) { goto NOT_IN_FP; }
11109+
11110+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11111+ param.op = SPPE_OP_GET;
11112+
11113+ param.data.flow_nat_ipv4.sip = ntohl(iph->saddr);
11114+ param.data.flow_nat_ipv4.dip = ntohl(iph->daddr);
11115+
11116+ switch (iph->protocol) {
11117+ case IPPROTO_TCP:
11118+ th = (struct tcphdr *) ((int *)iph + 5); /* IP header length is 20 */
11119+
11120+ if ((th->syn) || (th->fin) || (th->rst)) { goto NOT_IN_FP; }
11121+
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);
11125+ break;
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);
11131+ break;
11132+ default:
11133+ goto NOT_IN_FP;
11134+ }
11135+
11136+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(&param)) {
11137+ goto NOT_IN_FP;
11138+ } else {
11139+ struct ethhdr *eth;
11140+
11141+ eth = (struct ethhdr *)skb->mac_header;
11142+
11143+ memset(&param, 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;
11155+
11156+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(&param)) {
11157+ printk("add ARP fail\n");
11158+ #if 0
11159+ } else {
11160+ param.data.sppe_arp.unused_1 = 0xf;
11161+ param.op = SPPE_OP_GET;
11162+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(&param)) {
11163+ printk("read ARP fail\n");
11164+ } else {
11165+ printk("param.data.sppe_arp.unused_1 %d\n", param.data.sppe_arp.unused_1);
11166+ }
11167+ #endif
11168+ }
11169+ }
11170+ break; /* case ETH_P_IP: */
11171+#if defined (CONFIG_IPV6)
11172+ case ETH_P_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 */
11177+
11178+ if ((th->syn) || (th->fin) || (th->rst)) { goto NOT_IN_FP; }
11179+
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;
11184+ break;
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);
11190+ break;
11191+ default:
11192+ goto NOT_IN_FP;
11193+ }
11194+
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]);
11203+
11204+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11205+ param.op = SPPE_OP_GET;
11206+
11207+ if (SPPE_RESULT_SUCCESS != sppe_func_hook(&param)) {
11208+ goto NOT_IN_FP;
11209+ }
11210+
11211+ break; /* case ETH_P_IPV6: */
11212+#endif
11213+ case ETH_P_PPP_SES:
11214+ break;
11215+ default: /* unsupport protocol */
11216+ goto NOT_IN_FP;
11217+ }
11218+ /* Update counter */
11219+ skb->dev = tun_netdev;
11220+ skb->ip_summed = CHECKSUM_NONE;
11221+ skb_push(skb, ETH_HLEN);
11222+
11223+ dev_queue_xmit(skb);
11224+
11225+return 0;
11226+
11227+NOT_IN_FP:
11228+ return (-1);
11229+}
11230+#endif
11231+
11232+
11233+
11234 
11235 /**
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;
11240 
11241+#if defined (CONFIG_CNS3XXX_SPPE)
11242+ if (0 == sppe_pci_fp(skb)) {
11243+ return NET_RX_SUCCESS;
11244+ }
11245+#endif
11246+
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);
11253 
11254+#if defined (CONFIG_CNS3XXX_SPPE)
11255+ if (0 == sppe_pci_fp(skb)) {
11256+ return NET_RX_SUCCESS;
11257+ }
11258+#endif
11259+
11260     if (skb->vlan_tci && vlan_hwaccel_do_receive(skb))
11261         return NET_RX_SUCCESS;
11262 
11263--- a/net/netfilter/nf_conntrack_core.c
11264+++ b/net/netfilter/nf_conntrack_core.c
11265@@ -42,6 +42,9 @@
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>
11271+#endif
11272 
11273 #define NF_CONNTRACK_VERSION "0.5.0"
11274 
11275@@ -275,6 +278,92 @@ void nf_ct_insert_dying_list(struct nf_c
11276 }
11277 EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
11278 
11279+#if defined (CONFIG_CNS3XXX_SPPE)
11280+static int sppe_flow_del(struct nf_conn *ct)
11281+{
11282+ if (sppe_hook_ready) {
11283+ SPPE_PARAM param;
11284+
11285+ struct nf_conntrack_tuple *orig, *reply;
11286+
11287+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11288+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11289+
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;
11294+ } else {
11295+ goto SPPE_FLOW_DEL_FINI;
11296+ }
11297+
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;
11304+ } else {
11305+ goto SPPE_FLOW_DEL_FINI;
11306+ }
11307+
11308+ param.op = SPPE_OP_DELETE_OUTDATED;
11309+
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);
11322+ } else {
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);
11327+ }
11328+
11329+ if (SPPE_RESULT_FAIL == sppe_func_hook(&param)) {
11330+ return (-1);
11331+ }
11332+
11333+ param.data.flow_nat_ipv4.fw = 1;
11334+
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]);
11344+
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);
11347+ } else {
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);
11352+ }
11353+
11354+ if (SPPE_RESULT_FAIL == sppe_func_hook(&param)) {
11355+ return (-1);
11356+ }
11357+ }
11358+
11359+SPPE_FLOW_DEL_FINI:
11360+ return 0;
11361+}
11362+#endif
11363+
11364+
11365 static void death_by_timeout(unsigned long ul_conntrack)
11366 {
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);
11371     nf_ct_put(ct);
11372+
11373+#if defined (CONFIG_CNS3XXX_SPPE)
11374+ if (sppe_flow_del(ct)) {
11375+ #if 0
11376+ ct->timeout.expires = jiffies + (120*HZ);
11377+ add_timer(&ct->timeout);
11378+ #endif
11379+ }
11380+#endif
11381+
11382 }
11383 
11384 /*
11385--- a/net/netfilter/nf_conntrack_proto_gre.c
11386+++ b/net/netfilter/nf_conntrack_proto_gre.c
11387@@ -40,6 +40,10 @@
11388 #include <linux/netfilter/nf_conntrack_proto_gre.h>
11389 #include <linux/netfilter/nf_conntrack_pptp.h>
11390 
11391+#if defined (CONFIG_CNS3XXX_SPPE)
11392+#include <linux/cns3xxx/sppe.h>
11393+#endif
11394+
11395 #define GRE_TIMEOUT (30 * HZ)
11396 #define GRE_STREAM_TIMEOUT (180 * HZ)
11397 
11398@@ -226,6 +230,57 @@ static int gre_print_conntrack(struct se
11399               (ct->proto.gre.stream_timeout / HZ));
11400 }
11401 
11402+#if defined (CONFIG_CNS3XXX_SPPE)
11403+static int sppe_gre_flow_add(struct nf_conn *ct)
11404+{
11405+ SPPE_PARAM param;
11406+ struct nf_conntrack_tuple *orig, *reply;
11407+
11408+ if (0 == sppe_hook_ready) {
11409+ return 0;
11410+ }
11411+
11412+ memset(&param, 0, sizeof(SPPE_PARAM));
11413+
11414+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11415+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11416+
11417+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11418+ param.op = SPPE_OP_SET;
11419+
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);
11423+
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);
11426+
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);
11429+
11430+ if (sppe_func_hook(&param)) {
11431+ printk("<0><%s> fail to add IPv4 from-LAN flow!!\n", __FUNCTION__);
11432+ }
11433+
11434+ param.data.flow_nat_ipv4.fw = 1;
11435+
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);
11439+
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);
11442+
11443+ if (sppe_func_hook(&param)) {
11444+ printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__);
11445+ }
11446+
11447+ return 0;
11448+}
11449+#endif
11450+
11451+
11452+
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);
11462+#endif
11463+
11464     } else
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
11469@@ -29,6 +29,10 @@
11470 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
11471 #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
11472 
11473+#if defined (CONFIG_CNS3XXX_SPPE)
11474+#include <linux/cns3xxx/sppe.h>
11475+#endif
11476+
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,
11481     return NF_ACCEPT;
11482 }
11483 
11484+#if defined (CONFIG_CNS3XXX_SPPE)
11485+static int sppe_tcp_flow_add_ipv4(struct nf_conn *ct)
11486+{
11487+ SPPE_PARAM param;
11488+ struct nf_conntrack_tuple *orig, *reply;
11489+
11490+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11491+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11492+
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 */
11496+ return 0;
11497+ }
11498+#endif
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 */
11502+ return 0;
11503+ }
11504+#endif
11505+
11506+ memset(&param, 0, sizeof(SPPE_PARAM));
11507+
11508+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11509+ param.op = SPPE_OP_SET;
11510+
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);
11514+
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);
11518+
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;
11522+
11523+ if (sppe_func_hook(&param)) {
11524+ printk("<0><%s> fail to add IPv4 from-LAN flow!!\n", __FUNCTION__);
11525+ }
11526+
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);
11532+
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);
11535+
11536+ if (sppe_func_hook(&param)) {
11537+ printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__);
11538+ }
11539+
11540+ return 0;
11541+}
11542+
11543+static int sppe_tcp_flow_add_ipv6(struct nf_conn *ct)
11544+{
11545+ SPPE_PARAM param;
11546+ struct nf_conntrack_tuple *orig, *reply;
11547+
11548+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11549+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11550+
11551+ if (1723 == htons(orig->dst.u.tcp.port)) {
11552+ /* PPTP Control Protocol, PPTP GRE tunneling need this kind of packet */
11553+ return 0;
11554+ }
11555+
11556+ memset(&param, 0, sizeof(SPPE_PARAM));
11557+
11558+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11559+ param.op = SPPE_OP_SET;
11560+
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;
11575+
11576+ if (sppe_func_hook(&param)) {
11577+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11578+ }
11579+
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);
11592+
11593+ if (sppe_func_hook(&param)) {
11594+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11595+ }
11596+
11597+ return 0;
11598+}
11599+
11600+static int sppe_tcp_flow_add(struct nf_conn *ct)
11601+{
11602+ if (0 == sppe_hook_ready) {
11603+ return 0;
11604+ }
11605+
11606+ if (AF_INET == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11607+ sppe_tcp_flow_add_ipv4(ct);
11608+ return 0;
11609+ } else if (AF_INET6 == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11610+ sppe_tcp_flow_add_ipv6(ct);
11611+ return 0;
11612+ }
11613+
11614+ /* return fail */
11615+ return (-1);
11616+}
11617+#endif
11618+
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
11623         break;
11624     }
11625 
11626+#if defined (CONFIG_CNS3XXX_SPPE)
11627+ if(!(th->rst == 1 || th->fin == 1)) {
11628+#endif
11629     if (!tcp_in_window(ct, &ct->proto.tcp, dir, index,
11630                skb, dataoff, th, pf)) {
11631         spin_unlock_bh(&ct->lock);
11632         return -NF_ACCEPT;
11633     }
11634+#if defined (CONFIG_CNS3XXX_SPPE)
11635+ }
11636+#endif
11637+
11638      in_window:
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
11642            connection. */
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);
11648+#endif
11649     }
11650     nf_ct_refresh_acct(ct, ctinfo, skb, timeout);
11651 
11652--- a/net/netfilter/nf_conntrack_proto_udp.c
11653+++ b/net/netfilter/nf_conntrack_proto_udp.c
11654@@ -24,6 +24,9 @@
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>
11660+#endif
11661 
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));
11666 }
11667 
11668+#if defined (CONFIG_CNS3XXX_SPPE)
11669+static int sppe_udp_flow_add_ipv4(struct nf_conn *ct)
11670+{
11671+ SPPE_PARAM param;
11672+ struct nf_conntrack_tuple *orig, *reply;
11673+
11674+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11675+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11676+
11677+ memset(&param, 0, sizeof(SPPE_PARAM));
11678+
11679+ param.cmd = SPPE_CMD_FLOW_NAT_IPV4;
11680+ param.op = SPPE_OP_SET;
11681+
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;
11686+
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);
11689+
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);
11692+
11693+ if (sppe_func_hook(&param)) {
11694+ printk("<0><%s> fail to add IPv4 UDP from-LAN flow!!\n", __FUNCTION__);
11695+ }
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);
11699+
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);
11702+
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);
11705+
11706+ if (sppe_func_hook(&param)) {
11707+ printk("<0><%s> fail to add IPv4 from-WAN flow!!\n", __FUNCTION__);
11708+ }
11709+
11710+ return 0;
11711+}
11712+
11713+static int sppe_udp_flow_add_ipv6(struct nf_conn *ct)
11714+{
11715+ SPPE_PARAM param;
11716+ struct nf_conntrack_tuple *orig, *reply;
11717+
11718+ orig = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple;
11719+ reply = &ct->tuplehash[IP_CT_DIR_REPLY].tuple;
11720+
11721+ memset(&param, 0, sizeof(SPPE_PARAM));
11722+
11723+ param.cmd = SPPE_CMD_FLOW_ROUTE_IPV6;
11724+ param.op = SPPE_OP_SET;
11725+
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);
11739+
11740+ if (sppe_func_hook(&param)) {
11741+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11742+ }
11743+
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);
11756+
11757+ if (sppe_func_hook(&param)) {
11758+ printk("<0><%s> fail to add IPv6 from-LAN flow!!\n", __FUNCTION__);
11759+ }
11760+
11761+ return 0;
11762+}
11763+
11764+static int sppe_udp_flow_add(struct nf_conn *ct)
11765+{
11766+ if (0 == sppe_hook_ready) {
11767+ return 0;
11768+ }
11769+
11770+ if (AF_INET == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11771+ sppe_udp_flow_add_ipv4(ct);
11772+ return 0;
11773+ } else if (AF_INET6 == ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num) {
11774+ sppe_udp_flow_add_ipv6(ct);
11775+ return 0;
11776+ }
11777+
11778+ /* return fail */
11779+ return (-1);
11780+}
11781+#endif
11782+
11783+
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)
11792+ {
11793+#endif
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);
11798+ }
11799+#endif
11800     } else
11801         nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);
11802 
11803

Archive Download this file



interactive