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.
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.
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.
16 //-----------------------------------------------------------------------
19 * Driver for Infineon Amazon 3 port switch
21 //-----------------------------------------------------------------------
22 /* Author: Wu Qi Ming[Qi-Ming.Wu@infineon.com]
23 * Created: 7-April-2004
25 //-----------------------------------------------------------------------
27 * Changed on: Jun 28, 2004
28 * Changed by: peng.liu@infineon.com
29 * Reason: add hardware flow control (HFC) (CONFIG_NET_HW_FLOWCONTROL)
31 * Changed on: Apr 6, 2005
32 * Changed by: mars.lin@infineon.com
33 * Reason : supoort port identification
37 // copyright 2004-2005 infineon.com
39 // copyright 2007 john crispin <blogic@openwrt.org>
40 // copyright 2007 felix fietkau <nbd@openwrt.org>
44 // port vlan code from bcrm target... the tawainese code was scrapped due to crappyness
45 // check all the mmi reg settings and possibly document them better
46 // verify the ethtool code
47 // remove the while(1) stuff
48 // further clean up and rework ... but it works for now
49 // check the mode[]=bridge stuff
50 // verify that the ethaddr can be set from u-boot
58 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
62 #if defined(MODVERSIONS) && !defined(__GENKSYMS__)
63 #include <linux/modversions.h>
66 #include <linux/module.h>
67 #include <linux/string.h>
68 #include <linux/sched.h>
69 #include <linux/kernel.h>
70 #include <linux/slab.h>
71 #include <linux/errno.h>
72 #include <linux/types.h>
73 #include <linux/interrupt.h>
74 #include <linux/mii.h>
75 #include <asm/uaccess.h>
77 #include <linux/netdevice.h>
78 #include <linux/etherdevice.h>
80 #include <linux/tcp.h>
81 #include <linux/skbuff.h>
82 #include <linux/in6.h>
83 #include <linux/proc_fs.h>
85 #include <linux/ethtool.h>
86 #include <asm/checksum.h>
87 #include <linux/init.h>
89 #include <asm/amazon/amazon.h>
90 #include <asm/amazon/amazon_dma.h>
91 #include <asm/amazon/amazon_sw.h>
93 // how many mii ports are there ?
94 #define AMAZON_SW_INT_NO 2
96 #define ETHERNET_PACKET_DMA_BUFFER_SIZE 1536
98 /***************************************** Module Parameters *************************************/
99 char mode
[] = "bridge";
100 module_param_array(mode
, charp
, NULL
, 0);
102 static int timeout
= 1 * HZ
;
103 module_param(timeout
, int, 0);
105 int switch_init(struct net_device
*dev
);
106 void switch_tx_timeout(struct net_device
*dev
);
108 static struct net_device
*switch_devs
[2];
110 int add_mac_table_entry(u64 entry_value
)
115 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL
) = ~7;
117 for (i
= 0; i
< 32; i
++) {
118 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) = 0x80000000 | 0x20 | i
;
119 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) & (0x80000000)) {};
120 data1
= AMAZON_SW_REG32(AMAZON_SW_DATA1
);
121 data2
= AMAZON_SW_REG32(AMAZON_SW_DATA2
);
122 if ((data1
& (0x00700000)) != 0x00700000)
124 AMAZON_SW_REG32(AMAZON_SW_DATA1
) = (u32
) (entry_value
>> 32);
125 AMAZON_SW_REG32(AMAZON_SW_DATA2
) = (u32
) entry_value
& 0xffffffff;
126 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) = 0xc0000020 | i
;
127 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) & (0x80000000)) {};
130 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL
) |= 7;
136 u64
read_mac_table_entry(int index
)
140 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) = 0x80000000 | 0x20 | index
;
141 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) & (0x80000000)) {};
142 data1
= AMAZON_SW_REG32(AMAZON_SW_DATA1
) & 0xffffff;
143 data2
= AMAZON_SW_REG32(AMAZON_SW_DATA2
);
144 value
= (u64
) data1
<< 32 | (u64
) data2
;
148 int write_mac_table_entry(int index
, u64 value
)
151 data1
= (u32
) (value
>> 32);
152 data2
= (u32
) value
& 0xffffffff;
153 AMAZON_SW_REG32(AMAZON_SW_DATA1
) = data1
;
154 AMAZON_SW_REG32(AMAZON_SW_DATA2
) = data2
;
155 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) = 0xc0000020 | index
;
156 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL
) & (0x80000000)) {};
160 u32
get_mdio_reg(int phy_addr
, int reg_num
)
163 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) = (3 << 30) | ((phy_addr
& 0x1f) << 21) | ((reg_num
& 0x1f) << 16);
164 while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) & (1 << 31)) {};
165 value
= AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) & 0xffff;
169 int set_mdio_reg(int phy_addr
, int reg_num
, u32 value
)
171 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) = (2 << 30) | ((phy_addr
& 0x1f) << 21) | ((reg_num
& 0x1f) << 16) | (value
& 0xffff);
172 while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) & (1 << 31)) {};
176 int auto_negotiate(int phy_addr
)
179 value
= get_mdio_reg(phy_addr
, MDIO_BASE_CONTROL_REG
);
180 set_mdio_reg(phy_addr
, MDIO_BASE_CONTROL_REG
, (value
| RESTART_AUTO_NEGOTIATION
| AUTO_NEGOTIATION_ENABLE
| PHY_RESET
));
185 In this version of switch driver, we split the dma channels for the switch.
186 2 for port0 and 2 for port1. So that we can do internal bridging if necessary.
187 In switch mode, packets coming in from port0 or port1 is able to do Destination
188 address lookup. Packets coming from port0 with destination address of port1 should
189 not go to pmac again. The switch hardware should be able to do the switch in the hard
190 ware level. Packets coming from the pmac should not do the DA look up in that the
191 desination is already known for the kernel. It only needs to go to the correct NIC to
194 int amazon_sw_chip_init(void)
199 /* Aging tick select: 5mins */
201 if (strcmp(mode
, "bridge") == 0) {
202 // bridge mode, set militarised mode to 1, no learning!
205 // enable learning for P0 and P1,
209 /* unknown broadcast/multicast/unicast to all ports */
210 AMAZON_SW_REG32(AMAZON_SW_UN_DEST
) = 0x1ff;
212 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL
) = tmp1
;
214 /* OCS:1 set OCS bit, split the two NIC in rx direction EDL:1 (enable DA lookup) */
215 #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
216 AMAZON_SW_REG32(AMAZON_SW_P2_PCTL
) = 0x700;
218 AMAZON_SW_REG32(AMAZON_SW_P2_PCTL
) = 0x401;
221 /* EPC: 1 split the two NIC in tx direction CRC is generated */
222 AMAZON_SW_REG32(AMAZON_SW_P2_CTL
) = 0x6;
224 // for bi-directional
225 AMAZON_SW_REG32(AMAZON_SW_P0_WM
) = 0x14141412;
226 AMAZON_SW_REG32(AMAZON_SW_P1_WM
) = 0x14141412;
227 AMAZON_SW_REG32(AMAZON_SW_P2_WM
) = 0x28282826;
228 AMAZON_SW_REG32(AMAZON_SW_GBL_WM
) = 0x0;
230 AMAZON_SW_REG32(AMAZON_CGU_PLL0SR
) = (AMAZON_SW_REG32(AMAZON_CGU_PLL0SR
)) | 0x58000000;
232 AMAZON_SW_REG32(AMAZON_CGU_IFCCR
) = (AMAZON_SW_REG32(AMAZON_CGU_IFCCR
)) | 0x80000004;
233 // enable power for PHY
234 AMAZON_SW_REG32(AMAZON_PMU_PWDCR
) = (AMAZON_SW_REG32(AMAZON_PMU_PWDCR
)) | AMAZON_PMU_PWDCR_EPHY
;
235 // set reverse MII, enable MDIO statemachine
236 AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG
) = 0x800027bf;
238 if (((AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG
)) & 0x80000000) == 0)
240 AMAZON_SW_REG32(AMAZON_SW_EPHY
) = 0xff;
243 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) = 0x83e08000;
244 auto_negotiate(0x1f);
246 /* enable all ports */
247 AMAZON_SW_REG32(AMAZON_SW_PS_CTL
) = 0x7;
248 for (i
= 0; i
< 32; i
++)
249 write_mac_table_entry(i
, 1 << 50);
253 static unsigned char my_ethaddr
[MAX_ADDR_LEN
];
254 /* need to get the ether addr from u-boot */
255 static int __init
ethaddr_setup(char *line
)
260 memset(my_ethaddr
, 0, MAX_ADDR_LEN
);
261 for (i
= 0; i
< 6; i
++) {
262 my_ethaddr
[i
] = line
? simple_strtoul(line
, &ep
, 16) : 0;
264 line
= (*ep
) ? ep
+ 1 : ep
;
266 printk("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]);
270 __setup("ethaddr=", ethaddr_setup
);
272 static void open_rx_dma(struct net_device
*dev
)
274 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
275 struct dma_device_info
*dma_dev
= priv
->dma_device
;
278 for (i
= 0; i
< dma_dev
->num_rx_chan
; i
++)
279 dma_dev
->rx_chan
[i
].control
= 1;
280 dma_device_update_rx(dma_dev
);
283 #ifdef CONFIG_NET_HW_FLOWCONTROL
284 static void close_rx_dma(struct net_device
*dev
)
286 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
287 struct dma_device_info
*dma_dev
= priv
->dma_device
;
290 for (i
= 0; i
< dma_dev
->num_rx_chan
; i
++)
291 dma_dev
->rx_chan
[i
].control
= 0;
292 dma_device_update_rx(dma_dev
);
295 void amazon_xon(struct net_device
*dev
)
298 local_irq_save(flag
);
300 local_irq_restore(flag
);
304 int switch_open(struct net_device
*dev
)
306 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
307 if (!strcmp(dev
->name
, "eth1")) {
308 priv
->mdio_phy_addr
= PHY0_ADDR
;
312 #ifdef CONFIG_NET_HW_FLOWCONTROL
313 if ((priv
->fc_bit
= netdev_register_fc(dev
, amazon_xon
)) == 0) {
314 printk("Hardware Flow Control register fails\n");
318 netif_start_queue(dev
);
322 int switch_release(struct net_device
*dev
)
325 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
326 struct dma_device_info
*dma_dev
= priv
->dma_device
;
328 for (i
= 0; i
< dma_dev
->num_tx_chan
; i
++)
329 dma_dev
->tx_chan
[i
].control
= 0;
330 for (i
= 0; i
< dma_dev
->num_rx_chan
; i
++)
331 dma_dev
->rx_chan
[i
].control
= 0;
333 dma_device_update(dma_dev
);
335 #ifdef CONFIG_NET_HW_FLOWCONTROL
337 netdev_unregister_fc(priv
->fc_bit
);
340 netif_stop_queue(dev
);
346 void switch_rx(struct net_device
*dev
, int len
, struct sk_buff
*skb
)
348 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
349 #ifdef CONFIG_NET_HW_FLOWCONTROL
353 skb
->protocol
= eth_type_trans(skb
, dev
);
355 #ifdef CONFIG_NET_HW_FLOWCONTROL
356 mit_sel
= netif_rx(skb
);
366 && (!test_and_set_bit(priv
->fc_bit
, &netdev_fc_xoff
))) {
374 priv
->stats
.rx_packets
++;
375 priv
->stats
.rx_bytes
+= len
;
379 int asmlinkage
switch_hw_tx(char *buf
, int len
, struct net_device
*dev
)
381 struct switch_priv
*priv
= netdev_priv(dev
);
382 struct dma_device_info
*dma_dev
= priv
->dma_device
;
384 dma_dev
->current_tx_chan
= 0;
385 return dma_device_write(dma_dev
, buf
, len
, priv
->skb
);
388 int asmlinkage
switch_tx(struct sk_buff
*skb
, struct net_device
*dev
)
392 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
394 len
= skb
->len
< ETH_ZLEN
? ETH_ZLEN
: skb
->len
;
397 dev
->trans_start
= jiffies
;
399 if (switch_hw_tx(data
, len
, dev
) != len
) {
400 dev_kfree_skb_any(skb
);
404 priv
->stats
.tx_packets
++;
405 priv
->stats
.tx_bytes
+= len
;
409 void switch_tx_timeout(struct net_device
*dev
)
411 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
412 priv
->stats
.tx_errors
++;
413 netif_wake_queue(dev
);
417 void negotiate(struct net_device
*dev
)
419 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
420 unsigned short data
= get_mdio_reg(priv
->mdio_phy_addr
, MDIO_ADVERTISMENT_REG
);
422 data
&= ~(MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
| MDIO_ADVERT_10_FD
| MDIO_ADVERT_10_HD
);
424 switch (priv
->current_speed_selection
) {
426 if (priv
->current_duplex
== full
)
427 data
|= MDIO_ADVERT_10_FD
;
428 else if (priv
->current_duplex
== half
)
429 data
|= MDIO_ADVERT_10_HD
;
431 data
|= MDIO_ADVERT_10_HD
| MDIO_ADVERT_10_FD
;
435 if (priv
->current_duplex
== full
)
436 data
|= MDIO_ADVERT_100_FD
;
437 else if (priv
->current_duplex
== half
)
438 data
|= MDIO_ADVERT_100_HD
;
440 data
|= MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
;
444 if (priv
->current_duplex
== full
)
445 data
|= MDIO_ADVERT_100_FD
| MDIO_ADVERT_10_FD
;
446 else if (priv
->current_duplex
== half
)
447 data
|= MDIO_ADVERT_100_HD
| MDIO_ADVERT_10_HD
;
449 data
|= MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
| MDIO_ADVERT_10_FD
| MDIO_ADVERT_10_HD
;
452 default: /* assume autoneg speed and duplex */
453 data
|= MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
| MDIO_ADVERT_10_FD
| MDIO_ADVERT_10_HD
;
456 set_mdio_reg(priv
->mdio_phy_addr
, MDIO_ADVERTISMENT_REG
, data
);
458 /* Renegotiate with link partner */
460 data
= get_mdio_reg(priv
->mdio_phy_addr
, MDIO_BASE_CONTROL_REG
);
461 data
|= MDIO_BC_NEGOTIATE
;
463 set_mdio_reg(priv
->mdio_phy_addr
, MDIO_BASE_CONTROL_REG
, data
);
468 void set_duplex(struct net_device
*dev
, enum duplex new_duplex
)
470 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
471 if (new_duplex
!= priv
->current_duplex
) {
472 priv
->current_duplex
= new_duplex
;
477 void set_speed(struct net_device
*dev
, unsigned long speed
)
479 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
480 priv
->current_speed_selection
= speed
;
484 static int switch_ethtool_ioctl(struct net_device
*dev
, struct ifreq
*ifr
)
486 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
487 struct ethtool_cmd ecmd
;
489 if (copy_from_user(&ecmd
, ifr
->ifr_data
, sizeof(ecmd
)))
494 memset((void *) &ecmd
, 0, sizeof(ecmd
));
495 ecmd
.supported
= SUPPORTED_Autoneg
| SUPPORTED_TP
| SUPPORTED_MII
| SUPPORTED_10baseT_Half
| SUPPORTED_10baseT_Full
|
496 SUPPORTED_100baseT_Half
| SUPPORTED_100baseT_Full
;
498 ecmd
.transceiver
= XCVR_EXTERNAL
;
499 ecmd
.phy_address
= priv
->mdio_phy_addr
;
501 ecmd
.speed
= priv
->current_speed
;
503 ecmd
.duplex
= priv
->full_duplex
? DUPLEX_FULL
: DUPLEX_HALF
;
505 ecmd
.advertising
= ADVERTISED_TP
;
506 if (priv
->current_duplex
== autoneg
&& priv
->current_speed_selection
== 0)
507 ecmd
.advertising
|= ADVERTISED_Autoneg
;
509 ecmd
.advertising
|= ADVERTISED_10baseT_Half
| ADVERTISED_10baseT_Full
|
510 ADVERTISED_100baseT_Half
| ADVERTISED_100baseT_Full
;
511 if (priv
->current_speed_selection
== 10)
512 ecmd
.advertising
&= ~(ADVERTISED_100baseT_Half
| ADVERTISED_100baseT_Full
);
513 else if (priv
->current_speed_selection
== 100)
514 ecmd
.advertising
&= ~(ADVERTISED_10baseT_Half
| ADVERTISED_10baseT_Full
);
515 if (priv
->current_duplex
== half
)
516 ecmd
.advertising
&= ~(ADVERTISED_10baseT_Full
| ADVERTISED_100baseT_Full
);
517 else if (priv
->current_duplex
== full
)
518 ecmd
.advertising
&= ~(ADVERTISED_10baseT_Half
| ADVERTISED_100baseT_Half
);
520 ecmd
.autoneg
= AUTONEG_ENABLE
;
521 if (copy_to_user(ifr
->ifr_data
, &ecmd
, sizeof(ecmd
)))
526 if (!capable(CAP_NET_ADMIN
)) {
529 if (ecmd
.autoneg
== AUTONEG_ENABLE
) {
530 set_duplex(dev
, autoneg
);
533 set_duplex(dev
, ecmd
.duplex
== DUPLEX_HALF
? half
: full
);
534 set_speed(dev
, ecmd
.speed
== SPEED_10
? 10 : 100);
538 case ETHTOOL_GDRVINFO
:
540 struct ethtool_drvinfo info
;
541 memset((void *) &info
, 0, sizeof(info
));
542 strncpy(info
.driver
, "AMAZONE", sizeof(info
.driver
) - 1);
543 strncpy(info
.fw_version
, "N/A", sizeof(info
.fw_version
) - 1);
544 strncpy(info
.bus_info
, "N/A", sizeof(info
.bus_info
) - 1);
545 info
.regdump_len
= 0;
547 info
.testinfo_len
= 0;
548 if (copy_to_user(ifr
->ifr_data
, &info
, sizeof(info
)))
552 case ETHTOOL_NWAY_RST
:
553 if (priv
->current_duplex
== autoneg
&& priv
->current_speed_selection
== 0)
565 int mac_table_tools_ioctl(struct net_device
*dev
, struct mac_table_req
*req
)
571 case RESET_MAC_TABLE
:
572 for (i
= 0; i
< 32; i
++) {
573 write_mac_table_entry(i
, 0);
577 req
->entry_value
= read_mac_table_entry(req
->index
);
579 case WRITE_MAC_ENTRY
:
580 write_mac_table_entry(req
->index
, req
->entry_value
);
583 add_mac_table_entry(req
->entry_value
);
594 the ioctl for the switch driver is developed in the conventional way
595 the control type falls into some basic categories, among them, the
596 SIOCETHTOOL is the traditional eth interface. VLAN_TOOLS and
597 MAC_TABLE_TOOLS are designed specifically for amazon chip. User
598 should be aware of the data structures used in these interfaces.
600 int switch_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
)
602 struct data_req
*switch_data_req
= (struct data_req
*) ifr
->ifr_data
;
603 struct mac_table_req
*switch_mac_table_req
;
606 switch_ethtool_ioctl(dev
, ifr
);
608 case SIOCGMIIPHY
: /* Get PHY address */
610 case SIOCGMIIREG
: /* Read MII register */
612 case SIOCSMIIREG
: /* Write MII register */
614 case SET_ETH_SPEED_10
: /* 10 Mbps */
616 case SET_ETH_SPEED_100
: /* 100 Mbps */
618 case SET_ETH_SPEED_AUTO
: /* Auto negotiate speed */
620 case SET_ETH_DUPLEX_HALF
: /* Half duplex. */
622 case SET_ETH_DUPLEX_FULL
: /* Full duplex. */
624 case SET_ETH_DUPLEX_AUTO
: /* Autonegotiate duplex */
627 AMAZON_SW_REG32(switch_data_req
->index
) = switch_data_req
->value
;
629 case MAC_TABLE_TOOLS
:
630 switch_mac_table_req
= (struct mac_table_req
*) ifr
->ifr_data
;
631 mac_table_tools_ioctl(dev
, switch_mac_table_req
);
640 struct net_device_stats
*switch_stats(struct net_device
*dev
)
642 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
646 int switch_change_mtu(struct net_device
*dev
, int new_mtu
)
654 int switch_hw_receive(struct net_device
*dev
, struct dma_device_info
*dma_dev
)
658 struct sk_buff
*skb
= NULL
;
660 len
= dma_device_read(dma_dev
, &buf
, (void **) &skb
);
663 printk("packet too large %d\n", len
);
664 goto switch_hw_receive_err_exit
;
670 printk("cannot restore pointer\n");
671 goto switch_hw_receive_err_exit
;
673 if (len
> (skb
->end
- skb
->tail
)) {
674 printk("BUG, len:%d end:%p tail:%p\n", (len
+ 4), skb
->end
, skb
->tail
);
675 goto switch_hw_receive_err_exit
;
679 switch_rx(dev
, len
, skb
);
682 switch_hw_receive_err_exit
:
684 dev_kfree_skb_any(skb
);
688 int dma_intr_handler(struct dma_device_info
*dma_dev
, int status
)
690 struct net_device
*dev
;
695 switch_hw_receive(dev
, dma_dev
);
697 case TX_BUF_FULL_INT
:
698 netif_stop_queue(dev
);
700 case TRANSMIT_CPT_INT
:
701 netif_wake_queue(dev
);
707 /* reserve 2 bytes in front of data pointer*/
708 u8
*dma_buffer_alloc(int len
, int *byte_offset
, void **opt
)
711 struct sk_buff
*skb
= NULL
;
712 skb
= dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE
);
716 buffer
= (u8
*) (skb
->data
);
718 *(int *) opt
= (int) skb
;
723 int dma_buffer_free(u8
* dataptr
, void *opt
)
725 struct sk_buff
*skb
= NULL
;
729 skb
= (struct sk_buff
*) opt
;
730 dev_kfree_skb_any(skb
);
735 int init_dma_device(_dma_device_info
* dma_dev
, struct net_device
*dev
)
738 int num_tx_chan
, num_rx_chan
;
739 if (strcmp(dma_dev
->device_name
, "switch1") == 0) {
749 dma_dev
->num_tx_chan
= num_tx_chan
;
750 dma_dev
->num_rx_chan
= num_rx_chan
;
752 dma_dev
->tx_burst_len
= 4;
753 dma_dev
->rx_burst_len
= 4;
754 for (i
= 0; i
< dma_dev
->num_tx_chan
; i
++) {
755 dma_dev
->tx_chan
[i
].weight
= QOS_DEFAULT_WGT
;
756 dma_dev
->tx_chan
[i
].desc_num
= 10;
757 dma_dev
->tx_chan
[i
].packet_size
= 0;
758 dma_dev
->tx_chan
[i
].control
= 0;
760 for (i
= 0; i
< num_rx_chan
; i
++) {
761 dma_dev
->rx_chan
[i
].weight
= QOS_DEFAULT_WGT
;
762 dma_dev
->rx_chan
[i
].desc_num
= 10;
763 dma_dev
->rx_chan
[i
].packet_size
= ETHERNET_PACKET_DMA_BUFFER_SIZE
;
764 dma_dev
->rx_chan
[i
].control
= 0;
766 dma_dev
->intr_handler
= dma_intr_handler
;
767 dma_dev
->buffer_alloc
= dma_buffer_alloc
;
768 dma_dev
->buffer_free
= dma_buffer_free
;
772 int switch_set_mac_address(struct net_device
*dev
, void *p
)
774 struct sockaddr
*addr
= p
;
775 memcpy(dev
->dev_addr
, addr
->sa_data
, dev
->addr_len
);
780 int switch_init(struct net_device
*dev
)
785 struct switch_priv
*priv
;
786 ether_setup(dev
); /* assign some of the fields */
787 printk("%s up using ", dev
->name
);
788 dev
->open
= switch_open
;
789 dev
->stop
= switch_release
;
790 dev
->hard_start_xmit
= switch_tx
;
791 dev
->do_ioctl
= switch_ioctl
;
792 dev
->get_stats
= switch_stats
;
793 dev
->change_mtu
= switch_change_mtu
;
794 dev
->set_mac_address
= switch_set_mac_address
;
795 dev
->tx_timeout
= switch_tx_timeout
;
796 dev
->watchdog_timeo
= timeout
;
798 priv
= netdev_priv(dev
);
799 priv
->dma_device
= (struct dma_device_info
*) kmalloc(sizeof(struct dma_device_info
), GFP_KERNEL
);
800 if (priv
->num
== 0) {
801 sprintf(priv
->dma_device
->device_name
, "switch1");
802 } else if (priv
->num
== 1) {
803 sprintf(priv
->dma_device
->device_name
, "switch2");
805 printk("\"%s\"\n", priv
->dma_device
->device_name
);
806 init_dma_device(priv
->dma_device
, dev
);
807 result
= dma_device_register(priv
->dma_device
);
809 /* read the mac address from the mac table and put them into the mac table. */
810 for (i
= 0; i
< 6; i
++) {
811 retval
+= my_ethaddr
[i
];
813 /* ethaddr not set in u-boot ? */
815 dev
->dev_addr
[0] = 0x00;
816 dev
->dev_addr
[1] = 0x20;
817 dev
->dev_addr
[2] = 0xda;
818 dev
->dev_addr
[3] = 0x86;
819 dev
->dev_addr
[4] = 0x23;
820 dev
->dev_addr
[5] = 0x74 + (unsigned char) priv
->num
;
822 for (i
= 0; i
< 6; i
++) {
823 dev
->dev_addr
[i
] = my_ethaddr
[i
];
825 dev
->dev_addr
[5] += +(unsigned char) priv
->num
;
830 int switch_init_module(void)
832 int i
= 0, result
, device_present
= 0;
833 struct switch_priv
*priv
;
835 for (i
= 0; i
< AMAZON_SW_INT_NO
; i
++) {
836 switch_devs
[i
] = alloc_etherdev(sizeof(struct switch_priv
));
837 switch_devs
[i
]->init
= switch_init
;
838 strcpy(switch_devs
[i
]->name
, "eth%d");
839 priv
= (struct switch_priv
*) netdev_priv(switch_devs
[i
]);
841 if ((result
= register_netdev(switch_devs
[i
])))
842 printk("error %i registering device \"%s\"\n", result
, switch_devs
[i
]->name
);
846 amazon_sw_chip_init();
847 return device_present
? 0 : -ENODEV
;
850 void switch_cleanup(void)
853 struct switch_priv
*priv
;
854 for (i
= 0; i
< AMAZON_SW_INT_NO
; i
++) {
855 priv
= netdev_priv(switch_devs
[i
]);
856 if (priv
->dma_device
) {
857 dma_device_unregister(priv
->dma_device
);
858 kfree(priv
->dma_device
);
860 kfree(netdev_priv(switch_devs
[i
]));
861 unregister_netdev(switch_devs
[i
]);
866 module_init(switch_init_module
);
867 module_exit(switch_cleanup
);
869 MODULE_LICENSE("GPL");
870 MODULE_AUTHOR("Wu Qi Ming");