x86: allow both old and new grub signatures in sysupgrade
[openwrt.git] / target / linux / coldfire / patches / 021-Add-ethernet-switch-driver-for-MCF54418.patch
1 From 51e66f289f280a33bb17047717d2e6539a2917e1 Mon Sep 17 00:00:00 2001
2 From: Alison Wang <b18965@freescale.com>
3 Date: Thu, 4 Aug 2011 09:59:44 +0800
4 Subject: [PATCH 21/52] Add ethernet switch driver for MCF54418
5
6 Add ethernet switch driver support for MCF54418.
7
8 Signed-off-by: Alison Wang <b18965@freescale.com>
9 ---
10  arch/m68k/coldfire/m5441x/l2switch.c |  284 +++
11  arch/m68k/include/asm/mcfswitch.h    |  324 +++
12  drivers/net/Kconfig                  |    8 +
13  drivers/net/Makefile                 |    1 +
14  drivers/net/modelo_switch.c          | 4293 ++++++++++++++++++++++++++++++++++
15  drivers/net/modelo_switch.h          | 1141 +++++++++
16  include/linux/fsl_devices.h          |   17 +
17  net/core/dev.c                       |    8 +
18  8 files changed, 6076 insertions(+), 0 deletions(-)
19  create mode 100644 arch/m68k/coldfire/m5441x/l2switch.c
20  create mode 100644 arch/m68k/include/asm/mcfswitch.h
21  create mode 100644 drivers/net/modelo_switch.c
22  create mode 100644 drivers/net/modelo_switch.h
23
24 --- /dev/null
25 +++ b/arch/m68k/coldfire/m5441x/l2switch.c
26 @@ -0,0 +1,284 @@
27 +/*
28 + * l2switch.c
29 + *
30 + * Sub-architcture dependant initialization code for the Freescale
31 + * 5441X L2 Switch module.
32 + *
33 + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
34 + * ShrekWu B16972@freescale.com
35 + *
36 + *
37 + * This program is free software; you can redistribute  it and/or modify it
38 + * under  the terms of  the GNU General  Public License as published by the
39 + * Free Software Foundation;  either version 2 of the  License, or (at your
40 + * option) any later version.
41 + *
42 + * This program is distributed in the hope that it will be useful,
43 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
44 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
45 + * GNU General Public License for more details.
46 + *
47 + * You should have received a copy of the GNU General Public License
48 + * along with this program; if not, write to the Free Software
49 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
50 + */
51 +#include <linux/kernel.h>
52 +#include <linux/sched.h>
53 +#include <linux/param.h>
54 +#include <linux/init.h>
55 +#include <linux/interrupt.h>
56 +#include <linux/device.h>
57 +#include <linux/platform_device.h>
58 +#include <linux/fsl_devices.h>
59 +
60 +#include <asm/traps.h>
61 +#include <asm/machdep.h>
62 +#include <asm/coldfire.h>
63 +#include <asm/mcfswitch.h>
64 +#include <asm/mcfsim.h>
65 +
66 +static unsigned char    switch_mac_default[] = {
67 +       0x00, 0x04, 0x9F, 0x00, 0xB3, 0x49,
68 +};
69 +
70 +static unsigned char switch_mac_addr[6];
71 +
72 +static void switch_request_intrs(struct net_device *dev,
73 +       irqreturn_t switch_net_irq_handler(int irq, void *private),
74 +       void *irq_privatedata)
75 +{
76 +       struct switch_enet_private *fep;
77 +       int b;
78 +       static const struct idesc {
79 +               char *name;
80 +               unsigned short irq;
81 +       } *idp, id[] = {
82 +               /*{ "esw_isr(EBERR)", 38 },*/
83 +               { "esw_isr(RxBuffer)", 39 },
84 +               { "esw_isr(RxFrame)", 40 },
85 +               { "esw_isr(TxBuffer)", 41 },
86 +               { "esw_isr(TxFrame)", 42 },
87 +               { "esw_isr(QM)", 43 },
88 +               { "esw_isr(P0OutputDiscard)", 44 },
89 +               { "esw_isr(P1OutputDiscard)", 45 },
90 +               { "esw_isr(P2OutputDiscard)", 46 },
91 +               { "esw_isr(LearningRecord)", 47 },
92 +               { NULL },
93 +       };
94 +
95 +       fep = netdev_priv(dev);
96 +       /*intrruption L2 ethernet SWITCH */
97 +       b = 64 + 64 + 64;
98 +
99 +       /* Setup interrupt handlers. */
100 +       for (idp = id; idp->name; idp++) {
101 +               if (request_irq(b+idp->irq,
102 +                       switch_net_irq_handler, IRQF_DISABLED,
103 +                       idp->name, irq_privatedata) != 0)
104 +                       printk(KERN_ERR "FEC: Could not alloc %s IRQ(%d)!\n",
105 +                               idp->name, b+idp->irq);
106 +       }
107 +
108 +       /* Configure RMII */
109 +       MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
110 +               MCF_GPIO_PAR_FEC_FEC_MASK) |
111 +               MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
112 +
113 +       MCF_GPIO_PAR_FEC =
114 +               (MCF_GPIO_PAR_FEC &
115 +               MCF_GPIO_PAR_FEC_FEC_MASK) |
116 +               MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
117 +
118 +       MCF_GPIO_SRCR_FEC = 0x0F;
119 +
120 +       MCF_GPIO_PAR_SIMP0H =
121 +               (MCF_GPIO_PAR_SIMP0H &
122 +               MCF_GPIO_PAR_SIMP0H_DAT_MASK) |
123 +               MCF_GPIO_PAR_SIMP0H_DAT_GPIO;
124 +
125 +       MCF_GPIO_PDDR_G =
126 +               (MCF_GPIO_PDDR_G &
127 +               MCF_GPIO_PDDR_G4_MASK) |
128 +               MCF_GPIO_PDDR_G4_OUTPUT;
129 +
130 +       MCF_GPIO_PODR_G =
131 +               (MCF_GPIO_PODR_G &
132 +               MCF_GPIO_PODR_G4_MASK);
133 +}
134 +
135 +static void switch_set_mii(struct net_device *dev)
136 +{
137 +       struct switch_enet_private *fep = netdev_priv(dev);
138 +       volatile switch_t *fecp;
139 +
140 +       fecp = fep->hwp;
141 +
142 +       MCF_FEC_RCR0 = (MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
143 +                       MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD);
144 +       MCF_FEC_RCR1 = (MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
145 +                       MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD);
146 +       /* TCR */
147 +       MCF_FEC_TCR0 = MCF_FEC_TCR_FDEN;
148 +       MCF_FEC_TCR1 = MCF_FEC_TCR_FDEN;
149 +       /* ECR */
150 +#ifdef MODELO_ENHANCE_BUFFER
151 +       MCF_FEC_ECR0 = MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588;
152 +       MCF_FEC_ECR1 = MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588;
153 +#else /*legac buffer*/
154 +       MCF_FEC_ECR0 = MCF_FEC_ECR_ETHER_EN;
155 +       MCF_FEC_ECR1 = MCF_FEC_ECR_ETHER_EN;
156 +#endif
157 +       /*
158 +       * Set MII speed to 2.5 MHz
159 +       */
160 +       MCF_FEC_MSCR0 = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
161 +       MCF_FEC_MSCR1 = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
162 +
163 +}
164 +
165 +static void switch_get_mac(struct net_device *dev)
166 +{
167 +       struct switch_enet_private *fep = netdev_priv(dev);
168 +       volatile switch_t *fecp;
169 +       unsigned char *iap;
170 +
171 +       fecp = fep->hwp;
172 +
173 +       if (FEC_FLASHMAC) {
174 +               /*
175 +               * Get MAC address from FLASH.
176 +               * If it is all 1's or 0's, use the default.
177 +               */
178 +               iap = FEC_FLASHMAC;
179 +               if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
180 +                       (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
181 +                       iap = switch_mac_default;
182 +               if ((iap[0] == 0xff) && (iap[1] == 0xff) &&
183 +                       (iap[2] == 0xff) && (iap[3] == 0xff) &&
184 +                       (iap[4] == 0xff) && (iap[5] == 0xff))
185 +                       iap = switch_mac_default;
186 +
187 +       } else {
188 +               iap = &switch_mac_addr[0];
189 +
190 +               if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
191 +                       (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
192 +                       iap = switch_mac_default;
193 +               if ((iap[0] == 0xff) && (iap[1] == 0xff) &&
194 +                       (iap[2] == 0xff) && (iap[3] == 0xff) &&
195 +                       (iap[4] == 0xff) && (iap[5] == 0xff))
196 +                       iap = switch_mac_default;
197 +       }
198 +
199 +       memcpy(dev->dev_addr, iap, ETH_ALEN);
200 +       /* Adjust MAC if using default MAC address */
201 +       if (iap == switch_mac_default)
202 +               dev->dev_addr[ETH_ALEN-1] = switch_mac_default[ETH_ALEN-1] +
203 +                                               fep->index;
204 +}
205 +
206 +static void switch_enable_phy_intr(void)
207 +{
208 +}
209 +
210 +static void switch_disable_phy_intr(void)
211 +{
212 +}
213 +
214 +static void switch_phy_ack_intr(void)
215 +{
216 +}
217 +
218 +static void switch_localhw_setup(void)
219 +{
220 +}
221 +
222 +static void switch_uncache(unsigned long addr)
223 +{
224 +}
225 +
226 +static void switch_platform_flush_cache(void)
227 +{
228 +}
229 +
230 +/*
231 + * Define the fixed address of the FEC hardware.
232 + */
233 +static unsigned int switch_platform_hw[] = {
234 +       (0xfc0dc000),
235 +       (0xfc0e000),
236 +};
237 +
238 +static struct coldfire_switch_platform_data mcf5441x_switch_data = {
239 +       .hash_table = 0,
240 +       .switch_hw = switch_platform_hw,
241 +       .request_intrs = switch_request_intrs,
242 +       .set_mii = switch_set_mii,
243 +       .get_mac = switch_get_mac,
244 +       .enable_phy_intr = switch_enable_phy_intr,
245 +       .disable_phy_intr = switch_disable_phy_intr,
246 +       .phy_ack_intr = switch_phy_ack_intr,
247 +       .localhw_setup = switch_localhw_setup,
248 +       .uncache = switch_uncache,
249 +       .platform_flush_cache = switch_platform_flush_cache,
250 +};
251 +
252 +static struct resource l2switch_coldfire_resources[] = {
253 +       [0] = {
254 +               .start  = 0xFC0DC000,
255 +               .end    = 0xFC0DC508,
256 +               .flags  = IORESOURCE_MEM,
257 +       },
258 +       [1] = {
259 +               .start  = (64 + 64 + 64 + 38),
260 +               .end    = (64 + 64 + 64 + 48),
261 +               .flags  = IORESOURCE_IRQ,
262 +       },
263 +       [2] = {
264 +               .start  = 0xFC0E0000,
265 +               .end    = 0xFC0E3FFC,
266 +               .flags  = IORESOURCE_MEM,
267 +       },
268 +};
269 +
270 +static struct platform_device l2switch_coldfire_device = {
271 +       .name = "coldfire-switch",
272 +       .id = 0,
273 +       .resource = l2switch_coldfire_resources,
274 +       .num_resources = ARRAY_SIZE(l2switch_coldfire_resources),
275 +       .dev = {
276 +               .platform_data = &mcf5441x_switch_data,
277 +               .coherent_dma_mask = ~0,        /* $$$ REVISIT */
278 +       }
279 +};
280 +
281 +
282 +static int __init mcf5441x_switch_dev_init(void)
283 +{
284 +       int retval = 0;
285 +
286 +       retval = platform_device_register(&l2switch_coldfire_device);
287 +
288 +       if (retval < 0) {
289 +               printk(KERN_ERR "MCF5441x L2Switch: platform_device_register"
290 +                               " failed with code=%d\n", retval);
291 +       }
292 +
293 +       return retval;
294 +}
295 +
296 +static int __init param_switch_addr_setup(char *str)
297 +{
298 +       char *end;
299 +       int i;
300 +
301 +       for (i = 0; i < 6; i++) {
302 +               switch_mac_addr[i] = str ? simple_strtoul(str, &end, 16) : 0;
303 +               if (str)
304 +                       str = (*end) ? end + 1 : end;
305 +       }
306 +       return 0;
307 +}
308 +__setup("switchaddr=", param_switch_addr_setup);
309 +
310 +arch_initcall(mcf5441x_switch_dev_init);
311 --- /dev/null
312 +++ b/arch/m68k/include/asm/mcfswitch.h
313 @@ -0,0 +1,324 @@
314 +/****************************************************************************/
315 +
316 +/*
317 + *     mcfswitch --  L2 SWITCH  Controller for Motorola ColdFire SoC
318 + *                processors.
319 + *
320 + *  Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
321 + *
322 + * This program is free software; you can redistribute  it and/or modify it
323 + * under  the terms of  the GNU General  Public License as published by the
324 + * Free Software Foundation;  either version 2 of the  License, or (at your
325 + * option) any later version.
326 + *
327 + * This program is distributed in the hope that it will be useful,
328 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
329 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
330 + * GNU General Public License for more details.
331 + *
332 + * You should have received a copy of the GNU General Public License
333 + * along with this program; if not, write to the Free Software
334 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
335 + */
336 +
337 +/****************************************************************************/
338 +#ifndef SWITCH_H
339 +#define        SWITCH_H
340 +/****************************************************************************/
341 +#include <linux/netdevice.h>
342 +#include <linux/etherdevice.h>
343 +#include <linux/skbuff.h>
344 +#include <linux/spinlock.h>
345 +#include <linux/workqueue.h>
346 +#include <linux/platform_device.h>
347 +#include <asm/pgtable.h>
348 +
349 +#define FEC_FLASHMAC           0
350 +#define SWITCH_EPORT_NUMBER    2
351 +
352 +#ifdef CONFIG_SWITCH_DMA_USE_SRAM
353 +#define TX_RING_SIZE            8      /* Must be power of two */
354 +#define TX_RING_MOD_MASK        7      /*   for this to work */
355 +#else
356 +#define TX_RING_SIZE            16      /* Must be power of two */
357 +#define TX_RING_MOD_MASK        15      /*   for this to work */
358 +#endif
359 +
360 +typedef struct l2switch_port_statistics_status {
361 +       /*outgoing frames discarded due to transmit queue congestion*/
362 +       unsigned long MCF_ESW_POQC;
363 +       /*incoming frames discarded due to VLAN domain mismatch*/
364 +       unsigned long MCF_ESW_PMVID;
365 +       /*incoming frames discarded due to untagged discard*/
366 +       unsigned long MCF_ESW_PMVTAG;
367 +       /*incoming frames discarded due port is in blocking state*/
368 +       unsigned long MCF_ESW_PBL;
369 +} esw_port_statistics_status;
370 +
371 +typedef struct l2switch {
372 +       unsigned long ESW_REVISION;
373 +       unsigned long ESW_SCRATCH;
374 +       unsigned long ESW_PER;
375 +       unsigned long reserved0[1];
376 +       unsigned long ESW_VLANV;
377 +       unsigned long ESW_DBCR;
378 +       unsigned long ESW_DMCR;
379 +       unsigned long ESW_BKLR;
380 +       unsigned long ESW_BMPC;
381 +       unsigned long ESW_MODE;
382 +       unsigned long ESW_VIMSEL;
383 +       unsigned long ESW_VOMSEL;
384 +       unsigned long ESW_VIMEN;
385 +       unsigned long ESW_VID;/*0x34*/
386 +       /*from 0x38 0x3C*/
387 +       unsigned long esw_reserved0[2];
388 +       unsigned long ESW_MCR;/*0x40*/
389 +       unsigned long ESW_EGMAP;
390 +       unsigned long ESW_INGMAP;
391 +       unsigned long ESW_INGSAL;
392 +       unsigned long ESW_INGSAH;
393 +       unsigned long ESW_INGDAL;
394 +       unsigned long ESW_INGDAH;
395 +       unsigned long ESW_ENGSAL;
396 +       unsigned long ESW_ENGSAH;
397 +       unsigned long ESW_ENGDAL;
398 +       unsigned long ESW_ENGDAH;
399 +       unsigned long ESW_MCVAL;/*0x6C*/
400 +       /*from 0x70--0x7C*/
401 +       unsigned long esw_reserved1[4];
402 +       unsigned long ESW_MMSR;/*0x80*/
403 +       unsigned long ESW_LMT;
404 +       unsigned long ESW_LFC;
405 +       unsigned long ESW_PCSR;
406 +       unsigned long ESW_IOSR;
407 +       unsigned long ESW_QWT;/*0x94*/
408 +       unsigned long esw_reserved2[1];/*0x98*/
409 +       unsigned long ESW_P0BCT;/*0x9C*/
410 +       /*from 0xA0-0xB8*/
411 +       unsigned long esw_reserved3[7];
412 +       unsigned long ESW_P0FFEN;/*0xBC*/
413 +       unsigned long ESW_PSNP[8];
414 +       unsigned long ESW_IPSNP[8];
415 +       unsigned long ESW_PVRES[3];
416 +       /*from 0x10C-0x13C*/
417 +       unsigned long esw_reserved4[13];
418 +       unsigned long ESW_IPRES;/*0x140*/
419 +       /*from 0x144-0x17C*/
420 +       unsigned long esw_reserved5[15];
421 +
422 +       /*port0-port2 Priority Configuration  0xFC0D_C180-C188*/
423 +       unsigned long ESW_PRES[3];
424 +       /*from 0x18C-0x1FC*/
425 +       unsigned long esw_reserved6[29];
426 +
427 +       /*port0-port2 VLAN ID 0xFC0D_C200-C208*/
428 +       unsigned long ESW_PID[3];
429 +       /*from 0x20C-0x27C*/
430 +       unsigned long esw_reserved7[29];
431 +
432 +       /*port0-port2 VLAN domain resolution entry 0xFC0D_C280-C2FC*/
433 +       unsigned long ESW_VRES[32];
434 +
435 +       unsigned long ESW_DISCN;/*0x300*/
436 +       unsigned long ESW_DISCB;
437 +       unsigned long ESW_NDISCN;
438 +       unsigned long ESW_NDISCB;/*0xFC0DC30C*/
439 +       /*per port statistics 0xFC0DC310_C33C*/
440 +       esw_port_statistics_status port_statistics_status[3];
441 +       /*from 0x340-0x400*/
442 +       unsigned long esw_reserved8[48];
443 +
444 +       /*0xFC0DC400---0xFC0DC418*/
445 +       /*unsigned long MCF_ESW_ISR;*/
446 +       unsigned long   switch_ievent;             /* Interrupt event reg */
447 +       /*unsigned long MCF_ESW_IMR;*/
448 +       unsigned long   switch_imask;              /* Interrupt mask reg */
449 +       /*unsigned long MCF_ESW_RDSR;*/
450 +       unsigned long   fec_r_des_start;        /* Receive descriptor ring */
451 +       /*unsigned long MCF_ESW_TDSR;*/
452 +       unsigned long   fec_x_des_start;        /* Transmit descriptor ring */
453 +       /*unsigned long MCF_ESW_MRBR;*/
454 +       unsigned long   fec_r_buff_size;        /* Maximum receive buff size */
455 +       /*unsigned long MCF_ESW_RDAR;*/
456 +       unsigned long   fec_r_des_active;       /* Receive descriptor reg */
457 +       /*unsigned long MCF_ESW_TDAR;*/
458 +       unsigned long   fec_x_des_active;       /* Transmit descriptor reg */
459 +       /*from 0x420-0x4FC*/
460 +       unsigned long esw_reserved9[57];
461 +
462 +       /*0xFC0DC500---0xFC0DC508*/
463 +       unsigned long ESW_LREC0;
464 +       unsigned long ESW_LREC1;
465 +       unsigned long ESW_LSR;
466 +} switch_t;
467 +
468 +typedef struct _64bTableEntry {
469 +       unsigned int lo;  /* lower 32 bits */
470 +       unsigned int hi;  /* upper 32 bits */
471 +} AddrTable64bEntry;
472 +
473 +typedef struct l2switchaddrtable {
474 +       AddrTable64bEntry  eswTable64bEntry[2048];
475 +} eswAddrTable_t;
476 +
477 +#define MCF_FEC_MSCR0      (*(volatile unsigned long *)(0xFC0D4044))
478 +#define MCF_FEC_MSCR1      (*(volatile unsigned long *)(0xFC0D8044))
479 +#define MCF_FEC_RCR0       (*(volatile unsigned long *)(0xFC0D4084))
480 +#define MCF_FEC_RCR1       (*(volatile unsigned long *)(0xFC0D8084))
481 +#define MCF_FEC_TCR0       (*(volatile unsigned long *)(0xFC0D40C4))
482 +#define MCF_FEC_TCR1       (*(volatile unsigned long *)(0xFC0D80C4))
483 +#define MCF_FEC_ECR0       (*(volatile unsigned long *)(0xFC0D4024))
484 +#define MCF_FEC_ECR1       (*(volatile unsigned long *)(0xFC0D8024))
485 +
486 +#define MCF_FEC_RCR_PROM                     (0x00000008)
487 +#define MCF_FEC_RCR_RMII_MODE                (0x00000100)
488 +#define MCF_FEC_RCR_MAX_FL(x)                (((x)&0x00003FFF)<<16)
489 +#define MCF_FEC_RCR_CRC_FWD                  (0x00004000)
490 +
491 +#define MCF_FEC_TCR_FDEN                     (0x00000004)
492 +
493 +#define MCF_FEC_ECR_ETHER_EN                 (0x00000002)
494 +#define MCF_FEC_ECR_ENA_1588                 (0x00000010)
495 +
496 +
497 +typedef struct bufdesc {
498 +       unsigned short  cbd_sc;                 /* Control and status info */
499 +       unsigned short  cbd_datlen;             /* Data length */
500 +       unsigned long   cbd_bufaddr;            /* Buffer address */
501 +#ifdef MODELO_BUFFER
502 +       unsigned long   ebd_status;
503 +       unsigned short  length_proto_type;
504 +       unsigned short  payload_checksum;
505 +       unsigned long   bdu;
506 +       unsigned long   timestamp;
507 +       unsigned long   reserverd_word1;
508 +       unsigned long   reserverd_word2;
509 +#endif
510 +} cbd_t;
511 +
512 +/* Forward declarations of some structures to support different PHYs
513 + */
514 +typedef struct {
515 +       uint mii_data;
516 +       void (*funct)(uint mii_reg, struct net_device *dev);
517 +} phy_cmd_t;
518 +
519 +typedef struct {
520 +       uint id;
521 +       char *name;
522 +
523 +       const phy_cmd_t *config;
524 +       const phy_cmd_t *startup;
525 +       const phy_cmd_t *ack_int;
526 +       const phy_cmd_t *shutdown;
527 +} phy_info_t;
528 +
529 +/* The switch buffer descriptors track the ring buffers.  The rx_bd_base and
530 + * tx_bd_base always point to the base of the buffer descriptors.  The
531 + * cur_rx and cur_tx point to the currently available buffer.
532 + * The dirty_tx tracks the current buffer that is being sent by the
533 + * controller.  The cur_tx and dirty_tx are equal under both completely
534 + * empty and completely full conditions.  The empty/ready indicator in
535 + * the buffer descriptor determines the actual condition.
536 + */
537 +struct switch_enet_private {
538 +       /* Hardware registers of the switch device */
539 +       volatile switch_t *hwp;
540 +       volatile eswAddrTable_t *hwentry;
541 +
542 +       struct net_device *netdev;
543 +       struct platform_device *pdev;
544 +       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
545 +       unsigned char *tx_bounce[TX_RING_SIZE];
546 +       struct  sk_buff *tx_skbuff[TX_RING_SIZE];
547 +       ushort  skb_cur;
548 +       ushort  skb_dirty;
549 +
550 +       /* CPM dual port RAM relative addresses.
551 +        */
552 +       cbd_t   *rx_bd_base;            /* Address of Rx and Tx buffers. */
553 +       cbd_t   *tx_bd_base;
554 +       cbd_t   *cur_rx, *cur_tx;               /* The next free ring entry */
555 +       cbd_t   *dirty_tx;      /* The ring entries to be free()ed. */
556 +       uint    tx_full;
557 +       /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
558 +       spinlock_t hw_lock;
559 +
560 +       /* hold while accessing the mii_list_t() elements */
561 +       spinlock_t mii_lock;
562 +       struct mii_bus *mdio_bus;
563 +       struct phy_device *phydev[SWITCH_EPORT_NUMBER];
564 +
565 +       uint    phy_id;
566 +       uint    phy_id_done;
567 +       uint    phy_status;
568 +       uint    phy_speed;
569 +       phy_info_t const        *phy;
570 +       struct work_struct phy_task;
571 +       volatile switch_t  *phy_hwp;
572 +
573 +       uint    sequence_done;
574 +       uint    mii_phy_task_queued;
575 +
576 +       uint    phy_addr;
577 +
578 +       int     index;
579 +       int     opened;
580 +       int     full_duplex;
581 +       int     msg_enable;
582 +       int     phy1_link;
583 +       int     phy1_old_link;
584 +       int     phy1_duplex;
585 +       int     phy1_speed;
586 +
587 +       int     phy2_link;
588 +       int     phy2_old_link;
589 +       int     phy2_duplex;
590 +       int     phy2_speed;
591 +       /* --------------Statistics--------------------------- */
592 +       /* when a new element deleted a element with in
593 +        * a block due to lack of space */
594 +       int atBlockOverflows;
595 +       /* Peak number of valid entries in the address table */
596 +       int atMaxEntries;
597 +       /* current number of valid entries in the address table */
598 +       int atCurrEntries;
599 +       /* maximum entries within a block found
600 +        * (updated within ageing)*/
601 +       int atMaxEntriesPerBlock;
602 +
603 +       /* -------------------ageing function------------------ */
604 +       /* maximum age allowed for an entry */
605 +       int ageMax;
606 +       /* last LUT entry to block that was
607 +        * inspected by the Ageing task*/
608 +       int ageLutIdx;
609 +       /* last element within block inspected by the Ageing task */
610 +       int ageBlockElemIdx;
611 +       /* complete table has been processed by ageing process */
612 +       int ageCompleted;
613 +       /* delay setting */
614 +       int ageDelay;
615 +       /* current delay Counter */
616 +       int  ageDelayCnt;
617 +
618 +       /* ----------------timer related---------------------------- */
619 +       /* current time (for timestamping) */
620 +       int currTime;
621 +       /* flag set by timer when currTime changed
622 +        * and cleared by serving function*/
623 +       int timeChanged;
624 +
625 +       /* Timer for Aging */
626 +       struct timer_list       timer_aging;
627 +       int learning_irqhandle_enable;
628 +};
629 +
630 +struct switch_platform_private {
631 +       struct platform_device  *pdev;
632 +
633 +       unsigned long           quirks;
634 +       int                     num_slots;      /* Slots on controller */
635 +       struct switch_enet_private *fep_host[0];      /* Pointers to hosts */
636 +};
637 +#endif
638 --- a/drivers/net/Kconfig
639 +++ b/drivers/net/Kconfig
640 @@ -1950,6 +1950,14 @@ config FEC
641           Say Y here if you want to use the built-in 10/100 Fast ethernet
642           controller on some Motorola ColdFire and Freescale i.MX processors.
643  
644 +config MODELO_SWITCH
645 +       bool "ethernet switch controller (of ColdFire CPUs)"
646 +       depends on !FEC && M5441X
647 +       help
648 +         Say Y here if you want to use the built-in ethernet switch
649 +         controller on some ColdFire processors.
650 +         The Integrated Ethernet switch engine is compatible with
651 +         10/100 MAC-NET core.
652  
653  config FEC2
654         bool "Second FEC ethernet controller (on some ColdFire CPUs)"
655 --- a/drivers/net/Makefile
656 +++ b/drivers/net/Makefile
657 @@ -127,6 +127,7 @@ ifeq ($(CONFIG_FEC_1588), y)
658  obj-$(CONFIG_FEC) += fec_1588.o
659  endif
660  obj-$(CONFIG_FEC_548x) += fec_m547x.o
661 +obj-$(CONFIG_MODELO_SWITCH) += modelo_switch.o
662  obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
663  ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
664         obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
665 --- /dev/null
666 +++ b/drivers/net/modelo_switch.c
667 @@ -0,0 +1,4293 @@
668 +/*
669 + *  L2 switch Controller (Etheren switch) driver for MCF5441x.
670 + *
671 + *  Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
672 + *    Shrek Wu (B16972@freescale.com)
673 + *    Alison Wang (b18965@freescale.com)
674 + *    Jason Jin (Jason.jin@freescale.com)
675 + *
676 + *  This program is free software; you can redistribute  it and/or modify it
677 + *  under  the terms of  the GNU General  Public License as published by the
678 + *  Free Software Foundation;  either version 2 of the  License, or (at your
679 + *  option) any later version.
680 + */
681 +
682 +#include <linux/module.h>
683 +#include <linux/kernel.h>
684 +#include <linux/string.h>
685 +#include <linux/ptrace.h>
686 +#include <linux/errno.h>
687 +#include <linux/ioport.h>
688 +#include <linux/slab.h>
689 +#include <linux/interrupt.h>
690 +#include <linux/pci.h>
691 +#include <linux/init.h>
692 +#include <linux/delay.h>
693 +#include <linux/netdevice.h>
694 +#include <linux/etherdevice.h>
695 +#include <linux/skbuff.h>
696 +#include <linux/spinlock.h>
697 +#include <linux/workqueue.h>
698 +#include <linux/bitops.h>
699 +#include <linux/platform_device.h>
700 +#include <linux/fsl_devices.h>
701 +#include <linux/phy.h>
702 +#include <linux/kthread.h>
703 +#include <linux/syscalls.h>
704 +#include <linux/uaccess.h>
705 +#include <linux/io.h>
706 +#include <linux/signal.h>
707 +
708 +#include <asm/irq.h>
709 +#include <asm/pgtable.h>
710 +#include <asm/cacheflush.h>
711 +#include <asm/coldfire.h>
712 +#include <asm/mcfsim.h>
713 +#include "modelo_switch.h"
714 +
715 +#define        SWITCH_MAX_PORTS        1
716 +#define CONFIG_FEC_SHARED_PHY
717 +
718 +/* Interrupt events/masks.
719 +*/
720 +#define FEC_ENET_HBERR ((uint)0x80000000)      /* Heartbeat error */
721 +#define FEC_ENET_BABR  ((uint)0x40000000)      /* Babbling receiver */
722 +#define FEC_ENET_BABT  ((uint)0x20000000)      /* Babbling transmitter */
723 +#define FEC_ENET_GRA   ((uint)0x10000000)      /* Graceful stop complete */
724 +#define FEC_ENET_TXF   ((uint)0x08000000)      /* Full frame transmitted */
725 +#define FEC_ENET_TXB   ((uint)0x04000000)      /* A buffer was transmitted */
726 +#define FEC_ENET_RXF   ((uint)0x02000000)      /* Full frame received */
727 +#define FEC_ENET_RXB   ((uint)0x01000000)      /* A buffer was received */
728 +#define FEC_ENET_MII   ((uint)0x00800000)      /* MII interrupt */
729 +#define FEC_ENET_EBERR ((uint)0x00400000)      /* SDMA bus error */
730 +
731 +static int switch_enet_open(struct net_device *dev);
732 +static int switch_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
733 +static irqreturn_t switch_enet_interrupt(int irq, void *dev_id);
734 +static void switch_enet_tx(struct net_device *dev);
735 +static void switch_enet_rx(struct net_device *dev);
736 +static int switch_enet_close(struct net_device *dev);
737 +static void set_multicast_list(struct net_device *dev);
738 +static void switch_restart(struct net_device *dev, int duplex);
739 +static void switch_stop(struct net_device *dev);
740 +static void switch_set_mac_address(struct net_device *dev);
741 +
742 +#define                NMII    20
743 +
744 +/* Make MII read/write commands for the FEC.
745 +*/
746 +#define mk_mii_read(REG)       (0x60020000 | ((REG & 0x1f) << 18))
747 +#define mk_mii_write(REG, VAL) (0x50020000 | ((REG & 0x1f) << 18) | \
748 +                                               (VAL & 0xffff))
749 +
750 +/* Transmitter timeout.
751 +*/
752 +#define TX_TIMEOUT (2*HZ)
753 +
754 +/*last read entry from learning interface*/
755 +eswPortInfo g_info;
756 +/* switch ports status */
757 +struct port_status ports_link_status;
758 +
759 +/* the user space pid, used to send the link change to user space */
760 +long user_pid = 1;
761 +
762 +/* ----------------------------------------------------------------*/
763 +/*
764 + * Calculate Galois Field Arithmetic CRC for Polynom x^8+x^2+x+1.
765 + * It omits the final shift in of 8 zeroes a "normal" CRC would do
766 + * (getting the remainder).
767 + *
768 + *  Examples (hexadecimal values):<br>
769 + *   10-11-12-13-14-15  => CRC=0xc2
770 + *   10-11-cc-dd-ee-00  => CRC=0xe6
771 + *
772 + *   param: pmacaddress
773 + *          A 6-byte array with the MAC address.
774 + *          The first byte is the first byte transmitted
775 + *   return The 8-bit CRC in bits 7:0
776 + */
777 +int crc8_calc(unsigned char *pmacaddress)
778 +{
779 +       /* byte index */
780 +       int byt;
781 +       /* bit index */
782 +       int bit;
783 +       int inval;
784 +       int crc;
785 +       /* preset */
786 +       crc   = 0x12;
787 +       for (byt = 0; byt < 6; byt++) {
788 +               inval = (((int)pmacaddress[byt]) & 0xff);
789 +               /*
790 +                * shift bit 0 to bit 8 so all our bits
791 +                * travel through bit 8
792 +                * (simplifies below calc)
793 +                */
794 +               inval <<= 8;
795 +
796 +               for (bit = 0; bit < 8; bit++) {
797 +                       /* next input bit comes into d7 after shift */
798 +                       crc |= inval & 0x100;
799 +                       if (crc & 0x01)
800 +                               /* before shift  */
801 +                               crc ^= 0x1c0;
802 +
803 +                       crc >>= 1;
804 +                       inval >>= 1;
805 +               }
806 +
807 +       }
808 +       /* upper bits are clean as we shifted in zeroes! */
809 +       return crc;
810 +}
811 +
812 +void read_atable(struct switch_enet_private *fep,
813 +       int index, unsigned long *read_lo, unsigned long *read_hi)
814 +{
815 +       unsigned long atable_base = 0xFC0E0000;
816 +
817 +       *read_lo = *((volatile unsigned long *)(atable_base + (index<<3)));
818 +       *read_hi = *((volatile unsigned long *)(atable_base + (index<<3) + 4));
819 +}
820 +
821 +void write_atable(struct switch_enet_private *fep,
822 +       int index, unsigned long write_lo, unsigned long write_hi)
823 +{
824 +       unsigned long atable_base = 0xFC0E0000;
825 +
826 +       *((volatile unsigned long *)(atable_base + (index<<3))) = write_lo;
827 +       *((volatile unsigned long *)(atable_base + (index<<3) + 4)) = write_hi;
828 +}
829 +
830 +/* Check if the Port Info FIFO has data available
831 + * for reading. 1 valid, 0 invalid*/
832 +int esw_portinfofifo_status(struct switch_enet_private *fep)
833 +{
834 +       volatile switch_t  *fecp;
835 +       fecp = fep->hwp;
836 +       return fecp->ESW_LSR;
837 +}
838 +
839 +/* Initialize the Port Info FIFO. */
840 +void esw_portinfofifo_initialize(struct switch_enet_private *fep)
841 +{
842 +       volatile switch_t  *fecp;
843 +       unsigned long tmp;
844 +       fecp = fep->hwp;
845 +
846 +       /*disable all learn*/
847 +       fecp->switch_imask &= (~MCF_ESW_IMR_LRN);
848 +       /* remove all entries from FIFO */
849 +       while (esw_portinfofifo_status(fep)) {
850 +               /* read one data word */
851 +               tmp = fecp->ESW_LREC0;
852 +               tmp = fecp->ESW_LREC1;
853 +       }
854 +
855 +}
856 +
857 +/* Read one element from the HW receive FIFO (Queue)
858 + * if available and return it.
859 + * return ms_HwPortInfo or null if no data is available
860 + */
861 +eswPortInfo *esw_portinfofifo_read(struct switch_enet_private *fep)
862 +{
863 +       volatile switch_t  *fecp;
864 +       unsigned long tmp;
865 +
866 +       fecp = fep->hwp;
867 +       /* check learning record valid */
868 +       if (fecp->ESW_LSR == 0)
869 +               return NULL;
870 +
871 +       /*read word from FIFO*/
872 +       g_info.maclo = fecp->ESW_LREC0;
873 +
874 +       /*but verify that we actually did so
875 +        * (0=no data available)*/
876 +       if (g_info.maclo == 0)
877 +               return NULL;
878 +
879 +       /* read 2nd word from FIFO */
880 +       tmp = fecp->ESW_LREC1;
881 +       g_info.machi = tmp & 0xffff;
882 +       g_info.hash  = (tmp >> 16) & 0xff;
883 +       g_info.port  = (tmp >> 24) & 0xf;
884 +
885 +       return &g_info;
886 +}
887 +
888 +/*
889 + * Clear complete MAC Look Up Table
890 + */
891 +void esw_clear_atable(struct switch_enet_private *fep)
892 +{
893 +       int index;
894 +       for (index = 0; index < 2048; index++)
895 +               write_atable(fep, index, 0, 0);
896 +}
897 +
898 +void esw_dump_atable(struct switch_enet_private *fep)
899 +{
900 +       int index;
901 +       unsigned long read_lo, read_hi;
902 +       for (index = 0; index < 2048; index++)
903 +               read_atable(fep, index, &read_lo, &read_hi);
904 +}
905 +
906 +/*
907 + * pdates MAC address lookup table with a static entry
908 + * Searches if the MAC address is already there in the block and replaces
909 + * the older entry with new one. If MAC address is not there then puts a
910 + * new entry in the first empty slot available in the block
911 + *
912 + * mac_addr Pointer to the array containing MAC address to
913 + *          be put as static entry
914 + * port     Port bitmask numbers to be added in static entry,
915 + *          valid values are 1-7
916 + * priority Priority for the static entry in table
917 + *
918 + * return 0 for a successful update else -1  when no slot available
919 + */
920 +int esw_update_atable_static(unsigned char *mac_addr,
921 +       unsigned int port, unsigned int priority,
922 +       struct switch_enet_private *fep)
923 +{
924 +       unsigned long block_index, entry, index_end;
925 +       unsigned long read_lo, read_hi;
926 +       unsigned long write_lo, write_hi;
927 +
928 +       write_lo = (unsigned long)((mac_addr[3] << 24) |
929 +                       (mac_addr[2] << 16) |
930 +                       (mac_addr[1] << 8) |
931 +                       mac_addr[0]);
932 +       write_hi = (unsigned long)(0 |
933 +                       (port << AT_SENTRY_PORTMASK_shift) |
934 +                       (priority << AT_SENTRY_PRIO_shift) |
935 +                       (AT_ENTRY_TYPE_STATIC << AT_ENTRY_TYPE_shift) |
936 +                       (AT_ENTRY_RECORD_VALID << AT_ENTRY_VALID_shift) |
937 +                       (mac_addr[5] << 8) | (mac_addr[4]));
938 +
939 +       block_index = GET_BLOCK_PTR(crc8_calc(mac_addr));
940 +       index_end = block_index + ATABLE_ENTRY_PER_SLOT;
941 +       /* Now search all the entries in the selected block */
942 +       for (entry = block_index; entry < index_end; entry++) {
943 +               read_atable(fep, entry, &read_lo, &read_hi);
944 +               /*
945 +                * MAC address matched, so update the
946 +                * existing entry
947 +                * even if its a dynamic one
948 +                */
949 +               if ((read_lo == write_lo) && ((read_hi & 0x0000ffff) ==
950 +                        (write_hi & 0x0000ffff))) {
951 +                       write_atable(fep, entry, write_lo, write_hi);
952 +                       return 0;
953 +               } else if (!(read_hi & (1 << 16))) {
954 +                       /*
955 +                        * Fill this empty slot (valid bit zero),
956 +                        * assuming no holes in the block
957 +                        */
958 +                       write_atable(fep, entry, write_lo, write_hi);
959 +                       fep->atCurrEntries++;
960 +                       return 0;
961 +               }
962 +       }
963 +
964 +       /* No space available for this static entry */
965 +       return -1;
966 +}
967 +
968 +/* lookup entry in given Address Table slot and
969 + * insert (learn) it if it is not found.
970 + * return 0 if entry was found and updated.
971 + *        1 if entry was not found and has been inserted (learned).
972 + */
973 +int esw_update_atable_dynamic(unsigned char *mac_addr, unsigned int port,
974 +               unsigned int currTime, struct switch_enet_private *fep)
975 +{
976 +       unsigned long block_index, entry, index_end;
977 +       unsigned long read_lo, read_hi;
978 +       unsigned long write_lo, write_hi;
979 +       unsigned long tmp;
980 +       int time, timeold, indexold;
981 +
982 +       /* prepare update port and timestamp */
983 +       write_hi = (mac_addr[5] << 8) | (mac_addr[4]);
984 +       write_lo = (unsigned long)((mac_addr[3] << 24) |
985 +                       (mac_addr[2] << 16) |
986 +                       (mac_addr[1] << 8) |
987 +                       mac_addr[0]);
988 +       tmp = AT_ENTRY_RECORD_VALID << AT_ENTRY_VALID_shift;
989 +       tmp |= AT_ENTRY_TYPE_DYNAMIC << AT_ENTRY_TYPE_shift;
990 +       tmp |= currTime << AT_DENTRY_TIME_shift;
991 +       tmp |= port << AT_DENTRY_PORT_shift;
992 +       tmp |= write_hi;
993 +
994 +       /*
995 +        * linear search through all slot
996 +        * entries and update if found
997 +        */
998 +       block_index = GET_BLOCK_PTR(crc8_calc(mac_addr));
999 +       index_end = block_index + ATABLE_ENTRY_PER_SLOT;
1000 +        /* Now search all the entries in the selected block */
1001 +       for (entry = block_index; entry < index_end; entry++) {
1002 +               read_atable(fep, entry, &read_lo, &read_hi);
1003 +
1004 +               if ((read_lo == write_lo) &&
1005 +                       ((read_hi & 0x0000ffff) ==
1006 +                       (write_hi & 0x0000ffff))) {
1007 +                       /* found correct address,
1008 +                        * update timestamp. */
1009 +                       write_atable(fep, entry, write_lo, tmp);
1010 +                       return 0;
1011 +               } else if (!(read_hi & (1 << 16))) {
1012 +                       /* slot is empty, then use it
1013 +                        * for new entry
1014 +                        * Note: There are no holes,
1015 +                        * therefore cannot be any
1016 +                        * more that need to be compared.
1017 +                        */
1018 +                       write_atable(fep, entry, write_lo, tmp);
1019 +                       /* statistics (we do it between writing
1020 +                        * .hi an .lo due to
1021 +                        * hardware limitation...
1022 +                        */
1023 +                       fep->atCurrEntries++;
1024 +                       /* newly inserted */
1025 +                       return 1;
1026 +               }
1027 +       }
1028 +
1029 +       /*
1030 +        * no more entry available in blockk ...
1031 +        * overwrite oldest
1032 +        */
1033 +       timeold = 0;
1034 +       indexold = 0;
1035 +       for (entry = block_index; entry < index_end; entry++) {
1036 +               read_atable(fep, entry, &read_lo, &read_hi);
1037 +               time = AT_EXTRACT_TIMESTAMP(read_hi);
1038 +               time = TIMEDELTA(currTime, time);
1039 +               if (time > timeold) {
1040 +                       /* is it older ?*/
1041 +                       timeold = time;
1042 +                       indexold = entry;
1043 +               }
1044 +       }
1045 +
1046 +       write_atable(fep, indexold, write_lo, tmp);
1047 +       /* Statistics (do it inbetween
1048 +        * writing to .lo and .hi*/
1049 +       fep->atBlockOverflows++;
1050 +       /* newly inserted */
1051 +       return 1;
1052 +}
1053 +
1054 +int esw_update_atable_dynamic1(unsigned long write_lo, unsigned long write_hi,
1055 +               int block_index, unsigned int port, unsigned int currTime,
1056 +               struct switch_enet_private *fep)
1057 +{
1058 +       unsigned long entry, index_end;
1059 +       unsigned long read_lo, read_hi;
1060 +       unsigned long tmp;
1061 +       int time, timeold, indexold;
1062 +
1063 +       /* prepare update port and timestamp */
1064 +       tmp = AT_ENTRY_RECORD_VALID << AT_ENTRY_VALID_shift;
1065 +       tmp |= AT_ENTRY_TYPE_DYNAMIC << AT_ENTRY_TYPE_shift;
1066 +       tmp |= currTime << AT_DENTRY_TIME_shift;
1067 +       tmp |= port << AT_DENTRY_PORT_shift;
1068 +       tmp |= write_hi;
1069 +
1070 +       /*
1071 +       * linear search through all slot
1072 +       * entries and update if found
1073 +       */
1074 +       index_end = block_index + ATABLE_ENTRY_PER_SLOT;
1075 +       /* Now search all the entries in the selected block */
1076 +       for (entry = block_index; entry < index_end; entry++) {
1077 +               read_atable(fep, entry, &read_lo, &read_hi);
1078 +               if ((read_lo == write_lo) &&
1079 +                       ((read_hi & 0x0000ffff) ==
1080 +                       (write_hi & 0x0000ffff))) {
1081 +                       /* found correct address,
1082 +                        * update timestamp. */
1083 +                       write_atable(fep, entry, write_lo, tmp);
1084 +                       return 0;
1085 +               } else if (!(read_hi & (1 << 16))) {
1086 +                       /* slot is empty, then use it
1087 +                       * for new entry
1088 +                       * Note: There are no holes,
1089 +                       * therefore cannot be any
1090 +                       * more that need to be compared.
1091 +                       */
1092 +                       write_atable(fep, entry, write_lo, tmp);
1093 +                       /* statistics (we do it between writing
1094 +                       *  .hi an .lo due to
1095 +                       * hardware limitation...
1096 +                       */
1097 +                       fep->atCurrEntries++;
1098 +                       /* newly inserted */
1099 +                       return 1;
1100 +               }
1101 +       }
1102 +
1103 +       /*
1104 +       * no more entry available in block ...
1105 +       * overwrite oldest
1106 +       */
1107 +       timeold = 0;
1108 +       indexold = 0;
1109 +       for (entry = block_index; entry < index_end; entry++) {
1110 +               read_atable(fep, entry, &read_lo, &read_hi);
1111 +               time = AT_EXTRACT_TIMESTAMP(read_hi);
1112 +               time = TIMEDELTA(currTime, time);
1113 +               if (time > timeold) {
1114 +                       /* is it older ?*/
1115 +                       timeold = time;
1116 +                       indexold = entry;
1117 +               }
1118 +       }
1119 +
1120 +       write_atable(fep, indexold, write_lo, tmp);
1121 +       /* Statistics (do it inbetween
1122 +       * writing to .lo and .hi*/
1123 +       fep->atBlockOverflows++;
1124 +       /* newly inserted */
1125 +       return 1;
1126 +}
1127 +
1128 +/*
1129 + * Delete one dynamic entry within the given block
1130 + * of 64-bit entries.
1131 + * return number of valid entries in the block after deletion.
1132 + */
1133 +int esw_del_atable_dynamic(struct switch_enet_private *fep,
1134 +       int blockidx, int entryidx)
1135 +{
1136 +       unsigned long index_start, index_end;
1137 +       int i;
1138 +       unsigned long read_lo, read_hi;
1139 +
1140 +       /* the entry to delete */
1141 +       index_start = blockidx + entryidx;
1142 +       /* one after last */
1143 +       index_end = blockidx + ATABLE_ENTRY_PER_SLOT;
1144 +       /* Statistics */
1145 +       fep->atCurrEntries--;
1146 +
1147 +       if (entryidx == (ATABLE_ENTRY_PER_SLOT - 1)) {
1148 +               /* if it is the very last entry,
1149 +               * just delete it without further efford*/
1150 +               write_atable(fep, index_start, 0, 0);
1151 +               /*number of entries left*/
1152 +               i = ATABLE_ENTRY_PER_SLOT - 1;
1153 +               return i;
1154 +       } else {
1155 +               /*not the last in the block, then
1156 +                * shift all that follow the one
1157 +                * that is deleted to avoid "holes".
1158 +                */
1159 +               for (i = index_start; i < (index_end - 1); i++) {
1160 +                       read_atable(fep, i + 1, &read_lo, &read_hi);
1161 +                       /* move it down */
1162 +                       write_atable(fep, i, read_lo, read_hi);
1163 +                       if (!(read_hi & (1 << 16))) {
1164 +                               /* stop if we just copied the last */
1165 +                               return i - blockidx;
1166 +                       }
1167 +               }
1168 +
1169 +               /*moved all entries up to the last.
1170 +                * then set invalid flag in the last*/
1171 +               write_atable(fep, index_end - 1, 0, 0);
1172 +               /* number of valid entries left */
1173 +               return i - blockidx;
1174 +       }
1175 +}
1176 +
1177 +void esw_atable_dynamicms_del_entries_for_port(
1178 +       struct switch_enet_private *fep, int port_index)
1179 +{
1180 +       unsigned long read_lo, read_hi;
1181 +       unsigned int port_idx;
1182 +       int i;
1183 +
1184 +       for (i = 0; i < ESW_ATABLE_MEM_NUM_ENTRIES; i++) {
1185 +               read_atable(fep, i, &read_lo, &read_hi);
1186 +               if (read_hi & (1 << 16)) {
1187 +                       port_idx = AT_EXTRACT_PORT(read_hi);
1188 +
1189 +                       if (port_idx == port_index)
1190 +                               write_atable(fep, i, 0, 0);
1191 +               }
1192 +       }
1193 +}
1194 +
1195 +void esw_atable_dynamicms_del_entries_for_other_port(
1196 +       struct switch_enet_private *fep,
1197 +       int port_index)
1198 +{
1199 +       unsigned long read_lo, read_hi;
1200 +       unsigned int port_idx;
1201 +       int i;
1202 +
1203 +       for (i = 0; i < ESW_ATABLE_MEM_NUM_ENTRIES; i++) {
1204 +               read_atable(fep, i, &read_lo, &read_hi);
1205 +               if (read_hi & (1 << 16)) {
1206 +                       port_idx = AT_EXTRACT_PORT(read_hi);
1207 +
1208 +                       if (port_idx != port_index)
1209 +                               write_atable(fep, i, 0, 0);
1210 +               }
1211 +       }
1212 +}
1213 +
1214 +/*
1215 + *  Scan one complete block (Slot) for outdated entries and delete them.
1216 + *  blockidx index of block of entries that should be analyzed.
1217 + *  return number of deleted entries, 0 if nothing was modified.
1218 + */
1219 +int esw_atable_dynamicms_check_block_age(
1220 +       struct switch_enet_private *fep, int blockidx) {
1221 +
1222 +       int i, tm, tdelta;
1223 +       int deleted = 0, entries = 0;
1224 +       unsigned long read_lo, read_hi;
1225 +       /* Scan all entries from last down to
1226 +        * have faster deletion speed if necessary*/
1227 +       for (i = (blockidx + ATABLE_ENTRY_PER_SLOT - 1);
1228 +               i >= blockidx; i--) {
1229 +               read_atable(fep, i, &read_lo, &read_hi);
1230 +
1231 +               if (read_hi & (1 << 16)) {
1232 +                       /* the entry is valide*/
1233 +                       tm = AT_EXTRACT_TIMESTAMP(read_hi);
1234 +                       tdelta = TIMEDELTA(fep->currTime, tm);
1235 +                       if (tdelta > fep->ageMax) {
1236 +                               esw_del_atable_dynamic(fep,
1237 +                                       blockidx, i-blockidx);
1238 +                               deleted++;
1239 +                       } else {
1240 +                               /* statistics */
1241 +                               entries++;
1242 +                       }
1243 +               }
1244 +       }
1245 +
1246 +       /*update statistics*/
1247 +       if (fep->atMaxEntriesPerBlock < entries)
1248 +               fep->atMaxEntriesPerBlock = entries;
1249 +
1250 +       return deleted;
1251 +}
1252 +
1253 +/* scan the complete address table and find the most current entry.
1254 + * The time of the most current entry then is used as current time
1255 + * for the context structure.
1256 + * In addition the atCurrEntries value is updated as well.
1257 + * return time that has been set in the context.
1258 + */
1259 +int esw_atable_dynamicms_find_set_latesttime(
1260 +       struct switch_enet_private *fep) {
1261 +
1262 +       int tm_min, tm_max, tm;
1263 +       int delta, current, i;
1264 +       unsigned long read_lo, read_hi;
1265 +
1266 +       tm_min = (1 << AT_DENTRY_TIMESTAMP_WIDTH) - 1;
1267 +       tm_max = 0;
1268 +       current = 0;
1269 +
1270 +       for (i = 0; i < ESW_ATABLE_MEM_NUM_ENTRIES; i++) {
1271 +               read_atable(fep, i, &read_lo, &read_hi);
1272 +               if (read_hi & (1 << 16)) {
1273 +                       /*the entry is valid*/
1274 +                       tm = AT_EXTRACT_TIMESTAMP(read_hi);
1275 +                       if (tm > tm_max)
1276 +                               tm_max = tm;
1277 +                       if (tm < tm_min)
1278 +                               tm_min = tm;
1279 +                       current++;
1280 +               }
1281 +       }
1282 +
1283 +       delta = TIMEDELTA(tm_max, tm_min);
1284 +       if (delta < fep->ageMax) {
1285 +               /*Difference must be in range*/
1286 +               fep->currTime = tm_max;
1287 +       } else {
1288 +               fep->currTime = tm_min;
1289 +       }
1290 +
1291 +       fep->atCurrEntries = current;
1292 +       return fep->currTime;
1293 +}
1294 +
1295 +int esw_atable_dynamicms_get_port(
1296 +       struct switch_enet_private *fep,
1297 +       unsigned long write_lo,
1298 +       unsigned long write_hi,
1299 +       int block_index)
1300 +{
1301 +       int i, index_end;
1302 +       unsigned long read_lo, read_hi, port;
1303 +
1304 +       index_end = block_index + ATABLE_ENTRY_PER_SLOT;
1305 +       /* Now search all the entries in the selected block */
1306 +       for (i = block_index; i < index_end; i++) {
1307 +               read_atable(fep, i, &read_lo, &read_hi);
1308 +
1309 +               if ((read_lo == write_lo) &&
1310 +                       ((read_hi & 0x0000ffff) ==
1311 +                       (write_hi & 0x0000ffff))) {
1312 +                       /* found correct address,*/
1313 +                       if (read_hi & (1 << 16)) {
1314 +                               /*extract the port index  from the valid entry*/
1315 +                               port = AT_EXTRACT_PORT(read_hi);
1316 +                               return port;
1317 +                       }
1318 +               }
1319 +       }
1320 +
1321 +       return -1;
1322 +}
1323 +
1324 +/* Get the port index from the source MAC address
1325 + * of the received frame
1326 + * @return port index
1327 + */
1328 +int esw_atable_dynamicms_get_portindex_from_mac(
1329 +       struct switch_enet_private *fep,
1330 +       unsigned char *mac_addr,
1331 +       unsigned long write_lo,
1332 +       unsigned long write_hi)
1333 +{
1334 +       int blockIdx;
1335 +       int rc;
1336 +       /*compute the block index*/
1337 +       blockIdx = GET_BLOCK_PTR(crc8_calc(mac_addr));
1338 +       /* Get the ingress port index of the received BPDU */
1339 +       rc = esw_atable_dynamicms_get_port(fep,
1340 +               write_lo, write_hi, blockIdx);
1341 +
1342 +       return rc;
1343 +}
1344 +
1345 +/* dynamicms MAC address table learn and migration*/
1346 +int esw_atable_dynamicms_learn_migration(
1347 +       struct switch_enet_private *fep,
1348 +       int currTime)
1349 +{
1350 +       eswPortInfo *pESWPortInfo;
1351 +       int index;
1352 +       int inserted = 0;
1353 +
1354 +       pESWPortInfo = esw_portinfofifo_read(fep);
1355 +       /* Anything to learn */
1356 +       if (pESWPortInfo != 0) {
1357 +               /*get block index from lookup table*/
1358 +               index = GET_BLOCK_PTR(pESWPortInfo->hash);
1359 +               inserted = esw_update_atable_dynamic1(
1360 +                       pESWPortInfo->maclo,
1361 +                       pESWPortInfo->machi, index,
1362 +                       pESWPortInfo->port, currTime, fep);
1363 +       }
1364 +
1365 +       return 0;
1366 +}
1367 +/* -----------------------------------------------------------------*/
1368 +/*
1369 + * esw_forced_forward
1370 + * The frame is forwared to the forced destination ports.
1371 + * It only replace the MAC lookup function,
1372 + * all other filtering(eg.VLAN verification) act as normal
1373 + */
1374 +int esw_forced_forward(struct switch_enet_private *fep,
1375 +       int port1, int port2, int enable)
1376 +{
1377 +       unsigned long tmp = 0;
1378 +       volatile switch_t  *fecp;
1379 +
1380 +       fecp = fep->hwp;
1381 +
1382 +       /* Enable Forced forwarding for port num */
1383 +       if ((port1 == 1) && (port2 == 1))
1384 +               tmp |= MCF_ESW_P0FFEN_FD(3);
1385 +       else if (port1 == 1)
1386 +               /*Enable Forced forwarding for port 1 only*/
1387 +               tmp |= MCF_ESW_P0FFEN_FD(1);
1388 +       else if (port2 == 1)
1389 +               /*Enable Forced forwarding for port 2 only*/
1390 +               tmp |= MCF_ESW_P0FFEN_FD(2);
1391 +       else {
1392 +               printk(KERN_ERR "%s:do not support "
1393 +                       "the forced forward mode"
1394 +                       "port1 %x port2 %x\n",
1395 +                       __func__, port1, port2);
1396 +               return -1;
1397 +       }
1398 +
1399 +       if (enable == 1)
1400 +               tmp |= MCF_ESW_P0FFEN_FEN;
1401 +       else if (enable == 0)
1402 +               tmp &= ~MCF_ESW_P0FFEN_FEN;
1403 +       else {
1404 +               printk(KERN_ERR "%s: the enable %x is error\n",
1405 +                       __func__, enable);
1406 +               return -2;
1407 +       }
1408 +
1409 +       fecp->ESW_P0FFEN = tmp;
1410 +       return 0;
1411 +}
1412 +
1413 +void esw_get_forced_forward(
1414 +       struct switch_enet_private *fep,
1415 +       unsigned long *ulForceForward)
1416 +{
1417 +       volatile switch_t  *fecp;
1418 +
1419 +       fecp = fep->hwp;
1420 +       *ulForceForward = fecp->ESW_P0FFEN;
1421 +}
1422 +
1423 +void esw_get_port_enable(
1424 +       struct switch_enet_private *fep,
1425 +       unsigned long *ulPortEnable)
1426 +{
1427 +       volatile switch_t  *fecp;
1428 +
1429 +       fecp = fep->hwp;
1430 +       *ulPortEnable = fecp->ESW_PER;
1431 +}
1432 +/*
1433 + * enable or disable port n tx or rx
1434 + * tx_en 0 disable port n tx
1435 + * tx_en 1 enable  port n tx
1436 + * rx_en 0 disbale port n rx
1437 + * rx_en 1 enable  port n rx
1438 + */
1439 +int esw_port_enable_config(struct switch_enet_private *fep,
1440 +       int port, int tx_en, int rx_en)
1441 +{
1442 +       unsigned long tmp = 0;
1443 +       volatile switch_t  *fecp;
1444 +
1445 +       fecp = fep->hwp;
1446 +       tmp = fecp->ESW_PER;
1447 +       if (tx_en == 1) {
1448 +               if (port == 0)
1449 +                       tmp |= MCF_ESW_PER_TE0;
1450 +               else if (port == 1)
1451 +                       tmp |= MCF_ESW_PER_TE1;
1452 +               else if (port == 2)
1453 +                       tmp |= MCF_ESW_PER_TE2;
1454 +               else {
1455 +                       printk(KERN_ERR "%s:do not support the"
1456 +                               " port %x tx enable\n",
1457 +                               __func__, port);
1458 +                       return -1;
1459 +               }
1460 +       } else if (tx_en == 0) {
1461 +               if (port == 0)
1462 +                       tmp &= (~MCF_ESW_PER_TE0);
1463 +               else if (port == 1)
1464 +                       tmp &= (~MCF_ESW_PER_TE1);
1465 +               else if (port == 2)
1466 +                       tmp &= (~MCF_ESW_PER_TE2);
1467 +               else {
1468 +                       printk(KERN_ERR "%s:do not support "
1469 +                               "the port %x tx disable\n",
1470 +                               __func__, port);
1471 +                       return -2;
1472 +               }
1473 +       } else {
1474 +               printk(KERN_ERR "%s:do not support the port %x"
1475 +                       " tx op value %x\n",
1476 +                       __func__, port, tx_en);
1477 +               return -3;
1478 +       }
1479 +
1480 +       if (rx_en == 1) {
1481 +               if (port == 0)
1482 +                       tmp |= MCF_ESW_PER_RE0;
1483 +               else if (port == 1)
1484 +                       tmp |= MCF_ESW_PER_RE1;
1485 +               else if (port == 2)
1486 +                       tmp |= MCF_ESW_PER_RE2;
1487 +               else {
1488 +                       printk(KERN_ERR "%s:do not support the "
1489 +                               "port %x rx enable\n",
1490 +                               __func__, port);
1491 +                       return -4;
1492 +               }
1493 +       } else if (rx_en == 0) {
1494 +               if (port == 0)
1495 +                       tmp &= (~MCF_ESW_PER_RE0);
1496 +               else if (port == 1)
1497 +                       tmp &= (~MCF_ESW_PER_RE1);
1498 +               else if (port == 2)
1499 +                       tmp &= (~MCF_ESW_PER_RE2);
1500 +               else {
1501 +                       printk(KERN_ERR "%s:do not support the "
1502 +                               "port %x rx disable\n",
1503 +                               __func__, port);
1504 +                       return -5;
1505 +               }
1506 +       } else {
1507 +               printk(KERN_ERR "%s:do not support the port %x"
1508 +                       " rx op value %x\n",
1509 +                       __func__, port, tx_en);
1510 +               return -6;
1511 +       }
1512 +
1513 +       fecp->ESW_PER = tmp;
1514 +       return 0;
1515 +}
1516 +
1517 +
1518 +void esw_get_port_broadcast(struct switch_enet_private *fep,
1519 +                       unsigned long *ulPortBroadcast)
1520 +{
1521 +       volatile switch_t  *fecp;
1522 +
1523 +       fecp = fep->hwp;
1524 +       *ulPortBroadcast = fecp->ESW_DBCR;
1525 +}
1526 +
1527 +int esw_port_broadcast_config(struct switch_enet_private *fep,
1528 +                       int port, int enable)
1529 +{
1530 +       unsigned long tmp = 0;
1531 +       volatile switch_t  *fecp;
1532 +
1533 +       fecp = fep->hwp;
1534 +
1535 +       if ((port > 2) || (port < 0)) {
1536 +               printk(KERN_ERR "%s:do not support the port %x"
1537 +                       " default broadcast\n",
1538 +                       __func__, port);
1539 +               return -1;
1540 +       }
1541 +
1542 +       tmp = fecp->ESW_DBCR;
1543 +       if (enable == 1) {
1544 +               if (port == 0)
1545 +                       tmp |= MCF_ESW_DBCR_P0;
1546 +               else if (port == 1)
1547 +                       tmp |= MCF_ESW_DBCR_P1;
1548 +               else if (port == 2)
1549 +                       tmp |= MCF_ESW_DBCR_P2;
1550 +       } else if (enable == 0) {
1551 +               if (port == 0)
1552 +                       tmp &= ~MCF_ESW_DBCR_P0;
1553 +               else if (port == 1)
1554 +                       tmp &= ~MCF_ESW_DBCR_P1;
1555 +               else if (port == 2)
1556 +                       tmp &= ~MCF_ESW_DBCR_P2;
1557 +       }
1558 +
1559 +       fecp->ESW_DBCR = tmp;
1560 +       return 0;
1561 +}
1562 +
1563 +
1564 +void esw_get_port_multicast(struct switch_enet_private *fep,
1565 +       unsigned long *ulPortMulticast)
1566 +{
1567 +       volatile switch_t  *fecp;
1568 +
1569 +       fecp = fep->hwp;
1570 +       *ulPortMulticast = fecp->ESW_DMCR;
1571 +}
1572 +
1573 +int esw_port_multicast_config(struct switch_enet_private *fep,
1574 +       int port, int enable)
1575 +{
1576 +       unsigned long tmp = 0;
1577 +       volatile switch_t  *fecp;
1578 +
1579 +       fecp = fep->hwp;
1580 +
1581 +       if ((port > 2) || (port < 0)) {
1582 +               printk(KERN_ERR "%s:do not support the port %x"
1583 +                       " default broadcast\n",
1584 +                       __func__, port);
1585 +               return -1;
1586 +       }
1587 +
1588 +       tmp = fecp->ESW_DMCR;
1589 +       if (enable == 1) {
1590 +               if (port == 0)
1591 +                       tmp |= MCF_ESW_DMCR_P0;
1592 +               else if (port == 1)
1593 +                       tmp |= MCF_ESW_DMCR_P1;
1594 +               else if (port == 2)
1595 +                       tmp |= MCF_ESW_DMCR_P2;
1596 +       } else if (enable == 0) {
1597 +               if (port == 0)
1598 +                       tmp &= ~MCF_ESW_DMCR_P0;
1599 +               else if (port == 1)
1600 +                       tmp &= ~MCF_ESW_DMCR_P1;
1601 +               else if (port == 2)
1602 +                       tmp &= ~MCF_ESW_DMCR_P2;
1603 +       }
1604 +
1605 +       fecp->ESW_DMCR = tmp;
1606 +       return 0;
1607 +}
1608 +
1609 +
1610 +void esw_get_port_blocking(struct switch_enet_private *fep,
1611 +       unsigned long *ulPortBlocking)
1612 +{
1613 +       volatile switch_t  *fecp;
1614 +
1615 +       fecp = fep->hwp;
1616 +       *ulPortBlocking = (fecp->ESW_BKLR & 0x0000000f);
1617 +}
1618 +
1619 +int esw_port_blocking_config(struct switch_enet_private *fep,
1620 +       int port, int enable)
1621 +{
1622 +       unsigned long tmp = 0;
1623 +       volatile switch_t  *fecp;
1624 +
1625 +       fecp = fep->hwp;
1626 +
1627 +       if ((port > 2) || (port < 0)) {
1628 +               printk(KERN_ERR "%s:do not support the port %x"
1629 +                       " default broadcast\n",
1630 +                       __func__, port);
1631 +               return -1;
1632 +       }
1633 +
1634 +       tmp = fecp->ESW_BKLR;
1635 +       if (enable == 1) {
1636 +               if (port == 0)
1637 +                       tmp |= MCF_ESW_BKLR_BE0;
1638 +               else if (port == 1)
1639 +                       tmp |= MCF_ESW_BKLR_BE1;
1640 +               else if (port == 2)
1641 +                       tmp |= MCF_ESW_BKLR_BE2;
1642 +       } else if (enable == 0) {
1643 +               if (port == 0)
1644 +                       tmp &= ~MCF_ESW_BKLR_BE0;
1645 +               else if (port == 1)
1646 +                       tmp &= ~MCF_ESW_BKLR_BE1;
1647 +               else if (port == 2)
1648 +                       tmp &= ~MCF_ESW_BKLR_BE2;
1649 +       }
1650 +
1651 +       fecp->ESW_BKLR = tmp;
1652 +       return 0;
1653 +}
1654 +
1655 +
1656 +void esw_get_port_learning(struct switch_enet_private *fep,
1657 +       unsigned long *ulPortLearning)
1658 +{
1659 +       volatile switch_t  *fecp;
1660 +
1661 +       fecp = fep->hwp;
1662 +       *ulPortLearning = (fecp->ESW_BKLR & 0x000f0000) >> 16;
1663 +}
1664 +
1665 +int esw_port_learning_config(struct switch_enet_private *fep,
1666 +       int port, int disable)
1667 +{
1668 +       unsigned long tmp = 0;
1669 +       volatile switch_t  *fecp;
1670 +
1671 +       fecp = fep->hwp;
1672 +
1673 +       if ((port > 2) || (port < 0)) {
1674 +               printk(KERN_ERR "%s:do not support the port %x"
1675 +                       " default broadcast\n",
1676 +                       __func__, port);
1677 +               return -1;
1678 +       }
1679 +
1680 +       tmp = fecp->ESW_BKLR;
1681 +       if (disable == 0) {
1682 +               fep->learning_irqhandle_enable = 0;
1683 +               if (port == 0)
1684 +                       tmp |= MCF_ESW_BKLR_LD0;
1685 +               else if (port == 1)
1686 +                       tmp |= MCF_ESW_BKLR_LD1;
1687 +               else if (port == 2)
1688 +                       tmp |= MCF_ESW_BKLR_LD2;
1689 +       } else if (disable == 1) {
1690 +               if (port == 0)
1691 +                       tmp &= ~MCF_ESW_BKLR_LD0;
1692 +               else if (port == 1)
1693 +                       tmp &= ~MCF_ESW_BKLR_LD1;
1694 +               else if (port == 2)
1695 +                       tmp &= ~MCF_ESW_BKLR_LD2;
1696 +       }
1697 +
1698 +       fecp->ESW_BKLR = tmp;
1699 +       return 0;
1700 +}
1701 +/*********************************************************************/
1702 +void esw_mac_lookup_table_range(struct switch_enet_private *fep)
1703 +{
1704 +       int index;
1705 +       unsigned long read_lo, read_hi;
1706 +       /* Pointer to switch address look up memory*/
1707 +       for (index = 0; index < 2048; index++)
1708 +               write_atable(fep, index, index, (~index));
1709 +
1710 +       /* Pointer to switch address look up memory*/
1711 +       for (index = 0; index < 2048; index++) {
1712 +               read_atable(fep, index, &read_lo, &read_hi);
1713 +               if (read_lo != index) {
1714 +                       printk(KERN_ERR "%s:Mismatch at low %d\n",
1715 +                               __func__, index);
1716 +                       return;
1717 +               }
1718 +
1719 +               if (read_hi != (~index)) {
1720 +                       printk(KERN_ERR "%s:Mismatch at high %d\n",
1721 +                               __func__, index);
1722 +                       return;
1723 +               }
1724 +       }
1725 +}
1726 +
1727 +/*
1728 + * Checks IP Snoop options of handling the snooped frame.
1729 + * mode 0 : The snooped frame is forward only to management port
1730 + * mode 1 : The snooped frame is copy to management port and
1731 + *              normal forwarding is checked.
1732 + * mode 2 : The snooped frame is discarded.
1733 + * mode 3 : Disable the ip snoop function
1734 + * ip_header_protocol : the IP header protocol field
1735 + */
1736 +int esw_ip_snoop_config(struct switch_enet_private *fep,
1737 +               int mode, unsigned long ip_header_protocol)
1738 +{
1739 +       volatile switch_t  *fecp;
1740 +       unsigned long tmp = 0, protocol_type = 0;
1741 +       int num = 0;
1742 +
1743 +       fecp = fep->hwp;
1744 +       /* Config IP Snooping */
1745 +       if (mode == 0) {
1746 +               /* Enable IP Snooping */
1747 +               tmp = MCF_ESW_IPSNP_EN;
1748 +               tmp |= MCF_ESW_IPSNP_MODE(0);/*For Forward*/
1749 +       } else if (mode == 1) {
1750 +               /* Enable IP Snooping */
1751 +               tmp = MCF_ESW_IPSNP_EN;
1752 +               /*For Forward and copy_to_mangmnt_port*/
1753 +               tmp |= MCF_ESW_IPSNP_MODE(1);
1754 +       } else if (mode == 2) {
1755 +               /* Enable IP Snooping */
1756 +               tmp = MCF_ESW_IPSNP_EN;
1757 +               tmp |= MCF_ESW_IPSNP_MODE(2);/*discard*/
1758 +       } else if (mode == 3) {
1759 +               /* disable IP Snooping */
1760 +               tmp = MCF_ESW_IPSNP_EN;
1761 +               tmp &= ~MCF_ESW_IPSNP_EN;
1762 +       } else {
1763 +               printk(KERN_ERR "%s: the mode %x "
1764 +                       "we do not support\n", __func__, mode);
1765 +               return -1;
1766 +       }
1767 +
1768 +       protocol_type = ip_header_protocol;
1769 +       for (num = 0; num < 8; num++) {
1770 +               if (protocol_type ==
1771 +                               AT_EXTRACT_IP_PROTOCOL(fecp->ESW_IPSNP[num])) {
1772 +                       fecp->ESW_IPSNP[num] =
1773 +                               tmp | MCF_ESW_IPSNP_PROTOCOL(protocol_type);
1774 +                       break;
1775 +               } else if (!(fecp->ESW_IPSNP[num])) {
1776 +                       fecp->ESW_IPSNP[num] =
1777 +                               tmp | MCF_ESW_IPSNP_PROTOCOL(protocol_type);
1778 +                       break;
1779 +               }
1780 +       }
1781 +       if (num == 8) {
1782 +               printk(KERN_INFO "IP snooping table is full\n");
1783 +               return 0;
1784 +       }
1785 +
1786 +       return 0;
1787 +}
1788 +
1789 +void esw_get_ip_snoop_config(struct switch_enet_private *fep,
1790 +       unsigned long *ulpESW_IPSNP)
1791 +{
1792 +       int i;
1793 +       volatile switch_t  *fecp;
1794 +
1795 +       fecp = fep->hwp;
1796 +       for (i = 0; i < 8; i++)
1797 +               *(ulpESW_IPSNP + i) = fecp->ESW_IPSNP[i];
1798 +}
1799 +/*
1800 + * Checks TCP/UDP Port Snoop options of handling the snooped frame.
1801 + * mode 0 : The snooped frame is forward only to management port
1802 + * mode 1 : The snooped frame is copy to management port and
1803 + *              normal forwarding is checked.
1804 + * mode 2 : The snooped frame is discarded.
1805 + * mode 3 : Disable the TCP/UDP port snoop function
1806 + * compare_port : port number in the TCP/UDP header
1807 + * compare_num 1: TCP/UDP source port number is compared
1808 + * compare_num 2: TCP/UDP destination port number is compared
1809 + * compare_num 3: TCP/UDP source and destination port number is compared
1810 + */
1811 +int esw_tcpudp_port_snoop_config(struct switch_enet_private *fep,
1812 +               int mode, int compare_port, int compare_num)
1813 +{
1814 +       volatile switch_t  *fecp;
1815 +       unsigned long tmp;
1816 +       int num;
1817 +
1818 +       fecp = fep->hwp;
1819 +
1820 +       /* Enable TCP/UDP port Snooping */
1821 +       tmp = MCF_ESW_PSNP_EN;
1822 +       if (mode == 0)
1823 +               tmp |= MCF_ESW_PSNP_MODE(0);/*For Forward*/
1824 +       else if (mode == 1)/*For Forward and copy_to_mangmnt_port*/
1825 +               tmp |= MCF_ESW_PSNP_MODE(1);
1826 +       else if (mode == 2)
1827 +               tmp |= MCF_ESW_PSNP_MODE(2);/*discard*/
1828 +       else if (mode == 3) /*disable the port function*/
1829 +               tmp &= (~MCF_ESW_PSNP_EN);
1830 +       else {
1831 +               printk(KERN_ERR "%s: the mode %x we do not support\n",
1832 +                       __func__, mode);
1833 +               return -1;
1834 +       }
1835 +
1836 +       if (compare_num == 1)
1837 +               tmp |= MCF_ESW_PSNP_CS;
1838 +       else if (compare_num == 2)
1839 +               tmp |= MCF_ESW_PSNP_CD;
1840 +       else if (compare_num == 3)
1841 +               tmp |= MCF_ESW_PSNP_CD | MCF_ESW_PSNP_CS;
1842 +       else {
1843 +               printk(KERN_ERR "%s: the compare port address %x"
1844 +                       " we do not support\n",
1845 +                       __func__, compare_num);
1846 +               return -1;
1847 +       }
1848 +
1849 +       for (num = 0; num < 8; num++) {
1850 +               if (compare_port ==
1851 +                               AT_EXTRACT_TCP_UDP_PORT(fecp->ESW_PSNP[num])) {
1852 +                       fecp->ESW_PSNP[num] =
1853 +                               tmp | MCF_ESW_PSNP_PORT_COMPARE(compare_port);
1854 +                       break;
1855 +               } else if (!(fecp->ESW_PSNP[num])) {
1856 +                       fecp->ESW_PSNP[num] =
1857 +                               tmp | MCF_ESW_PSNP_PORT_COMPARE(compare_port);
1858 +                       break;
1859 +               }
1860 +       }
1861 +       if (num == 8) {
1862 +               printk(KERN_INFO "TCP/UDP port snooping table is full\n");
1863 +               return 0;
1864 +       }
1865 +
1866 +       return 0;
1867 +}
1868 +
1869 +void esw_get_tcpudp_port_snoop_config(
1870 +       struct switch_enet_private *fep,
1871 +       unsigned long *ulpESW_PSNP)
1872 +{
1873 +       int i;
1874 +       volatile switch_t  *fecp;
1875 +
1876 +       fecp = fep->hwp;
1877 +       for (i = 0; i < 8; i++)
1878 +               *(ulpESW_PSNP + i) = fecp->ESW_PSNP[i];
1879 +}
1880 +/*-----------------mirror----------------------------------------*/
1881 +void esw_get_port_mirroring(struct switch_enet_private *fep)
1882 +{
1883 +       volatile switch_t  *fecp;
1884 +
1885 +       fecp = fep->hwp;
1886 +
1887 +       printk(KERN_INFO "Mirror Port: %1ld   Egress Port Match:%s    "
1888 +               "Ingress Port Match:%s\n", fecp->ESW_MCR & 0xf,
1889 +               (fecp->ESW_MCR >> 6) & 1 ? "Y" : "N",
1890 +               (fecp->ESW_MCR >> 5) & 1 ? "Y" : "N");
1891 +
1892 +       if ((fecp->ESW_MCR >> 6) & 1)
1893 +               printk(KERN_INFO "Egress Port to be mirrored: Port %ld\n",
1894 +                       fecp->ESW_EGMAP >> 1);
1895 +       if ((fecp->ESW_MCR >> 5) & 1)
1896 +               printk(KERN_INFO "Ingress Port to be mirrored: Port %ld\n",
1897 +                       fecp->ESW_INGMAP >> 1);
1898 +
1899 +       printk(KERN_INFO "Egress Des Address Match:%s    "
1900 +               "Egress Src Address Match:%s\n",
1901 +               (fecp->ESW_MCR >> 10) & 1 ? "Y" : "N",
1902 +               (fecp->ESW_MCR >> 9) & 1 ? "Y" : "N");
1903 +       printk(KERN_INFO "Ingress Des Address Match:%s   "
1904 +               "Ingress Src Address Match:%s\n",
1905 +               (fecp->ESW_MCR >> 8) & 1 ? "Y" : "N",
1906 +               (fecp->ESW_MCR >> 7) & 1 ? "Y" : "N");
1907 +
1908 +       if ((fecp->ESW_MCR >> 10) & 1)
1909 +               printk(KERN_INFO "Egress Des Address to be mirrored: "
1910 +                       "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n",
1911 +                       fecp->ESW_ENGDAL & 0xff, (fecp->ESW_ENGDAL >> 8) & 0xff,
1912 +                       (fecp->ESW_ENGDAL >> 16) & 0xff,
1913 +                       (fecp->ESW_ENGDAL >> 24) & 0xff,
1914 +                       fecp->ESW_ENGDAH & 0xff,
1915 +                       (fecp->ESW_ENGDAH >> 8) & 0xff);
1916 +       if ((fecp->ESW_MCR >> 9) & 1)
1917 +               printk("Egress Src Address to be mirrored: "
1918 +                       "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n",
1919 +                       fecp->ESW_ENGSAL & 0xff, (fecp->ESW_ENGSAL >> 8) & 0xff,
1920 +                       (fecp->ESW_ENGSAL >> 16) & 0xff,
1921 +                       (fecp->ESW_ENGSAL >> 24) & 0xff,
1922 +                       fecp->ESW_ENGSAH & 0xff,
1923 +                       (fecp->ESW_ENGSAH >> 8) & 0xff);
1924 +       if ((fecp->ESW_MCR >> 8) & 1)
1925 +               printk("Ingress Des Address to be mirrored: "
1926 +                       "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n",
1927 +                       fecp->ESW_INGDAL & 0xff, (fecp->ESW_INGDAL >> 8) & 0xff,
1928 +                       (fecp->ESW_INGDAL >> 16) & 0xff,
1929 +                       (fecp->ESW_INGDAL >> 24) & 0xff,
1930 +                       fecp->ESW_INGDAH & 0xff,
1931 +                       (fecp->ESW_INGDAH >> 8) & 0xff);
1932 +       if ((fecp->ESW_MCR >> 7) & 1)
1933 +               printk("Ingress Src Address to be mirrored: "
1934 +                       "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx\n",
1935 +                       fecp->ESW_INGSAL & 0xff, (fecp->ESW_INGSAL >> 8) & 0xff,
1936 +                       (fecp->ESW_INGSAL >> 16) & 0xff,
1937 +                       (fecp->ESW_INGSAL >> 24) & 0xff,
1938 +                       fecp->ESW_INGSAH & 0xff,
1939 +                       (fecp->ESW_INGSAH >> 8) & 0xff);
1940 +}
1941 +
1942 +int esw_port_mirroring_config_port_match(struct switch_enet_private *fep,
1943 +       int mirror_port, int port_match_en, int port)
1944 +{
1945 +       volatile switch_t  *fecp;
1946 +       unsigned long tmp = 0;
1947 +
1948 +       fecp = fep->hwp;
1949 +
1950 +       tmp = fecp->ESW_MCR;
1951 +       if (mirror_port != (tmp & 0xf))
1952 +               tmp = 0;
1953 +
1954 +       switch (port_match_en) {
1955 +       case MIRROR_EGRESS_PORT_MATCH:
1956 +               tmp |= MCF_ESW_MCR_EGMAP;
1957 +               if (port == 0)
1958 +                       fecp->ESW_EGMAP = MCF_ESW_EGMAP_EG0;
1959 +               else if (port == 1)
1960 +                       fecp->ESW_EGMAP = MCF_ESW_EGMAP_EG1;
1961 +               else if (port == 2)
1962 +                       fecp->ESW_EGMAP = MCF_ESW_EGMAP_EG2;
1963 +               break;
1964 +       case MIRROR_INGRESS_PORT_MATCH:
1965 +               tmp |= MCF_ESW_MCR_INGMAP;
1966 +               if (port == 0)
1967 +                       fecp->ESW_INGMAP = MCF_ESW_INGMAP_ING0;
1968 +               else if (port == 1)
1969 +                       fecp->ESW_INGMAP = MCF_ESW_INGMAP_ING1;
1970 +               else if (port == 2)
1971 +                       fecp->ESW_INGMAP = MCF_ESW_INGMAP_ING2;
1972 +               break;
1973 +       default:
1974 +               tmp = 0;
1975 +               break;
1976 +       }
1977 +
1978 +       tmp = tmp & 0x07e0;
1979 +       if (port_match_en)
1980 +               tmp |= MCF_ESW_MCR_MEN | MCF_ESW_MCR_PORT(mirror_port);
1981 +
1982 +       fecp->ESW_MCR = tmp;
1983 +       return 0;
1984 +}
1985 +
1986 +int esw_port_mirroring_config(struct switch_enet_private *fep,
1987 +       int mirror_port, int port, int mirror_enable,
1988 +       unsigned char *src_mac, unsigned char *des_mac,
1989 +       int egress_en, int ingress_en,
1990 +       int egress_mac_src_en, int egress_mac_des_en,
1991 +       int ingress_mac_src_en, int ingress_mac_des_en)
1992 +{
1993 +       volatile switch_t  *fecp;
1994 +       unsigned long tmp;
1995 +
1996 +       fecp = fep->hwp;
1997 +
1998 +       /*mirroring config*/
1999 +       tmp = 0;
2000 +       if (egress_en == 1) {
2001 +               tmp |= MCF_ESW_MCR_EGMAP;
2002 +               if (port == 0)
2003 +                       fecp->ESW_EGMAP = MCF_ESW_EGMAP_EG0;
2004 +               else if (port == 1)
2005 +                       fecp->ESW_EGMAP = MCF_ESW_EGMAP_EG1;
2006 +               else if (port == 2)
2007 +                       fecp->ESW_EGMAP = MCF_ESW_EGMAP_EG2;
2008 +               else {
2009 +                       printk(KERN_ERR "%s: the port %x we do not support\n",
2010 +                                       __func__, port);
2011 +                       return -1;
2012 +               }
2013 +       } else if (egress_en == 0) {
2014 +               tmp &= (~MCF_ESW_MCR_EGMAP);
2015 +       } else {
2016 +               printk(KERN_ERR "%s: egress_en %x we do not support\n",
2017 +                       __func__, egress_en);
2018 +               return -1;
2019 +       }
2020 +
2021 +       if (ingress_en == 1) {
2022 +               tmp |= MCF_ESW_MCR_INGMAP;
2023 +               if (port == 0)
2024 +                       fecp->ESW_INGMAP = MCF_ESW_INGMAP_ING0;
2025 +               else if (port == 1)
2026 +                       fecp->ESW_INGMAP = MCF_ESW_INGMAP_ING1;
2027 +               else if (port == 2)
2028 +                       fecp->ESW_INGMAP = MCF_ESW_INGMAP_ING2;
2029 +               else {
2030 +                       printk(KERN_ERR "%s: the port %x we do not support\n",
2031 +                               __func__, port);
2032 +                       return -1;
2033 +               }
2034 +       } else if (ingress_en == 0) {
2035 +               tmp &= ~MCF_ESW_MCR_INGMAP;
2036 +       } else{
2037 +               printk(KERN_ERR "%s: ingress_en %x we do not support\n",
2038 +                               __func__, ingress_en);
2039 +               return -1;
2040 +       }
2041 +
2042 +       if (egress_mac_src_en == 1) {
2043 +               tmp |= MCF_ESW_MCR_EGSA;
2044 +               fecp->ESW_ENGSAH = (src_mac[5] << 8) | (src_mac[4]);
2045 +               fecp->ESW_ENGSAL = (unsigned long)((src_mac[3] << 24) |
2046 +                                       (src_mac[2] << 16) |
2047 +                                       (src_mac[1] << 8) |
2048 +                                       src_mac[0]);
2049 +       } else if (egress_mac_src_en == 0) {
2050 +               tmp &= ~MCF_ESW_MCR_EGSA;
2051 +       } else {
2052 +               printk(KERN_ERR "%s: egress_mac_src_en  %x we do not support\n",
2053 +                       __func__, egress_mac_src_en);
2054 +               return -1;
2055 +       }
2056 +
2057 +       if (egress_mac_des_en == 1) {
2058 +               tmp |= MCF_ESW_MCR_EGDA;
2059 +               fecp->ESW_ENGDAH = (des_mac[5] << 8) | (des_mac[4]);
2060 +               fecp->ESW_ENGDAL = (unsigned long)((des_mac[3] << 24) |
2061 +                                       (des_mac[2] << 16) |
2062 +                                       (des_mac[1] << 8) |
2063 +                                       des_mac[0]);
2064 +       } else if (egress_mac_des_en == 0) {
2065 +               tmp &= ~MCF_ESW_MCR_EGDA;
2066 +       } else {
2067 +               printk(KERN_ERR "%s: egress_mac_des_en  %x we do not support\n",
2068 +                       __func__, egress_mac_des_en);
2069 +               return -1;
2070 +       }
2071 +
2072 +       if (ingress_mac_src_en == 1) {
2073 +               tmp |= MCF_ESW_MCR_INGSA;
2074 +               fecp->ESW_INGSAH = (src_mac[5] << 8) | (src_mac[4]);
2075 +               fecp->ESW_INGSAL = (unsigned long)((src_mac[3] << 24) |
2076 +                                       (src_mac[2] << 16) |
2077 +                                       (src_mac[1] << 8) |
2078 +                                       src_mac[0]);
2079 +       } else if (ingress_mac_src_en == 0) {
2080 +               tmp &= ~MCF_ESW_MCR_INGSA;
2081 +       } else {
2082 +               printk(KERN_ERR "%s: ingress_mac_src_en  %x we do not support\n",
2083 +                       __func__, ingress_mac_src_en);
2084 +               return -1;
2085 +       }
2086 +
2087 +       if (ingress_mac_des_en == 1) {
2088 +               tmp |= MCF_ESW_MCR_INGDA;
2089 +               fecp->ESW_INGDAH = (des_mac[5] << 8) | (des_mac[4]);
2090 +               fecp->ESW_INGDAL = (unsigned long)((des_mac[3] << 24) |
2091 +                                       (des_mac[2] << 16) |
2092 +                                       (des_mac[1] << 8) |
2093 +                                       des_mac[0]);
2094 +       } else if (ingress_mac_des_en == 0) {
2095 +               tmp &= ~MCF_ESW_MCR_INGDA;
2096 +       } else {
2097 +               printk(KERN_ERR "%s: ingress_mac_des_en  %x we do not support\n",
2098 +                       __func__, ingress_mac_des_en);
2099 +               return -1;
2100 +       }
2101 +
2102 +       if (mirror_enable == 1)
2103 +               tmp |= MCF_ESW_MCR_MEN | MCF_ESW_MCR_PORT(mirror_port);
2104 +       else if (mirror_enable == 0)
2105 +               tmp &= ~MCF_ESW_MCR_MEN;
2106 +       else
2107 +               printk(KERN_ERR "%s: the mirror enable %x is error\n",
2108 +                       __func__, mirror_enable);
2109 +
2110 +
2111 +       fecp->ESW_MCR = tmp;
2112 +       return 0;
2113 +}
2114 +
2115 +int esw_port_mirroring_config_addr_match(struct switch_enet_private *fep,
2116 +       int mirror_port, int addr_match_enable, unsigned char *mac_addr)
2117 +{
2118 +       volatile switch_t  *fecp;
2119 +       unsigned long tmp = 0;
2120 +
2121 +       fecp = fep->hwp;
2122 +
2123 +       tmp = fecp->ESW_MCR;
2124 +       if (mirror_port != (tmp & 0xf))
2125 +               tmp = 0;
2126 +
2127 +       switch (addr_match_enable) {
2128 +       case MIRROR_EGRESS_SOURCE_MATCH:
2129 +               tmp |= MCF_ESW_MCR_EGSA;
2130 +               fecp->ESW_ENGSAH = (mac_addr[5] << 8) | (mac_addr[4]);
2131 +               fecp->ESW_ENGSAL = (unsigned long)((mac_addr[3] << 24) |
2132 +                       (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]);
2133 +               break;
2134 +       case MIRROR_INGRESS_SOURCE_MATCH:
2135 +               tmp |= MCF_ESW_MCR_INGSA;
2136 +               fecp->ESW_INGSAH = (mac_addr[5] << 8) | (mac_addr[4]);
2137 +               fecp->ESW_INGSAL = (unsigned long)((mac_addr[3] << 24) |
2138 +                       (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]);
2139 +               break;
2140 +       case MIRROR_EGRESS_DESTINATION_MATCH:
2141 +               tmp |= MCF_ESW_MCR_EGDA;
2142 +               fecp->ESW_ENGDAH = (mac_addr[5] << 8) | (mac_addr[4]);
2143 +               fecp->ESW_ENGDAL = (unsigned long)((mac_addr[3] << 24) |
2144 +                       (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]);
2145 +               break;
2146 +       case MIRROR_INGRESS_DESTINATION_MATCH:
2147 +               tmp |= MCF_ESW_MCR_INGDA;
2148 +               fecp->ESW_INGDAH = (mac_addr[5] << 8) | (mac_addr[4]);
2149 +               fecp->ESW_INGDAL = (unsigned long)((mac_addr[3] << 24) |
2150 +                       (mac_addr[2] << 16) | (mac_addr[1] << 8) | mac_addr[0]);
2151 +               break;
2152 +       default:
2153 +               tmp = 0;
2154 +               break;
2155 +       }
2156 +
2157 +       tmp = tmp & 0x07e0;
2158 +       if (addr_match_enable)
2159 +               tmp |= MCF_ESW_MCR_MEN | MCF_ESW_MCR_PORT(mirror_port);
2160 +
2161 +       fecp->ESW_MCR = tmp;
2162 +       return 0;
2163 +}
2164 +
2165 +void esw_get_vlan_verification(struct switch_enet_private *fep,
2166 +       unsigned long *ulValue)
2167 +{
2168 +       volatile switch_t  *fecp;
2169 +       fecp = fep->hwp;
2170 +       *ulValue = fecp->ESW_VLANV;
2171 +}
2172 +
2173 +int esw_set_vlan_verification(struct switch_enet_private *fep, int port,
2174 +       int vlan_domain_verify_en, int vlan_discard_unknown_en)
2175 +{
2176 +       volatile switch_t  *fecp;
2177 +
2178 +       fecp = fep->hwp;
2179 +       if ((port < 0) || (port > 2)) {
2180 +               printk(KERN_ERR "%s: do not support the port %d\n",
2181 +                       __func__, port);
2182 +               return -1;
2183 +       }
2184 +
2185 +       if (vlan_domain_verify_en == 1) {
2186 +               if (port == 0)
2187 +                       fecp->ESW_VLANV |= MCF_ESW_VLANV_VV0;
2188 +               else if (port == 1)
2189 +                       fecp->ESW_VLANV |= MCF_ESW_VLANV_VV1;
2190 +               else if (port == 2)
2191 +                       fecp->ESW_VLANV |= MCF_ESW_VLANV_VV2;
2192 +       } else if (vlan_domain_verify_en == 0) {
2193 +               if (port == 0)
2194 +                       fecp->ESW_VLANV &= ~MCF_ESW_VLANV_VV0;
2195 +               else if (port == 1)
2196 +                       fecp->ESW_VLANV &= ~MCF_ESW_VLANV_VV1;
2197 +               else if (port == 2)
2198 +                       fecp->ESW_VLANV &= ~MCF_ESW_VLANV_VV2;
2199 +       } else {
2200 +               printk(KERN_INFO "%s: donot support "
2201 +                       "vlan_domain_verify %x\n",
2202 +                       __func__, vlan_domain_verify_en);
2203 +               return -2;
2204 +       }
2205 +
2206 +       if (vlan_discard_unknown_en == 1) {
2207 +               if (port == 0)
2208 +                       fecp->ESW_VLANV |= MCF_ESW_VLANV_DU0;
2209 +               else if (port == 1)
2210 +                       fecp->ESW_VLANV |= MCF_ESW_VLANV_DU1;
2211 +               else if (port == 2)
2212 +                       fecp->ESW_VLANV |= MCF_ESW_VLANV_DU2;
2213 +       } else if (vlan_discard_unknown_en == 0) {
2214 +               if (port == 0)
2215 +                       fecp->ESW_VLANV &= ~MCF_ESW_VLANV_DU0;
2216 +               else if (port == 1)
2217 +                       fecp->ESW_VLANV &= ~MCF_ESW_VLANV_DU1;
2218 +               else if (port == 2)
2219 +                       fecp->ESW_VLANV &= ~MCF_ESW_VLANV_DU2;
2220 +       } else {
2221 +               printk(KERN_INFO "%s: donot support "
2222 +                       "vlan_discard_unknown %x\n",
2223 +                       __func__, vlan_discard_unknown_en);
2224 +               return -3;
2225 +       }
2226 +
2227 +       return 0;
2228 +}
2229 +
2230 +void esw_get_vlan_resolution_table(struct switch_enet_private *fep,
2231 +       struct eswVlanTableItem *tableaddr)
2232 +{
2233 +       volatile switch_t  *fecp;
2234 +       int vnum = 0;
2235 +       int i;
2236 +
2237 +       fecp = fep->hwp;
2238 +       for (i = 0; i < 32; i++) {
2239 +               if (fecp->ESW_VRES[i]) {
2240 +                       tableaddr->table[i].port_vlanid =
2241 +                               fecp->ESW_VRES[i] >> 3;
2242 +                       tableaddr->table[i].vlan_domain_port =
2243 +                               fecp->ESW_VRES[i] & 7;
2244 +                       vnum++;
2245 +               }
2246 +       }
2247 +       tableaddr->valid_num = vnum;
2248 +}
2249 +
2250 +int esw_set_vlan_id(struct switch_enet_private *fep, unsigned long configData)
2251 +{
2252 +       volatile switch_t  *fecp;
2253 +       int i;
2254 +
2255 +       fecp = fep->hwp;
2256 +
2257 +       for (i = 0; i < 32; i++) {
2258 +               if (fecp->ESW_VRES[i] == 0) {
2259 +                       fecp->ESW_VRES[i] = MCF_ESW_VRES_VLANID(configData);
2260 +                       return 0;
2261 +               } else if (((fecp->ESW_VRES[i] >> 3) & 0xfff) == configData) {
2262 +                       printk(KERN_INFO "The VLAN already exists\n");
2263 +                       return 0;
2264 +               }
2265 +       }
2266 +
2267 +       printk(KERN_INFO "The VLAN can't create, because VLAN table is full\n");
2268 +       return 0;
2269 +}
2270 +
2271 +int esw_set_vlan_id_cleared(struct switch_enet_private *fep,
2272 +               unsigned long configData)
2273 +{
2274 +       volatile switch_t  *fecp;
2275 +       int i;
2276 +
2277 +       fecp = fep->hwp;
2278 +
2279 +       for (i = 0; i < 32; i++) {
2280 +               if (((fecp->ESW_VRES[i] >> 3) & 0xfff) == configData) {
2281 +                       fecp->ESW_VRES[i] = 0;
2282 +                       break;
2283 +               }
2284 +       }
2285 +       return 0;
2286 +}
2287 +
2288 +int esw_set_port_in_vlan_id(struct switch_enet_private *fep,
2289 +              eswIoctlVlanResoultionTable configData)
2290 +{
2291 +       volatile switch_t  *fecp;
2292 +       int i;
2293 +       int lastnum = 0;
2294 +
2295 +       fecp = fep->hwp;
2296 +
2297 +       for (i = 0; i < 32; i++) {
2298 +               if (fecp->ESW_VRES[i] == 0) {
2299 +                       lastnum = i;
2300 +                       break;
2301 +               } else if (((fecp->ESW_VRES[i] >> 3) & 0xfff) ==
2302 +                               configData.port_vlanid) {
2303 +                       /* update the port members of this vlan */
2304 +                       fecp->ESW_VRES[i] |= 1 << configData.vlan_domain_port;
2305 +                       return 0;
2306 +               }
2307 +       }
2308 +       /* creat a new vlan in vlan table */
2309 +       fecp->ESW_VRES[lastnum] = MCF_ESW_VRES_VLANID(configData.port_vlanid) |
2310 +               (1 << configData.vlan_domain_port);
2311 +       return 0;
2312 +}
2313 +
2314 +int esw_set_vlan_resolution_table(struct switch_enet_private *fep,
2315 +       unsigned short port_vlanid, int vlan_domain_num,
2316 +       int vlan_domain_port)
2317 +{
2318 +       volatile switch_t  *fecp;
2319 +
2320 +       fecp = fep->hwp;
2321 +       if ((vlan_domain_num < 0)
2322 +               || (vlan_domain_num > 31)) {
2323 +               printk(KERN_ERR "%s: do not support the "
2324 +                       "vlan_domain_num %d\n",
2325 +               __func__, vlan_domain_num);
2326 +               return -1;
2327 +       }
2328 +
2329 +       if ((vlan_domain_port < 0)
2330 +               || (vlan_domain_port > 7)) {
2331 +               printk(KERN_ERR "%s: do not support the "
2332 +                       "vlan_domain_port %d\n",
2333 +                       __func__, vlan_domain_port);
2334 +               return -2;
2335 +       }
2336 +
2337 +       fecp->ESW_VRES[vlan_domain_num] =
2338 +               MCF_ESW_VRES_VLANID(port_vlanid)
2339 +               | vlan_domain_port;
2340 +
2341 +       return 0;
2342 +}
2343 +
2344 +void esw_get_vlan_input_config(struct switch_enet_private *fep,
2345 +       eswIoctlVlanInputStatus *pVlanInputConfig)
2346 +{
2347 +       volatile switch_t  *fecp;
2348 +       int i;
2349 +
2350 +       fecp = fep->hwp;
2351 +       for (i = 0; i < 3; i++)
2352 +               pVlanInputConfig->ESW_PID[i] = fecp->ESW_PID[i];
2353 +
2354 +       pVlanInputConfig->ESW_VLANV  = fecp->ESW_VLANV;
2355 +       pVlanInputConfig->ESW_VIMSEL = fecp->ESW_VIMSEL;
2356 +       pVlanInputConfig->ESW_VIMEN  = fecp->ESW_VIMEN;
2357 +
2358 +       for (i = 0; i < 32; i++)
2359 +               pVlanInputConfig->ESW_VRES[i] = fecp->ESW_VRES[i];
2360 +}
2361 +
2362 +
2363 +int esw_vlan_input_process(struct switch_enet_private *fep,
2364 +       int port, int mode, unsigned short port_vlanid)
2365 +{
2366 +       volatile switch_t  *fecp;
2367 +
2368 +       fecp = fep->hwp;
2369 +
2370 +       if ((mode < 0) || (mode > 5)) {
2371 +               printk(KERN_ERR "%s: do not support the"
2372 +                       " VLAN input processing mode %d\n",
2373 +                       __func__, mode);
2374 +               return -1;
2375 +       }
2376 +
2377 +       if ((port < 0) || (port > 3)) {
2378 +               printk(KERN_ERR "%s: do not support the port %d\n",
2379 +                       __func__, mode);
2380 +               return -2;
2381 +       }
2382 +
2383 +       fecp->ESW_PID[port] = MCF_ESW_PID_VLANID(port_vlanid);
2384 +       if (port == 0) {
2385 +               if (mode == 4)
2386 +                       fecp->ESW_VIMEN &= ~MCF_ESW_VIMEN_EN0;
2387 +               else
2388 +                       fecp->ESW_VIMEN |= MCF_ESW_VIMEN_EN0;
2389 +
2390 +               fecp->ESW_VIMSEL &= ~MCF_ESW_VIMSEL_IM0(3);
2391 +               fecp->ESW_VIMSEL |= MCF_ESW_VIMSEL_IM0(mode);
2392 +       } else if (port == 1) {
2393 +               if (mode == 4)
2394 +                       fecp->ESW_VIMEN &= ~MCF_ESW_VIMEN_EN1;
2395 +               else
2396 +                       fecp->ESW_VIMEN |= MCF_ESW_VIMEN_EN1;
2397 +
2398 +               fecp->ESW_VIMSEL &= ~MCF_ESW_VIMSEL_IM1(3);
2399 +               fecp->ESW_VIMSEL |= MCF_ESW_VIMSEL_IM1(mode);
2400 +       } else if (port == 2) {
2401 +               if (mode == 4)
2402 +                       fecp->ESW_VIMEN &= ~MCF_ESW_VIMEN_EN2;
2403 +               else
2404 +                       fecp->ESW_VIMEN |= MCF_ESW_VIMEN_EN2;
2405 +
2406 +               fecp->ESW_VIMSEL &= ~MCF_ESW_VIMSEL_IM2(3);
2407 +               fecp->ESW_VIMSEL |= MCF_ESW_VIMSEL_IM2(mode);
2408 +       } else {
2409 +               printk(KERN_ERR "%s: do not support the port %d\n",
2410 +                       __func__, port);
2411 +               return -2;
2412 +       }
2413 +
2414 +       return 0;
2415 +}
2416 +
2417 +void esw_get_vlan_output_config(struct switch_enet_private *fep,
2418 +       unsigned long *ulVlanOutputConfig)
2419 +{
2420 +       volatile switch_t  *fecp;
2421 +
2422 +       fecp = fep->hwp;
2423 +       *ulVlanOutputConfig = fecp->ESW_VOMSEL;
2424 +}
2425 +
2426 +int esw_vlan_output_process(struct switch_enet_private *fep,
2427 +       int port, int mode)
2428 +{
2429 +       volatile switch_t  *fecp;
2430 +
2431 +       fecp = fep->hwp;
2432 +
2433 +       if ((port < 0) || (port > 2)) {
2434 +               printk(KERN_ERR "%s: do not support the port %d\n",
2435 +                       __func__, mode);
2436 +               return -1;
2437 +       }
2438 +
2439 +       if (port == 0) {
2440 +               fecp->ESW_VOMSEL &= ~MCF_ESW_VOMSEL_OM0(3);
2441 +               fecp->ESW_VOMSEL |= MCF_ESW_VOMSEL_OM0(mode);
2442 +       } else if (port == 1) {
2443 +               fecp->ESW_VOMSEL &= ~MCF_ESW_VOMSEL_OM1(3);
2444 +               fecp->ESW_VOMSEL |= MCF_ESW_VOMSEL_OM1(mode);
2445 +       } else if (port == 2) {
2446 +               fecp->ESW_VOMSEL &= ~MCF_ESW_VOMSEL_OM2(3);
2447 +               fecp->ESW_VOMSEL |= MCF_ESW_VOMSEL_OM2(mode);
2448 +       } else {
2449 +               printk(KERN_ERR "%s: do not support the port %d\n",
2450 +                       __func__, port);
2451 +               return -1;
2452 +       }
2453 +
2454 +       return 0;
2455 +}
2456 +
2457 +/*------------frame calssify and priority resolution------------*/
2458 +/*vlan priority lookup*/
2459 +int esw_framecalssify_vlan_priority_lookup(struct switch_enet_private *fep,
2460 +       int port, int func_enable, int vlan_pri_table_num,
2461 +       int vlan_pri_table_value)
2462 +{
2463 +       volatile switch_t  *fecp;
2464 +
2465 +       fecp = fep->hwp;
2466 +
2467 +       if ((port < 0) || (port > 3)) {
2468 +               printk(KERN_ERR "%s: do not support the port %d\n",
2469 +                       __func__, port);
2470 +               return -1;
2471 +       }
2472 +
2473 +       if (func_enable == 0) {
2474 +               fecp->ESW_PRES[port] &= ~MCF_ESW_PRES_VLAN;
2475 +               printk(KERN_ERR "%s: disable port %d VLAN priority "
2476 +                       "lookup function\n", __func__, port);
2477 +               return 0;
2478 +       }
2479 +
2480 +       if ((vlan_pri_table_num < 0) || (vlan_pri_table_num > 7)) {
2481 +               printk(KERN_ERR "%s: do not support the priority %d\n",
2482 +                       __func__, vlan_pri_table_num);
2483 +               return -1;
2484 +       }
2485 +
2486 +       fecp->ESW_PVRES[port] |= ((vlan_pri_table_value & 0x3)
2487 +               << (vlan_pri_table_num*3));
2488 +       /* enable port  VLAN priority lookup function*/
2489 +       fecp->ESW_PRES[port] |= MCF_ESW_PRES_VLAN;
2490 +       return 0;
2491 +}
2492 +
2493 +int esw_framecalssify_ip_priority_lookup(struct switch_enet_private *fep,
2494 +       int port, int func_enable, int ipv4_en, int ip_priority_num,
2495 +       int ip_priority_value)
2496 +{
2497 +       volatile switch_t  *fecp;
2498 +       unsigned long tmp = 0, tmp_prio = 0;
2499 +
2500 +       fecp = fep->hwp;
2501 +
2502 +       if ((port < 0) || (port > 3)) {
2503 +               printk(KERN_ERR "%s: do not support the port %d\n",
2504 +                       __func__, port);
2505 +               return -1;
2506 +       }
2507 +
2508 +       if (func_enable == 0) {
2509 +               fecp->ESW_PRES[port] &= ~MCF_ESW_PRES_IP;
2510 +               printk(KERN_ERR "%s: disable port %d ip priority "
2511 +                       "lookup function\n", __func__, port);
2512 +               return 0;
2513 +       }
2514 +
2515 +       /* IPV4 priority 64 entry table lookup*/
2516 +       /* IPv4 head 6 bit TOS field*/
2517 +       if (ipv4_en == 1) {
2518 +               if ((ip_priority_num < 0) || (ip_priority_num > 63)) {
2519 +                       printk(KERN_ERR "%s: do not support the table entry %d\n",
2520 +                               __func__, ip_priority_num);
2521 +                       return -2;
2522 +               }
2523 +       } else { /* IPV6 priority 256 entry table lookup*/
2524 +               /* IPv6 head 8 bit COS field*/
2525 +               if ((ip_priority_num < 0) || (ip_priority_num > 255)) {
2526 +                       printk(KERN_ERR "%s: do not support the table entry %d\n",
2527 +                               __func__, ip_priority_num);
2528 +                       return -3;
2529 +               }
2530 +       }
2531 +
2532 +       /* IP priority  table lookup : address*/
2533 +       tmp = MCF_ESW_IPRES_ADDRESS(ip_priority_num);
2534 +       /* IP priority  table lookup : ipv4sel*/
2535 +       if (ipv4_en == 1)
2536 +               tmp = tmp | MCF_ESW_IPRES_IPV4SEL;
2537 +       /* IP priority  table lookup : priority*/
2538 +       if (port == 0)
2539 +               tmp |= MCF_ESW_IPRES_PRI0(ip_priority_value);
2540 +       else if (port == 1)
2541 +               tmp |= MCF_ESW_IPRES_PRI1(ip_priority_value);
2542 +       else if (port == 2)
2543 +               tmp |= MCF_ESW_IPRES_PRI2(ip_priority_value);
2544 +
2545 +       /* configure*/
2546 +       fecp->ESW_IPRES = MCF_ESW_IPRES_READ |
2547 +               MCF_ESW_IPRES_ADDRESS(ip_priority_num);
2548 +       tmp_prio = fecp->ESW_IPRES;
2549 +
2550 +       fecp->ESW_IPRES = tmp | tmp_prio;
2551 +
2552 +       fecp->ESW_IPRES = MCF_ESW_IPRES_READ |
2553 +               MCF_ESW_IPRES_ADDRESS(ip_priority_num);
2554 +       tmp_prio = fecp->ESW_IPRES;
2555 +
2556 +       /* enable port  IP priority lookup function*/
2557 +       fecp->ESW_PRES[port] |= MCF_ESW_PRES_IP;
2558 +       return 0;
2559 +}
2560 +
2561 +int esw_framecalssify_mac_priority_lookup(
2562 +               struct switch_enet_private *fep, int port)
2563 +{
2564 +       volatile switch_t  *fecp;
2565 +
2566 +       if ((port < 0) || (port > 3)) {
2567 +               printk(KERN_ERR "%s: do not support the port %d\n",
2568 +                       __func__, port);
2569 +               return -1;
2570 +       }
2571 +
2572 +       fecp = fep->hwp;
2573 +       fecp->ESW_PRES[port] |= MCF_ESW_PRES_MAC;
2574 +
2575 +       return 0;
2576 +}
2577 +
2578 +int esw_frame_calssify_priority_init(struct switch_enet_private *fep,
2579 +       int port, unsigned char priority_value)
2580 +{
2581 +       volatile switch_t  *fecp;
2582 +
2583 +       fecp = fep->hwp;
2584 +
2585 +       if ((port < 0) || (port > 3)) {
2586 +               printk(KERN_ERR "%s: do not support the port %d\n",
2587 +                       __func__, port);
2588 +               return -1;
2589 +       }
2590 +       /*disable all priority lookup function*/
2591 +       fecp->ESW_PRES[port] = 0;
2592 +       fecp->ESW_PRES[port] = MCF_ESW_PRES_DFLT_PRI(priority_value & 0x7);
2593 +
2594 +       return 0;
2595 +}
2596 +
2597 +/*---------------------------------------------------------------------------*/
2598 +int esw_get_statistics_status(struct switch_enet_private *fep,
2599 +       esw_statistics_status *pStatistics)
2600 +{
2601 +       volatile switch_t  *fecp;
2602 +       fecp = fep->hwp;
2603 +
2604 +       pStatistics->ESW_DISCN   = fecp->ESW_DISCN;
2605 +       pStatistics->ESW_DISCB   = fecp->ESW_DISCB;
2606 +       pStatistics->ESW_NDISCN  = fecp->ESW_NDISCN;
2607 +       pStatistics->ESW_NDISCB  = fecp->ESW_NDISCB;
2608 +       return 0;
2609 +}
2610 +
2611 +int esw_get_port_statistics_status(struct switch_enet_private *fep,
2612 +       int port, esw_port_statistics_status *pPortStatistics)
2613 +{
2614 +       volatile switch_t  *fecp;
2615 +
2616 +       if ((port < 0) || (port > 3)) {
2617 +               printk(KERN_ERR "%s: do not support the port %d\n",
2618 +                       __func__, port);
2619 +               return -1;
2620 +       }
2621 +
2622 +       fecp = fep->hwp;
2623 +
2624 +       pPortStatistics->MCF_ESW_POQC   =
2625 +               fecp->port_statistics_status[port].MCF_ESW_POQC;
2626 +       pPortStatistics->MCF_ESW_PMVID  =
2627 +               fecp->port_statistics_status[port].MCF_ESW_PMVID;
2628 +       pPortStatistics->MCF_ESW_PMVTAG =
2629 +               fecp->port_statistics_status[port].MCF_ESW_PMVTAG;
2630 +       pPortStatistics->MCF_ESW_PBL    =
2631 +               fecp->port_statistics_status[port].MCF_ESW_PBL;
2632 +       return 0;
2633 +}
2634 +/*----------------------------------------------------------------------*/
2635 +int esw_get_output_queue_status(struct switch_enet_private *fep,
2636 +       esw_output_queue_status *pOutputQueue)
2637 +{
2638 +       volatile switch_t  *fecp;
2639 +
2640 +       fecp = fep->hwp;
2641 +       pOutputQueue->ESW_MMSR  = fecp->ESW_MMSR;
2642 +       pOutputQueue->ESW_LMT   = fecp->ESW_LMT;
2643 +       pOutputQueue->ESW_LFC   = fecp->ESW_LFC;
2644 +       pOutputQueue->ESW_IOSR  = fecp->ESW_IOSR;
2645 +       pOutputQueue->ESW_PCSR  = fecp->ESW_PCSR;
2646 +       pOutputQueue->ESW_QWT   = fecp->ESW_QWT;
2647 +       pOutputQueue->ESW_P0BCT = fecp->ESW_P0BCT;
2648 +       return 0;
2649 +}
2650 +
2651 +/* set output queue memory status and configure*/
2652 +int esw_set_output_queue_memory(struct switch_enet_private *fep,
2653 +       int fun_num, esw_output_queue_status *pOutputQueue)
2654 +{
2655 +       volatile switch_t  *fecp;
2656 +
2657 +       fecp = fep->hwp;
2658 +
2659 +       if (fun_num == 1) {
2660 +               /* memory manager status*/
2661 +               fecp->ESW_MMSR = pOutputQueue->ESW_MMSR;
2662 +       } else if (fun_num == 2) {
2663 +               /*low memory threshold*/
2664 +               fecp->ESW_LMT = pOutputQueue->ESW_LMT;
2665 +       } else if (fun_num == 3) {
2666 +               /*lowest number of free cells*/
2667 +               fecp->ESW_LFC = pOutputQueue->ESW_LFC;
2668 +       } else if (fun_num == 4) {
2669 +               /*queue weights*/
2670 +               fecp->ESW_QWT = pOutputQueue->ESW_QWT;
2671 +       } else if (fun_num == 5) {
2672 +               /*port 0 backpressure congenstion thresled*/
2673 +               fecp->ESW_P0BCT = pOutputQueue->ESW_P0BCT;
2674 +       } else {
2675 +               printk(KERN_ERR "%s: do not support the cmd %x\n",
2676 +                       __func__, fun_num);
2677 +               return -1;
2678 +       }
2679 +       return 0;
2680 +}
2681 +/*--------------------------------------------------------------------*/
2682 +int esw_get_irq_status(struct switch_enet_private *fep,
2683 +       eswIoctlIrqStatus *pIrqStatus)
2684 +{
2685 +       volatile switch_t  *fecp;
2686 +
2687 +       fecp = fep->hwp;
2688 +       pIrqStatus->isr             = fecp->switch_ievent;
2689 +       pIrqStatus->imr             = fecp->switch_imask;
2690 +       pIrqStatus->rx_buf_pointer  = fecp->fec_r_des_start;
2691 +       pIrqStatus->tx_buf_pointer  = fecp->fec_x_des_start;
2692 +       pIrqStatus->rx_max_size     = fecp->fec_r_buff_size;
2693 +       pIrqStatus->rx_buf_active   = fecp->fec_r_des_active;
2694 +       pIrqStatus->tx_buf_active   = fecp->fec_x_des_active;
2695 +       return 0;
2696 +}
2697 +
2698 +int esw_set_irq_mask(struct switch_enet_private *fep,
2699 +       unsigned long mask, int enable)
2700 +{
2701 +       volatile switch_t  *fecp;
2702 +
2703 +       fecp = fep->hwp;
2704 +
2705 +       if (enable == 1)
2706 +               fecp->switch_imask |= mask;
2707 +       else if (enable == 1)
2708 +               fecp->switch_imask &= (~mask);
2709 +       else {
2710 +               printk(KERN_INFO "%s: enable %lx is error value\n",
2711 +                       __func__, mask);
2712 +               return -1;
2713 +       }
2714 +       return 0;
2715 +}
2716 +
2717 +void esw_clear_irq_event(struct switch_enet_private *fep,
2718 +       unsigned long mask)
2719 +{
2720 +       volatile switch_t  *fecp;
2721 +
2722 +       fecp = fep->hwp;
2723 +       fecp->switch_ievent |= mask;
2724 +}
2725 +
2726 +void esw_get_switch_mode(struct switch_enet_private *fep,
2727 +       unsigned long *ulModeConfig)
2728 +{
2729 +       volatile switch_t  *fecp;
2730 +
2731 +       fecp = fep->hwp;
2732 +       *ulModeConfig = fecp->ESW_MODE;
2733 +}
2734 +
2735 +void esw_switch_mode_configure(struct switch_enet_private *fep,
2736 +       unsigned long configure)
2737 +{
2738 +       volatile switch_t  *fecp;
2739 +
2740 +       fecp = fep->hwp;
2741 +       fecp->ESW_MODE |= configure;
2742 +}
2743 +
2744 +void esw_get_bridge_port(struct switch_enet_private *fep,
2745 +       unsigned long *ulBMPConfig)
2746 +{
2747 +       volatile switch_t  *fecp;
2748 +
2749 +       fecp = fep->hwp;
2750 +       *ulBMPConfig = fecp->ESW_BMPC;
2751 +}
2752 +
2753 +void  esw_bridge_port_configure(struct switch_enet_private *fep,
2754 +       unsigned long configure)
2755 +{
2756 +       volatile switch_t  *fecp;
2757 +
2758 +       fecp = fep->hwp;
2759 +       fecp->ESW_BMPC = configure;
2760 +}
2761 +
2762 +int esw_get_port_all_status(struct switch_enet_private *fep,
2763 +               unsigned char portnum, struct port_all_status *port_alstatus)
2764 +{
2765 +       volatile switch_t *fecp;
2766 +       unsigned long PortBlocking;
2767 +       unsigned long PortLearning;
2768 +       unsigned long VlanVerify;
2769 +       unsigned long DiscardUnknown;
2770 +       unsigned long MultiReso;
2771 +       unsigned long BroadReso;
2772 +       unsigned long FTransmit;
2773 +       unsigned long FReceive;
2774 +
2775 +       fecp = fep->hwp;
2776 +       PortBlocking = fecp->ESW_BKLR & 0x0000000f;
2777 +       PortLearning = (fecp->ESW_BKLR & 0x000f0000) >> 16;
2778 +       VlanVerify = fecp->ESW_VLANV & 0x0000000f;
2779 +       DiscardUnknown = (fecp->ESW_VLANV & 0x000f0000) >> 16;
2780 +       MultiReso = fecp->ESW_DMCR & 0x0000000f;
2781 +       BroadReso = fecp->ESW_DBCR & 0x0000000f;
2782 +       FTransmit = fecp->ESW_PER & 0x0000000f;
2783 +       FReceive = (fecp->ESW_PER & 0x000f0000) >> 16;
2784 +
2785 +       switch (portnum) {
2786 +       case 0:
2787 +               port_alstatus->link_status = 1;
2788 +               port_alstatus->block_status = PortBlocking & 1;
2789 +               port_alstatus->learn_status = PortLearning & 1;
2790 +               port_alstatus->vlan_verify = VlanVerify & 1;
2791 +               port_alstatus->discard_unknown = DiscardUnknown & 1;
2792 +               port_alstatus->multi_reso = MultiReso & 1;
2793 +               port_alstatus->broad_reso = BroadReso & 1;
2794 +               port_alstatus->ftransmit = FTransmit & 1;
2795 +               port_alstatus->freceive = FReceive & 1;
2796 +               break;
2797 +       case 1:
2798 +               port_alstatus->link_status =
2799 +                       ports_link_status.port1_link_status;
2800 +               port_alstatus->block_status = (PortBlocking >> 1) & 1;
2801 +               port_alstatus->learn_status = (PortLearning >> 1) & 1;
2802 +               port_alstatus->vlan_verify = (VlanVerify >> 1) & 1;
2803 +               port_alstatus->discard_unknown = (DiscardUnknown >> 1) & 1;
2804 +               port_alstatus->multi_reso = (MultiReso >> 1) & 1;
2805 +               port_alstatus->broad_reso = (BroadReso >> 1) & 1;
2806 +               port_alstatus->ftransmit = (FTransmit >> 1) & 1;
2807 +               port_alstatus->freceive = (FReceive >> 1) & 1;
2808 +               break;
2809 +       case 2:
2810 +               port_alstatus->link_status =
2811 +                       ports_link_status.port2_link_status;
2812 +               port_alstatus->block_status = (PortBlocking >> 2) & 1;
2813 +               port_alstatus->learn_status = (PortLearning >> 2) & 1;
2814 +               port_alstatus->vlan_verify = (VlanVerify >> 2) & 1;
2815 +               port_alstatus->discard_unknown = (DiscardUnknown >> 2) & 1;
2816 +               port_alstatus->multi_reso = (MultiReso >> 2) & 1;
2817 +               port_alstatus->broad_reso = (BroadReso >> 2) & 1;
2818 +               port_alstatus->ftransmit = (FTransmit >> 2) & 1;
2819 +               port_alstatus->freceive = (FReceive >> 2) & 1;
2820 +               break;
2821 +       default:
2822 +               printk(KERN_ERR "%s:do not support the port %d",
2823 +                                       __func__, portnum);
2824 +               break;
2825 +       }
2826 +       return 0;
2827 +}
2828 +
2829 +int esw_atable_get_entry_port_number(struct switch_enet_private *fep,
2830 +               unsigned char *mac_addr, unsigned char *port)
2831 +{
2832 +       int block_index, block_index_end, entry;
2833 +       unsigned long read_lo, read_hi;
2834 +       unsigned long mac_addr_lo, mac_addr_hi;
2835 +
2836 +       mac_addr_lo = (unsigned long)((mac_addr[3]<<24) | (mac_addr[2]<<16) |
2837 +               (mac_addr[1]<<8) | mac_addr[0]);
2838 +       mac_addr_hi = (unsigned long)((mac_addr[5]<<8) | (mac_addr[4]));
2839 +
2840 +       block_index = GET_BLOCK_PTR(crc8_calc(mac_addr));
2841 +       block_index_end = block_index + ATABLE_ENTRY_PER_SLOT;
2842 +
2843 +       /* now search all the entries in the selected block */
2844 +       for (entry = block_index; entry < block_index_end; entry++) {
2845 +               read_atable(fep, entry, &read_lo, &read_hi);
2846 +               if ((read_lo == mac_addr_lo) &&
2847 +                       ((read_hi & 0x0000ffff) ==
2848 +                        (mac_addr_hi & 0x0000ffff))) {
2849 +                       /* found the correct address */
2850 +                       if ((read_hi & (1 << 16)) && (!(read_hi & (1 << 17))))
2851 +                               *port = AT_EXTRACT_PORT(read_hi);
2852 +                       break;
2853 +               } else
2854 +                       *port = -1;
2855 +       }
2856 +
2857 +       return 0;
2858 +}
2859 +
2860 +int esw_get_mac_address_lookup_table(struct switch_enet_private *fep,
2861 +       unsigned long *tableaddr, unsigned long *dnum, unsigned long *snum)
2862 +{
2863 +       unsigned long read_lo, read_hi;
2864 +       unsigned long entry;
2865 +       unsigned long dennum = 0;
2866 +       unsigned long sennum = 0;
2867 +
2868 +       for (entry = 0; entry < ESW_ATABLE_MEM_NUM_ENTRIES; entry++) {
2869 +               read_atable(fep, entry, &read_lo, &read_hi);
2870 +               if ((read_hi & (1 << 17)) && (read_hi & (1 << 16))) {
2871 +                       /* static entry */
2872 +                       *(tableaddr + (2047 - sennum) * 11) = entry;
2873 +                       *(tableaddr + (2047 - sennum) * 11 + 2) =
2874 +                               read_lo & 0x000000ff;
2875 +                       *(tableaddr + (2047 - sennum) * 11 + 3) =
2876 +                               (read_lo & 0x0000ff00) >> 8;
2877 +                       *(tableaddr + (2047 - sennum) * 11 + 4) =
2878 +                               (read_lo & 0x00ff0000) >> 16;
2879 +                       *(tableaddr + (2047 - sennum) * 11 + 5) =
2880 +                               (read_lo & 0xff000000) >> 24;
2881 +                       *(tableaddr + (2047 - sennum) * 11 + 6) =
2882 +                               read_hi & 0x000000ff;
2883 +                       *(tableaddr + (2047 - sennum) * 11 + 7) =
2884 +                               (read_hi & 0x0000ff00) >> 8;
2885 +                       *(tableaddr + (2047 - sennum) * 11 + 8) =
2886 +                               AT_EXTRACT_PORTMASK(read_hi);
2887 +                       *(tableaddr + (2047 - sennum) * 11 + 9) =
2888 +                               AT_EXTRACT_PRIO(read_hi);
2889 +                       sennum++;
2890 +               } else if ((read_hi & (1 << 16)) && (!(read_hi & (1 << 17)))) {
2891 +                       /* dynamic entry */
2892 +                       *(tableaddr + dennum * 11) = entry;
2893 +                       *(tableaddr + dennum * 11 + 2) = read_lo & 0xff;
2894 +                       *(tableaddr + dennum * 11 + 3) =
2895 +                               (read_lo & 0x0000ff00) >> 8;
2896 +                       *(tableaddr + dennum * 11 + 4) =
2897 +                               (read_lo & 0x00ff0000) >> 16;
2898 +                       *(tableaddr + dennum * 11 + 5) =
2899 +                               (read_lo & 0xff000000) >> 24;
2900 +                       *(tableaddr + dennum * 11 + 6) = read_hi & 0xff;
2901 +                       *(tableaddr + dennum * 11 + 7) =
2902 +                               (read_hi & 0x0000ff00) >> 8;
2903 +                       *(tableaddr + dennum * 11 + 8) =
2904 +                               AT_EXTRACT_PORT(read_hi);
2905 +                       *(tableaddr + dennum * 11 + 9) =
2906 +                               AT_EXTRACT_TIMESTAMP(read_hi);
2907 +                       dennum++;
2908 +               }
2909 +       }
2910 +
2911 +       *dnum = dennum;
2912 +       *snum = sennum;
2913 +       return 0;
2914 +}
2915 +
2916 +/*----------------------------------------------------------------------------*/
2917 +/* The timer should create an interrupt every 4 seconds*/
2918 +static void l2switch_aging_timer(unsigned long data)
2919 +{
2920 +       struct switch_enet_private *fep;
2921 +
2922 +       fep = (struct switch_enet_private *)data;
2923 +
2924 +       if (fep) {
2925 +               TIMEINCREMENT(fep->currTime);
2926 +               fep->timeChanged++;
2927 +       }
2928 +
2929 +       mod_timer(&fep->timer_aging, jiffies + LEARNING_AGING_TIMER);
2930 +}
2931 +
2932 +/* ----------------------------------------------------------------------- */
2933 +void esw_check_rxb_txb_interrupt(struct switch_enet_private *fep)
2934 +{
2935 +       volatile switch_t  *fecp;
2936 +       fecp = fep->hwp;
2937 +
2938 +       /*Enable Forced forwarding for port 1*/
2939 +       fecp->ESW_P0FFEN = MCF_ESW_P0FFEN_FEN |
2940 +               MCF_ESW_P0FFEN_FD(1);
2941 +       /*Disable learning for all ports*/
2942 +       MCF_ESW_IMR = MCF_ESW_IMR_TXB | MCF_ESW_IMR_TXF |
2943 +               MCF_ESW_IMR_RXB | MCF_ESW_IMR_RXF;
2944 +}
2945 +
2946 +/*----------------------------------------------------------------*/
2947 +static int switch_enet_learning(void *arg)
2948 +{
2949 +       struct switch_enet_private *fep = arg;
2950 +       volatile switch_t  *fecp;
2951 +
2952 +       fecp = fep->hwp;
2953 +       while (!kthread_should_stop()) {
2954 +               set_current_state(TASK_INTERRUPTIBLE);
2955 +
2956 +               /* check learning record valid */
2957 +               if (fecp->ESW_LSR)
2958 +                       esw_atable_dynamicms_learn_migration(fep,
2959 +                                       fep->currTime);
2960 +               else
2961 +                       schedule_timeout(HZ/100);
2962 +       }
2963 +
2964 +       return 0;
2965 +}
2966 +
2967 +static int switch_enet_ioctl(struct net_device *dev,
2968 +               struct ifreq *ifr, int cmd)
2969 +{
2970 +       struct switch_enet_private *fep = netdev_priv(dev);
2971 +       volatile switch_t *fecp;
2972 +       int ret = 0;
2973 +
2974 +       fecp = (volatile switch_t *)dev->base_addr;
2975 +
2976 +       switch (cmd) {
2977 +       /*------------------------------------------------------------*/
2978 +       case ESW_SET_PORTENABLE_CONF:
2979 +       {
2980 +               eswIoctlPortEnableConfig configData;
2981 +               ret = copy_from_user(&configData,
2982 +                       ifr->ifr_data,
2983 +                       sizeof(eswIoctlPortEnableConfig));
2984 +               if (ret)
2985 +                       return -EFAULT;
2986 +
2987 +               ret = esw_port_enable_config(fep,
2988 +                       configData.port,
2989 +                       configData.tx_enable,
2990 +                       configData.rx_enable);
2991 +       }
2992 +               break;
2993 +       case ESW_SET_BROADCAST_CONF:
2994 +       {
2995 +               eswIoctlPortConfig configData;
2996 +               ret = copy_from_user(&configData,
2997 +                       ifr->ifr_data, sizeof(eswIoctlPortConfig));
2998 +               if (ret)
2999 +                       return -EFAULT;
3000 +
3001 +               ret = esw_port_broadcast_config(fep,
3002 +                       configData.port, configData.enable);
3003 +       }
3004 +               break;
3005 +
3006 +       case ESW_SET_MULTICAST_CONF:
3007 +       {
3008 +               eswIoctlPortConfig configData;
3009 +               ret = copy_from_user(&configData,
3010 +                       ifr->ifr_data, sizeof(eswIoctlPortConfig));
3011 +               if (ret)
3012 +                       return -EFAULT;
3013 +
3014 +               ret = esw_port_multicast_config(fep,
3015 +                       configData.port, configData.enable);
3016 +       }
3017 +               break;
3018 +
3019 +       case ESW_SET_BLOCKING_CONF:
3020 +       {
3021 +               eswIoctlPortConfig configData;
3022 +               ret = copy_from_user(&configData,
3023 +                       ifr->ifr_data, sizeof(eswIoctlPortConfig));
3024 +
3025 +               if (ret)
3026 +                       return -EFAULT;
3027 +
3028 +               ret = esw_port_blocking_config(fep,
3029 +                       configData.port, configData.enable);
3030 +       }
3031 +               break;
3032 +
3033 +       case ESW_SET_LEARNING_CONF:
3034 +       {
3035 +               eswIoctlPortConfig configData;
3036 +
3037 +               ret = copy_from_user(&configData,
3038 +                       ifr->ifr_data, sizeof(eswIoctlPortConfig));
3039 +               if (ret)
3040 +                       return -EFAULT;
3041 +
3042 +               ret = esw_port_learning_config(fep,
3043 +                       configData.port, configData.enable);
3044 +       }
3045 +               break;
3046 +
3047 +       case ESW_SET_PORT_ENTRY_EMPTY:
3048 +       {
3049 +               unsigned long portnum;
3050 +
3051 +               ret = copy_from_user(&portnum,
3052 +                       ifr->ifr_data, sizeof(portnum));
3053 +               if (ret)
3054 +                       return -EFAULT;
3055 +               esw_atable_dynamicms_del_entries_for_port(fep, portnum);
3056 +       }
3057 +               break;
3058 +
3059 +       case ESW_SET_OTHER_PORT_ENTRY_EMPTY:
3060 +       {
3061 +               unsigned long portnum;
3062 +
3063 +               ret = copy_from_user(&portnum,
3064 +                       ifr->ifr_data, sizeof(portnum));
3065 +               if (ret)
3066 +                       return -EFAULT;
3067 +
3068 +               esw_atable_dynamicms_del_entries_for_other_port(fep, portnum);
3069 +       }
3070 +               break;
3071 +
3072 +       case ESW_SET_IP_SNOOP_CONF:
3073 +       {
3074 +               eswIoctlIpsnoopConfig configData;
3075 +
3076 +               ret = copy_from_user(&configData,
3077 +                       ifr->ifr_data, sizeof(eswIoctlIpsnoopConfig));
3078 +               if (ret)
3079 +                       return -EFAULT;
3080 +
3081 +               ret = esw_ip_snoop_config(fep, configData.mode,
3082 +                               configData.ip_header_protocol);
3083 +       }
3084 +               break;
3085 +
3086 +       case ESW_SET_PORT_SNOOP_CONF:
3087 +       {
3088 +               eswIoctlPortsnoopConfig configData;
3089 +
3090 +               ret = copy_from_user(&configData,
3091 +                       ifr->ifr_data, sizeof(eswIoctlPortsnoopConfig));
3092 +               if (ret)
3093 +                       return -EFAULT;
3094 +
3095 +               ret = esw_tcpudp_port_snoop_config(fep, configData.mode,
3096 +                               configData.compare_port,
3097 +                               configData.compare_num);
3098 +       }
3099 +               break;
3100 +
3101 +       case ESW_SET_PORT_MIRROR_CONF_PORT_MATCH:
3102 +       {
3103 +               struct eswIoctlMirrorCfgPortMatch configData;
3104 +
3105 +               ret = copy_from_user(&configData,
3106 +                       ifr->ifr_data, sizeof(configData));
3107 +               if (ret)
3108 +                       return -EFAULT;
3109 +               ret = esw_port_mirroring_config_port_match(fep,
3110 +                       configData.mirror_port, configData.port_match_en,
3111 +                       configData.port);
3112 +       }
3113 +               break;
3114 +
3115 +       case ESW_SET_PORT_MIRROR_CONF:
3116 +       {
3117 +               eswIoctlPortMirrorConfig configData;
3118 +
3119 +               ret = copy_from_user(&configData,
3120 +                       ifr->ifr_data, sizeof(eswIoctlPortMirrorConfig));
3121 +               if (ret)
3122 +                       return -EFAULT;
3123 +
3124 +               ret = esw_port_mirroring_config(fep,
3125 +                       configData.mirror_port, configData.port,
3126 +                       configData.mirror_enable,
3127 +                       configData.src_mac, configData.des_mac,
3128 +                       configData.egress_en, configData.ingress_en,
3129 +                       configData.egress_mac_src_en,
3130 +                       configData.egress_mac_des_en,
3131 +                       configData.ingress_mac_src_en,
3132 +                       configData.ingress_mac_des_en);
3133 +       }
3134 +               break;
3135 +
3136 +       case ESW_SET_PORT_MIRROR_CONF_ADDR_MATCH:
3137 +       {
3138 +               struct eswIoctlMirrorCfgAddrMatch configData;
3139 +
3140 +               ret = copy_from_user(&configData,
3141 +                       ifr->ifr_data, sizeof(configData));
3142 +               if (ret)
3143 +                       return -EFAULT;
3144 +
3145 +               ret = esw_port_mirroring_config_addr_match(fep,
3146 +                       configData.mirror_port, configData.addr_match_en,
3147 +                       configData.mac_addr);
3148 +       }
3149 +               break;
3150 +
3151 +       case ESW_SET_PIRORITY_VLAN:
3152 +       {
3153 +               eswIoctlPriorityVlanConfig configData;
3154 +
3155 +               ret = copy_from_user(&configData,
3156 +                       ifr->ifr_data, sizeof(eswIoctlPriorityVlanConfig));
3157 +               if (ret)
3158 +                       return -EFAULT;
3159 +
3160 +               ret = esw_framecalssify_vlan_priority_lookup(fep,
3161 +                       configData.port, configData.func_enable,
3162 +                       configData.vlan_pri_table_num,
3163 +                       configData.vlan_pri_table_value);
3164 +       }
3165 +               break;
3166 +
3167 +       case ESW_SET_PIRORITY_IP:
3168 +       {
3169 +               eswIoctlPriorityIPConfig configData;
3170 +
3171 +               ret = copy_from_user(&configData,
3172 +                       ifr->ifr_data, sizeof(eswIoctlPriorityIPConfig));
3173 +               if (ret)
3174 +                       return -EFAULT;
3175 +
3176 +               ret = esw_framecalssify_ip_priority_lookup(fep,
3177 +                       configData.port, configData.func_enable,
3178 +                       configData.ipv4_en, configData.ip_priority_num,
3179 +                       configData.ip_priority_value);
3180 +       }
3181 +               break;
3182 +
3183 +       case ESW_SET_PIRORITY_MAC:
3184 +       {
3185 +               eswIoctlPriorityMacConfig configData;
3186 +
3187 +               ret = copy_from_user(&configData,
3188 +                       ifr->ifr_data, sizeof(eswIoctlPriorityMacConfig));
3189 +               if (ret)
3190 +                       return -EFAULT;
3191 +
3192 +               ret = esw_framecalssify_mac_priority_lookup(fep,
3193 +                       configData.port);
3194 +       }
3195 +               break;
3196 +
3197 +       case ESW_SET_PIRORITY_DEFAULT:
3198 +       {
3199 +               eswIoctlPriorityDefaultConfig configData;
3200 +
3201 +               ret = copy_from_user(&configData,
3202 +                       ifr->ifr_data, sizeof(eswIoctlPriorityDefaultConfig));
3203 +               if (ret)
3204 +                       return -EFAULT;
3205 +
3206 +               ret = esw_frame_calssify_priority_init(fep,
3207 +                       configData.port, configData.priority_value);
3208 +       }
3209 +               break;
3210 +
3211 +       case ESW_SET_P0_FORCED_FORWARD:
3212 +       {
3213 +               eswIoctlP0ForcedForwardConfig configData;
3214 +
3215 +               ret = copy_from_user(&configData,
3216 +                       ifr->ifr_data, sizeof(eswIoctlP0ForcedForwardConfig));
3217 +               if (ret)
3218 +                       return -EFAULT;
3219 +
3220 +               ret = esw_forced_forward(fep, configData.port1,
3221 +                       configData.port2, configData.enable);
3222 +       }
3223 +               break;
3224 +
3225 +       case ESW_SET_BRIDGE_CONFIG:
3226 +       {
3227 +               unsigned long configData;
3228 +
3229 +               ret = copy_from_user(&configData,
3230 +                       ifr->ifr_data, sizeof(unsigned long));
3231 +               if (ret)
3232 +                       return -EFAULT;
3233 +
3234 +               esw_bridge_port_configure(fep, configData);
3235 +       }
3236 +               break;
3237 +
3238 +       case ESW_SET_SWITCH_MODE:
3239 +       {
3240 +               unsigned long configData;
3241 +
3242 +               ret = copy_from_user(&configData,
3243 +                       ifr->ifr_data, sizeof(unsigned long));
3244 +               if (ret)
3245 +                       return -EFAULT;
3246 +
3247 +               esw_switch_mode_configure(fep, configData);
3248 +       }
3249 +               break;
3250 +
3251 +       case ESW_SET_OUTPUT_QUEUE_MEMORY:
3252 +       {
3253 +               eswIoctlOutputQueue configData;
3254 +
3255 +               ret = copy_from_user(&configData,
3256 +                       ifr->ifr_data, sizeof(eswIoctlOutputQueue));
3257 +               if (ret)
3258 +                       return -EFAULT;
3259 +
3260 +               ret = esw_set_output_queue_memory(fep,
3261 +                       configData.fun_num, &configData.sOutputQueue);
3262 +       }
3263 +               break;
3264 +
3265 +       case ESW_SET_VLAN_OUTPUT_PROCESS:
3266 +       {
3267 +               eswIoctlVlanOutputConfig configData;
3268 +
3269 +               ret = copy_from_user(&configData,
3270 +                       ifr->ifr_data, sizeof(eswIoctlVlanOutputConfig));
3271 +               if (ret)
3272 +                       return -EFAULT;
3273 +
3274 +               ret = esw_vlan_output_process(fep,
3275 +                       configData.port, configData.mode);
3276 +       }
3277 +               break;
3278 +
3279 +       case ESW_SET_VLAN_INPUT_PROCESS:
3280 +       {
3281 +               eswIoctlVlanInputConfig configData;
3282 +
3283 +               ret = copy_from_user(&configData,
3284 +                       ifr->ifr_data,
3285 +                       sizeof(eswIoctlVlanInputConfig));
3286 +               if (ret)
3287 +                       return -EFAULT;
3288 +
3289 +               ret = esw_vlan_input_process(fep, configData.port,
3290 +                               configData.mode, configData.port_vlanid);
3291 +       }
3292 +               break;
3293 +
3294 +       case ESW_SET_VLAN_DOMAIN_VERIFICATION:
3295 +       {
3296 +               eswIoctlVlanVerificationConfig configData;
3297 +
3298 +               ret = copy_from_user(&configData,
3299 +                       ifr->ifr_data,
3300 +                       sizeof(eswIoctlVlanVerificationConfig));
3301 +               if (ret)
3302 +                       return -EFAULT;
3303 +
3304 +               ret = esw_set_vlan_verification(
3305 +                       fep, configData.port,
3306 +                       configData.vlan_domain_verify_en,
3307 +                       configData.vlan_discard_unknown_en);
3308 +       }
3309 +               break;
3310 +
3311 +       case ESW_SET_VLAN_RESOLUTION_TABLE:
3312 +       {
3313 +               eswIoctlVlanResoultionTable configData;
3314 +
3315 +               ret = copy_from_user(&configData,
3316 +                       ifr->ifr_data,
3317 +                       sizeof(eswIoctlVlanResoultionTable));
3318 +               if (ret)
3319 +                       return -EFAULT;
3320 +
3321 +               ret = esw_set_vlan_resolution_table(
3322 +                       fep, configData.port_vlanid,
3323 +                       configData.vlan_domain_num,
3324 +                       configData.vlan_domain_port);
3325 +
3326 +       }
3327 +               break;
3328 +
3329 +       case ESW_SET_VLAN_ID:
3330 +       {
3331 +               unsigned long configData;
3332 +               ret = copy_from_user(&configData, ifr->ifr_data,
3333 +                               sizeof(configData));
3334 +               if (ret)
3335 +                       return -EFAULT;
3336 +
3337 +               ret = esw_set_vlan_id(fep, configData);
3338 +       }
3339 +               break;
3340 +
3341 +       case ESW_SET_VLAN_ID_CLEARED:
3342 +       {
3343 +               unsigned long configData;
3344 +               ret = copy_from_user(&configData, ifr->ifr_data,
3345 +                               sizeof(configData));
3346 +               if (ret)
3347 +                       return -EFAULT;
3348 +
3349 +               ret = esw_set_vlan_id_cleared(fep, configData);
3350 +       }
3351 +               break;
3352 +
3353 +       case ESW_SET_PORT_IN_VLAN_ID:
3354 +       {
3355 +               eswIoctlVlanResoultionTable configData;
3356 +
3357 +               ret = copy_from_user(&configData, ifr->ifr_data,
3358 +                               sizeof(configData));
3359 +               if (ret)
3360 +                       return -EFAULT;
3361 +
3362 +               ret = esw_set_port_in_vlan_id(fep, configData);
3363 +       }
3364 +               break;
3365 +
3366 +       /*--------------------------------------------------------------------*/
3367 +       case ESW_UPDATE_STATIC_MACTABLE:
3368 +       {
3369 +               eswIoctlUpdateStaticMACtable configData;
3370 +
3371 +               ret = copy_from_user(&configData,
3372 +                       ifr->ifr_data, sizeof(eswIoctlUpdateStaticMACtable));
3373 +               if (ret)
3374 +                       return -EFAULT;
3375 +
3376 +               ret = esw_update_atable_static(configData.mac_addr,
3377 +                               configData.port, configData.priority, fep);
3378 +       }
3379 +               break;
3380 +
3381 +       case ESW_CLEAR_ALL_MACTABLE:
3382 +       {
3383 +               esw_clear_atable(fep);
3384 +       }
3385 +               break;
3386 +
3387 +       /*-------------------get----------------------------------------------*/
3388 +       case ESW_GET_STATISTICS_STATUS:
3389 +       {
3390 +               esw_statistics_status Statistics;
3391 +               esw_port_statistics_status PortSta;
3392 +               int i;
3393 +
3394 +               ret = esw_get_statistics_status(fep, &Statistics);
3395 +               if (ret != 0) {
3396 +                       printk(KERN_ERR "%s: cmd %x fail\n", __func__, cmd);
3397 +                       return -1;
3398 +               }
3399 +               printk(KERN_INFO "DISCN : %10ld      DISCB : %10ld\n",
3400 +                               Statistics.ESW_DISCN, Statistics.ESW_DISCB);
3401 +               printk(KERN_INFO "NDISCN: %10ld      NDISCB: %10ld\n",
3402 +                               Statistics.ESW_NDISCN, Statistics.ESW_NDISCB);
3403 +
3404 +               for (i = 0; i < 3; i++) {
3405 +                       ret = esw_get_port_statistics_status(fep, i,
3406 +                                       &PortSta);
3407 +                       if (ret != 0) {
3408 +                               printk(KERN_ERR "%s: cmd %x fail\n",
3409 +                                       __func__, cmd);
3410 +                               return -1;
3411 +                       }
3412 +                       printk(KERN_INFO "port %d:  POQC  : %ld\n",
3413 +                                       i, PortSta.MCF_ESW_POQC);
3414 +                       printk(KERN_INFO "         PMVID : %ld\n",
3415 +                                       PortSta.MCF_ESW_PMVID);
3416 +                       printk(KERN_INFO "       PMVTAG: %ld\n",
3417 +                                       PortSta.MCF_ESW_PMVTAG);
3418 +                       printk(KERN_INFO "       PBL   : %ld\n",
3419 +                                       PortSta.MCF_ESW_PBL);
3420 +               }
3421 +       }
3422 +               break;
3423 +
3424 +       case ESW_GET_LEARNING_CONF:
3425 +       {
3426 +               unsigned long PortLearning;
3427 +
3428 +               esw_get_port_learning(fep, &PortLearning);
3429 +               ret = copy_to_user(ifr->ifr_data, &PortLearning,
3430 +                       sizeof(unsigned long));
3431 +               if (ret)
3432 +                       return -EFAULT;
3433 +       }
3434 +               break;
3435 +
3436 +       case ESW_GET_BLOCKING_CONF:
3437 +       {
3438 +               unsigned long PortBlocking;
3439 +
3440 +               esw_get_port_blocking(fep, &PortBlocking);
3441 +               ret = copy_to_user(ifr->ifr_data, &PortBlocking,
3442 +                       sizeof(unsigned long));
3443 +               if (ret)
3444 +                       return -EFAULT;
3445 +       }
3446 +               break;
3447 +
3448 +       case ESW_GET_MULTICAST_CONF:
3449 +       {
3450 +               unsigned long PortMulticast;
3451 +
3452 +               esw_get_port_multicast(fep, &PortMulticast);
3453 +               ret = copy_to_user(ifr->ifr_data, &PortMulticast,
3454 +                       sizeof(unsigned long));
3455 +               if (ret)
3456 +                       return -EFAULT;
3457 +       }
3458 +               break;
3459 +
3460 +       case ESW_GET_BROADCAST_CONF:
3461 +       {
3462 +               unsigned long PortBroadcast;
3463 +
3464 +               esw_get_port_broadcast(fep, &PortBroadcast);
3465 +               ret = copy_to_user(ifr->ifr_data, &PortBroadcast,
3466 +               sizeof(unsigned long));
3467 +               if (ret)
3468 +                       return -EFAULT;
3469 +       }
3470 +               break;
3471 +
3472 +       case ESW_GET_PORTENABLE_CONF:
3473 +       {
3474 +               unsigned long PortEnable;
3475 +
3476 +               esw_get_port_enable(fep, &PortEnable);
3477 +               ret = copy_to_user(ifr->ifr_data, &PortEnable,
3478 +                       sizeof(unsigned long));
3479 +               if (ret)
3480 +                       return -EFAULT;
3481 +       }
3482 +               break;
3483 +
3484 +       case ESW_GET_IP_SNOOP_CONF:
3485 +       {
3486 +               unsigned long ESW_IPSNP[8];
3487 +               int i;
3488 +
3489 +               esw_get_ip_snoop_config(fep, (unsigned long *)ESW_IPSNP);
3490 +               printk(KERN_INFO "IP Protocol     Mode     Type\n");
3491 +               for (i = 0; i < 8; i++) {
3492 +                       if (ESW_IPSNP[i] != 0)
3493 +                               printk(KERN_INFO "%3ld             "
3494 +                                       "%1ld        %s\n",
3495 +                                       (ESW_IPSNP[i] >> 8) & 0xff,
3496 +                                       (ESW_IPSNP[i] >> 1) & 3,
3497 +                                       ESW_IPSNP[i] & 1 ? "Active" :
3498 +                                       "Inactive");
3499 +               }
3500 +       }
3501 +               break;
3502 +
3503 +       case ESW_GET_PORT_SNOOP_CONF:
3504 +       {
3505 +               unsigned long ESW_PSNP[8];
3506 +               int i;
3507 +
3508 +               esw_get_tcpudp_port_snoop_config(fep,
3509 +                               (unsigned long *)ESW_PSNP);
3510 +               printk(KERN_INFO "TCP/UDP Port  SrcCompare  DesCompare  "
3511 +                               "Mode  Type\n");
3512 +               for (i = 0; i < 8; i++) {
3513 +                       if (ESW_PSNP[i] != 0)
3514 +                               printk(KERN_INFO "%5ld         %s           "
3515 +                                       "%s           %1ld     %s\n",
3516 +                                       (ESW_PSNP[i] >> 16) & 0xffff,
3517 +                                       (ESW_PSNP[i] >> 4) & 1 ? "Y" : "N",
3518 +                                       (ESW_PSNP[i] >> 3) & 1 ? "Y" : "N",
3519 +                                       (ESW_PSNP[i] >> 1) & 3,
3520 +                                       ESW_PSNP[i] & 1 ? "Active" :
3521 +                                       "Inactive");
3522 +               }
3523 +       }
3524 +               break;
3525 +
3526 +       case ESW_GET_PORT_MIRROR_CONF:
3527 +               esw_get_port_mirroring(fep);
3528 +               break;
3529 +
3530 +       case ESW_GET_P0_FORCED_FORWARD:
3531 +       {
3532 +               unsigned long ForceForward;
3533 +
3534 +               esw_get_forced_forward(fep, &ForceForward);
3535 +               ret = copy_to_user(ifr->ifr_data, &ForceForward,
3536 +                       sizeof(unsigned long));
3537 +               if (ret)
3538 +                       return -EFAULT;
3539 +       }
3540 +               break;
3541 +
3542 +       case ESW_GET_SWITCH_MODE:
3543 +       {
3544 +               unsigned long Config;
3545 +
3546 +               esw_get_switch_mode(fep, &Config);
3547 +               ret = copy_to_user(ifr->ifr_data, &Config,
3548 +                       sizeof(unsigned long));
3549 +               if (ret)
3550 +                       return -EFAULT;
3551 +       }
3552 +               break;
3553 +
3554 +       case ESW_GET_BRIDGE_CONFIG:
3555 +       {
3556 +               unsigned long Config;
3557 +
3558 +               esw_get_bridge_port(fep, &Config);
3559 +               ret = copy_to_user(ifr->ifr_data, &Config,
3560 +                       sizeof(unsigned long));
3561 +               if (ret)
3562 +                       return -EFAULT;
3563 +       }
3564 +               break;
3565 +       case ESW_GET_OUTPUT_QUEUE_STATUS:
3566 +       {
3567 +               esw_output_queue_status Config;
3568 +               esw_get_output_queue_status(fep,
3569 +                       &Config);
3570 +               ret = copy_to_user(ifr->ifr_data, &Config,
3571 +                       sizeof(esw_output_queue_status));
3572 +               if (ret)
3573 +                       return -EFAULT;
3574 +       }
3575 +               break;
3576 +
3577 +       case ESW_GET_VLAN_OUTPUT_PROCESS:
3578 +       {
3579 +               unsigned long Config;
3580 +               int tmp;
3581 +               int i;
3582 +
3583 +               esw_get_vlan_output_config(fep, &Config);
3584 +
3585 +               for (i = 0; i < 3; i++) {
3586 +                       tmp = (Config >> (i << 1)) & 3;
3587 +
3588 +                       if (tmp != 0)
3589 +                               printk(KERN_INFO "port %d: vlan output "
3590 +                                       "manipulation enable (mode %d)\n",
3591 +                                       i, tmp);
3592 +                       else
3593 +                               printk(KERN_INFO "port %d: vlan output "
3594 +                                       "manipulation disable\n", i);
3595 +               }
3596 +       }
3597 +               break;
3598 +
3599 +       case ESW_GET_VLAN_INPUT_PROCESS:
3600 +       {
3601 +               eswIoctlVlanInputStatus Config;
3602 +               int i;
3603 +
3604 +               esw_get_vlan_input_config(fep, &Config);
3605 +
3606 +               for (i = 0; i < 3; i++) {
3607 +                       if (((Config.ESW_VIMEN >> i) & 1) == 0)
3608 +                               printk(KERN_INFO "port %d: vlan input "
3609 +                                               "manipulation disable\n", i);
3610 +                       else
3611 +                               printk("port %d: vlan input manipulation enable"
3612 +                                       " (mode %ld, vlan id %ld)\n", i,
3613 +                                       (((Config.ESW_VIMSEL >> (i << 1)) & 3)
3614 +                                        + 1), Config.ESW_PID[i]);
3615 +               }
3616 +       }
3617 +               break;
3618 +
3619 +       case ESW_GET_VLAN_RESOLUTION_TABLE:
3620 +       {
3621 +               struct eswVlanTableItem vtableitem;
3622 +               unsigned char tmp0, tmp1, tmp2;
3623 +               int i;
3624 +
3625 +               esw_get_vlan_resolution_table(fep, &vtableitem);
3626 +
3627 +               printk(KERN_INFO "VLAN Name      VLAN Id      Ports\n");
3628 +               for (i = 0; i < vtableitem.valid_num; i++) {
3629 +                       tmp0 = vtableitem.table[i].vlan_domain_port & 1;
3630 +                       tmp1 = (vtableitem.table[i].vlan_domain_port >> 1) & 1;
3631 +                       tmp2 = (vtableitem.table[i].vlan_domain_port >> 2) & 1;
3632 +                       printk(KERN_INFO "%2d             %4d         %s%s%s\n",
3633 +                               i, vtableitem.table[i].port_vlanid,
3634 +                               tmp0 ? "0 " : "", tmp1 ? "1 " : "",
3635 +                               tmp2 ? "2" : "");
3636 +               }
3637 +       }
3638 +               break;
3639 +
3640 +       case ESW_GET_VLAN_DOMAIN_VERIFICATION:
3641 +       {
3642 +               unsigned long Config;
3643 +
3644 +               esw_get_vlan_verification(fep, &Config);
3645 +               ret = copy_to_user(ifr->ifr_data, &Config,
3646 +                       sizeof(unsigned long));
3647 +               if (ret)
3648 +                       return -EFAULT;
3649 +       }
3650 +               break;
3651 +
3652 +       case ESW_GET_ENTRY_PORT_NUMBER:
3653 +       {
3654 +               unsigned char mac_addr[6];
3655 +               unsigned char portnum;
3656 +
3657 +               ret = copy_from_user(mac_addr,
3658 +                       ifr->ifr_data, sizeof(mac_addr));
3659 +               if (ret)
3660 +                       return -EFAULT;
3661 +
3662 +               ret = esw_atable_get_entry_port_number(fep, mac_addr,
3663 +                               &portnum);
3664 +
3665 +               ret = copy_to_user(ifr->ifr_data, &portnum,
3666 +                               sizeof(unsigned char));
3667 +               if (ret)
3668 +                       return -EFAULT;
3669 +       }
3670 +               break;
3671 +
3672 +       case ESW_GET_LOOKUP_TABLE:
3673 +       {
3674 +               unsigned long *ConfigData;
3675 +               unsigned long dennum, sennum;
3676 +               int i;
3677 +               int tmp;
3678 +
3679 +               ConfigData = kmalloc(sizeof(struct eswAddrTableEntryExample) *
3680 +                               ESW_ATABLE_MEM_NUM_ENTRIES, GFP_KERNEL);
3681 +               ret = esw_get_mac_address_lookup_table(fep, ConfigData,
3682 +                               &dennum, &sennum);
3683 +               printk(KERN_INFO "Dynamic entries number: %ld\n", dennum);
3684 +               printk(KERN_INFO "Static entries number: %ld\n", sennum);
3685 +               printk(KERN_INFO "Type      MAC address         Port   Timestamp\n");
3686 +               for (i = 0; i < dennum; i++) {
3687 +                       printk(KERN_INFO "dynamic   "
3688 +                               "%02lx-%02lx-%02lx-%02lx-%02lx-%02lx   "
3689 +                               "%01lx      %4ld\n", *(ConfigData + i * 11 + 2),
3690 +                               *(ConfigData + i * 11 + 3),
3691 +                               *(ConfigData + i * 11 + 4),
3692 +                               *(ConfigData + i * 11 + 5),
3693 +                               *(ConfigData + i * 11 + 6),
3694 +                               *(ConfigData + i * 11 + 7),
3695 +                               *(ConfigData + i * 11 + 8),
3696 +                               *(ConfigData + i * 11 + 9));
3697 +               }
3698 +
3699 +               if (sennum != 0)
3700 +                       printk(KERN_INFO "Type      MAC address"
3701 +                                       "         Port   Priority\n");
3702 +
3703 +               for (i = 0; i < sennum; i++) {
3704 +                       printk(KERN_INFO "static    %02lx-%02lx-%02lx-%02lx"
3705 +                                       "-%02lx-%02lx   ",
3706 +                                       *(ConfigData + (2047 - i) * 11 + 2),
3707 +                                       *(ConfigData + (2047 - i) * 11 + 3),
3708 +                                       *(ConfigData + (2047 - i) * 11 + 4),
3709 +                                       *(ConfigData + (2047 - i) * 11 + 5),
3710 +                                       *(ConfigData + (2047 - i) * 11 + 6),
3711 +                                       *(ConfigData + (2047 - i) * 11 + 7));
3712 +
3713 +                       tmp = *(ConfigData + (2047 - i) * 11 + 8);
3714 +                       if ((tmp == 0) || (tmp == 2) || (tmp == 4))
3715 +                               printk("%01x      ", tmp >> 1);
3716 +                       else if (tmp == 3)
3717 +                               printk("0,1    ");
3718 +                       else if (tmp == 5)
3719 +                               printk("0,2    ");
3720 +                       else if (tmp == 6)
3721 +                               printk("1,2    ");
3722 +
3723 +                       printk("%4ld\n", *(ConfigData + (2047 - i) * 11 + 9));
3724 +               }
3725 +               kfree(ConfigData);
3726 +       }
3727 +               break;
3728 +
3729 +       case ESW_GET_PORT_STATUS:
3730 +       {
3731 +               unsigned long PortBlocking;
3732 +
3733 +               esw_get_port_blocking(fep, &PortBlocking);
3734 +
3735 +               ports_link_status.port0_block_status = PortBlocking & 1;
3736 +               ports_link_status.port1_block_status = (PortBlocking >> 1) & 1;
3737 +               ports_link_status.port2_block_status = PortBlocking >> 2;
3738 +
3739 +               ret = copy_to_user(ifr->ifr_data, &ports_link_status,
3740 +                               sizeof(ports_link_status));
3741 +               if (ret)
3742 +                       return -EFAULT;
3743 +       }
3744 +               break;
3745 +
3746 +       case ESW_GET_PORT_ALL_STATUS:
3747 +       {
3748 +               unsigned char portnum;
3749 +               struct port_all_status port_astatus;
3750 +
3751 +               ret = copy_from_user(&portnum,
3752 +                       ifr->ifr_data, sizeof(portnum));
3753 +               if (ret)
3754 +                       return -EFAULT;
3755 +
3756 +               esw_get_port_all_status(fep, portnum, &port_astatus);
3757 +               printk(KERN_INFO "Port %d status:\n", portnum);
3758 +               printk(KERN_INFO "Link:%-4s          Blocking:%1s          "
3759 +                       "Learning:%1s\n",
3760 +                       port_astatus.link_status ? "Up" : "Down",
3761 +                       port_astatus.block_status ? "Y" : "N",
3762 +                       port_astatus.learn_status ? "N" : "Y");
3763 +               printk(KERN_INFO "VLAN Verify:%1s      Discard Unknown:%1s   "
3764 +                       "Multicast Res:%1s\n",
3765 +                       port_astatus.vlan_verify ? "Y" : "N",
3766 +                       port_astatus.discard_unknown ? "Y" : "N",
3767 +                       port_astatus.multi_reso ? "Y" : "N");
3768 +               printk(KERN_INFO "Broadcast Res:%1s    Transmit:%-7s    "
3769 +                       "Receive:%7s\n",
3770 +                       port_astatus.broad_reso ? "Y" : "N",
3771 +                       port_astatus.ftransmit ? "Enable" : "Disable",
3772 +                       port_astatus.freceive ? "Enable" : "Disable");
3773 +
3774 +       }
3775 +               break;
3776 +
3777 +       case ESW_GET_USER_PID:
3778 +       {
3779 +               long get_pid = 0;
3780 +               ret = copy_from_user(&get_pid,
3781 +                       ifr->ifr_data, sizeof(get_pid));
3782 +
3783 +               if (ret)
3784 +                       return -EFAULT;
3785 +               user_pid = get_pid;
3786 +       }
3787 +               break;
3788 +       /*------------------------------------------------------------------*/
3789 +       default:
3790 +               return -EOPNOTSUPP;
3791 +       }
3792 +
3793 +       return ret;
3794 +}
3795 +
3796 +static netdev_tx_t switch_enet_start_xmit(struct sk_buff *skb,
3797 +                               struct net_device *dev)
3798 +{
3799 +       struct switch_enet_private *fep;
3800 +       volatile switch_t       *fecp;
3801 +       cbd_t   *bdp;
3802 +       unsigned short  status;
3803 +       unsigned long flags;
3804 +
3805 +       fep = netdev_priv(dev);
3806 +       fecp = (switch_t *)fep->hwp;
3807 +
3808 +       spin_lock_irqsave(&fep->hw_lock, flags);
3809 +       /* Fill in a Tx ring entry */
3810 +       bdp = fep->cur_tx;
3811 +
3812 +       status = bdp->cbd_sc;
3813 +
3814 +       /* Clear all of the status flags.
3815 +        */
3816 +       status &= ~BD_ENET_TX_STATS;
3817 +
3818 +       /* Set buffer length and buffer pointer.
3819 +       */
3820 +       bdp->cbd_bufaddr = __pa(skb->data);
3821 +       bdp->cbd_datlen = skb->len;
3822 +
3823 +       /*
3824 +        *      On some FEC implementations data must be aligned on
3825 +        *      4-byte boundaries. Use bounce buffers to copy data
3826 +        *      and get it aligned. Ugh.
3827 +        */
3828 +       if (bdp->cbd_bufaddr & 0x3) {
3829 +               unsigned int index1;
3830 +               index1 = bdp - fep->tx_bd_base;
3831 +
3832 +               memcpy(fep->tx_bounce[index1],
3833 +                      (void *)skb->data, bdp->cbd_datlen);
3834 +               bdp->cbd_bufaddr = __pa(fep->tx_bounce[index1]);
3835 +       }
3836 +
3837 +       /* Save skb pointer. */
3838 +       fep->tx_skbuff[fep->skb_cur] = skb;
3839 +
3840 +       dev->stats.tx_bytes += skb->len;
3841 +       fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
3842 +
3843 +       /* Push the data cache so the CPM does not get stale memory
3844 +        * data.
3845 +        */
3846 +       flush_dcache_range((unsigned long)skb->data,
3847 +                          (unsigned long)skb->data + skb->len);
3848 +
3849 +       /* Send it on its way.  Tell FEC it's ready, interrupt when done,
3850 +        * it's the last BD of the frame, and to put the CRC on the end.
3851 +        */
3852 +
3853 +       status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
3854 +                       | BD_ENET_TX_LAST | BD_ENET_TX_TC);
3855 +       bdp->cbd_sc = status;
3856 +       dev->trans_start = jiffies;
3857 +
3858 +       /* Trigger transmission start */
3859 +       fecp->fec_x_des_active = MCF_ESW_TDAR_X_DES_ACTIVE;
3860 +
3861 +       /* If this was the last BD in the ring,
3862 +        * start at the beginning again.*/
3863 +       if (status & BD_ENET_TX_WRAP)
3864 +               bdp = fep->tx_bd_base;
3865 +       else
3866 +               bdp++;
3867 +
3868 +       if (bdp == fep->dirty_tx) {
3869 +               fep->tx_full = 1;
3870 +               netif_stop_queue(dev);
3871 +               printk(KERN_ERR "%s:  net stop\n", __func__);
3872 +       }
3873 +
3874 +       fep->cur_tx = (cbd_t *)bdp;
3875 +
3876 +       spin_unlock_irqrestore(&fep->hw_lock, flags);
3877 +
3878 +       return NETDEV_TX_OK;
3879 +}
3880 +
3881 +static void switch_timeout(struct net_device *dev)
3882 +{
3883 +       struct switch_enet_private *fep = netdev_priv(dev);
3884 +
3885 +       printk(KERN_ERR "%s: transmit timed out.\n", dev->name);
3886 +       dev->stats.tx_errors++;
3887 +       switch_restart(dev, fep->full_duplex);
3888 +       netif_wake_queue(dev);
3889 +}
3890 +
3891 +/* The interrupt handler.
3892 + * This is called from the MPC core interrupt.
3893 + */
3894 +static irqreturn_t switch_enet_interrupt(int irq, void *dev_id)
3895 +{
3896 +       struct  net_device *dev = dev_id;
3897 +       volatile switch_t *fecp;
3898 +       uint    int_events;
3899 +       irqreturn_t ret = IRQ_NONE;
3900 +
3901 +       fecp = (switch_t *)dev->base_addr;
3902 +
3903 +       /* Get the interrupt events that caused us to be here.
3904 +       */
3905 +       do {
3906 +               int_events = fecp->switch_ievent;
3907 +               fecp->switch_ievent = int_events;
3908 +               /* Handle receive event in its own function. */
3909 +
3910 +               /* Transmit OK, or non-fatal error. Update the buffer
3911 +                  descriptors. Switch handles all errors, we just discover
3912 +                  them as part of the transmit process.
3913 +               */
3914 +               if (int_events & MCF_ESW_ISR_OD0)
3915 +                       ret = IRQ_HANDLED;
3916 +
3917 +               if (int_events & MCF_ESW_ISR_OD1)
3918 +                       ret = IRQ_HANDLED;
3919 +
3920 +               if (int_events & MCF_ESW_ISR_OD2)
3921 +                       ret = IRQ_HANDLED;
3922 +
3923 +               if (int_events & MCF_ESW_ISR_RXB)
3924 +                       ret = IRQ_HANDLED;
3925 +
3926 +               if (int_events & MCF_ESW_ISR_RXF) {
3927 +                       ret = IRQ_HANDLED;
3928 +                       switch_enet_rx(dev);
3929 +               }
3930 +
3931 +               if (int_events & MCF_ESW_ISR_TXB)
3932 +                       ret = IRQ_HANDLED;
3933 +
3934 +               if (int_events & MCF_ESW_ISR_TXF) {
3935 +                       ret = IRQ_HANDLED;
3936 +                       switch_enet_tx(dev);
3937 +               }
3938 +
3939 +       } while (int_events);
3940 +
3941 +       return ret;
3942 +}
3943 +
3944 +static void switch_enet_tx(struct net_device *dev)
3945 +{
3946 +       struct  switch_enet_private *fep;
3947 +       cbd_t   *bdp;
3948 +       unsigned short status;
3949 +       struct  sk_buff *skb;
3950 +
3951 +       fep = netdev_priv(dev);
3952 +       spin_lock_irq(&fep->hw_lock);
3953 +       bdp = fep->dirty_tx;
3954 +
3955 +       while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
3956 +               if (bdp == fep->cur_tx && fep->tx_full == 0)
3957 +                       break;
3958 +
3959 +               skb = fep->tx_skbuff[fep->skb_dirty];
3960 +               /* Check for errors. */
3961 +               if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
3962 +                                  BD_ENET_TX_RL | BD_ENET_TX_UN |
3963 +                                  BD_ENET_TX_CSL)) {
3964 +                       dev->stats.tx_errors++;
3965 +                       if (status & BD_ENET_TX_HB)  /* No heartbeat */
3966 +                               dev->stats.tx_heartbeat_errors++;
3967 +                       if (status & BD_ENET_TX_LC)  /* Late collision */
3968 +                               dev->stats.tx_window_errors++;
3969 +                       if (status & BD_ENET_TX_RL)  /* Retrans limit */
3970 +                               dev->stats.tx_aborted_errors++;
3971 +                       if (status & BD_ENET_TX_UN)  /* Underrun */
3972 +                               dev->stats.tx_fifo_errors++;
3973 +                       if (status & BD_ENET_TX_CSL) /* Carrier lost */
3974 +                               dev->stats.tx_carrier_errors++;
3975 +               } else {
3976 +                       dev->stats.tx_packets++;
3977 +               }
3978 +
3979 +               /* Deferred means some collisions occurred during transmit,
3980 +                * but we eventually sent the packet OK.
3981 +                */
3982 +               if (status & BD_ENET_TX_DEF)
3983 +                       dev->stats.collisions++;
3984 +
3985 +               /* Free the sk buffer associated with this last transmit.
3986 +                */
3987 +               dev_kfree_skb_any(skb);
3988 +               fep->tx_skbuff[fep->skb_dirty] = NULL;
3989 +               fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
3990 +
3991 +               /* Update pointer to next buffer descriptor to be transmitted.
3992 +                */
3993 +               if (status & BD_ENET_TX_WRAP)
3994 +                       bdp = fep->tx_bd_base;
3995 +               else
3996 +                       bdp++;
3997 +
3998 +               /* Since we have freed up a buffer, the ring is no longer
3999 +                * full.
4000 +                */
4001 +               if (fep->tx_full) {
4002 +                       fep->tx_full = 0;
4003 +                       printk(KERN_ERR "%s: tx full is zero\n", __func__);
4004 +                       if (netif_queue_stopped(dev))
4005 +                               netif_wake_queue(dev);
4006 +               }
4007 +       }
4008 +       fep->dirty_tx = (cbd_t *)bdp;
4009 +       spin_unlock_irq(&fep->hw_lock);
4010 +}
4011 +
4012 +
4013 +/* During a receive, the cur_rx points to the current incoming buffer.
4014 + * When we update through the ring, if the next incoming buffer has
4015 + * not been given to the system, we just set the empty indicator,
4016 + * effectively tossing the packet.
4017 + */
4018 +static void switch_enet_rx(struct net_device *dev)
4019 +{
4020 +       struct  switch_enet_private *fep;
4021 +       volatile switch_t *fecp;
4022 +       cbd_t *bdp;
4023 +       unsigned short status;
4024 +       struct  sk_buff *skb;
4025 +       ushort  pkt_len;
4026 +       __u8 *data;
4027 +
4028 +       fep = netdev_priv(dev);
4029 +       /*fecp = (volatile switch_t *)dev->base_addr;*/
4030 +       fecp = (volatile switch_t *)fep->hwp;
4031 +
4032 +       spin_lock_irq(&fep->hw_lock);
4033 +       /* First, grab all of the stats for the incoming packet.
4034 +        * These get messed up if we get called due to a busy condition.
4035 +        */
4036 +       bdp = fep->cur_rx;
4037 +
4038 +       while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
4039 +
4040 +               /* Since we have allocated space to hold a complete frame,
4041 +                * the last indicator should be set.
4042 +                * */
4043 +               if ((status & BD_ENET_RX_LAST) == 0)
4044 +                       printk(KERN_ERR "SWITCH ENET: rcv is not +last\n");
4045 +
4046 +               if (!fep->opened)
4047 +                       goto rx_processing_done;
4048 +
4049 +               /* Check for errors. */
4050 +               if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
4051 +                          BD_ENET_RX_CR | BD_ENET_RX_OV)) {
4052 +                       dev->stats.rx_errors++;
4053 +                       if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
4054 +                               /* Frame too long or too short. */
4055 +                               dev->stats.rx_length_errors++;
4056 +                       }
4057 +                       if (status & BD_ENET_RX_NO)     /* Frame alignment */
4058 +                               dev->stats.rx_frame_errors++;
4059 +                       if (status & BD_ENET_RX_CR)     /* CRC Error */
4060 +                               dev->stats.rx_crc_errors++;
4061 +                       if (status & BD_ENET_RX_OV)     /* FIFO overrun */
4062 +                               dev->stats.rx_fifo_errors++;
4063 +               }
4064 +               /* Report late collisions as a frame error.
4065 +                * On this error, the BD is closed, but we don't know what we
4066 +                * have in the buffer.  So, just drop this frame on the floor.
4067 +                * */
4068 +               if (status & BD_ENET_RX_CL) {
4069 +                       dev->stats.rx_errors++;
4070 +                       dev->stats.rx_frame_errors++;
4071 +                       goto rx_processing_done;
4072 +               }
4073 +               /* Process the incoming frame */
4074 +               dev->stats.rx_packets++;
4075 +               pkt_len = bdp->cbd_datlen;
4076 +               dev->stats.rx_bytes += pkt_len;
4077 +               data = (__u8 *)__va(bdp->cbd_bufaddr);
4078 +
4079 +               /* This does 16 byte alignment, exactly what we need.
4080 +                * The packet length includes FCS, but we don't want to
4081 +                * include that when passing upstream as it messes up
4082 +                * bridging applications.
4083 +                * */
4084 +               skb = dev_alloc_skb(pkt_len);
4085 +
4086 +               if (skb == NULL)
4087 +                       dev->stats.rx_dropped++;
4088 +               else {
4089 +                       skb_put(skb, pkt_len);  /* Make room */
4090 +                       skb_copy_to_linear_data(skb, data, pkt_len);
4091 +                       skb->protocol = eth_type_trans(skb, dev);
4092 +                       netif_rx(skb);
4093 +               }
4094 +rx_processing_done:
4095 +
4096 +               /* Clear the status flags for this buffer */
4097 +               status &= ~BD_ENET_RX_STATS;
4098 +
4099 +               /* Mark the buffer empty */
4100 +               status |= BD_ENET_RX_EMPTY;
4101 +               bdp->cbd_sc = status;
4102 +
4103 +               /* Update BD pointer to next entry */
4104 +               if (status & BD_ENET_RX_WRAP)
4105 +                       bdp = fep->rx_bd_base;
4106 +               else
4107 +                       bdp++;
4108 +
4109 +               /* Doing this here will keep the FEC running while we process
4110 +                * incoming frames.  On a heavily loaded network, we should be
4111 +                * able to keep up at the expense of system resources.
4112 +                * */
4113 +               fecp->fec_r_des_active = MCF_ESW_RDAR_R_DES_ACTIVE;
4114 +       }
4115 +       fep->cur_rx = (cbd_t *)bdp;
4116 +
4117 +       spin_unlock_irq(&fep->hw_lock);
4118 +}
4119 +
4120 +static int fec_mdio_transfer(struct mii_bus *bus, int phy_id,
4121 +       int reg, int regval)
4122 +{
4123 +       struct net_device *dev = bus->priv;
4124 +       unsigned long   flags;
4125 +       struct switch_enet_private *fep;
4126 +       int tries = 100;
4127 +       int retval = 0;
4128 +
4129 +       fep = netdev_priv(dev);
4130 +       spin_lock_irqsave(&fep->mii_lock, flags);
4131 +
4132 +       regval |= phy_id << 23;
4133 +       MCF_FEC_MMFR0 = regval;
4134 +
4135 +       /* wait for it to finish, this takes about 23 us on lite5200b */
4136 +       while (!(MCF_FEC_EIR0 & FEC_ENET_MII) && --tries)
4137 +               udelay(5);
4138 +
4139 +       if (!tries) {
4140 +               printk(KERN_ERR "%s timeout\n", __func__);
4141 +               return -ETIMEDOUT;
4142 +       }
4143 +
4144 +       MCF_FEC_EIR0 = FEC_ENET_MII;
4145 +       retval = MCF_FEC_MMFR0;
4146 +       spin_unlock_irqrestore(&fep->mii_lock, flags);
4147 +
4148 +       return retval;
4149 +}
4150 +
4151 +
4152 +static int coldfire_fec_mdio_read(struct mii_bus *bus,
4153 +       int phy_id, int reg)
4154 +{
4155 +       int ret;
4156 +       ret = fec_mdio_transfer(bus, phy_id, reg,
4157 +               mk_mii_read(reg));
4158 +       return ret;
4159 +}
4160 +
4161 +static int coldfire_fec_mdio_write(struct mii_bus *bus,
4162 +       int phy_id, int reg, u16 data)
4163 +{
4164 +       return fec_mdio_transfer(bus, phy_id, reg,
4165 +                       mk_mii_write(reg, data));
4166 +}
4167 +
4168 +static void switch_adjust_link1(struct net_device *dev)
4169 +{
4170 +       struct switch_enet_private *priv = netdev_priv(dev);
4171 +       struct phy_device *phydev1 = priv->phydev[0];
4172 +       int new_state = 0;
4173 +
4174 +       if (phydev1->link != PHY_DOWN) {
4175 +               if (phydev1->duplex != priv->phy1_duplex) {
4176 +                       new_state = 1;
4177 +                       priv->phy1_duplex = phydev1->duplex;
4178 +               }
4179 +
4180 +               if (phydev1->speed != priv->phy1_speed) {
4181 +                       new_state = 1;
4182 +                       priv->phy1_speed = phydev1->speed;
4183 +               }
4184 +
4185 +               if (priv->phy1_old_link == PHY_DOWN) {
4186 +                       new_state = 1;
4187 +                       priv->phy1_old_link = phydev1->link;
4188 +               }
4189 +       } else if (priv->phy1_old_link) {
4190 +               new_state = 1;
4191 +               priv->phy1_old_link = PHY_DOWN;
4192 +               priv->phy1_speed = 0;
4193 +               priv->phy1_duplex = -1;
4194 +       }
4195 +
4196 +       if (new_state) {
4197 +               ports_link_status.port1_link_status = phydev1->link;
4198 +               if (phydev1->link == PHY_DOWN)
4199 +                       esw_atable_dynamicms_del_entries_for_port(priv, 1);
4200 +
4201 +               /*Send the new status to user space*/
4202 +               if (user_pid != 1)
4203 +                       sys_tkill(user_pid, SIGUSR1);
4204 +       }
4205 +}
4206 +
4207 +static void switch_adjust_link2(struct net_device *dev)
4208 +{
4209 +       struct switch_enet_private *priv = netdev_priv(dev);
4210 +       struct phy_device *phydev2 = priv->phydev[1];
4211 +       int new_state = 0;
4212 +
4213 +       if (phydev2->link != PHY_DOWN) {
4214 +               if (phydev2->duplex != priv->phy2_duplex) {
4215 +                       new_state = 1;
4216 +                       priv->phy2_duplex = phydev2->duplex;
4217 +               }
4218 +
4219 +               if (phydev2->speed != priv->phy2_speed) {
4220 +                       new_state = 1;
4221 +                       priv->phy2_speed = phydev2->speed;
4222 +               }
4223 +
4224 +               if (priv->phy2_old_link == PHY_DOWN) {
4225 +                       new_state = 1;
4226 +                       priv->phy2_old_link = phydev2->link;
4227 +               }
4228 +       } else if (priv->phy2_old_link) {
4229 +               new_state = 1;
4230 +               priv->phy2_old_link = PHY_DOWN;
4231 +               priv->phy2_speed = 0;
4232 +               priv->phy2_duplex = -1;
4233 +       }
4234 +
4235 +       if (new_state) {
4236 +               ports_link_status.port2_link_status = phydev2->link;
4237 +               if (phydev2->link == PHY_DOWN)
4238 +                       esw_atable_dynamicms_del_entries_for_port(priv, 2);
4239 +
4240 +               /*Send the new status to user space*/
4241 +               if (user_pid != 1)
4242 +                       sys_tkill(user_pid, SIGUSR1);
4243 +       }
4244 +}
4245 +
4246 +static int coldfire_switch_init_phy(struct net_device *dev)
4247 +{
4248 +       struct switch_enet_private *priv = netdev_priv(dev);
4249 +       struct phy_device *phydev[SWITCH_EPORT_NUMBER] = {NULL, NULL};
4250 +       int i, startnode = 0;
4251 +
4252 +       /* search for connect PHY device */
4253 +       for (i = 0; i < PHY_MAX_ADDR; i++) {
4254 +               struct phy_device *const tmp_phydev =
4255 +                       priv->mdio_bus->phy_map[i];
4256 +
4257 +               if (!tmp_phydev)
4258 +                       continue;
4259 +
4260 +#ifdef CONFIG_FEC_SHARED_PHY
4261 +               if (priv->index == 0)
4262 +                       phydev[i] = tmp_phydev;
4263 +               else if (priv->index == 1) {
4264 +                       if (startnode == 1) {
4265 +                               phydev[i] = tmp_phydev;
4266 +                               startnode = 0;
4267 +                       } else {
4268 +                               startnode++;
4269 +                               continue;
4270 +                       }
4271 +               } else
4272 +                       printk(KERN_INFO "%s now we do not"
4273 +                               "support (%d) more than"
4274 +                               "2 phys shared "
4275 +                               "one mdio bus\n",
4276 +                               __func__, startnode);
4277 +#else
4278 +               phydev[i] = tmp_phydev;
4279 +#endif
4280 +       }
4281 +
4282 +       /* now we are supposed to have a proper phydev, to attach to... */
4283 +       if ((!phydev[0]) && (!phydev[1])) {
4284 +               printk(KERN_INFO "%s: Don't found any phy device at all\n",
4285 +                       dev->name);
4286 +               return -ENODEV;
4287 +       }
4288 +
4289 +       priv->phy1_link = PHY_DOWN;
4290 +       priv->phy1_old_link = PHY_DOWN;
4291 +       priv->phy1_speed = 0;
4292 +       priv->phy1_duplex = -1;
4293 +
4294 +       priv->phy2_link = PHY_DOWN;
4295 +       priv->phy2_old_link = PHY_DOWN;
4296 +       priv->phy2_speed = 0;
4297 +       priv->phy2_duplex = -1;
4298 +
4299 +       phydev[0] = phy_connect(dev, dev_name(&phydev[0]->dev),
4300 +               &switch_adjust_link1, 0, PHY_INTERFACE_MODE_MII);
4301 +       if (IS_ERR(phydev[0])) {
4302 +               printk(KERN_ERR " %s phy_connect failed\n", __func__);
4303 +               return PTR_ERR(phydev[0]);
4304 +       }
4305 +
4306 +       phydev[1] = phy_connect(dev, dev_name(&phydev[1]->dev),
4307 +               &switch_adjust_link2, 0, PHY_INTERFACE_MODE_MII);
4308 +       if (IS_ERR(phydev[1])) {
4309 +               printk(KERN_ERR " %s phy_connect failed\n", __func__);
4310 +               return PTR_ERR(phydev[1]);
4311 +       }
4312 +
4313 +       for (i = 0; i < SWITCH_EPORT_NUMBER; i++) {
4314 +               printk(KERN_INFO "attached phy %i to driver %s\n",
4315 +                       phydev[i]->addr, phydev[i]->drv->name);
4316 +               priv->phydev[i] = phydev[i];
4317 +       }
4318 +
4319 +       return 0;
4320 +}
4321 +/* -----------------------------------------------------------------------*/
4322 +static int switch_enet_open(struct net_device *dev)
4323 +{
4324 +       struct switch_enet_private *fep = netdev_priv(dev);
4325 +       volatile switch_t *fecp;
4326 +       int i;
4327 +
4328 +       fecp = (volatile switch_t *)fep->hwp;
4329 +       /* I should reset the ring buffers here, but I don't yet know
4330 +        * a simple way to do that.
4331 +        */
4332 +       switch_set_mac_address(dev);
4333 +
4334 +       fep->phy1_link = 0;
4335 +       fep->phy2_link = 0;
4336 +
4337 +       coldfire_switch_init_phy(dev);
4338 +       for (i = 0; i < SWITCH_EPORT_NUMBER; i++) {
4339 +               phy_write(fep->phydev[i], MII_BMCR, BMCR_RESET);
4340 +               phy_start(fep->phydev[i]);
4341 +       }
4342 +
4343 +       fep->phy1_old_link = 0;
4344 +       fep->phy2_old_link = 0;
4345 +       fep->phy1_link = 1;
4346 +       fep->phy2_link = 1;
4347 +
4348 +       /* no phy,  go full duplex,  it's most likely a hub chip */
4349 +       switch_restart(dev, 1);
4350 +
4351 +       /* if the fec is the fist open, we need to do nothing*/
4352 +       /* if the fec is not the fist open, we need to restart the FEC*/
4353 +       if (fep->sequence_done == 0)
4354 +               switch_restart(dev, 1);
4355 +       else
4356 +               fep->sequence_done = 0;
4357 +
4358 +       fep->currTime = 0;
4359 +       fep->learning_irqhandle_enable = 0;
4360 +
4361 +       MCF_ESW_PER = 0x70007;
4362 +       fecp->ESW_DBCR = MCF_ESW_DBCR_P0 | MCF_ESW_DBCR_P1 | MCF_ESW_DBCR_P2;
4363 +       fecp->ESW_DMCR = MCF_ESW_DMCR_P0 | MCF_ESW_DMCR_P1 | MCF_ESW_DMCR_P2;
4364 +
4365 +       netif_start_queue(dev);
4366 +       fep->opened = 1;
4367 +
4368 +       return 0;
4369 +}
4370 +
4371 +static int switch_enet_close(struct net_device *dev)
4372 +{
4373 +       struct switch_enet_private *fep = netdev_priv(dev);
4374 +       int i;
4375 +
4376 +       /* Don't know what to do yet.*/
4377 +       fep->opened = 0;
4378 +       netif_stop_queue(dev);
4379 +       switch_stop(dev);
4380 +
4381 +       for (i = 0; i < SWITCH_EPORT_NUMBER; i++) {
4382 +               phy_disconnect(fep->phydev[i]);
4383 +               phy_stop(fep->phydev[i]);
4384 +               phy_write(fep->phydev[i], MII_BMCR, BMCR_PDOWN);
4385 +       }
4386 +
4387 +       return 0;
4388 +}
4389 +
4390 +/* Set or clear the multicast filter for this adaptor.
4391 + * Skeleton taken from sunlance driver.
4392 + * The CPM Ethernet implementation allows Multicast as well as individual
4393 + * MAC address filtering.  Some of the drivers check to make sure it is
4394 + * a group multicast address, and discard those that are not.  I guess I
4395 + * will do the same for now, but just remove the test if you want
4396 + * individual filtering as well (do the upper net layers want or support
4397 + * this kind of feature?).
4398 + */
4399 +
4400 +#define HASH_BITS      6               /* #bits in hash */
4401 +#define CRC32_POLY     0xEDB88320
4402 +
4403 +static void set_multicast_list(struct net_device *dev)
4404 +{
4405 +       struct switch_enet_private *fep;
4406 +       volatile switch_t *ep;
4407 +       unsigned int i, bit, data, crc;
4408 +       struct netdev_hw_addr *ha;
4409 +
4410 +       fep = netdev_priv(dev);
4411 +       ep = fep->hwp;
4412 +
4413 +       if (dev->flags & IFF_PROMISC) {
4414 +               printk(KERN_INFO "%s IFF_PROMISC\n", __func__);
4415 +       } else {
4416 +               if (dev->flags & IFF_ALLMULTI)
4417 +                       /* Catch all multicast addresses, so set the
4418 +                        * filter to all 1's.
4419 +                        */
4420 +                       printk(KERN_INFO "%s IFF_ALLMULTI\n", __func__);
4421 +               else {
4422 +                       netdev_for_each_mc_addr(ha, dev) {
4423 +                               if (!(ha->addr[0] & 1))
4424 +                                       continue;
4425 +
4426 +                               /* calculate crc32 value of mac address
4427 +                               */
4428 +                               crc = 0xffffffff;
4429 +
4430 +                               for (i = 0; i < dev->addr_len; i++) {
4431 +                                       data = ha->addr[i];
4432 +                                       for (bit = 0; bit < 8; bit++,
4433 +                                               data >>= 1) {
4434 +                                               crc = (crc >> 1) ^
4435 +                                               (((crc ^ data) & 1) ?
4436 +                                               CRC32_POLY : 0);
4437 +                                       }
4438 +                               }
4439 +
4440 +                       }
4441 +               }
4442 +       }
4443 +}
4444 +
4445 +/* Set a MAC change in hardware.*/
4446 +static void switch_set_mac_address(struct net_device *dev)
4447 +{
4448 +       volatile switch_t *fecp;
4449 +
4450 +       fecp = ((struct switch_enet_private *)netdev_priv(dev))->hwp;
4451 +}
4452 +
4453 +static void switch_hw_init(void)
4454 +{
4455 +       /* GPIO config - RMII mode for both MACs */
4456 +       MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC &
4457 +               MCF_GPIO_PAR_FEC_FEC_MASK) |
4458 +               MCF_GPIO_PAR_FEC_FEC_RMII0FUL_1FUL;
4459 +
4460 +       /* Initialize MAC 0/1 */
4461 +       /* RCR */
4462 +       MCF_FEC_RCR0 = (MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
4463 +                       MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD);
4464 +       MCF_FEC_RCR1 = (MCF_FEC_RCR_PROM | MCF_FEC_RCR_RMII_MODE |
4465 +                       MCF_FEC_RCR_MAX_FL(1522) | MCF_FEC_RCR_CRC_FWD);
4466 +       /* TCR */
4467 +       MCF_FEC_TCR0 = MCF_FEC_TCR_FDEN;
4468 +       MCF_FEC_TCR1 = MCF_FEC_TCR_FDEN;
4469 +       /* ECR */
4470 +#ifdef MODELO_BUFFER
4471 +       MCF_FEC_ECR0 = MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588;
4472 +       MCF_FEC_ECR1 = MCF_FEC_ECR_ETHER_EN | MCF_FEC_ECR_ENA_1588;
4473 +#else
4474 +       MCF_FEC_ECR0 = MCF_FEC_ECR_ETHER_EN;
4475 +       MCF_FEC_ECR1 = MCF_FEC_ECR_ETHER_EN;
4476 +#endif
4477 +       MCF_FEC_MSCR0 = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
4478 +       MCF_FEC_MSCR1 = ((((MCF_CLK / 2) / (2500000 / 10)) + 5) / 10) * 2;
4479 +
4480 +       MCF_FEC_EIMR0 = FEC_ENET_TXF | FEC_ENET_RXF;
4481 +       MCF_FEC_EIMR1 = FEC_ENET_TXF | FEC_ENET_RXF;
4482 +       /*MCF_PPMHR0*/
4483 +       MCF_PPMCR0 = 0;
4484 +}
4485 +
4486 +static const struct net_device_ops switch_netdev_ops = {
4487 +       .ndo_open               = switch_enet_open,
4488 +       .ndo_stop               = switch_enet_close,
4489 +       .ndo_start_xmit         = switch_enet_start_xmit,
4490 +       .ndo_set_multicast_list = set_multicast_list,
4491 +       .ndo_do_ioctl           = switch_enet_ioctl,
4492 +       .ndo_tx_timeout         = switch_timeout,
4493 +};
4494 +
4495 +/* Initialize the FEC Ethernet.
4496 + */
4497 + /*
4498 +  * XXX:  We need to clean up on failure exits here.
4499 +  */
4500 +static int switch_enet_init(struct platform_device *pdev)
4501 +{
4502 +       struct net_device *dev = platform_get_drvdata(pdev);
4503 +       struct switch_enet_private *fep = netdev_priv(dev);
4504 +       unsigned long mem_addr;
4505 +       cbd_t *bdp;
4506 +       cbd_t *cbd_base;
4507 +       volatile switch_t *fecp;
4508 +       int i, j;
4509 +       struct coldfire_switch_platform_data *plat =
4510 +               pdev->dev.platform_data;
4511 +
4512 +       /* Allocate memory for buffer descriptors.
4513 +       */
4514 +       mem_addr = __get_free_page(GFP_DMA);
4515 +       if (mem_addr == 0) {
4516 +               printk(KERN_ERR "Switch: allocate descriptor memory failed?\n");
4517 +               return -ENOMEM;
4518 +       }
4519 +
4520 +       spin_lock_init(&fep->hw_lock);
4521 +       spin_lock_init(&fep->mii_lock);
4522 +
4523 +       /* Create an Ethernet device instance.
4524 +       */
4525 +       fecp = (volatile switch_t *)plat->switch_hw[0];
4526 +       fep->hwp = fecp;
4527 +       fep->netdev = dev;
4528 +
4529 +       /*
4530 +        * SWITCH CONFIGURATION
4531 +        */
4532 +       fecp->ESW_MODE = MCF_ESW_MODE_SW_RST;
4533 +       udelay(10);
4534 +       /* enable switch*/
4535 +       fecp->ESW_MODE = MCF_ESW_MODE_STATRST;
4536 +       fecp->ESW_MODE = MCF_ESW_MODE_SW_EN;
4537 +
4538 +       /* Enable transmit/receive on all ports */
4539 +       fecp->ESW_PER = 0xffffffff;
4540 +
4541 +       /* Management port configuration,
4542 +        * make port 0 as management port */
4543 +       fecp->ESW_BMPC = 0;
4544 +
4545 +       /* clear all switch irq*/
4546 +       fecp->switch_ievent = 0xffffffff;
4547 +       fecp->switch_imask  = 0;
4548 +
4549 +       udelay(10);
4550 +
4551 +       /* Set the Ethernet address.  If using multiple Enets on the 8xx,
4552 +        * this needs some work to get unique addresses.
4553 +        *
4554 +        * This is our default MAC address unless the user changes
4555 +        * it via eth_mac_addr (our dev->set_mac_addr handler).
4556 +        */
4557 +       if (plat && plat->get_mac)
4558 +               plat->get_mac(dev);
4559 +
4560 +       cbd_base = (cbd_t *)mem_addr;
4561 +       /* XXX: missing check for allocation failure */
4562 +       if (plat && plat->uncache)
4563 +               plat->uncache(mem_addr);
4564 +
4565 +       /* Set receive and transmit descriptor base.
4566 +       */
4567 +       fep->rx_bd_base = cbd_base;
4568 +       fep->tx_bd_base = cbd_base + RX_RING_SIZE;
4569 +
4570 +       dev->base_addr = (unsigned long)fecp;
4571 +
4572 +       /* The FEC Ethernet specific entries in the device structure. */
4573 +       dev->watchdog_timeo = TX_TIMEOUT;
4574 +       dev->netdev_ops = &switch_netdev_ops;
4575 +
4576 +       fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
4577 +       fep->cur_rx = fep->rx_bd_base;
4578 +
4579 +       fep->skb_cur = fep->skb_dirty = 0;
4580 +
4581 +       /* Initialize the receive buffer descriptors. */
4582 +       bdp = fep->rx_bd_base;
4583 +
4584 +       for (i = 0; i < SWITCH_ENET_RX_PAGES; i++) {
4585 +
4586 +               /* Allocate a page.
4587 +               */
4588 +               mem_addr = __get_free_page(GFP_DMA);
4589 +               /* XXX: missing check for allocation failure */
4590 +               if (plat && plat->uncache)
4591 +                       plat->uncache(mem_addr);
4592 +
4593 +               /* Initialize the BD for every fragment in the page.
4594 +               */
4595 +               for (j = 0; j < SWITCH_ENET_RX_FRPPG; j++) {
4596 +                       bdp->cbd_sc = BD_ENET_RX_EMPTY;
4597 +                       bdp->cbd_bufaddr = __pa(mem_addr);
4598 +#ifdef MODELO_BUFFER
4599 +                       bdp->bdu = 0x00000000;
4600 +                       bdp->ebd_status = RX_BD_INT;
4601 +#endif
4602 +                       mem_addr += SWITCH_ENET_RX_FRSIZE;
4603 +                       bdp++;
4604 +               }
4605 +       }
4606 +
4607 +       /* Set the last buffer to wrap.
4608 +       */
4609 +       bdp--;
4610 +       bdp->cbd_sc |= BD_SC_WRAP;
4611 +
4612 +       /* ...and the same for transmmit.
4613 +       */
4614 +       bdp = fep->tx_bd_base;
4615 +       for (i = 0, j = SWITCH_ENET_TX_FRPPG; i < TX_RING_SIZE; i++) {
4616 +               if (j >= SWITCH_ENET_TX_FRPPG) {
4617 +                       mem_addr = __get_free_page(GFP_DMA);
4618 +                       j = 1;
4619 +               } else {
4620 +                       mem_addr += SWITCH_ENET_TX_FRSIZE;
4621 +                       j++;
4622 +               }
4623 +               fep->tx_bounce[i] = (unsigned char *) mem_addr;
4624 +
4625 +               /* Initialize the BD for every fragment in the page.
4626 +               */
4627 +               bdp->cbd_sc = 0;
4628 +               bdp->cbd_bufaddr = 0;
4629 +               bdp++;
4630 +       }
4631 +
4632 +       /* Set the last buffer to wrap.
4633 +       */
4634 +       bdp--;
4635 +       bdp->cbd_sc |= BD_SC_WRAP;
4636 +
4637 +       /* Set receive and transmit descriptor base.
4638 +       */
4639 +       fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base));
4640 +       fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
4641 +
4642 +       /* Install our interrupt handlers. This varies depending on
4643 +        * the architecture.
4644 +       */
4645 +       if (plat && plat->request_intrs)
4646 +               plat->request_intrs(dev, switch_enet_interrupt, dev);
4647 +
4648 +       fecp->fec_r_buff_size = RX_BUFFER_SIZE;
4649 +       fecp->fec_r_des_active = MCF_ESW_RDAR_R_DES_ACTIVE;
4650 +
4651 +       /* setup MII interface */
4652 +       if (plat && plat->set_mii)
4653 +               plat->set_mii(dev);
4654 +
4655 +       /* Clear and enable interrupts */
4656 +       fecp->switch_ievent = 0xffffffff;
4657 +       fecp->switch_imask  = MCF_ESW_IMR_RXB | MCF_ESW_IMR_TXB |
4658 +               MCF_ESW_IMR_RXF | MCF_ESW_IMR_TXF;
4659 +       esw_clear_atable(fep);
4660 +       /* Queue up command to detect the PHY and initialize the
4661 +        * remainder of the interface.
4662 +        */
4663 +#ifndef CONFIG_FEC_SHARED_PHY
4664 +       fep->phy_addr = 0;
4665 +#else
4666 +       fep->phy_addr = fep->index;
4667 +#endif
4668 +
4669 +       fep->sequence_done = 1;
4670 +       return 0;
4671 +}
4672 +
4673 +/* This function is called to start or restart the FEC during a link
4674 + * change.  This only happens when switching between half and full
4675 + * duplex.
4676 + */
4677 +static void switch_restart(struct net_device *dev, int duplex)
4678 +{
4679 +       struct switch_enet_private *fep;
4680 +       cbd_t *bdp;
4681 +       volatile switch_t *fecp;
4682 +       int i;
4683 +       struct coldfire_switch_platform_data *plat;
4684 +
4685 +       fep = netdev_priv(dev);
4686 +       fecp = fep->hwp;
4687 +       plat = fep->pdev->dev.platform_data;
4688 +       /* Whack a reset.  We should wait for this.*/
4689 +       MCF_FEC_ECR0 = 1;
4690 +       MCF_FEC_ECR1 = 1;
4691 +       udelay(10);
4692 +
4693 +       fecp->ESW_MODE = MCF_ESW_MODE_SW_RST;
4694 +       udelay(10);
4695 +       fecp->ESW_MODE = MCF_ESW_MODE_STATRST;
4696 +       fecp->ESW_MODE = MCF_ESW_MODE_SW_EN;
4697 +
4698 +       /* Enable transmit/receive on all ports */
4699 +       fecp->ESW_PER = 0xffffffff;
4700 +
4701 +       /* Management port configuration,
4702 +        * make port 0 as management port */
4703 +       fecp->ESW_BMPC = 0;
4704 +
4705 +       /* Clear any outstanding interrupt.
4706 +       */
4707 +       fecp->switch_ievent = 0xffffffff;
4708 +
4709 +       /* Set station address.*/
4710 +       switch_set_mac_address(dev);
4711 +
4712 +       switch_hw_init();
4713 +
4714 +       /* Reset all multicast.*/
4715 +
4716 +       /* Set maximum receive buffer size.
4717 +       */
4718 +       fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
4719 +
4720 +       if (plat && plat->localhw_setup)
4721 +               plat->localhw_setup();
4722 +       /* Set receive and transmit descriptor base.
4723 +       */
4724 +       fecp->fec_r_des_start = __pa((uint)(fep->rx_bd_base));
4725 +       fecp->fec_x_des_start = __pa((uint)(fep->tx_bd_base));
4726 +
4727 +       fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
4728 +       fep->cur_rx = fep->rx_bd_base;
4729 +
4730 +       /* Reset SKB transmit buffers.
4731 +       */
4732 +       fep->skb_cur = fep->skb_dirty = 0;
4733 +       for (i = 0; i <= TX_RING_MOD_MASK; i++) {
4734 +               if (fep->tx_skbuff[i] != NULL) {
4735 +                       dev_kfree_skb_any(fep->tx_skbuff[i]);
4736 +                       fep->tx_skbuff[i] = NULL;
4737 +               }
4738 +       }
4739 +
4740 +       /* Initialize the receive buffer descriptors.
4741 +       */
4742 +       bdp = fep->rx_bd_base;
4743 +       for (i = 0; i < RX_RING_SIZE; i++) {
4744 +
4745 +               /* Initialize the BD for every fragment in the page.
4746 +               */
4747 +               bdp->cbd_sc = BD_ENET_RX_EMPTY;
4748 +#ifdef MODELO_BUFFER
4749 +               bdp->bdu = 0x00000000;
4750 +               bdp->ebd_status = RX_BD_INT;
4751 +#endif
4752 +               bdp++;
4753 +       }
4754 +
4755 +       /* Set the last buffer to wrap.
4756 +       */
4757 +       bdp--;
4758 +       bdp->cbd_sc |= BD_SC_WRAP;
4759 +
4760 +       /* ...and the same for transmmit.
4761 +       */
4762 +       bdp = fep->tx_bd_base;
4763 +       for (i = 0; i < TX_RING_SIZE; i++) {
4764 +
4765 +               /* Initialize the BD for every fragment in the page.*/
4766 +               bdp->cbd_sc = 0;
4767 +               bdp->cbd_bufaddr = 0;
4768 +               bdp++;
4769 +       }
4770 +
4771 +       /* Set the last buffer to wrap.*/
4772 +       bdp--;
4773 +       bdp->cbd_sc |= BD_SC_WRAP;
4774 +
4775 +       fep->full_duplex = duplex;
4776 +
4777 +       /* And last, enable the transmit and receive processing.*/
4778 +       fecp->fec_r_buff_size = RX_BUFFER_SIZE;
4779 +       fecp->fec_r_des_active = MCF_ESW_RDAR_R_DES_ACTIVE;
4780 +
4781 +       /* Enable interrupts we wish to service.
4782 +       */
4783 +       fecp->switch_ievent = 0xffffffff;
4784 +       fecp->switch_imask  = MCF_ESW_IMR_RXF | MCF_ESW_IMR_TXF |
4785 +               MCF_ESW_IMR_RXB | MCF_ESW_IMR_TXB;
4786 +}
4787 +
4788 +static void switch_stop(struct net_device *dev)
4789 +{
4790 +       volatile switch_t *fecp;
4791 +       struct switch_enet_private *fep;
4792 +       struct coldfire_switch_platform_data *plat;
4793 +
4794 +       fep = netdev_priv(dev);
4795 +       fecp = fep->hwp;
4796 +       plat = fep->pdev->dev.platform_data;
4797 +       /*
4798 +       ** We cannot expect a graceful transmit stop without link !!!
4799 +       */
4800 +       if (fep->phy1_link)
4801 +               udelay(10);
4802 +       if (fep->phy2_link)
4803 +               udelay(10);
4804 +
4805 +       /* Whack a reset.  We should wait for this.
4806 +       */
4807 +       udelay(10);
4808 +}
4809 +
4810 +static int fec_mdio_register(struct net_device *dev)
4811 +{
4812 +       int err = 0;
4813 +       struct switch_enet_private *fep = netdev_priv(dev);
4814 +
4815 +       fep->mdio_bus = mdiobus_alloc();
4816 +       if (!fep->mdio_bus) {
4817 +               printk(KERN_ERR "ethernet switch mdiobus_alloc fail\n");
4818 +               return -ENOMEM;
4819 +       }
4820 +
4821 +       fep->mdio_bus->name = "Coldfire switch MII 0 Bus";
4822 +       strcpy(fep->mdio_bus->id, "0");
4823 +
4824 +       fep->mdio_bus->read = &coldfire_fec_mdio_read;
4825 +       fep->mdio_bus->write = &coldfire_fec_mdio_write;
4826 +       fep->mdio_bus->priv = dev;
4827 +       err = mdiobus_register(fep->mdio_bus);
4828 +       if (err) {
4829 +               mdiobus_free(fep->mdio_bus);
4830 +               printk(KERN_ERR "%s: ethernet mdiobus_register fail\n",
4831 +                       dev->name);
4832 +               return -EIO;
4833 +       }
4834 +
4835 +       printk(KERN_INFO "mdiobus_register %s ok\n",
4836 +               fep->mdio_bus->name);
4837 +       return err;
4838 +}
4839 +
4840 +static int __devinit eth_switch_probe(struct platform_device *pdev)
4841 +{
4842 +       struct net_device *dev;
4843 +       int err;
4844 +       struct switch_enet_private *fep;
4845 +       struct task_struct *task;
4846 +
4847 +       printk(KERN_INFO "Ethernet Switch Version 1.0\n");
4848 +
4849 +       dev = alloc_etherdev(sizeof(struct switch_enet_private));
4850 +       if (!dev) {
4851 +               printk(KERN_ERR "%s: ethernet switch alloc_etherdev fail\n",
4852 +                               dev->name);
4853 +               return -ENOMEM;
4854 +       }
4855 +
4856 +       SET_NETDEV_DEV(dev, &pdev->dev);
4857 +
4858 +       fep = netdev_priv(dev);
4859 +       memset(fep, 0, sizeof(*fep));
4860 +
4861 +       fep->pdev = pdev;
4862 +       platform_set_drvdata(pdev, dev);
4863 +       printk(KERN_ERR "%s: ethernet switch port 0 init\n",
4864 +                       __func__);
4865 +       err = switch_enet_init(pdev);
4866 +       if (err) {
4867 +               free_netdev(dev);
4868 +               platform_set_drvdata(pdev, NULL);
4869 +       }
4870 +
4871 +       err = fec_mdio_register(dev);
4872 +       if (err) {
4873 +               printk(KERN_ERR "%s: ethernet switch fec_mdio_register\n",
4874 +                               dev->name);
4875 +               free_netdev(dev);
4876 +               platform_set_drvdata(pdev, NULL);
4877 +               return -ENOMEM;
4878 +       }
4879 +
4880 +       /* setup timer for Learning Aging function */
4881 +       init_timer(&fep->timer_aging);
4882 +       fep->timer_aging.function = l2switch_aging_timer;
4883 +       fep->timer_aging.data = (unsigned long) fep;
4884 +       fep->timer_aging.expires = jiffies + LEARNING_AGING_TIMER;
4885 +       add_timer(&fep->timer_aging);
4886 +
4887 +       /* register network device*/
4888 +       if (register_netdev(dev) != 0) {
4889 +               /* XXX: missing cleanup here */
4890 +               free_netdev(dev);
4891 +               platform_set_drvdata(pdev, NULL);
4892 +               printk(KERN_ERR "%s: ethernet switch register_netdev fail\n",
4893 +                               dev->name);
4894 +               return -EIO;
4895 +       }
4896 +
4897 +       task = kthread_run(switch_enet_learning, fep,
4898 +                       "modelo l2switch");
4899 +       if (IS_ERR(task)) {
4900 +               err = PTR_ERR(task);
4901 +               return err;
4902 +       }
4903 +
4904 +       printk(KERN_INFO "%s: ethernet switch %pM\n",
4905 +                       dev->name, dev->dev_addr);
4906 +       return 0;
4907 +}
4908 +
4909 +static int __devexit eth_switch_remove(struct platform_device *pdev)
4910 +{
4911 +       int i;
4912 +       struct net_device *dev;
4913 +       struct switch_enet_private *fep;
4914 +       struct switch_platform_private *chip;
4915 +
4916 +       chip = platform_get_drvdata(pdev);
4917 +       if (chip) {
4918 +               for (i = 0; i < chip->num_slots; i++) {
4919 +                       fep = chip->fep_host[i];
4920 +                       dev = fep->netdev;
4921 +                       fep->sequence_done = 1;
4922 +                       unregister_netdev(dev);
4923 +                       free_netdev(dev);
4924 +
4925 +                       del_timer_sync(&fep->timer_aging);
4926 +               }
4927 +
4928 +               platform_set_drvdata(pdev, NULL);
4929 +               kfree(chip);
4930 +
4931 +       } else
4932 +               printk(KERN_ERR "%s: can not get the "
4933 +                       "switch_platform_private %x\n", __func__,
4934 +                       (unsigned int)chip);
4935 +
4936 +       return 0;
4937 +}
4938 +
4939 +static struct platform_driver eth_switch_driver = {
4940 +       .probe          = eth_switch_probe,
4941 +       .remove         = __devexit_p(eth_switch_remove),
4942 +       .driver         = {
4943 +               .name   = "coldfire-switch",
4944 +               .owner  = THIS_MODULE,
4945 +       },
4946 +};
4947 +
4948 +static int __init coldfire_switch_init(void)
4949 +{
4950 +       return platform_driver_register(&eth_switch_driver);
4951 +}
4952 +
4953 +static void __exit coldfire_switch_exit(void)
4954 +{
4955 +       platform_driver_unregister(&eth_switch_driver);
4956 +}
4957 +
4958 +module_init(coldfire_switch_init);
4959 +module_exit(coldfire_switch_exit);
4960 +MODULE_LICENSE("GPL");
4961 --- /dev/null
4962 +++ b/drivers/net/modelo_switch.h
4963 @@ -0,0 +1,1141 @@
4964 +/****************************************************************************/
4965 +
4966 +/*
4967 + *   mcfswitch -- L2 Switch Controller for Modelo ColdFire SoC
4968 + *                processors.
4969 + *
4970 + *   Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
4971 + *
4972 + *   This program is free software; you can redistribute it and/or modify
4973 + *   it under the terms of the GNU General Public License as published by
4974 + *   the Free Software Foundation; either version 2 of the License, or (at
4975 + *   your option) any later version.
4976 + *
4977 + */
4978 +
4979 +/****************************************************************************/
4980 +#ifndef SWITCH_H
4981 +#define        SWITCH_H
4982 +/****************************************************************************/
4983 +/* The Switch stores dest/src/type, data, and checksum for receive packets.
4984 + */
4985 +#define PKT_MAXBUF_SIZE         1518
4986 +#define PKT_MINBUF_SIZE         64
4987 +#define PKT_MAXBLR_SIZE         1520
4988 +
4989 +/*
4990 + * The 5441x RX control register also contains maximum frame
4991 + * size bits.
4992 + */
4993 +#define OPT_FRAME_SIZE  (PKT_MAXBUF_SIZE << 16)
4994 +
4995 +/*
4996 + * Some hardware gets it MAC address out of local flash memory.
4997 + * if this is non-zero then assume it is the address to get MAC from.
4998 + */
4999 +#define FEC_FLASHMAC    0
5000 +
5001 +/* The number of Tx and Rx buffers.  These are allocated from the page
5002 + * pool.  The code may assume these are power of two, so it it best
5003 + * to keep them that size.
5004 + * We don't need to allocate pages for the transmitter.  We just use
5005 + * the skbuffer directly.
5006 + */
5007 +#ifdef CONFIG_SWITCH_DMA_USE_SRAM
5008 +#define SWITCH_ENET_RX_PAGES       6
5009 +#else
5010 +#define SWITCH_ENET_RX_PAGES       8
5011 +#endif
5012 +
5013 +#define SWITCH_ENET_RX_FRSIZE      2048
5014 +#define SWITCH_ENET_RX_FRPPG       (PAGE_SIZE / SWITCH_ENET_RX_FRSIZE)
5015 +#define RX_RING_SIZE            (SWITCH_ENET_RX_FRPPG * SWITCH_ENET_RX_PAGES)
5016 +#define SWITCH_ENET_TX_FRSIZE      2048
5017 +#define SWITCH_ENET_TX_FRPPG       (PAGE_SIZE / SWITCH_ENET_TX_FRSIZE)
5018 +
5019 +#ifdef CONFIG_SWITCH_DMA_USE_SRAM
5020 +#define TX_RING_SIZE            8      /* Must be power of two */
5021 +#define TX_RING_MOD_MASK        7      /*   for this to work */
5022 +#else
5023 +#define TX_RING_SIZE            16      /* Must be power of two */
5024 +#define TX_RING_MOD_MASK        15      /*   for this to work */
5025 +#endif
5026 +
5027 +#define SWITCH_EPORT_NUMBER    2
5028 +
5029 +#if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
5030 +#error "L2SWITCH: descriptor ring size constants too large"
5031 +#endif
5032 +/*-----------------------------------------------------------------------*/
5033 +typedef struct l2switch_output_queue_status {
5034 +       unsigned long ESW_MMSR;
5035 +       unsigned long ESW_LMT;
5036 +       unsigned long ESW_LFC;
5037 +       unsigned long ESW_PCSR;
5038 +       unsigned long ESW_IOSR;
5039 +       unsigned long ESW_QWT;
5040 +       unsigned long esw_reserved;
5041 +       unsigned long ESW_P0BCT;
5042 +} esw_output_queue_status;
5043 +
5044 +typedef struct l2switch_statistics_status {
5045 +       /*
5046 +        * Total number of incoming frames processed
5047 +        * but discarded in switch
5048 +        */
5049 +       unsigned long ESW_DISCN;
5050 +       /*Sum of bytes of frames counted in ESW_DISCN*/
5051 +       unsigned long ESW_DISCB;
5052 +       /*
5053 +        * Total number of incoming frames processed
5054 +        * but not discarded in switch
5055 +        */
5056 +       unsigned long ESW_NDISCN;
5057 +       /*Sum of bytes of frames counted in ESW_NDISCN*/
5058 +       unsigned long ESW_NDISCB;
5059 +} esw_statistics_status;
5060 +
5061 +typedef struct l2switch_port_statistics_status {
5062 +       /*outgoing frames discarded due to transmit queue congestion*/
5063 +       unsigned long MCF_ESW_POQC;
5064 +       /*incoming frames discarded due to VLAN domain mismatch*/
5065 +       unsigned long MCF_ESW_PMVID;
5066 +       /*incoming frames discarded due to untagged discard*/
5067 +       unsigned long MCF_ESW_PMVTAG;
5068 +       /*incoming frames discarded due port is in blocking state*/
5069 +       unsigned long MCF_ESW_PBL;
5070 +} esw_port_statistics_status;
5071 +
5072 +typedef struct l2switch {
5073 +       unsigned long ESW_REVISION;
5074 +       unsigned long ESW_SCRATCH;
5075 +       unsigned long ESW_PER;
5076 +       unsigned long reserved0[1];
5077 +       unsigned long ESW_VLANV;
5078 +       unsigned long ESW_DBCR;
5079 +       unsigned long ESW_DMCR;
5080 +       unsigned long ESW_BKLR;
5081 +       unsigned long ESW_BMPC;
5082 +       unsigned long ESW_MODE;
5083 +       unsigned long ESW_VIMSEL;
5084 +       unsigned long ESW_VOMSEL;
5085 +       unsigned long ESW_VIMEN;
5086 +       unsigned long ESW_VID;/*0x34*/
5087 +       /*from 0x38 0x3C*/
5088 +       unsigned long esw_reserved0[2];
5089 +       unsigned long ESW_MCR;/*0x40*/
5090 +       unsigned long ESW_EGMAP;
5091 +       unsigned long ESW_INGMAP;
5092 +       unsigned long ESW_INGSAL;
5093 +       unsigned long ESW_INGSAH;
5094 +       unsigned long ESW_INGDAL;
5095 +       unsigned long ESW_INGDAH;
5096 +       unsigned long ESW_ENGSAL;
5097 +       unsigned long ESW_ENGSAH;
5098 +       unsigned long ESW_ENGDAL;
5099 +       unsigned long ESW_ENGDAH;
5100 +       unsigned long ESW_MCVAL;/*0x6C*/
5101 +       /*from 0x70--0x7C*/
5102 +       unsigned long esw_reserved1[4];
5103 +       unsigned long ESW_MMSR;/*0x80*/
5104 +       unsigned long ESW_LMT;
5105 +       unsigned long ESW_LFC;
5106 +       unsigned long ESW_PCSR;
5107 +       unsigned long ESW_IOSR;
5108 +       unsigned long ESW_QWT;/*0x94*/
5109 +       unsigned long esw_reserved2[1];/*0x98*/
5110 +       unsigned long ESW_P0BCT;/*0x9C*/
5111 +       /*from 0xA0-0xB8*/
5112 +       unsigned long esw_reserved3[7];
5113 +       unsigned long ESW_P0FFEN;/*0xBC*/
5114 +       unsigned long ESW_PSNP[8];
5115 +       unsigned long ESW_IPSNP[8];
5116 +       /*port0-port2 VLAN Priority resolution map  0xFC0D_C100-C108*/
5117 +       unsigned long ESW_PVRES[3];
5118 +       /*from 0x10C-0x13C*/
5119 +       unsigned long esw_reserved4[13];
5120 +       unsigned long ESW_IPRES;/*0x140*/
5121 +       /*from 0x144-0x17C*/
5122 +       unsigned long esw_reserved5[15];
5123 +
5124 +       /*port0-port2 Priority Configuration  0xFC0D_C180-C188*/
5125 +       unsigned long ESW_PRES[3];
5126 +       /*from 0x18C-0x1FC*/
5127 +       unsigned long esw_reserved6[29];
5128 +
5129 +       /*port0-port2 VLAN ID 0xFC0D_C200-C208*/
5130 +       unsigned long ESW_PID[3];
5131 +       /*from 0x20C-0x27C*/
5132 +       unsigned long esw_reserved7[29];
5133 +
5134 +       /*port0-port2 VLAN domain resolution entry 0xFC0D_C280-C2FC*/
5135 +       unsigned long ESW_VRES[32];
5136 +
5137 +       unsigned long ESW_DISCN;/*0x300*/
5138 +       unsigned long ESW_DISCB;
5139 +       unsigned long ESW_NDISCN;
5140 +       unsigned long ESW_NDISCB;/*0xFC0DC30C*/
5141 +       /*per port statistics 0xFC0DC310_C33C*/
5142 +       esw_port_statistics_status port_statistics_status[3];
5143 +       /*from 0x340-0x400*/
5144 +       unsigned long esw_reserved8[48];
5145 +
5146 +       /*0xFC0DC400---0xFC0DC418*/
5147 +       /*unsigned long MCF_ESW_ISR;*/
5148 +       unsigned long   switch_ievent;             /* Interrupt event reg */
5149 +       /*unsigned long MCF_ESW_IMR;*/
5150 +       unsigned long   switch_imask;              /* Interrupt mask reg */
5151 +       /*unsigned long MCF_ESW_RDSR;*/
5152 +       unsigned long   fec_r_des_start;        /* Receive descriptor ring */
5153 +       /*unsigned long MCF_ESW_TDSR;*/
5154 +       unsigned long   fec_x_des_start;        /* Transmit descriptor ring */
5155 +       /*unsigned long MCF_ESW_MRBR;*/
5156 +       unsigned long   fec_r_buff_size;        /* Maximum receive buff size */
5157 +       /*unsigned long MCF_ESW_RDAR;*/
5158 +       unsigned long   fec_r_des_active;       /* Receive descriptor reg */
5159 +       /*unsigned long MCF_ESW_TDAR;*/
5160 +       unsigned long   fec_x_des_active;       /* Transmit descriptor reg */
5161 +       /*from 0x420-0x4FC*/
5162 +       unsigned long esw_reserved9[57];
5163 +
5164 +       /*0xFC0DC500---0xFC0DC508*/
5165 +       unsigned long ESW_LREC0;
5166 +       unsigned long ESW_LREC1;
5167 +       unsigned long ESW_LSR;
5168 +} switch_t;
5169 +
5170 +typedef struct _64bTableEntry {
5171 +       unsigned int lo;  /* lower 32 bits */
5172 +       unsigned int hi;  /* upper 32 bits */
5173 +} AddrTable64bEntry;
5174 +
5175 +typedef struct l2switchaddrtable {
5176 +       AddrTable64bEntry  eswTable64bEntry[2048];
5177 +} eswAddrTable_t;
5178 +
5179 +/*unsigned long MCF_ESW_LOOKUP_MEM;*/
5180 +#define MCF_ESW_REVISION   (*(volatile unsigned long *)(0xFC0DC000))
5181 +#define MCF_ESW_PER        (*(volatile unsigned long *)(0xFC0DC008))
5182 +#define MCF_ESW_VLANV      (*(volatile unsigned long *)(0xFC0DC010))
5183 +#define MCF_ESW_DBCR       (*(volatile unsigned long *)(0xFC0DC014))
5184 +#define MCF_ESW_DMCR       (*(volatile unsigned long *)(0xFC0DC018))
5185 +#define MCF_ESW_BKLR       (*(volatile unsigned long *)(0xFC0DC01C))
5186 +#define MCF_ESW_BMPC       (*(volatile unsigned long *)(0xFC0DC020))
5187 +#define MCF_ESW_MODE       (*(volatile unsigned long *)(0xFC0DC024))
5188 +
5189 +#define MCF_ESW_ISR        (*(volatile unsigned long *)(0xFC0DC400))
5190 +#define MCF_ESW_IMR        (*(volatile unsigned long *)(0xFC0DC404))
5191 +#define MCF_ESW_TDAR       (*(volatile unsigned long *)(0xFC0DC418))
5192 +#define MCF_ESW_LOOKUP_MEM (*(volatile unsigned long *)(0xFC0E0000))
5193 +
5194 +#define MCF_PPMCR0     (*(volatile unsigned short *)(0xFC04002D))
5195 +#define MCF_PPMHR0     (*(volatile unsigned long *)(0xFC040030))
5196 +
5197 +#define MCF_FEC_EIR0       (*(volatile unsigned long *)(0xFC0D4004))
5198 +#define MCF_FEC_EIR1       (*(volatile unsigned long *)(0xFC0D8004))
5199 +#define MCF_FEC_EIMR0      (*(volatile unsigned long *)(0xFC0D4008))
5200 +#define MCF_FEC_EIMR1      (*(volatile unsigned long *)(0xFC0D8008))
5201 +#define MCF_FEC_MMFR0      (*(volatile unsigned long *)(0xFC0D4040))
5202 +#define MCF_FEC_MMFR1      (*(volatile unsigned long *)(0xFC0D8040))
5203 +#define MCF_FEC_MSCR0      (*(volatile unsigned long *)(0xFC0D4044))
5204 +#define MCF_FEC_MSCR1      (*(volatile unsigned long *)(0xFC0D8044))
5205 +#define MCF_FEC_RCR0       (*(volatile unsigned long *)(0xFC0D4084))
5206 +#define MCF_FEC_RCR1       (*(volatile unsigned long *)(0xFC0D8084))
5207 +#define MCF_FEC_TCR0       (*(volatile unsigned long *)(0xFC0D40C4))
5208 +#define MCF_FEC_TCR1       (*(volatile unsigned long *)(0xFC0D80C4))
5209 +#define MCF_FEC_ECR0       (*(volatile unsigned long *)(0xFC0D4024))
5210 +#define MCF_FEC_ECR1       (*(volatile unsigned long *)(0xFC0D8024))
5211 +
5212 +
5213 +#define MCF_FEC_RCR_PROM                     (0x00000008)
5214 +#define MCF_FEC_RCR_RMII_MODE                (0x00000100)
5215 +#define MCF_FEC_RCR_MAX_FL(x)                (((x)&0x00003FFF)<<16)
5216 +#define MCF_FEC_RCR_CRC_FWD                  (0x00004000)
5217 +
5218 +#define MCF_FEC_TCR_FDEN                     (0x00000004)
5219 +
5220 +#define MCF_FEC_ECR_ETHER_EN                 (0x00000002)
5221 +#define MCF_FEC_ECR_ENA_1588                 (0x00000010)
5222 +
5223 +/*-------------ioctl command ---------------------------------------*/
5224 +#define ESW_SET_LEARNING_CONF               0x9101
5225 +#define ESW_GET_LEARNING_CONF               0x9201
5226 +#define ESW_SET_BLOCKING_CONF               0x9102
5227 +#define ESW_GET_BLOCKING_CONF               0x9202
5228 +#define ESW_SET_MULTICAST_CONF              0x9103
5229 +#define ESW_GET_MULTICAST_CONF              0x9203
5230 +#define ESW_SET_BROADCAST_CONF              0x9104
5231 +#define ESW_GET_BROADCAST_CONF              0x9204
5232 +#define ESW_SET_PORTENABLE_CONF             0x9105
5233 +#define ESW_GET_PORTENABLE_CONF             0x9205
5234 +#define ESW_SET_IP_SNOOP_CONF               0x9106
5235 +#define ESW_GET_IP_SNOOP_CONF               0x9206
5236 +#define ESW_SET_PORT_SNOOP_CONF             0x9107
5237 +#define ESW_GET_PORT_SNOOP_CONF             0x9207
5238 +#define ESW_SET_PORT_MIRROR_CONF           0x9108
5239 +#define ESW_GET_PORT_MIRROR_CONF            0x9208
5240 +#define ESW_SET_PIRORITY_VLAN               0x9109
5241 +#define ESW_GET_PIRORITY_VLAN               0x9209
5242 +#define ESW_SET_PIRORITY_IP                 0x910A
5243 +#define ESW_GET_PIRORITY_IP                 0x920A
5244 +#define ESW_SET_PIRORITY_MAC                0x910B
5245 +#define ESW_GET_PIRORITY_MAC                0x920B
5246 +#define ESW_SET_PIRORITY_DEFAULT            0x910C
5247 +#define ESW_GET_PIRORITY_DEFAULT            0x920C
5248 +#define ESW_SET_P0_FORCED_FORWARD           0x910D
5249 +#define ESW_GET_P0_FORCED_FORWARD           0x920D
5250 +#define ESW_SET_SWITCH_MODE                 0x910E
5251 +#define ESW_GET_SWITCH_MODE                 0x920E
5252 +#define ESW_SET_BRIDGE_CONFIG               0x910F
5253 +#define ESW_GET_BRIDGE_CONFIG               0x920F
5254 +#define ESW_SET_VLAN_OUTPUT_PROCESS         0x9110
5255 +#define ESW_GET_VLAN_OUTPUT_PROCESS         0x9210
5256 +#define ESW_SET_VLAN_INPUT_PROCESS          0x9111
5257 +#define ESW_GET_VLAN_INPUT_PROCESS          0x9211
5258 +#define ESW_SET_VLAN_DOMAIN_VERIFICATION    0x9112
5259 +#define ESW_GET_VLAN_DOMAIN_VERIFICATION    0x9212
5260 +#define ESW_SET_VLAN_RESOLUTION_TABLE       0x9113
5261 +#define ESW_GET_VLAN_RESOLUTION_TABLE       0x9213
5262 +#define ESW_GET_ENTRY_PORT_NUMBER          0x9214
5263 +#define ESW_GET_LOOKUP_TABLE               0x9215
5264 +#define ESW_GET_PORT_STATUS                 0x9216
5265 +#define ESW_SET_VLAN_ID                            0x9114
5266 +#define ESW_SET_VLAN_ID_CLEARED                    0x9115
5267 +#define ESW_SET_PORT_IN_VLAN_ID             0x9116
5268 +#define ESW_SET_PORT_ENTRY_EMPTY            0x9117
5269 +#define ESW_SET_OTHER_PORT_ENTRY_EMPTY      0x9118
5270 +#define ESW_GET_PORT_ALL_STATUS                    0x9217
5271 +#define ESW_SET_PORT_MIRROR_CONF_PORT_MATCH 0x9119
5272 +#define ESW_SET_PORT_MIRROR_CONF_ADDR_MATCH 0x911A
5273 +
5274 +#define ESW_GET_STATISTICS_STATUS           0x9221
5275 +#define ESW_SET_OUTPUT_QUEUE_MEMORY         0x9125
5276 +#define ESW_GET_OUTPUT_QUEUE_STATUS         0x9225
5277 +#define ESW_UPDATE_STATIC_MACTABLE          0x9226
5278 +#define ESW_CLEAR_ALL_MACTABLE              0x9227
5279 +#define ESW_GET_USER_PID                    0x9228
5280 +
5281 +typedef struct _eswIOCTL_PORT_CONF {
5282 +       int port;
5283 +       int enable;
5284 +} eswIoctlPortConfig;
5285 +
5286 +typedef struct _eswIOCTL_PORT_EN_CONF {
5287 +       int port;
5288 +       int tx_enable;
5289 +       int rx_enable;
5290 +} eswIoctlPortEnableConfig;
5291 +
5292 +typedef struct _eswIOCTL_IP_SNOOP_CONF {
5293 +       int mode;
5294 +       unsigned long ip_header_protocol;
5295 +} eswIoctlIpsnoopConfig;
5296 +
5297 +typedef struct _eswIOCTL_P0_FORCED_FORWARD_CONF {
5298 +       int port1;
5299 +       int port2;
5300 +       int enable;
5301 +} eswIoctlP0ForcedForwardConfig;
5302 +
5303 +typedef struct _eswIOCTL_PORT_SNOOP_CONF {
5304 +       int mode;
5305 +       unsigned short compare_port;
5306 +       int compare_num;
5307 +} eswIoctlPortsnoopConfig;
5308 +
5309 +typedef struct _eswIOCTL_PORT_Mirror_CONF {
5310 +       int mirror_port;
5311 +       int port;
5312 +       int egress_en;
5313 +       int ingress_en;
5314 +       int egress_mac_src_en;
5315 +       int egress_mac_des_en;
5316 +       int ingress_mac_src_en;
5317 +       int ingress_mac_des_en;
5318 +       unsigned char *src_mac;
5319 +       unsigned char *des_mac;
5320 +       int mirror_enable;
5321 +} eswIoctlPortMirrorConfig;
5322 +
5323 +struct eswIoctlMirrorCfgPortMatch {
5324 +       int mirror_port;
5325 +       int port_match_en;
5326 +       int port;
5327 +};
5328 +
5329 +struct eswIoctlMirrorCfgAddrMatch {
5330 +       int mirror_port;
5331 +       int addr_match_en;
5332 +       unsigned char *mac_addr;
5333 +};
5334 +
5335 +typedef struct _eswIOCTL_PRIORITY_VLAN_CONF {
5336 +       int port;
5337 +       int func_enable;
5338 +       int vlan_pri_table_num;
5339 +       int vlan_pri_table_value;
5340 +} eswIoctlPriorityVlanConfig;
5341 +
5342 +typedef struct _eswIOCTL_PRIORITY_IP_CONF {
5343 +       int port;
5344 +       int func_enable;
5345 +       int ipv4_en;
5346 +       int ip_priority_num;
5347 +       int ip_priority_value;
5348 +} eswIoctlPriorityIPConfig;
5349 +
5350 +typedef struct _eswIOCTL_PRIORITY_MAC_CONF {
5351 +       int port;
5352 +} eswIoctlPriorityMacConfig;
5353 +
5354 +typedef struct _eswIOCTL_PRIORITY_DEFAULT_CONF {
5355 +       int port;
5356 +       unsigned char priority_value;
5357 +} eswIoctlPriorityDefaultConfig;
5358 +
5359 +typedef struct _eswIOCTL_IRQ_STATUS {
5360 +       unsigned long isr;
5361 +       unsigned long imr;
5362 +       unsigned long rx_buf_pointer;
5363 +       unsigned long tx_buf_pointer;
5364 +       unsigned long rx_max_size;
5365 +       unsigned long rx_buf_active;
5366 +       unsigned long tx_buf_active;
5367 +} eswIoctlIrqStatus;
5368 +
5369 +typedef struct _eswIOCTL_PORT_Mirror_STATUS {
5370 +       unsigned long ESW_MCR;
5371 +       unsigned long ESW_EGMAP;
5372 +       unsigned long ESW_INGMAP;
5373 +       unsigned long ESW_INGSAL;
5374 +       unsigned long ESW_INGSAH;
5375 +       unsigned long ESW_INGDAL;
5376 +       unsigned long ESW_INGDAH;
5377 +       unsigned long ESW_ENGSAL;
5378 +       unsigned long ESW_ENGSAH;
5379 +       unsigned long ESW_ENGDAL;
5380 +       unsigned long ESW_ENGDAH;
5381 +       unsigned long ESW_MCVAL;
5382 +} eswIoctlPortMirrorStatus;
5383 +
5384 +typedef struct _eswIOCTL_VLAN_OUTPUT_CONF {
5385 +       int port;
5386 +       int mode;
5387 +} eswIoctlVlanOutputConfig;
5388 +
5389 +typedef struct _eswIOCTL_VLAN_INPUT_CONF {
5390 +       int port;
5391 +       int mode;
5392 +       unsigned short port_vlanid;
5393 +} eswIoctlVlanInputConfig;
5394 +
5395 +typedef struct _eswIOCTL_VLAN_DOMAIN_VERIFY_CONF {
5396 +       int port;
5397 +       int vlan_domain_verify_en;
5398 +       int vlan_discard_unknown_en;
5399 +} eswIoctlVlanVerificationConfig;
5400 +
5401 +typedef struct _eswIOCTL_VLAN_RESOULATION_TABLE {
5402 +       unsigned short port_vlanid;
5403 +       unsigned char vlan_domain_port;
5404 +       unsigned char vlan_domain_num;
5405 +} eswIoctlVlanResoultionTable;
5406 +
5407 +struct eswVlanTableItem {
5408 +       eswIoctlVlanResoultionTable table[32];
5409 +       unsigned char valid_num;
5410 +};
5411 +
5412 +typedef struct _eswIOCTL_VLAN_INPUT_STATUS {
5413 +       unsigned long ESW_VLANV;
5414 +       unsigned long ESW_PID[3];
5415 +       unsigned long ESW_VIMSEL;
5416 +       unsigned long ESW_VIMEN;
5417 +       unsigned long ESW_VRES[32];
5418 +} eswIoctlVlanInputStatus;
5419 +
5420 +typedef struct _eswIOCTL_Static_MACTable {
5421 +       unsigned char *mac_addr;
5422 +       int port;
5423 +       int priority;
5424 +} eswIoctlUpdateStaticMACtable;
5425 +
5426 +typedef struct _eswIOCTL_OUTPUT_QUEUE {
5427 +       int fun_num;
5428 +       esw_output_queue_status  sOutputQueue;
5429 +} eswIoctlOutputQueue;
5430 +
5431 +/*=============================================================*/
5432 +#define LEARNING_AGING_TIMER (10 * HZ)
5433 +/*
5434 + * Info received from Hardware Learning FIFO,
5435 + * holding MAC address and corresponding Hash Value and
5436 + * port number where the frame was received (disassembled).
5437 + */
5438 +typedef struct _eswPortInfo {
5439 +       /* MAC lower 32 bits (first byte is 7:0). */
5440 +       unsigned int   maclo;
5441 +       /* MAC upper 16 bits (47:32). */
5442 +       unsigned int   machi;
5443 +       /* the hash value for this MAC address. */
5444 +       unsigned int   hash;
5445 +       /* the port number this MAC address is associated with. */
5446 +       unsigned int   port;
5447 +} eswPortInfo;
5448 +
5449 +/*
5450 + * Hardware Look up Address Table 64-bit element.
5451 + */
5452 +typedef volatile struct _64bitTableEntry {
5453 +       unsigned int lo;  /* lower 32 bits */
5454 +       unsigned int hi;  /* upper 32 bits */
5455 +} eswTable64bitEntry;
5456 +
5457 +struct eswAddrTableEntryExample {
5458 +       /* the entry number */
5459 +       unsigned short entrynum;
5460 +       /* mac address array */
5461 +       unsigned char mac_addr[6];
5462 +       unsigned char item1;
5463 +       unsigned short item2;
5464 +};
5465 +
5466 +/*
5467 + *     Define the buffer descriptor structure.
5468 + */
5469 +typedef struct bufdesc {
5470 +       unsigned short  cbd_sc;                 /* Control and status info */
5471 +       unsigned short  cbd_datlen;             /* Data length */
5472 +       unsigned long   cbd_bufaddr;            /* Buffer address */
5473 +#ifdef MODELO_BUFFER
5474 +       unsigned long   ebd_status;
5475 +       unsigned short  length_proto_type;
5476 +       unsigned short  payload_checksum;
5477 +       unsigned long   bdu;
5478 +       unsigned long   timestamp;
5479 +       unsigned long   reserverd_word1;
5480 +       unsigned long   reserverd_word2;
5481 +#endif
5482 +} cbd_t;
5483 +
5484 +/* Forward declarations of some structures to support different PHYs
5485 + */
5486 +typedef struct {
5487 +       uint mii_data;
5488 +       void (*funct)(uint mii_reg, struct net_device *dev);
5489 +} phy_cmd_t;
5490 +
5491 +typedef struct {
5492 +       uint id;
5493 +       char *name;
5494 +
5495 +       const phy_cmd_t *config;
5496 +       const phy_cmd_t *startup;
5497 +       const phy_cmd_t *ack_int;
5498 +       const phy_cmd_t *shutdown;
5499 +} phy_info_t;
5500 +
5501 +struct port_status {
5502 +       /* 1: link is up, 0: link is down */
5503 +       int port1_link_status;
5504 +       int port2_link_status;
5505 +       /* 1: blocking, 0: unblocking */
5506 +       int port0_block_status;
5507 +       int port1_block_status;
5508 +       int port2_block_status;
5509 +};
5510 +
5511 +struct port_all_status {
5512 +       /* 1: link is up, 0: link is down */
5513 +       int link_status;
5514 +       /* 1: blocking, 0: unblocking */
5515 +       int block_status;
5516 +       /* 1: unlearning, 0: learning */
5517 +       int learn_status;
5518 +       /* vlan domain verify 1: enable 0: disable */
5519 +       int vlan_verify;
5520 +       /* discard unknow 1: enable 0: disable */
5521 +       int discard_unknown;
5522 +       /* multicast resolution 1: enable 0: disable */
5523 +       int multi_reso;
5524 +       /* broadcast resolution 1: enable 0: disalbe */
5525 +       int broad_reso;
5526 +       /* transmit 1: enable 0: disable */
5527 +       int ftransmit;
5528 +       /* receive 1: enable 0: disable */
5529 +       int freceive;
5530 +};
5531 +
5532 +/* The switch buffer descriptors track the ring buffers.  The rx_bd_base and
5533 + * tx_bd_base always point to the base of the buffer descriptors.  The
5534 + * cur_rx and cur_tx point to the currently available buffer.
5535 + * The dirty_tx tracks the current buffer that is being sent by the
5536 + * controller.  The cur_tx and dirty_tx are equal under both completely
5537 + * empty and completely full conditions.  The empty/ready indicator in
5538 + * the buffer descriptor determines the actual condition.
5539 + */
5540 +struct switch_enet_private {
5541 +       /* Hardware registers of the switch device */
5542 +       volatile switch_t  *hwp;
5543 +       volatile eswAddrTable_t  *hwentry;
5544 +
5545 +       struct net_device *netdev;
5546 +       struct platform_device *pdev;
5547 +       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
5548 +       unsigned char *tx_bounce[TX_RING_SIZE];
5549 +       struct  sk_buff *tx_skbuff[TX_RING_SIZE];
5550 +       ushort  skb_cur;
5551 +       ushort  skb_dirty;
5552 +
5553 +       /* CPM dual port RAM relative addresses.
5554 +        */
5555 +       cbd_t   *rx_bd_base;            /* Address of Rx and Tx buffers. */
5556 +       cbd_t   *tx_bd_base;
5557 +       cbd_t   *cur_rx, *cur_tx;               /* The next free ring entry */
5558 +       cbd_t   *dirty_tx;      /* The ring entries to be free()ed. */
5559 +       uint    tx_full;
5560 +       /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
5561 +       spinlock_t hw_lock;
5562 +
5563 +       /* hold while accessing the mii_list_t() elements */
5564 +       spinlock_t mii_lock;
5565 +       struct mii_bus *mdio_bus;
5566 +       struct phy_device *phydev[SWITCH_EPORT_NUMBER];
5567 +
5568 +       uint    phy_id;
5569 +       uint    phy_id_done;
5570 +       uint    phy_status;
5571 +       uint    phy_speed;
5572 +       phy_info_t const        *phy;
5573 +       struct work_struct phy_task;
5574 +       volatile switch_t  *phy_hwp;
5575 +
5576 +       uint    sequence_done;
5577 +       uint    mii_phy_task_queued;
5578 +
5579 +       uint    phy_addr;
5580 +
5581 +       int     index;
5582 +       int     opened;
5583 +       int     full_duplex;
5584 +       int     msg_enable;
5585 +       int     phy1_link;
5586 +       int     phy1_old_link;
5587 +       int     phy1_duplex;
5588 +       int     phy1_speed;
5589 +
5590 +       int     phy2_link;
5591 +       int     phy2_old_link;
5592 +       int     phy2_duplex;
5593 +       int     phy2_speed;
5594 +       /* --------------Statistics--------------------------- */
5595 +       /* when a new element deleted a element with in
5596 +        * a block due to lack of space */
5597 +       int atBlockOverflows;
5598 +       /* Peak number of valid entries in the address table */
5599 +       int atMaxEntries;
5600 +       /* current number of valid entries in the address table */
5601 +       int atCurrEntries;
5602 +       /* maximum entries within a block found
5603 +        * (updated within ageing)*/
5604 +       int atMaxEntriesPerBlock;
5605 +
5606 +       /* -------------------ageing function------------------ */
5607 +       /* maximum age allowed for an entry */
5608 +       int ageMax;
5609 +       /* last LUT entry to block that was
5610 +        * inspected by the Ageing task*/
5611 +       int ageLutIdx;
5612 +       /* last element within block inspected by the Ageing task */
5613 +       int ageBlockElemIdx;
5614 +       /* complete table has been processed by ageing process */
5615 +       int ageCompleted;
5616 +       /* delay setting */
5617 +       int ageDelay;
5618 +       /* current delay Counter */
5619 +       int  ageDelayCnt;
5620 +
5621 +       /* ----------------timer related---------------------------- */
5622 +       /* current time (for timestamping) */
5623 +       int currTime;
5624 +       /* flag set by timer when currTime changed
5625 +        * and cleared by serving function*/
5626 +       int timeChanged;
5627 +
5628 +       /**/
5629 +       /* Timer for Aging */
5630 +       struct timer_list       timer_aging;
5631 +       int learning_irqhandle_enable;
5632 +};
5633 +
5634 +struct switch_platform_private {
5635 +       unsigned long           quirks;
5636 +       int                     num_slots;      /* Slots on controller */
5637 +       struct switch_enet_private *fep_host[0];      /* Pointers to hosts */
5638 +};
5639 +
5640 +/******************************************************************************/
5641 +/* Recieve is empty */
5642 +#define BD_SC_EMPTY     ((unsigned short)0x8000)
5643 +/* Transmit is ready */
5644 +#define BD_SC_READY     ((unsigned short)0x8000)
5645 +/* Last buffer descriptor */
5646 +#define BD_SC_WRAP      ((unsigned short)0x2000)
5647 +/* Interrupt on change */
5648 +#define BD_SC_INTRPT    ((unsigned short)0x1000)
5649 +/* Continous mode */
5650 +#define BD_SC_CM        ((unsigned short)0x0200)
5651 +/* Rec'd too many idles */
5652 +#define BD_SC_ID        ((unsigned short)0x0100)
5653 +/* xmt preamble */
5654 +#define BD_SC_P         ((unsigned short)0x0100)
5655 +/* Break received */
5656 +#define BD_SC_BR        ((unsigned short)0x0020)
5657 +/* Framing error */
5658 +#define BD_SC_FR        ((unsigned short)0x0010)
5659 +/* Parity error */
5660 +#define BD_SC_PR        ((unsigned short)0x0008)
5661 +/* Overrun */
5662 +#define BD_SC_OV        ((unsigned short)0x0002)
5663 +#define BD_SC_CD        ((unsigned short)0x0001)
5664 +
5665 +/* Buffer descriptor control/status used by Ethernet receive.
5666 +*/
5667 +#define BD_ENET_RX_EMPTY        ((unsigned short)0x8000)
5668 +#define BD_ENET_RX_WRAP         ((unsigned short)0x2000)
5669 +#define BD_ENET_RX_INTR         ((unsigned short)0x1000)
5670 +#define BD_ENET_RX_LAST         ((unsigned short)0x0800)
5671 +#define BD_ENET_RX_FIRST        ((unsigned short)0x0400)
5672 +#define BD_ENET_RX_MISS         ((unsigned short)0x0100)
5673 +#define BD_ENET_RX_LG           ((unsigned short)0x0020)
5674 +#define BD_ENET_RX_NO           ((unsigned short)0x0010)
5675 +#define BD_ENET_RX_SH           ((unsigned short)0x0008)
5676 +#define BD_ENET_RX_CR           ((unsigned short)0x0004)
5677 +#define BD_ENET_RX_OV           ((unsigned short)0x0002)
5678 +#define BD_ENET_RX_CL           ((unsigned short)0x0001)
5679 +/* All status bits */
5680 +#define BD_ENET_RX_STATS        ((unsigned short)0x013f)
5681 +
5682 +/* Buffer descriptor control/status used by Ethernet transmit.
5683 +*/
5684 +#define BD_ENET_TX_READY        ((unsigned short)0x8000)
5685 +#define BD_ENET_TX_PAD          ((unsigned short)0x4000)
5686 +#define BD_ENET_TX_WRAP         ((unsigned short)0x2000)
5687 +#define BD_ENET_TX_INTR         ((unsigned short)0x1000)
5688 +#define BD_ENET_TX_LAST         ((unsigned short)0x0800)
5689 +#define BD_ENET_TX_TC           ((unsigned short)0x0400)
5690 +#define BD_ENET_TX_DEF          ((unsigned short)0x0200)
5691 +#define BD_ENET_TX_HB           ((unsigned short)0x0100)
5692 +#define BD_ENET_TX_LC           ((unsigned short)0x0080)
5693 +#define BD_ENET_TX_RL           ((unsigned short)0x0040)
5694 +#define BD_ENET_TX_RCMASK       ((unsigned short)0x003c)
5695 +#define BD_ENET_TX_UN           ((unsigned short)0x0002)
5696 +#define BD_ENET_TX_CSL          ((unsigned short)0x0001)
5697 +/* All status bits */
5698 +#define BD_ENET_TX_STATS        ((unsigned short)0x03ff)
5699 +
5700 +/*Copy from validation code */
5701 +#define RX_BUFFER_SIZE 1520
5702 +#define TX_BUFFER_SIZE 1520
5703 +#define NUM_RXBDS 20
5704 +#define NUM_TXBDS 20
5705 +
5706 +#define TX_BD_R                 0x8000
5707 +#define TX_BD_TO1               0x4000
5708 +#define TX_BD_W                 0x2000
5709 +#define TX_BD_TO2               0x1000
5710 +#define TX_BD_L                 0x0800
5711 +#define TX_BD_TC                0x0400
5712 +
5713 +#define TX_BD_INT       0x40000000
5714 +#define TX_BD_TS        0x20000000
5715 +#define TX_BD_PINS      0x10000000
5716 +#define TX_BD_IINS      0x08000000
5717 +#define TX_BD_TXE       0x00008000
5718 +#define TX_BD_UE        0x00002000
5719 +#define TX_BD_EE        0x00001000
5720 +#define TX_BD_FE        0x00000800
5721 +#define TX_BD_LCE       0x00000400
5722 +#define TX_BD_OE        0x00000200
5723 +#define TX_BD_TSE       0x00000100
5724 +#define TX_BD_BDU       0x80000000
5725 +
5726 +#define RX_BD_E                 0x8000
5727 +#define RX_BD_R01               0x4000
5728 +#define RX_BD_W                 0x2000
5729 +#define RX_BD_R02               0x1000
5730 +#define RX_BD_L                 0x0800
5731 +#define RX_BD_M                 0x0100
5732 +#define RX_BD_BC                0x0080
5733 +#define RX_BD_MC                0x0040
5734 +#define RX_BD_LG                0x0020
5735 +#define RX_BD_NO                0x0010
5736 +#define RX_BD_CR                0x0004
5737 +#define RX_BD_OV                0x0002
5738 +#define RX_BD_TR                0x0001
5739 +
5740 +#define RX_BD_ME               0x80000000
5741 +#define RX_BD_PE               0x04000000
5742 +#define RX_BD_CE               0x02000000
5743 +#define RX_BD_UC               0x01000000
5744 +#define RX_BD_INT              0x00800000
5745 +#define RX_BD_ICE              0x00000020
5746 +#define RX_BD_PCR              0x00000010
5747 +#define RX_BD_VLAN             0x00000004
5748 +#define RX_BD_IPV6             0x00000002
5749 +#define RX_BD_FRAG             0x00000001
5750 +#define RX_BD_BDU              0x80000000
5751 +/****************************************************************************/
5752 +
5753 +/* Address Table size in bytes(2048 64bit entry ) */
5754 +#define ESW_ATABLE_MEM_SIZE         (2048*8)
5755 +/* How many 64-bit elements fit in the address table */
5756 +#define ESW_ATABLE_MEM_NUM_ENTRIES  (2048)
5757 +/* Address Table Maximum number of entries in each Slot */
5758 +#define ATABLE_ENTRY_PER_SLOT 8
5759 +/* log2(ATABLE_ENTRY_PER_SLOT)*/
5760 +#define ATABLE_ENTRY_PER_SLOT_bits 3
5761 +/* entry size in byte */
5762 +#define ATABLE_ENTRY_SIZE     8
5763 +/*  slot size in byte */
5764 +#define ATABLE_SLOT_SIZE    (ATABLE_ENTRY_PER_SLOT * ATABLE_ENTRY_SIZE)
5765 +/* width of timestamp variable (bits) within address table entry */
5766 +#define AT_DENTRY_TIMESTAMP_WIDTH    10
5767 +/* number of bits for port number storage */
5768 +#define AT_DENTRY_PORT_WIDTH     4
5769 +/* number of bits for port bitmask number storage */
5770 +#define AT_SENTRY_PORT_WIDTH     7
5771 +/* address table static entry port bitmask start address bit */
5772 +#define AT_SENTRY_PORTMASK_shift     21
5773 +/* number of bits for port priority storage */
5774 +#define AT_SENTRY_PRIO_WIDTH   7
5775 +/* address table static entry priority start address bit */
5776 +#define AT_SENTRY_PRIO_shift     18
5777 +/* address table dynamic entry port start address bit */
5778 +#define AT_DENTRY_PORT_shift     28
5779 +/* address table dynamic entry timestamp start address bit */
5780 +#define AT_DENTRY_TIME_shift     18
5781 +/* address table entry record type start address bit */
5782 +#define AT_ENTRY_TYPE_shift     17
5783 +/* address table entry record type bit: 1 static, 0 dynamic */
5784 +#define AT_ENTRY_TYPE_STATIC      1
5785 +#define AT_ENTRY_TYPE_DYNAMIC     0
5786 +/* address table entry record valid start address bit */
5787 +#define AT_ENTRY_VALID_shift     16
5788 +#define AT_ENTRY_RECORD_VALID     1
5789 +
5790 +#define AT_EXTRACT_VALID(x)   \
5791 +       ((x >> AT_ENTRY_VALID_shift) & AT_ENTRY_RECORD_VALID)
5792 +
5793 +#define AT_EXTRACT_PORTMASK(x)  \
5794 +       ((x >> AT_SENTRY_PORTMASK_shift) & AT_SENTRY_PORT_WIDTH)
5795 +
5796 +#define AT_EXTRACT_PRIO(x)  \
5797 +       ((x >> AT_SENTRY_PRIO_shift) & AT_SENTRY_PRIO_WIDTH)
5798 +
5799 +/* return block corresponding to the 8 bit hash value calculated */
5800 +#define GET_BLOCK_PTR(hash)  (hash << 3)
5801 +#define AT_EXTRACT_TIMESTAMP(x) \
5802 +       ((x >> AT_DENTRY_TIME_shift) & ((1 << AT_DENTRY_TIMESTAMP_WIDTH)-1))
5803 +#define AT_EXTRACT_PORT(x)   \
5804 +       ((x >> AT_DENTRY_PORT_shift) & ((1 << AT_DENTRY_PORT_WIDTH)-1))
5805 +#define AT_SEXTRACT_PORT(x)  \
5806 +       ((~((x >> AT_SENTRY_PORTMASK_shift) &  \
5807 +          ((1 << AT_DENTRY_PORT_WIDTH)-1))) >> 1)
5808 +#define TIMEDELTA(newtime, oldtime) \
5809 +        ((newtime - oldtime) & \
5810 +         ((1 << AT_DENTRY_TIMESTAMP_WIDTH)-1))
5811 +
5812 +#define AT_EXTRACT_IP_PROTOCOL(x) ((x >> 8) & 0xff)
5813 +#define AT_EXTRACT_TCP_UDP_PORT(x) ((x >> 16) & 0xffff)
5814 +
5815 +/* increment time value respecting modulo. */
5816 +#define TIMEINCREMENT(time) \
5817 +       ((time) = ((time)+1) & ((1 << AT_DENTRY_TIMESTAMP_WIDTH)-1))
5818 +/* ------------------------------------------------------------------------- */
5819 +/* Bit definitions and macros for MCF_ESW_REVISION */
5820 +#define MCF_ESW_REVISION_CORE_REVISION(x)      (((x)&0x0000FFFF)<<0)
5821 +#define MCF_ESW_REVISION_CUSTOMER_REVISION(x)  (((x)&0x0000FFFF)<<16)
5822 +
5823 +/* Bit definitions and macros for MCF_ESW_PER */
5824 +#define MCF_ESW_PER_TE0                        (0x00000001)
5825 +#define MCF_ESW_PER_TE1                        (0x00000002)
5826 +#define MCF_ESW_PER_TE2                        (0x00000004)
5827 +#define MCF_ESW_PER_RE0                        (0x00010000)
5828 +#define MCF_ESW_PER_RE1                        (0x00020000)
5829 +#define MCF_ESW_PER_RE2                        (0x00040000)
5830 +
5831 +/* Bit definitions and macros for MCF_ESW_VLANV */
5832 +#define MCF_ESW_VLANV_VV0                      (0x00000001)
5833 +#define MCF_ESW_VLANV_VV1                      (0x00000002)
5834 +#define MCF_ESW_VLANV_VV2                      (0x00000004)
5835 +#define MCF_ESW_VLANV_DU0                      (0x00010000)
5836 +#define MCF_ESW_VLANV_DU1                      (0x00020000)
5837 +#define MCF_ESW_VLANV_DU2                      (0x00040000)
5838 +
5839 +/* Bit definitions and macros for MCF_ESW_DBCR */
5840 +#define MCF_ESW_DBCR_P0                        (0x00000001)
5841 +#define MCF_ESW_DBCR_P1                        (0x00000002)
5842 +#define MCF_ESW_DBCR_P2                        (0x00000004)
5843 +
5844 +/* Bit definitions and macros for MCF_ESW_DMCR */
5845 +#define MCF_ESW_DMCR_P0                        (0x00000001)
5846 +#define MCF_ESW_DMCR_P1                        (0x00000002)
5847 +#define MCF_ESW_DMCR_P2                        (0x00000004)
5848 +
5849 +/* Bit definitions and macros for MCF_ESW_BKLR */
5850 +#define MCF_ESW_BKLR_BE0                       (0x00000001)
5851 +#define MCF_ESW_BKLR_BE1                       (0x00000002)
5852 +#define MCF_ESW_BKLR_BE2                       (0x00000004)
5853 +#define MCF_ESW_BKLR_LD0                       (0x00010000)
5854 +#define MCF_ESW_BKLR_LD1                       (0x00020000)
5855 +#define MCF_ESW_BKLR_LD2                       (0x00040000)
5856 +
5857 +/* Bit definitions and macros for MCF_ESW_BMPC */
5858 +#define MCF_ESW_BMPC_PORT(x)                   (((x)&0x0000000F)<<0)
5859 +#define MCF_ESW_BMPC_MSG_TX                    (0x00000020)
5860 +#define MCF_ESW_BMPC_EN                        (0x00000040)
5861 +#define MCF_ESW_BMPC_DIS                       (0x00000080)
5862 +#define MCF_ESW_BMPC_PRIORITY(x)               (((x)&0x00000007)<<13)
5863 +#define MCF_ESW_BMPC_PORTMASK(x)               (((x)&0x00000007)<<16)
5864 +
5865 +/* Bit definitions and macros for MCF_ESW_MODE */
5866 +#define MCF_ESW_MODE_SW_RST                    (0x00000001)
5867 +#define MCF_ESW_MODE_SW_EN                     (0x00000002)
5868 +#define MCF_ESW_MODE_STOP                      (0x00000080)
5869 +#define MCF_ESW_MODE_CRC_TRAN                  (0x00000100)
5870 +#define MCF_ESW_MODE_P0CT                      (0x00000200)
5871 +#define MCF_ESW_MODE_STATRST                   (0x80000000)
5872 +
5873 +/* Bit definitions and macros for MCF_ESW_VIMSEL */
5874 +#define MCF_ESW_VIMSEL_IM0(x)                  (((x)&0x00000003)<<0)
5875 +#define MCF_ESW_VIMSEL_IM1(x)                  (((x)&0x00000003)<<2)
5876 +#define MCF_ESW_VIMSEL_IM2(x)                  (((x)&0x00000003)<<4)
5877 +
5878 +/* Bit definitions and macros for MCF_ESW_VOMSEL */
5879 +#define MCF_ESW_VOMSEL_OM0(x)                  (((x)&0x00000003)<<0)
5880 +#define MCF_ESW_VOMSEL_OM1(x)                  (((x)&0x00000003)<<2)
5881 +#define MCF_ESW_VOMSEL_OM2(x)                  (((x)&0x00000003)<<4)
5882 +
5883 +/* Bit definitions and macros for MCF_ESW_VIMEN */
5884 +#define MCF_ESW_VIMEN_EN0                      (0x00000001)
5885 +#define MCF_ESW_VIMEN_EN1                      (0x00000002)
5886 +#define MCF_ESW_VIMEN_EN2                      (0x00000004)
5887 +
5888 +/* Bit definitions and macros for MCF_ESW_VID */
5889 +#define MCF_ESW_VID_TAG(x)                     (((x)&0xFFFFFFFF)<<0)
5890 +
5891 +/* Bit definitions and macros for MCF_ESW_MCR */
5892 +#define MCF_ESW_MCR_PORT(x)                    (((x)&0x0000000F)<<0)
5893 +#define MCF_ESW_MCR_MEN                        (0x00000010)
5894 +#define MCF_ESW_MCR_INGMAP                     (0x00000020)
5895 +#define MCF_ESW_MCR_EGMAP                      (0x00000040)
5896 +#define MCF_ESW_MCR_INGSA                      (0x00000080)
5897 +#define MCF_ESW_MCR_INGDA                      (0x00000100)
5898 +#define MCF_ESW_MCR_EGSA                       (0x00000200)
5899 +#define MCF_ESW_MCR_EGDA                       (0x00000400)
5900 +
5901 +/* Bit definitions and macros for MCF_ESW_EGMAP */
5902 +#define MCF_ESW_EGMAP_EG0                      (0x00000001)
5903 +#define MCF_ESW_EGMAP_EG1                      (0x00000002)
5904 +#define MCF_ESW_EGMAP_EG2                      (0x00000004)
5905 +
5906 +/* Bit definitions and macros for MCF_ESW_INGMAP */
5907 +#define MCF_ESW_INGMAP_ING0                    (0x00000001)
5908 +#define MCF_ESW_INGMAP_ING1                    (0x00000002)
5909 +#define MCF_ESW_INGMAP_ING2                    (0x00000004)
5910 +
5911 +/* Bit definitions and macros for MCF_ESW_INGSAL */
5912 +#define MCF_ESW_INGSAL_ADDLOW(x)               (((x)&0xFFFFFFFF)<<0)
5913 +
5914 +/* Bit definitions and macros for MCF_ESW_INGSAH */
5915 +#define MCF_ESW_INGSAH_ADDHIGH(x)              (((x)&0x0000FFFF)<<0)
5916 +
5917 +/* Bit definitions and macros for MCF_ESW_INGDAL */
5918 +#define MCF_ESW_INGDAL_ADDLOW(x)               (((x)&0xFFFFFFFF)<<0)
5919 +
5920 +/* Bit definitions and macros for MCF_ESW_INGDAH */
5921 +#define MCF_ESW_INGDAH_ADDHIGH(x)              (((x)&0x0000FFFF)<<0)
5922 +
5923 +/* Bit definitions and macros for MCF_ESW_ENGSAL */
5924 +#define MCF_ESW_ENGSAL_ADDLOW(x)               (((x)&0xFFFFFFFF)<<0)
5925 +
5926 +/* Bit definitions and macros for MCF_ESW_ENGSAH */
5927 +#define MCF_ESW_ENGSAH_ADDHIGH(x)              (((x)&0x0000FFFF)<<0)
5928 +
5929 +/* Bit definitions and macros for MCF_ESW_ENGDAL */
5930 +#define MCF_ESW_ENGDAL_ADDLOW(x)               (((x)&0xFFFFFFFF)<<0)
5931 +
5932 +/* Bit definitions and macros for MCF_ESW_ENGDAH */
5933 +#define MCF_ESW_ENGDAH_ADDHIGH(x)              (((x)&0x0000FFFF)<<0)
5934 +
5935 +/* Bit definitions and macros for MCF_ESW_MCVAL */
5936 +#define MCF_ESW_MCVAL_COUNT(x)                 (((x)&0x000000FF)<<0)
5937 +
5938 +/* Bit definitions and macros for MCF_ESW_MMSR */
5939 +#define MCF_ESW_MMSR_BUSY                      (0x00000001)
5940 +#define MCF_ESW_MMSR_NOCELL                    (0x00000002)
5941 +#define MCF_ESW_MMSR_MEMFULL                   (0x00000004)
5942 +#define MCF_ESW_MMSR_MFLATCH                   (0x00000008)
5943 +#define MCF_ESW_MMSR_DQ_GRNT                   (0x00000040)
5944 +#define MCF_ESW_MMSR_CELLS_AVAIL(x)            (((x)&0x000000FF)<<16)
5945 +
5946 +/* Bit definitions and macros for MCF_ESW_LMT */
5947 +#define MCF_ESW_LMT_THRESH(x)                  (((x)&0x000000FF)<<0)
5948 +
5949 +/* Bit definitions and macros for MCF_ESW_LFC */
5950 +#define MCF_ESW_LFC_COUNT(x)                   (((x)&0xFFFFFFFF)<<0)
5951 +
5952 +/* Bit definitions and macros for MCF_ESW_PCSR */
5953 +#define MCF_ESW_PCSR_PC0                       (0x00000001)
5954 +#define MCF_ESW_PCSR_PC1                       (0x00000002)
5955 +#define MCF_ESW_PCSR_PC2                       (0x00000004)
5956 +
5957 +/* Bit definitions and macros for MCF_ESW_IOSR */
5958 +#define MCF_ESW_IOSR_OR0                       (0x00000001)
5959 +#define MCF_ESW_IOSR_OR1                       (0x00000002)
5960 +#define MCF_ESW_IOSR_OR2                       (0x00000004)
5961 +
5962 +/* Bit definitions and macros for MCF_ESW_QWT */
5963 +#define MCF_ESW_QWT_Q0WT(x)                    (((x)&0x0000001F)<<0)
5964 +#define MCF_ESW_QWT_Q1WT(x)                    (((x)&0x0000001F)<<8)
5965 +#define MCF_ESW_QWT_Q2WT(x)                    (((x)&0x0000001F)<<16)
5966 +#define MCF_ESW_QWT_Q3WT(x)                    (((x)&0x0000001F)<<24)
5967 +
5968 +/* Bit definitions and macros for MCF_ESW_P0BCT */
5969 +#define MCF_ESW_P0BCT_THRESH(x)                (((x)&0x000000FF)<<0)
5970 +
5971 +/* Bit definitions and macros for MCF_ESW_P0FFEN */
5972 +#define MCF_ESW_P0FFEN_FEN                     (0x00000001)
5973 +#define MCF_ESW_P0FFEN_FD(x)                   (((x)&0x00000003)<<2)
5974 +
5975 +/* Bit definitions and macros for MCF_ESW_PSNP */
5976 +#define MCF_ESW_PSNP_EN                        (0x00000001)
5977 +#define MCF_ESW_PSNP_MODE(x)                   (((x)&0x00000003)<<1)
5978 +#define MCF_ESW_PSNP_CD                        (0x00000008)
5979 +#define MCF_ESW_PSNP_CS                        (0x00000010)
5980 +#define MCF_ESW_PSNP_PORT_COMPARE(x)           (((x)&0x0000FFFF)<<16)
5981 +
5982 +/* Bit definitions and macros for MCF_ESW_IPSNP */
5983 +#define MCF_ESW_IPSNP_EN                       (0x00000001)
5984 +#define MCF_ESW_IPSNP_MODE(x)                  (((x)&0x00000003)<<1)
5985 +#define MCF_ESW_IPSNP_PROTOCOL(x)              (((x)&0x000000FF)<<8)
5986 +
5987 +/* Bit definitions and macros for MCF_ESW_PVRES */
5988 +#define MCF_ESW_PVRES_PRI0(x)                  (((x)&0x00000007)<<0)
5989 +#define MCF_ESW_PVRES_PRI1(x)                  (((x)&0x00000007)<<3)
5990 +#define MCF_ESW_PVRES_PRI2(x)                  (((x)&0x00000007)<<6)
5991 +#define MCF_ESW_PVRES_PRI3(x)                  (((x)&0x00000007)<<9)
5992 +#define MCF_ESW_PVRES_PRI4(x)                  (((x)&0x00000007)<<12)
5993 +#define MCF_ESW_PVRES_PRI5(x)                  (((x)&0x00000007)<<15)
5994 +#define MCF_ESW_PVRES_PRI6(x)                  (((x)&0x00000007)<<18)
5995 +#define MCF_ESW_PVRES_PRI7(x)                  (((x)&0x00000007)<<21)
5996 +
5997 +/* Bit definitions and macros for MCF_ESW_IPRES */
5998 +#define MCF_ESW_IPRES_ADDRESS(x)               (((x)&0x000000FF)<<0)
5999 +#define MCF_ESW_IPRES_IPV4SEL                  (0x00000100)
6000 +#define MCF_ESW_IPRES_PRI0(x)                  (((x)&0x00000003)<<9)
6001 +#define MCF_ESW_IPRES_PRI1(x)                  (((x)&0x00000003)<<11)
6002 +#define MCF_ESW_IPRES_PRI2(x)                   (((x)&0x00000003)<<13)
6003 +#define MCF_ESW_IPRES_READ                     (0x80000000)
6004 +
6005 +/* Bit definitions and macros for MCF_ESW_PRES */
6006 +#define MCF_ESW_PRES_VLAN                      (0x00000001)
6007 +#define MCF_ESW_PRES_IP                        (0x00000002)
6008 +#define MCF_ESW_PRES_MAC                       (0x00000004)
6009 +#define MCF_ESW_PRES_DFLT_PRI(x)               (((x)&0x00000007)<<4)
6010 +
6011 +/* Bit definitions and macros for MCF_ESW_PID */
6012 +#define MCF_ESW_PID_VLANID(x)                  (((x)&0x0000FFFF)<<0)
6013 +
6014 +/* Bit definitions and macros for MCF_ESW_VRES */
6015 +#define MCF_ESW_VRES_P0                        (0x00000001)
6016 +#define MCF_ESW_VRES_P1                        (0x00000002)
6017 +#define MCF_ESW_VRES_P2                        (0x00000004)
6018 +#define MCF_ESW_VRES_VLANID(x)                 (((x)&0x00000FFF)<<3)
6019 +
6020 +/* Bit definitions and macros for MCF_ESW_DISCN */
6021 +#define MCF_ESW_DISCN_COUNT(x)                 (((x)&0xFFFFFFFF)<<0)
6022 +
6023 +/* Bit definitions and macros for MCF_ESW_DISCB */
6024 +#define MCF_ESW_DISCB_COUNT(x)                 (((x)&0xFFFFFFFF)<<0)
6025 +
6026 +/* Bit definitions and macros for MCF_ESW_NDISCN */
6027 +#define MCF_ESW_NDISCN_COUNT(x)                (((x)&0xFFFFFFFF)<<0)
6028 +
6029 +/* Bit definitions and macros for MCF_ESW_NDISCB */
6030 +#define MCF_ESW_NDISCB_COUNT(x)                (((x)&0xFFFFFFFF)<<0)
6031 +
6032 +/* Bit definitions and macros for MCF_ESW_POQC */
6033 +#define MCF_ESW_POQC_COUNT(x)                  (((x)&0xFFFFFFFF)<<0)
6034 +
6035 +/* Bit definitions and macros for MCF_ESW_PMVID */
6036 +#define MCF_ESW_PMVID_COUNT(x)                 (((x)&0xFFFFFFFF)<<0)
6037 +
6038 +/* Bit definitions and macros for MCF_ESW_PMVTAG */
6039 +#define MCF_ESW_PMVTAG_COUNT(x)                (((x)&0xFFFFFFFF)<<0)
6040 +
6041 +/* Bit definitions and macros for MCF_ESW_PBL */
6042 +#define MCF_ESW_PBL_COUNT(x)                   (((x)&0xFFFFFFFF)<<0)
6043 +
6044 +/* Bit definitions and macros for MCF_ESW_ISR */
6045 +#define MCF_ESW_ISR_EBERR                      (0x00000001)
6046 +#define MCF_ESW_ISR_RXB                        (0x00000002)
6047 +#define MCF_ESW_ISR_RXF                        (0x00000004)
6048 +#define MCF_ESW_ISR_TXB                        (0x00000008)
6049 +#define MCF_ESW_ISR_TXF                        (0x00000010)
6050 +#define MCF_ESW_ISR_QM                         (0x00000020)
6051 +#define MCF_ESW_ISR_OD0                        (0x00000040)
6052 +#define MCF_ESW_ISR_OD1                        (0x00000080)
6053 +#define MCF_ESW_ISR_OD2                        (0x00000100)
6054 +#define MCF_ESW_ISR_LRN                        (0x00000200)
6055 +
6056 +/* Bit definitions and macros for MCF_ESW_IMR */
6057 +#define MCF_ESW_IMR_EBERR                      (0x00000001)
6058 +#define MCF_ESW_IMR_RXB                        (0x00000002)
6059 +#define MCF_ESW_IMR_RXF                        (0x00000004)
6060 +#define MCF_ESW_IMR_TXB                        (0x00000008)
6061 +#define MCF_ESW_IMR_TXF                        (0x00000010)
6062 +#define MCF_ESW_IMR_QM                         (0x00000020)
6063 +#define MCF_ESW_IMR_OD0                        (0x00000040)
6064 +#define MCF_ESW_IMR_OD1                        (0x00000080)
6065 +#define MCF_ESW_IMR_OD2                        (0x00000100)
6066 +#define MCF_ESW_IMR_LRN                        (0x00000200)
6067 +
6068 +/* Bit definitions and macros for MCF_ESW_RDSR */
6069 +#define MCF_ESW_RDSR_ADDRESS(x)                (((x)&0x3FFFFFFF)<<2)
6070 +
6071 +/* Bit definitions and macros for MCF_ESW_TDSR */
6072 +#define MCF_ESW_TDSR_ADDRESS(x)                (((x)&0x3FFFFFFF)<<2)
6073 +
6074 +/* Bit definitions and macros for MCF_ESW_MRBR */
6075 +#define MCF_ESW_MRBR_SIZE(x)                   (((x)&0x000003FF)<<4)
6076 +
6077 +/* Bit definitions and macros for MCF_ESW_RDAR */
6078 +#define MCF_ESW_RDAR_R_DES_ACTIVE              (0x01000000)
6079 +
6080 +/* Bit definitions and macros for MCF_ESW_TDAR */
6081 +#define MCF_ESW_TDAR_X_DES_ACTIVE              (0x01000000)
6082 +
6083 +/* Bit definitions and macros for MCF_ESW_LREC0 */
6084 +#define MCF_ESW_LREC0_MACADDR0(x)              (((x)&0xFFFFFFFF)<<0)
6085 +
6086 +/* Bit definitions and macros for MCF_ESW_LREC1 */
6087 +#define MCF_ESW_LREC1_MACADDR1(x)              (((x)&0x0000FFFF)<<0)
6088 +#define MCF_ESW_LREC1_HASH(x)                  (((x)&0x000000FF)<<16)
6089 +#define MCF_ESW_LREC1_SWPORT(x)                (((x)&0x00000003)<<24)
6090 +
6091 +/* Bit definitions and macros for MCF_ESW_LSR */
6092 +#define MCF_ESW_LSR_DA                         (0x00000001)
6093 +
6094 +/* port mirroring port number match */
6095 +#define MIRROR_EGRESS_PORT_MATCH               1
6096 +#define MIRROR_INGRESS_PORT_MATCH              2
6097 +
6098 +/* port mirroring mac address match */
6099 +#define MIRROR_EGRESS_SOURCE_MATCH             1
6100 +#define MIRROR_INGRESS_SOURCE_MATCH            2
6101 +#define MIRROR_EGRESS_DESTINATION_MATCH                3
6102 +#define MIRROR_INGRESS_DESTINATION_MATCH       4
6103 +
6104 +#endif /* SWITCH_H */
6105 --- a/include/linux/fsl_devices.h
6106 +++ b/include/linux/fsl_devices.h
6107 @@ -129,4 +129,21 @@ struct fsl_ata_platform_data {
6108         void    (*exit)(void);
6109         int     (*get_clk_rate)(void);
6110  };
6111 +
6112 +struct net_device;
6113 +struct coldfire_switch_platform_data {
6114 +       int     hash_table;
6115 +       unsigned int *switch_hw;
6116 +       void    (*request_intrs)(struct net_device *dev,
6117 +               irqreturn_t (*)(int, void *),
6118 +               void *irq_privatedata);
6119 +       void    (*set_mii)(struct net_device *dev);
6120 +       void    (*get_mac)(struct net_device *dev);
6121 +       void    (*enable_phy_intr)(void);
6122 +       void    (*disable_phy_intr)(void);
6123 +       void    (*phy_ack_intr)(void);
6124 +       void    (*localhw_setup)(void);
6125 +       void    (*uncache)(unsigned long addr);
6126 +       void    (*platform_flush_cache)(void);
6127 +};
6128  #endif /* _FSL_DEVICE_H_ */
6129 --- a/net/core/dev.c
6130 +++ b/net/core/dev.c
6131 @@ -4756,6 +4756,10 @@ static int dev_ifsioc(struct net *net, s
6132         default:
6133                 if ((cmd >= SIOCDEVPRIVATE &&
6134                     cmd <= SIOCDEVPRIVATE + 15) ||
6135 +#if defined(CONFIG_MODELO_SWITCH)
6136 +                       (cmd >= 0x9101 &&
6137 +                        cmd <= 0x92ff) ||
6138 +#endif
6139                     cmd == SIOCBONDENSLAVE ||
6140                     cmd == SIOCBONDRELEASE ||
6141                     cmd == SIOCBONDSETHWADDR ||
6142 @@ -4948,6 +4952,10 @@ int dev_ioctl(struct net *net, unsigned
6143          */
6144         default:
6145                 if (cmd == SIOCWANDEV ||
6146 +#if defined(CONFIG_MODELO_SWITCH)
6147 +                       (cmd >= 0x9101 &&
6148 +                        cmd <= 0x92ff) ||
6149 +#endif
6150                     (cmd >= SIOCDEVPRIVATE &&
6151                      cmd <= SIOCDEVPRIVATE + 15)) {
6152                         dev_load(net, ifr.ifr_name);