modules: package the leds-wndr3700-usb driver
[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
42
43 // TODO
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
51
52
53 #ifndef __KERNEL__
54 #define __KERNEL__
55 #endif
56
57
58 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
59 #define MODVERSIONS
60 #endif
61
62 #if defined(MODVERSIONS) && !defined(__GENKSYMS__)
63 #include <linux/modversions.h>
64 #endif
65
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>
76 #include <linux/in.h>
77 #include <linux/netdevice.h>
78 #include <linux/etherdevice.h>
79 #include <linux/ip.h>
80 #include <linux/tcp.h>
81 #include <linux/skbuff.h>
82 #include <linux/in6.h>
83 #include <linux/proc_fs.h>
84 #include <linux/mm.h>
85 #include <linux/ethtool.h>
86 #include <asm/checksum.h>
87 #include <linux/init.h>
88
89 #include <asm/amazon/amazon.h>
90 #include <asm/amazon/amazon_dma.h>
91 #include <asm/amazon/amazon_sw.h>
92
93 // how many mii ports are there ?
94 #define AMAZON_SW_INT_NO 2
95
96 #define ETHERNET_PACKET_DMA_BUFFER_SIZE 1536
97
98 /***************************************** Module Parameters *************************************/
99 char mode[] = "bridge";
100 module_param_array(mode, charp, NULL, 0);
101
102 static int timeout = 1 * HZ;
103 module_param(timeout, int, 0);
104
105 int switch_init(struct net_device *dev);
106 void switch_tx_timeout(struct net_device *dev);
107
108 static struct net_device *switch_devs[2];
109
110 int add_mac_table_entry(u64 entry_value)
111 {
112 int i;
113 u32 data1, data2;
114
115 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = ~7;
116
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)
123 continue;
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)) {};
128 break;
129 }
130 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) |= 7;
131 if (i >= 32)
132 return -1;
133 return OK;
134 }
135
136 u64 read_mac_table_entry(int index)
137 {
138 u32 data1, data2;
139 u64 value;
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;
145 return value;
146 }
147
148 int write_mac_table_entry(int index, u64 value)
149 {
150 u32 data1, data2;
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)) {};
157 return OK;
158 }
159
160 u32 get_mdio_reg(int phy_addr, int reg_num)
161 {
162 u32 value;
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;
166 return value;
167 }
168
169 int set_mdio_reg(int phy_addr, int reg_num, u32 value)
170 {
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)) {};
173 return OK;
174 }
175
176 int auto_negotiate(int phy_addr)
177 {
178 u32 value = 0;
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));
181 return OK;
182 }
183
184 /*
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
192 find its way out.
193 */
194 int amazon_sw_chip_init(void)
195 {
196 u32 tmp1;
197 int i = 0;
198
199 /* Aging tick select: 5mins */
200 tmp1 = 0xa0;
201 if (strcmp(mode, "bridge") == 0) {
202 // bridge mode, set militarised mode to 1, no learning!
203 tmp1 |= 0xC00;
204 } else {
205 // enable learning for P0 and P1,
206 tmp1 |= 3;
207 }
208
209 /* unknown broadcast/multicast/unicast to all ports */
210 AMAZON_SW_REG32(AMAZON_SW_UN_DEST) = 0x1ff;
211
212 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = tmp1;
213
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;
217 #else
218 AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x401;
219 #endif
220
221 /* EPC: 1 split the two NIC in tx direction CRC is generated */
222 AMAZON_SW_REG32(AMAZON_SW_P2_CTL) = 0x6;
223
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;
229
230 AMAZON_SW_REG32(AMAZON_CGU_PLL0SR) = (AMAZON_SW_REG32(AMAZON_CGU_PLL0SR)) | 0x58000000;
231 // clock for PHY
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;
237 while (1)
238 if (((AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG)) & 0x80000000) == 0)
239 break;
240 AMAZON_SW_REG32(AMAZON_SW_EPHY) = 0xff;
241
242 // auto negotiation
243 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = 0x83e08000;
244 auto_negotiate(0x1f);
245
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);
250 return 0;
251 }
252
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)
256 {
257 char *ep;
258 int i;
259
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;
263 if (line)
264 line = (*ep) ? ep + 1 : ep;
265 }
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]);
267 return 0;
268 }
269
270 __setup("ethaddr=", ethaddr_setup);
271
272 static void open_rx_dma(struct net_device *dev)
273 {
274 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
275 struct dma_device_info *dma_dev = priv->dma_device;
276 int i;
277
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);
281 }
282
283 #ifdef CONFIG_NET_HW_FLOWCONTROL
284 static void close_rx_dma(struct net_device *dev)
285 {
286 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
287 struct dma_device_info *dma_dev = priv->dma_device;
288 int i;
289
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);
293 }
294
295 void amazon_xon(struct net_device *dev)
296 {
297 unsigned long flag;
298 local_irq_save(flag);
299 open_rx_dma(dev);
300 local_irq_restore(flag);
301 }
302 #endif
303
304 int switch_open(struct net_device *dev)
305 {
306 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
307 if (!strcmp(dev->name, "eth1")) {
308 priv->mdio_phy_addr = PHY0_ADDR;
309 }
310 open_rx_dma(dev);
311
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");
315 }
316 #endif
317
318 netif_start_queue(dev);
319 return OK;
320 }
321
322 int switch_release(struct net_device *dev)
323 {
324 int i;
325 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
326 struct dma_device_info *dma_dev = priv->dma_device;
327
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;
332
333 dma_device_update(dma_dev);
334
335 #ifdef CONFIG_NET_HW_FLOWCONTROL
336 if (priv->fc_bit) {
337 netdev_unregister_fc(priv->fc_bit);
338 }
339 #endif
340 netif_stop_queue(dev);
341
342 return OK;
343 }
344
345
346 void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
347 {
348 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
349 #ifdef CONFIG_NET_HW_FLOWCONTROL
350 int mit_sel = 0;
351 #endif
352 skb->dev = dev;
353 skb->protocol = eth_type_trans(skb, dev);
354
355 #ifdef CONFIG_NET_HW_FLOWCONTROL
356 mit_sel = netif_rx(skb);
357 switch (mit_sel) {
358 case NET_RX_SUCCESS:
359 case NET_RX_CN_LOW:
360 case NET_RX_CN_MOD:
361 break;
362 case NET_RX_CN_HIGH:
363 break;
364 case NET_RX_DROP:
365 if ((priv->fc_bit)
366 && (!test_and_set_bit(priv->fc_bit, &netdev_fc_xoff))) {
367 close_rx_dma(dev);
368 }
369 break;
370 }
371 #else
372 netif_rx(skb);
373 #endif
374 priv->stats.rx_packets++;
375 priv->stats.rx_bytes += len;
376 return;
377 }
378
379 int asmlinkage switch_hw_tx(char *buf, int len, struct net_device *dev)
380 {
381 struct switch_priv *priv = netdev_priv(dev);
382 struct dma_device_info *dma_dev = priv->dma_device;
383
384 dma_dev->current_tx_chan = 0;
385 return dma_device_write(dma_dev, buf, len, priv->skb);
386 }
387
388 int asmlinkage switch_tx(struct sk_buff *skb, struct net_device *dev)
389 {
390 int len;
391 char *data;
392 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
393
394 len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
395 data = skb->data;
396 priv->skb = skb;
397 dev->trans_start = jiffies;
398
399 if (switch_hw_tx(data, len, dev) != len) {
400 dev_kfree_skb_any(skb);
401 return OK;
402 }
403
404 priv->stats.tx_packets++;
405 priv->stats.tx_bytes += len;
406 return OK;
407 }
408
409 void switch_tx_timeout(struct net_device *dev)
410 {
411 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
412 priv->stats.tx_errors++;
413 netif_wake_queue(dev);
414 return;
415 }
416
417 void negotiate(struct net_device *dev)
418 {
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);
421
422 data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);
423
424 switch (priv->current_speed_selection) {
425 case 10:
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;
430 else
431 data |= MDIO_ADVERT_10_HD | MDIO_ADVERT_10_FD;
432 break;
433
434 case 100:
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;
439 else
440 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD;
441 break;
442
443 case 0: /* Auto */
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;
448 else
449 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
450 break;
451
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;
454 }
455
456 set_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG, data);
457
458 /* Renegotiate with link partner */
459
460 data = get_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG);
461 data |= MDIO_BC_NEGOTIATE;
462
463 set_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG, data);
464
465 }
466
467
468 void set_duplex(struct net_device *dev, enum duplex new_duplex)
469 {
470 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
471 if (new_duplex != priv->current_duplex) {
472 priv->current_duplex = new_duplex;
473 negotiate(dev);
474 }
475 }
476
477 void set_speed(struct net_device *dev, unsigned long speed)
478 {
479 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
480 priv->current_speed_selection = speed;
481 negotiate(dev);
482 }
483
484 static int switch_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
485 {
486 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
487 struct ethtool_cmd ecmd;
488
489 if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
490 return -EFAULT;
491
492 switch (ecmd.cmd) {
493 case ETHTOOL_GSET:
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;
497 ecmd.port = PORT_TP;
498 ecmd.transceiver = XCVR_EXTERNAL;
499 ecmd.phy_address = priv->mdio_phy_addr;
500
501 ecmd.speed = priv->current_speed;
502
503 ecmd.duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
504
505 ecmd.advertising = ADVERTISED_TP;
506 if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
507 ecmd.advertising |= ADVERTISED_Autoneg;
508 else {
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);
519 }
520 ecmd.autoneg = AUTONEG_ENABLE;
521 if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
522 return -EFAULT;
523 break;
524
525 case ETHTOOL_SSET:
526 if (!capable(CAP_NET_ADMIN)) {
527 return -EPERM;
528 }
529 if (ecmd.autoneg == AUTONEG_ENABLE) {
530 set_duplex(dev, autoneg);
531 set_speed(dev, 0);
532 } else {
533 set_duplex(dev, ecmd.duplex == DUPLEX_HALF ? half : full);
534 set_speed(dev, ecmd.speed == SPEED_10 ? 10 : 100);
535 }
536 break;
537
538 case ETHTOOL_GDRVINFO:
539 {
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;
546 info.eedump_len = 0;
547 info.testinfo_len = 0;
548 if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
549 return -EFAULT;
550 }
551 break;
552 case ETHTOOL_NWAY_RST:
553 if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
554 negotiate(dev);
555 break;
556 default:
557 return -EOPNOTSUPP;
558 break;
559 }
560 return 0;
561 }
562
563
564
565 int mac_table_tools_ioctl(struct net_device *dev, struct mac_table_req *req)
566 {
567 int cmd;
568 int i;
569 cmd = req->cmd;
570 switch (cmd) {
571 case RESET_MAC_TABLE:
572 for (i = 0; i < 32; i++) {
573 write_mac_table_entry(i, 0);
574 }
575 break;
576 case READ_MAC_ENTRY:
577 req->entry_value = read_mac_table_entry(req->index);
578 break;
579 case WRITE_MAC_ENTRY:
580 write_mac_table_entry(req->index, req->entry_value);
581 break;
582 case ADD_MAC_ENTRY:
583 add_mac_table_entry(req->entry_value);
584 break;
585 default:
586 return -EINVAL;
587 }
588
589 return 0;
590 }
591
592
593 /*
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.
599 */
600 int switch_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
601 {
602 struct data_req *switch_data_req = (struct data_req *) ifr->ifr_data;
603 struct mac_table_req *switch_mac_table_req;
604 switch (cmd) {
605 case SIOCETHTOOL:
606 switch_ethtool_ioctl(dev, ifr);
607 break;
608 case SIOCGMIIPHY: /* Get PHY address */
609 break;
610 case SIOCGMIIREG: /* Read MII register */
611 break;
612 case SIOCSMIIREG: /* Write MII register */
613 break;
614 case SET_ETH_SPEED_10: /* 10 Mbps */
615 break;
616 case SET_ETH_SPEED_100: /* 100 Mbps */
617 break;
618 case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */
619 break;
620 case SET_ETH_DUPLEX_HALF: /* Half duplex. */
621 break;
622 case SET_ETH_DUPLEX_FULL: /* Full duplex. */
623 break;
624 case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex */
625 break;
626 case SET_ETH_REG:
627 AMAZON_SW_REG32(switch_data_req->index) = switch_data_req->value;
628 break;
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);
632 break;
633 default:
634 return -EINVAL;
635 }
636
637 return 0;
638 }
639
640 struct net_device_stats *switch_stats(struct net_device *dev)
641 {
642 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
643 return &priv->stats;
644 }
645
646 int switch_change_mtu(struct net_device *dev, int new_mtu)
647 {
648 if (new_mtu >= 1516)
649 new_mtu = 1516;
650 dev->mtu = new_mtu;
651 return 0;
652 }
653
654 int switch_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
655 {
656 u8 *buf = NULL;
657 int len = 0;
658 struct sk_buff *skb = NULL;
659
660 len = dma_device_read(dma_dev, &buf, (void **) &skb);
661
662 if (len >= 0x600) {
663 printk("packet too large %d\n", len);
664 goto switch_hw_receive_err_exit;
665 }
666
667 /* remove CRC */
668 len -= 4;
669 if (skb == NULL) {
670 printk("cannot restore pointer\n");
671 goto switch_hw_receive_err_exit;
672 }
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;
676 }
677 skb_put(skb, len);
678 skb->dev = dev;
679 switch_rx(dev, len, skb);
680 return OK;
681
682 switch_hw_receive_err_exit:
683 if (skb)
684 dev_kfree_skb_any(skb);
685 return -EIO;
686 }
687
688 int dma_intr_handler(struct dma_device_info *dma_dev, int status)
689 {
690 struct net_device *dev;
691
692 dev = dma_dev->priv;
693 switch (status) {
694 case RCV_INT:
695 switch_hw_receive(dev, dma_dev);
696 break;
697 case TX_BUF_FULL_INT:
698 netif_stop_queue(dev);
699 break;
700 case TRANSMIT_CPT_INT:
701 netif_wake_queue(dev);
702 break;
703 }
704 return OK;
705 }
706
707 /* reserve 2 bytes in front of data pointer*/
708 u8 *dma_buffer_alloc(int len, int *byte_offset, void **opt)
709 {
710 u8 *buffer = NULL;
711 struct sk_buff *skb = NULL;
712 skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
713 if (skb == NULL) {
714 return NULL;
715 }
716 buffer = (u8 *) (skb->data);
717 skb_reserve(skb, 2);
718 *(int *) opt = (int) skb;
719 *byte_offset = 2;
720 return buffer;
721 }
722
723 int dma_buffer_free(u8 * dataptr, void *opt)
724 {
725 struct sk_buff *skb = NULL;
726 if (opt == NULL) {
727 kfree(dataptr);
728 } else {
729 skb = (struct sk_buff *) opt;
730 dev_kfree_skb_any(skb);
731 }
732 return OK;
733 }
734
735 int init_dma_device(_dma_device_info * dma_dev, struct net_device *dev)
736 {
737 int i;
738 int num_tx_chan, num_rx_chan;
739 if (strcmp(dma_dev->device_name, "switch1") == 0) {
740 num_tx_chan = 1;
741 num_rx_chan = 2;
742 } else {
743 num_tx_chan = 1;
744 num_rx_chan = 2;
745 }
746 dma_dev->priv = dev;
747
748 dma_dev->weight = 1;
749 dma_dev->num_tx_chan = num_tx_chan;
750 dma_dev->num_rx_chan = num_rx_chan;
751 dma_dev->ack = 1;
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;
759 }
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;
765 }
766 dma_dev->intr_handler = dma_intr_handler;
767 dma_dev->buffer_alloc = dma_buffer_alloc;
768 dma_dev->buffer_free = dma_buffer_free;
769 return 0;
770 }
771
772 int switch_set_mac_address(struct net_device *dev, void *p)
773 {
774 struct sockaddr *addr = p;
775 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
776 return OK;
777 }
778
779
780 int switch_init(struct net_device *dev)
781 {
782 u64 retval = 0;
783 int i;
784 int result;
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;
797
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");
804 }
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);
808
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];
812 }
813 /* ethaddr not set in u-boot ? */
814 if (retval == 0) {
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;
821 } else {
822 for (i = 0; i < 6; i++) {
823 dev->dev_addr[i] = my_ethaddr[i];
824 }
825 dev->dev_addr[5] += +(unsigned char) priv->num;
826 }
827 return OK;
828 }
829
830 int switch_init_module(void)
831 {
832 int i = 0, result, device_present = 0;
833 struct switch_priv *priv;
834
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]);
840 priv->num = i;
841 if ((result = register_netdev(switch_devs[i])))
842 printk("error %i registering device \"%s\"\n", result, switch_devs[i]->name);
843 else
844 device_present++;
845 }
846 amazon_sw_chip_init();
847 return device_present ? 0 : -ENODEV;
848 }
849
850 void switch_cleanup(void)
851 {
852 int i;
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);
859 }
860 kfree(netdev_priv(switch_devs[i]));
861 unregister_netdev(switch_devs[i]);
862 }
863 return;
864 }
865
866 module_init(switch_init_module);
867 module_exit(switch_cleanup);
868
869 MODULE_LICENSE("GPL");
870 MODULE_AUTHOR("Wu Qi Ming");
This page took 0.090126 seconds and 5 git commands to generate.