54a70622e49ac41fa584a2cc955c0ced3a1bdad1
[openwrt.git] / target / linux / amazon / files / drivers / net / amazon_sw.c
1 /*
2  *   This program is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or
5  *   (at your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15  */
16 //-----------------------------------------------------------------------
17 /*
18  * Description:
19  *      Driver for Infineon Amazon 3 port switch
20  */
21 //-----------------------------------------------------------------------
22 /* Author:      Wu Qi Ming[Qi-Ming.Wu@infineon.com]
23  * Created:     7-April-2004
24  */
25 //-----------------------------------------------------------------------
26 /* History
27  * Changed on: Jun 28, 2004
28  * Changed by: peng.liu@infineon.com
29  * Reason:      add hardware flow control (HFC) (CONFIG_NET_HW_FLOWCONTROL)
30  *
31  * Changed on: Apr 6, 2005
32  * Changed by: mars.lin@infineon.com
33  * Reason    : supoort port identification
34  */
35
36
37 // copyright 2004-2005 infineon.com
38
39 // copyright 2007 john crispin <blogic@openwrt.org>
40 // copyright 2007 felix fietkau <nbd@openwrt.org>
41 // copyright 2009 hauke mehrtens <hauke@hauke-m.de>
42
43
44 // TODO
45 //              port vlan code from bcrm target... the tawainese code was scrapped due to crappyness
46 //              check all the mmi reg settings and possibly document them better
47 //              verify the ethtool code
48 //              remove the while(1) stuff
49 //              further clean up and rework ... but it works for now
50 //              check the mode[]=bridge stuff
51 //              verify that the ethaddr can be set from u-boot
52
53
54 #ifndef __KERNEL__
55 #define __KERNEL__
56 #endif
57
58
59 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
60 #define MODVERSIONS
61 #endif
62
63 #if defined(MODVERSIONS) && !defined(__GENKSYMS__)
64 #include <linux/modversions.h>
65 #endif
66
67 #include <linux/module.h>
68 #include <linux/string.h>
69 #include <linux/sched.h>
70 #include <linux/kernel.h>
71 #include <linux/slab.h>
72 #include <linux/errno.h>
73 #include <linux/types.h>
74 #include <linux/interrupt.h>
75 #include <linux/mii.h>
76 #include <asm/uaccess.h>
77 #include <linux/in.h>
78 #include <linux/netdevice.h>
79 #include <linux/etherdevice.h>
80 #include <linux/ip.h>
81 #include <linux/tcp.h>
82 #include <linux/skbuff.h>
83 #include <linux/in6.h>
84 #include <linux/proc_fs.h>
85 #include <linux/mm.h>
86 #include <linux/ethtool.h>
87 #include <asm/checksum.h>
88 #include <linux/init.h>
89 #include <linux/platform_device.h>
90
91 #include <asm/amazon/amazon.h>
92 #include <asm/amazon/amazon_dma.h>
93 #include <asm/amazon/amazon_sw.h>
94
95 // how many mii ports are there ?
96 #define AMAZON_SW_INT_NO 2
97
98 #define ETHERNET_PACKET_DMA_BUFFER_SIZE 1536
99
100 /***************************************** Module Parameters *************************************/
101 char mode[] = "bridge";
102 module_param_array(mode, charp, NULL, 0);
103
104 static int timeout = 1 * HZ;
105 module_param(timeout, int, 0);
106
107 int switch_init(struct net_device *dev);
108 void switch_tx_timeout(struct net_device *dev);
109
110 static struct net_device *switch_devs[2];
111
112 int add_mac_table_entry(u64 entry_value)
113 {
114         int i;
115         u32 data1, data2;
116
117         AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = ~7;
118
119         for (i = 0; i < 32; i++) {
120                 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0x80000000 | 0x20 | i;
121                 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
122                 data1 = AMAZON_SW_REG32(AMAZON_SW_DATA1);
123                 data2 = AMAZON_SW_REG32(AMAZON_SW_DATA2);
124                 if ((data1 & (0x00700000)) != 0x00700000)
125                         continue;
126                 AMAZON_SW_REG32(AMAZON_SW_DATA1) = (u32) (entry_value >> 32);
127                 AMAZON_SW_REG32(AMAZON_SW_DATA2) = (u32) entry_value & 0xffffffff;
128                 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0xc0000020 | i;
129                 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
130                 break;
131         }
132         AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) |= 7;
133         if (i >= 32)
134                 return -1;
135         return OK;
136 }
137
138 u64 read_mac_table_entry(int index)
139 {
140         u32 data1, data2;
141         u64 value;
142         AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0x80000000 | 0x20 | index;
143         while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
144         data1 = AMAZON_SW_REG32(AMAZON_SW_DATA1) & 0xffffff;
145         data2 = AMAZON_SW_REG32(AMAZON_SW_DATA2);
146         value = (u64) data1 << 32 | (u64) data2;
147         return value;
148 }
149
150 int write_mac_table_entry(int index, u64 value)
151 {
152         u32 data1, data2;
153         data1 = (u32) (value >> 32);
154         data2 = (u32) value & 0xffffffff;
155         AMAZON_SW_REG32(AMAZON_SW_DATA1) = data1;
156         AMAZON_SW_REG32(AMAZON_SW_DATA2) = data2;
157         AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0xc0000020 | index;
158         while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
159         return OK;
160 }
161
162 u32 get_mdio_reg(int phy_addr, int reg_num)
163 {
164         u32 value;
165         AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = (3 << 30) | ((phy_addr & 0x1f) << 21) | ((reg_num & 0x1f) << 16);
166         while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & (1 << 31)) {};
167         value = AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & 0xffff;
168         return value;
169 }
170
171 int set_mdio_reg(int phy_addr, int reg_num, u32 value)
172 {
173         AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = (2 << 30) | ((phy_addr & 0x1f) << 21) | ((reg_num & 0x1f) << 16) | (value & 0xffff);
174         while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & (1 << 31)) {};
175         return OK;
176 }
177
178 int auto_negotiate(int phy_addr)
179 {
180         u32 value = 0;
181         value = get_mdio_reg(phy_addr, MDIO_BASE_CONTROL_REG);
182         set_mdio_reg(phy_addr, MDIO_BASE_CONTROL_REG, (value | RESTART_AUTO_NEGOTIATION | AUTO_NEGOTIATION_ENABLE | PHY_RESET));
183         return OK;
184 }
185
186 /*
187      In this version of switch driver, we split the dma channels for the switch.
188      2 for port0 and 2 for port1. So that we can do internal bridging if necessary.
189      In switch mode, packets coming in from port0 or port1 is able to do Destination 
190      address lookup. Packets coming from port0 with destination address of port1 should 
191      not go to pmac again. The switch hardware should be able to do the switch in the hard 
192      ware level. Packets coming from the pmac should not do the DA look up in that the
193      desination is already known for the kernel. It only needs to go to the correct NIC to 
194      find its way out.
195   */
196 int amazon_sw_chip_init(void)
197 {
198         u32 tmp1;
199         int i = 0;
200
201         /* Aging tick select: 5mins */
202         tmp1 = 0xa0;
203         if (strcmp(mode, "bridge") == 0) {
204                 // bridge mode, set militarised mode to 1, no learning!
205                 tmp1 |= 0xC00;
206         } else {
207                 // enable learning for P0 and P1,
208                 tmp1 |= 3;
209         }
210
211         /* unknown broadcast/multicast/unicast to all ports */
212         AMAZON_SW_REG32(AMAZON_SW_UN_DEST) = 0x1ff;
213
214         AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = tmp1;
215
216         /* OCS:1 set OCS bit, split the two NIC in rx direction EDL:1 (enable DA lookup) */
217 #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
218         AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x700;
219 #else
220         AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x401;
221 #endif
222
223         /* EPC: 1 split the two NIC in tx direction CRC is generated */
224         AMAZON_SW_REG32(AMAZON_SW_P2_CTL) = 0x6;
225
226         // for bi-directional 
227         AMAZON_SW_REG32(AMAZON_SW_P0_WM) = 0x14141412;
228         AMAZON_SW_REG32(AMAZON_SW_P1_WM) = 0x14141412;
229         AMAZON_SW_REG32(AMAZON_SW_P2_WM) = 0x28282826;
230         AMAZON_SW_REG32(AMAZON_SW_GBL_WM) = 0x0;
231
232         AMAZON_SW_REG32(AMAZON_CGU_PLL0SR) = (AMAZON_SW_REG32(AMAZON_CGU_PLL0SR)) | 0x58000000;
233         // clock for PHY
234         AMAZON_SW_REG32(AMAZON_CGU_IFCCR) =     (AMAZON_SW_REG32(AMAZON_CGU_IFCCR)) | 0x80000004;
235         // enable power for PHY
236         AMAZON_SW_REG32(AMAZON_PMU_PWDCR) = (AMAZON_SW_REG32(AMAZON_PMU_PWDCR)) | AMAZON_PMU_PWDCR_EPHY;
237         // set reverse MII, enable MDIO statemachine
238         AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG) = 0x800027bf;
239         while (1)
240                 if (((AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG)) & 0x80000000) == 0)
241                         break;
242         AMAZON_SW_REG32(AMAZON_SW_EPHY) = 0xff;
243
244         // auto negotiation
245         AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = 0x83e08000;
246         auto_negotiate(0x1f);
247
248         /* enable all ports */
249         AMAZON_SW_REG32(AMAZON_SW_PS_CTL) = 0x7;
250         for (i = 0; i < 32; i++)
251                 write_mac_table_entry(i, 1 << 50);
252         return 0;
253 }
254
255 static unsigned char my_ethaddr[MAX_ADDR_LEN];
256 /* need to get the ether addr from u-boot */
257 static int __init ethaddr_setup(char *line)
258 {
259         char *ep;
260         int i;
261
262         memset(my_ethaddr, 0, MAX_ADDR_LEN);
263         for (i = 0; i < 6; i++) {
264                 my_ethaddr[i] = line ? simple_strtoul(line, &ep, 16) : 0;
265                 if (line)
266                         line = (*ep) ? ep + 1 : ep;
267         }
268         printk(KERN_INFO "amazon_mii0: mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]);
269         return 0;
270 }
271
272 __setup("ethaddr=", ethaddr_setup);
273
274 static void open_rx_dma(struct net_device *dev)
275 {
276         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
277         struct dma_device_info *dma_dev = priv->dma_device;
278         int i;
279
280         for (i = 0; i < dma_dev->num_rx_chan; i++)
281                 dma_dev->rx_chan[i].control = 1;
282         dma_device_update_rx(dma_dev);
283 }
284
285 #ifdef CONFIG_NET_HW_FLOWCONTROL
286 static void close_rx_dma(struct net_device *dev)
287 {
288         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
289         struct dma_device_info *dma_dev = priv->dma_device;
290         int i;
291
292         for (i = 0; i < dma_dev->num_rx_chan; i++)
293                 dma_dev->rx_chan[i].control = 0;
294         dma_device_update_rx(dma_dev);
295 }
296
297 void amazon_xon(struct net_device *dev)
298 {
299         unsigned long flag;
300         local_irq_save(flag);
301         open_rx_dma(dev);
302         local_irq_restore(flag);
303 }
304 #endif
305
306 int switch_open(struct net_device *dev)
307 {
308         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
309         if (!strcmp(dev->name, "eth1")) {
310                 priv->mdio_phy_addr = PHY0_ADDR;
311         }
312         open_rx_dma(dev);                       
313
314 #ifdef CONFIG_NET_HW_FLOWCONTROL
315         if ((priv->fc_bit = netdev_register_fc(dev, amazon_xon)) == 0) {
316                 printk(KERN_WARNING "amazon_mii0: Hardware Flow Control register fails\n");
317         }
318 #endif
319
320         netif_start_queue(dev);
321         return OK;
322 }
323
324 int switch_release(struct net_device *dev)
325 {
326         int i;
327         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
328         struct dma_device_info *dma_dev = priv->dma_device;
329
330         for (i = 0; i < dma_dev->num_tx_chan; i++)
331                 dma_dev->tx_chan[i].control = 0;
332         for (i = 0; i < dma_dev->num_rx_chan; i++)
333                 dma_dev->rx_chan[i].control = 0;
334
335         dma_device_update(dma_dev);
336
337 #ifdef CONFIG_NET_HW_FLOWCONTROL
338         if (priv->fc_bit) {
339                 netdev_unregister_fc(priv->fc_bit);
340         }
341 #endif
342         netif_stop_queue(dev);
343
344         return OK;
345 }
346
347
348 void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
349 {
350         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
351 #ifdef CONFIG_NET_HW_FLOWCONTROL
352         int mit_sel = 0;
353 #endif
354         skb->dev = dev;
355         skb->protocol = eth_type_trans(skb, dev);
356
357 #ifdef CONFIG_NET_HW_FLOWCONTROL
358         mit_sel = netif_rx(skb);
359         switch (mit_sel) {
360         case NET_RX_SUCCESS:
361         case NET_RX_CN_LOW:
362         case NET_RX_CN_MOD:
363                 break;
364         case NET_RX_CN_HIGH:
365                 break;
366         case NET_RX_DROP:
367                 if ((priv->fc_bit)
368                         && (!test_and_set_bit(priv->fc_bit, &netdev_fc_xoff))) {
369                         close_rx_dma(dev);
370                 }
371                 break;
372         }
373 #else
374         netif_rx(skb);
375 #endif
376         priv->stats.rx_packets++;
377         priv->stats.rx_bytes += len;
378         return;
379 }
380
381 int asmlinkage switch_hw_tx(char *buf, int len, struct net_device *dev)
382 {
383         struct switch_priv *priv = netdev_priv(dev);
384         struct dma_device_info *dma_dev = priv->dma_device;
385
386         dma_dev->current_tx_chan = 0;
387         return dma_device_write(dma_dev, buf, len, priv->skb);
388 }
389
390 int asmlinkage switch_tx(struct sk_buff *skb, struct net_device *dev)
391 {
392         int len;
393         char *data;
394         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
395
396         len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
397         data = skb->data;
398         priv->skb = skb;
399         dev->trans_start = jiffies;
400
401         if (switch_hw_tx(data, len, dev) != len) {
402                 dev_kfree_skb_any(skb);
403                 return OK;
404         }
405
406         priv->stats.tx_packets++;
407         priv->stats.tx_bytes += len;
408         return OK;
409 }
410
411 void switch_tx_timeout(struct net_device *dev)
412 {
413         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
414         priv->stats.tx_errors++;
415         netif_wake_queue(dev);
416         return;
417 }
418
419 void negotiate(struct net_device *dev)
420 {
421         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
422         unsigned short data = get_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG);
423
424         data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);
425
426         switch (priv->current_speed_selection) {
427         case 10:
428                 if (priv->current_duplex == full)
429                         data |= MDIO_ADVERT_10_FD;
430                 else if (priv->current_duplex == half)
431                         data |= MDIO_ADVERT_10_HD;
432                 else
433                         data |= MDIO_ADVERT_10_HD | MDIO_ADVERT_10_FD;
434                 break;
435
436         case 100:
437                 if (priv->current_duplex == full)
438                         data |= MDIO_ADVERT_100_FD;
439                 else if (priv->current_duplex == half)
440                         data |= MDIO_ADVERT_100_HD;
441                 else
442                         data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD;
443                 break;
444
445         case 0:                                 /* Auto */
446                 if (priv->current_duplex == full)
447                         data |= MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD;
448                 else if (priv->current_duplex == half)
449                         data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_10_HD;
450                 else
451                         data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD     | MDIO_ADVERT_10_HD;
452                 break;
453
454         default:                                        /* assume autoneg speed and duplex */
455                 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
456         }
457
458         set_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG, data);
459
460         /* Renegotiate with link partner */
461
462         data = get_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG);
463         data |= MDIO_BC_NEGOTIATE;
464
465         set_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG, data);
466
467 }
468
469
470 void set_duplex(struct net_device *dev, enum duplex new_duplex)
471 {
472         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
473         if (new_duplex != priv->current_duplex) {
474                 priv->current_duplex = new_duplex;
475                 negotiate(dev);
476         }
477 }
478
479 void set_speed(struct net_device *dev, unsigned long speed)
480 {
481         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
482         priv->current_speed_selection = speed;
483         negotiate(dev);
484 }
485
486 static int switch_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
487 {
488         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
489         struct ethtool_cmd ecmd;
490
491         if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
492                 return -EFAULT;
493
494         switch (ecmd.cmd) {
495         case ETHTOOL_GSET:
496                 memset((void *) &ecmd, 0, sizeof(ecmd));
497                 ecmd.supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII |     SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
498                                                 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
499                 ecmd.port = PORT_TP;
500                 ecmd.transceiver = XCVR_EXTERNAL;
501                 ecmd.phy_address = priv->mdio_phy_addr;
502
503                 ecmd.speed = priv->current_speed;
504
505                 ecmd.duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
506
507                 ecmd.advertising = ADVERTISED_TP;
508                 if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
509                         ecmd.advertising |= ADVERTISED_Autoneg;
510                 else {
511                         ecmd.advertising |=     ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
512                                 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
513                         if (priv->current_speed_selection == 10)
514                                 ecmd.advertising &=     ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full);
515                         else if (priv->current_speed_selection == 100)
516                                 ecmd.advertising &=     ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full);
517                         if (priv->current_duplex == half)
518                                 ecmd.advertising &=     ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full);
519                         else if (priv->current_duplex == full)
520                                 ecmd.advertising &=     ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half);
521                 }
522                 ecmd.autoneg = AUTONEG_ENABLE;
523                 if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
524                         return -EFAULT;
525                 break;
526
527         case ETHTOOL_SSET:
528                 if (!capable(CAP_NET_ADMIN)) {
529                         return -EPERM;
530                 }
531                 if (ecmd.autoneg == AUTONEG_ENABLE) {
532                         set_duplex(dev, autoneg);
533                         set_speed(dev, 0);
534                 } else {
535                         set_duplex(dev, ecmd.duplex == DUPLEX_HALF ? half : full);
536                         set_speed(dev, ecmd.speed == SPEED_10 ? 10 : 100);
537                 }
538                 break;
539
540         case ETHTOOL_GDRVINFO:
541                 {
542                         struct ethtool_drvinfo info;
543                         memset((void *) &info, 0, sizeof(info));
544                         strncpy(info.driver, "AMAZONE", sizeof(info.driver) - 1);
545                         strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1);
546                         strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1);
547                         info.regdump_len = 0;
548                         info.eedump_len = 0;
549                         info.testinfo_len = 0;
550                         if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
551                                 return -EFAULT;
552                 }
553                 break;
554         case ETHTOOL_NWAY_RST:
555                 if (priv->current_duplex == autoneg     && priv->current_speed_selection == 0)
556                         negotiate(dev);
557                 break;
558         default:
559                 return -EOPNOTSUPP;
560                 break;
561         }
562         return 0;
563 }
564
565
566
567 int mac_table_tools_ioctl(struct net_device *dev, struct mac_table_req *req)
568 {
569         int cmd;
570         int i;
571         cmd = req->cmd;
572         switch (cmd) {
573         case RESET_MAC_TABLE:
574                 for (i = 0; i < 32; i++) {
575                         write_mac_table_entry(i, 0);
576                 }
577                 break;
578         case READ_MAC_ENTRY:
579                 req->entry_value = read_mac_table_entry(req->index);
580                 break;
581         case WRITE_MAC_ENTRY:
582                 write_mac_table_entry(req->index, req->entry_value);
583                 break;
584         case ADD_MAC_ENTRY:
585                 add_mac_table_entry(req->entry_value);
586                 break;
587         default:
588                 return -EINVAL;
589         }
590
591         return 0;
592 }
593
594
595 /*
596     the ioctl for the switch driver is developed in the conventional way
597     the control type falls into some basic categories, among them, the 
598     SIOCETHTOOL is the traditional eth interface. VLAN_TOOLS and  
599     MAC_TABLE_TOOLS are designed specifically for amazon chip. User 
600     should be aware of the data structures used in these interfaces. 
601 */
602 int switch_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
603 {
604         struct data_req *switch_data_req = (struct data_req *) ifr->ifr_data;
605         struct mac_table_req *switch_mac_table_req;
606         switch (cmd) {
607         case SIOCETHTOOL:
608                 switch_ethtool_ioctl(dev, ifr);
609                 break;
610         case SIOCGMIIPHY:                       /* Get PHY address */
611                 break;
612         case SIOCGMIIREG:                       /* Read MII register */
613                 break;
614         case SIOCSMIIREG:                       /* Write MII register */
615                 break;
616         case SET_ETH_SPEED_10:          /* 10 Mbps */
617                 break;
618         case SET_ETH_SPEED_100: /* 100 Mbps */
619                 break;
620         case SET_ETH_SPEED_AUTO:        /* Auto negotiate speed */
621                 break;
622         case SET_ETH_DUPLEX_HALF:       /* Half duplex. */
623                 break;
624         case SET_ETH_DUPLEX_FULL:       /* Full duplex. */
625                 break;
626         case SET_ETH_DUPLEX_AUTO:       /* Autonegotiate duplex */
627                 break;
628         case SET_ETH_REG:
629                 AMAZON_SW_REG32(switch_data_req->index) = switch_data_req->value;
630                 break;
631         case MAC_TABLE_TOOLS:
632                 switch_mac_table_req = (struct mac_table_req *) ifr->ifr_data;
633                 mac_table_tools_ioctl(dev, switch_mac_table_req);
634                 break;
635         default:
636                 return -EINVAL;
637         }
638
639         return 0;
640 }
641
642 struct net_device_stats *switch_stats(struct net_device *dev)
643 {
644         struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
645         return &priv->stats;
646 }
647
648 int switch_change_mtu(struct net_device *dev, int new_mtu)
649 {
650         if (new_mtu >= 1516)
651                 new_mtu = 1516;
652         dev->mtu = new_mtu;
653         return 0;
654 }
655
656 int switch_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
657 {
658         u8 *buf = NULL;
659         int len = 0;
660         struct sk_buff *skb = NULL;
661
662         len = dma_device_read(dma_dev, &buf, (void **) &skb);
663
664         if (len >= 0x600) {
665                 printk(KERN_WARNING "amazon_mii0: packet too large %d\n", len);
666                 goto switch_hw_receive_err_exit;
667         }
668
669         /* remove CRC */
670         len -= 4;
671         if (skb == NULL) {
672                 printk(KERN_WARNING "amazon_mii0: cannot restore pointer\n");
673                 goto switch_hw_receive_err_exit;
674         }
675         if (len > (skb->end - skb->tail)) {
676                 printk(KERN_WARNING "amazon_mii0: BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
677                 goto switch_hw_receive_err_exit;
678         }
679         skb_put(skb, len);
680         skb->dev = dev;
681         switch_rx(dev, len, skb);
682         return OK;
683   
684   switch_hw_receive_err_exit:
685         if (skb)
686                 dev_kfree_skb_any(skb);
687         return -EIO;
688 }
689
690 int dma_intr_handler(struct dma_device_info *dma_dev, int status)
691 {
692         struct net_device *dev;
693
694         dev = dma_dev->priv;
695         switch (status) {
696         case RCV_INT:
697                 switch_hw_receive(dev, dma_dev);
698                 break;
699         case TX_BUF_FULL_INT:
700                 netif_stop_queue(dev);
701                 break;
702         case TRANSMIT_CPT_INT:
703                 netif_wake_queue(dev);
704                 break;
705         }
706         return OK;
707 }
708
709 /* reserve 2 bytes in front of data pointer*/
710 u8 *dma_buffer_alloc(int len, int *byte_offset, void **opt)
711 {
712         u8 *buffer = NULL;
713         struct sk_buff *skb = NULL;
714         skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
715         if (skb == NULL) {
716                 return NULL;
717         }
718         buffer = (u8 *) (skb->data);
719         skb_reserve(skb, 2);
720         *(int *) opt = (int) skb;
721         *byte_offset = 2;
722         return buffer;
723 }
724
725 int dma_buffer_free(u8 * dataptr, void *opt)
726 {
727         struct sk_buff *skb = NULL;
728         if (opt == NULL) {
729                 kfree(dataptr);
730         } else {
731                 skb = (struct sk_buff *) opt;
732                 dev_kfree_skb_any(skb);
733         }
734         return OK;
735 }
736
737 int init_dma_device(_dma_device_info * dma_dev, struct net_device *dev)
738 {
739         int i;
740         int num_tx_chan, num_rx_chan;
741         if (strcmp(dma_dev->device_name, "switch1") == 0) {
742                 num_tx_chan = 1;
743                 num_rx_chan = 2;
744         } else {
745                 num_tx_chan = 1;
746                 num_rx_chan = 2;
747         }
748         dma_dev->priv = dev;
749
750         dma_dev->weight = 1;
751         dma_dev->num_tx_chan = num_tx_chan;
752         dma_dev->num_rx_chan = num_rx_chan;
753         dma_dev->ack = 1;
754         dma_dev->tx_burst_len = 4;
755         dma_dev->rx_burst_len = 4;
756         for (i = 0; i < dma_dev->num_tx_chan; i++) {
757                 dma_dev->tx_chan[i].weight = QOS_DEFAULT_WGT;
758                 dma_dev->tx_chan[i].desc_num = 10;
759                 dma_dev->tx_chan[i].packet_size = 0;
760                 dma_dev->tx_chan[i].control = 0;
761         }
762         for (i = 0; i < num_rx_chan; i++) {
763                 dma_dev->rx_chan[i].weight = QOS_DEFAULT_WGT;
764                 dma_dev->rx_chan[i].desc_num = 10;
765                 dma_dev->rx_chan[i].packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE;
766                 dma_dev->rx_chan[i].control = 0;
767         }
768         dma_dev->intr_handler = dma_intr_handler;
769         dma_dev->buffer_alloc = dma_buffer_alloc;
770         dma_dev->buffer_free = dma_buffer_free;
771         return 0;
772 }
773
774 int switch_set_mac_address(struct net_device *dev, void *p)
775 {
776         struct sockaddr *addr = p;
777         memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
778         return OK;
779 }
780
781 static const struct net_device_ops amazon_mii_ops = {
782         .ndo_init               = switch_init,
783         .ndo_open               = switch_open,
784         .ndo_stop               = switch_release,
785         .ndo_start_xmit         = switch_tx,
786         .ndo_do_ioctl           = switch_ioctl,
787         .ndo_get_stats          = switch_stats,
788         .ndo_change_mtu         = switch_change_mtu,
789         .ndo_set_mac_address            = switch_set_mac_address,
790         .ndo_tx_timeout         = switch_tx_timeout,
791 };
792
793 int switch_init(struct net_device *dev)
794 {
795         u64 retval = 0;
796         int i;
797         int result;
798         struct switch_priv *priv;
799         ether_setup(dev);                       /* assign some of the fields */
800         printk(KERN_INFO "amazon_mii0: %s up using ", dev->name);
801         dev->watchdog_timeo = timeout;
802
803         priv = netdev_priv(dev);
804         priv->dma_device = (struct dma_device_info *) kmalloc(sizeof(struct dma_device_info), GFP_KERNEL);
805         if (priv->num == 0) {
806                 sprintf(priv->dma_device->device_name, "switch1");
807         } else if (priv->num == 1) {
808                 sprintf(priv->dma_device->device_name, "switch2");
809         }
810         printk("\"%s\"\n", priv->dma_device->device_name);
811         init_dma_device(priv->dma_device, dev);
812         result = dma_device_register(priv->dma_device);
813
814         /* read the mac address from the mac table and put them into the mac table. */
815         for (i = 0; i < 6; i++) {
816                 retval += my_ethaddr[i];
817         }
818         /* ethaddr not set in u-boot ? */
819         if (retval == 0) {
820                 dev->dev_addr[0] = 0x00;
821                 dev->dev_addr[1] = 0x20;
822                 dev->dev_addr[2] = 0xda;
823                 dev->dev_addr[3] = 0x86;
824                 dev->dev_addr[4] = 0x23;
825                 dev->dev_addr[5] = 0x74 + (unsigned char) priv->num;
826         } else {
827                 for (i = 0; i < 6; i++) {
828                         dev->dev_addr[i] = my_ethaddr[i];
829                 }
830                 dev->dev_addr[5] += +(unsigned char) priv->num;
831         }
832         return OK;
833 }
834
835 static int amazon_mii_probe(struct platform_device *dev)
836 {
837         int i = 0, result, device_present = 0;
838         struct switch_priv *priv;
839
840         for (i = 0; i < AMAZON_SW_INT_NO; i++) {
841                 switch_devs[i] = alloc_etherdev(sizeof(struct switch_priv));
842                 switch_devs[i]->netdev_ops = &amazon_mii_ops;
843                 strcpy(switch_devs[i]->name, "eth%d");
844                 priv = (struct switch_priv *) netdev_priv(switch_devs[i]);
845                 priv->num = i;
846                 if ((result = register_netdev(switch_devs[i])))
847                         printk(KERN_WARNING "amazon_mii0: error %i registering device \"%s\"\n", result, switch_devs[i]->name);
848                 else
849                         device_present++;
850         }
851         amazon_sw_chip_init();
852         return device_present ? 0 : -ENODEV;
853 }
854
855 static int amazon_mii_remove(struct platform_device *dev)
856 {
857         int i;
858         struct switch_priv *priv;
859         for (i = 0; i < AMAZON_SW_INT_NO; i++) {
860                 priv = netdev_priv(switch_devs[i]);
861                 if (priv->dma_device) {
862                         dma_device_unregister(priv->dma_device);
863                         kfree(priv->dma_device);
864                 }
865                 kfree(netdev_priv(switch_devs[i]));
866                 unregister_netdev(switch_devs[i]);
867         }
868         return 0;
869 }
870
871 static struct platform_driver amazon_mii_driver = {
872         .probe = amazon_mii_probe,
873         .remove = amazon_mii_remove,
874         .driver = {
875                 .name = "amazon_mii0",
876                 .owner = THIS_MODULE,
877         },
878 };
879
880 static int __init amazon_mii_init(void)
881 {
882         int ret = platform_driver_register(&amazon_mii_driver);
883         if (ret)
884                 printk(KERN_WARNING "amazon_mii0: Error registering platfom driver!\n");
885         return ret;
886 }
887
888 static void __exit amazon_mii_cleanup(void)
889 {
890         platform_driver_unregister(&amazon_mii_driver);
891 }
892
893 module_init(amazon_mii_init);
894 module_exit(amazon_mii_cleanup);
895
896 MODULE_LICENSE("GPL");
897 MODULE_AUTHOR("Wu Qi Ming");
898 MODULE_DESCRIPTION("ethernet driver for AMAZON boards");
899