Changeset e1e379b in freewrt


Ignore:
Timestamp:
Nov 16, 2006, 12:29:12 AM (19 years ago)
Author:
Phil Sutter <n0-1@…>
Children:
6615be8
Parents:
7a23d2e
Message:
  • reorganized patches again (hope now finally)
  • added yaffs2 support

git-svn-id: svn://www.freewrt.org/trunk/freewrt@1142 afb5a338-a214-0410-bd46-81f09a774fd1

Location:
target/linux/rb-2.4/patches
Files:
4 added
2 deleted
2 moved

Legend:

Unmodified
Added
Removed
  • target/linux/rb-2.4/patches/004-net.patch

    r7a23d2e re1e379b  
     1diff -NaurB linux-2.4.33.3/drivers/net/admtek.c linux-2.4.33.3.patched/drivers/net/admtek.c
     2--- linux-2.4.33.3/drivers/net/admtek.c 1970-01-01 01:00:00.000000000 +0100
     3+++ linux-2.4.33.3.patched/drivers/net/admtek.c 2006-11-15 10:34:04.000000000 +0100
     4@@ -0,0 +1,812 @@
     5+#include <asm/unaligned.h>
     6+#include <linux/module.h>
     7+#include <linux/init.h>
     8+#include <linux/bitops.h>
     9+#include <linux/pci.h>
     10+#include <linux/netdevice.h>
     11+#include <linux/etherdevice.h>
     12+#include <linux/ethtool.h>
     13+
     14+
     15+#define ADMTEK_REG_BASE                0x12000000
     16+
     17+// register offsets
     18+#define SWReset_REG            0x000C
     19+#define PHY_st_REG             0x0014
     20+#define Port_st_REG            0x0018
     21+#define SW_conf_REG            0x0020
     22+#define CPUp_conf_REG          0x0024
     23+#define Port_conf0_REG         0x0028
     24+#define Port_conf1_REG         0x002C
     25+#define Port_conf2_REG         0x0030
     26+#define VLAN_G1_REG            0x0040
     27+#define VLAN_G2_REG            0x0044
     28+#define Send_trig_REG          0x0048
     29+#define MAC_wt0_REG            0x0058
     30+#define MAC_wt1_REG            0x005C
     31+#define PHY_cntl0_REG          0x0068
     32+#define PHY_cntl1_REG          0x006C
     33+#define PHY_cntl2_REG          0x007C
     34+#define PHY_cntl3_REG          0x0080
     35+#define SW_Int_st_REG          0x00B0
     36+#define SW_Int_mask_REG                0x00B4
     37+#define Send_HBaddr_REG                0x00D0
     38+#define Send_LBaddr_REG                0x00D4
     39+#define Recv_HBaddr_REG                0x00D8
     40+#define Recv_LBaddr_REG                0x00DC
     41+#define Send_HWaddr_REG                0x00E0
     42+#define Send_LWaddr_REG                0x00E4
     43+#define Recv_HWaddr_REG                0x00E8
     44+#define Recv_LWaddr_REG                0x00EC
     45+
     46+#define ADMTEK_REG(reg) \
     47+    (*((volatile unsigned long *)(KSEG1ADDR(ADMTEK_REG_BASE + (reg)))))
     48+
     49+
     50+/* CPUp_conf_REG */
     51+#define SW_CPU_PORT_DISABLE    0x00000001
     52+#define SW_PADING_CRC          0x00000002
     53+
     54+#define SW_DIS_UN_SHIFT                9
     55+#define SW_DIS_UN_MASK         (0x3F << SW_DIS_UN_SHIFT)
     56+#define SW_DIS_MC_SHIFT                16
     57+#define SW_DIS_MC_MASK         (0x3F << SW_DIS_MC_SHIFT)
     58+#define SW_DIS_BC_SHIFT                24
     59+#define SW_DIS_BC_MASK         (0x3F << SW_DIS_BC_SHIFT)
     60+
     61+/* Port_conf0_REG */
     62+#define SW_DISABLE_PORT_MASK   0x0000003F
     63+#define SW_EN_MC_MASK          0x00003F00
     64+#define SW_EN_MC_SHIFT         8
     65+#define SW_EN_BP_MASK          0x003F0000
     66+#define SW_EN_BP_SHIFT         16
     67+#define SW_EN_FC_MASK          0x3F000000
     68+#define SW_EN_FC_SHIFT         24
     69+
     70+/* MAC_wt0_REG */
     71+#define SW_MAC_WRITE           0x00000001
     72+#define SW_MAC_WRITE_DONE      0x00000002
     73+#define SW_MAC_VLANID_SHIFT    3
     74+#define SW_MAC_VLANID_MASK     0x00000038
     75+#define SW_MAC_VLANID_EN       0x00000040
     76+
     77+/* PHY_cntl0_REG */
     78+#define SW_PHY_WRITE           0x00002000
     79+#define SW_PHY_READ            0x00004000
     80+
     81+/* PHY_cntl2_REG */
     82+#define SW_PHY_AN_MASK         0x0000001F
     83+#define SW_PHY_NORMAL_MASK     0x01F00000
     84+
     85+/* SW_Int_st_REG & SW_Int_mask_REG */
     86+#define TX_H_INT               0x0000001
     87+#define TX_L_INT               0x0000002
     88+#define RX_H_INT               0x0000004
     89+#define RX_L_INT               0x0000008
     90+#define RX_H_DESC_FULL_INT     0x0000010
     91+#define RX_L_DESC_FULL_INT     0x0000020
     92+#define PORT_STATUS_CHANGE_INT 0x0040000
     93+#define RX_DESC_ERR_INT                0x0400000
     94+#define TX_DESC_ERR_INT                0x0800000
     95+#define SWITCH_INT_MASK                0x1FDEFFF
     96+
     97+
     98+
     99+// descriptor bits
     100+#define DESC_OWN           0x80000000
     101+#define DESC_RING_END      0x10000000
     102+#define DESC_ADDR_MASK     0x00ffffff
     103+#define DESC_LEN_MASK      0x07ff0000
     104+#define DESC_LEN_SHIFT     16
     105+
     106+// rx descr status
     107+#define DESC_RX_PORT_MASK  0x00007000
     108+#define DESC_RX_PORT_SHIFT 12
     109+#define DESC_RX_FRAME_MASK 0x00000030
     110+#define DESC_RX_FRAME_UC   0x00000000
     111+#define DESC_RX_FRAME_MC   0x00000010
     112+#define DESC_RX_FRAME_BC   0x00000020
     113+#define DESC_RX_CSUM_ERR   0x00000008
     114+#define DESC_RX_VLAN_TAG   0x00000004
     115+
     116+// tx descr ctrl
     117+#define DESC_TX_CSUM       0x80000000
     118+#define DESC_TX_PORT_MASK  0x00003F00
     119+#define DESC_TX_VLAN_MASK  0x0000003F
     120+
     121+
     122+#define RX_BUF_SIZE 1550
     123+
     124+#define SW_IRQ 9
     125+
     126+#define VLAN_PORT_MASK 0x7f
     127+
     128+
     129+struct admtek_rx_desc {
     130+    unsigned long buf1;
     131+    unsigned long buf2;
     132+    unsigned long len;
     133+    unsigned long status;
     134+};
     135+
     136+struct admtek_tx_desc {
     137+    unsigned long buf1;
     138+    unsigned long buf2;
     139+    unsigned long len;
     140+    unsigned long ctrl;
     141+};
     142+
     143+#define RX_DESC_COUNT 128
     144+#define TX_DESC_PER_PORT 32
     145+#define PORT_COUNT 5
     146+#define TX_DESC_COUNT ((TX_DESC_PER_PORT + 1) * PORT_COUNT)
     147+
     148+struct admtek_dev_priv {
     149+    struct net_device *dev;
     150+    struct net_device_stats stats;
     151+
     152+    unsigned port;
     153+
     154+    int in_transmit;
     155+};
     156+
     157+
     158+struct admtek_switch {
     159+    struct admtek_rx_desc *rx_descs;
     160+    struct admtek_tx_desc *tx_descs;
     161+    dma_addr_t rx_descs_dma;
     162+    dma_addr_t tx_descs_dma;
     163+
     164+    struct sk_buff **rx_skbs;
     165+    struct sk_buff **tx_skbs;
     166+
     167+    unsigned cur_rx, dirty_rx;
     168+    unsigned cur_tx, dirty_tx;
     169+
     170+    struct net_device *devs[PORT_COUNT];
     171+
     172+    spinlock_t lock;
     173+
     174+    struct tasklet_struct rx_tasklet;
     175+    struct tasklet_struct tx_tasklet;
     176+
     177+    unsigned link_status;
     178+
     179+    unsigned irq;
     180+};
     181+
     182+static struct admtek_switch sw;
     183+
     184+extern unsigned char mips_mac_address[6];
     185+
     186+
     187+static void admtek_init_engine(void) {
     188+    unsigned i;
     189+
     190+    // initialize engine
     191+    ADMTEK_REG(CPUp_conf_REG) =
     192+       SW_CPU_PORT_DISABLE | SW_PADING_CRC | SW_DIS_UN_MASK;
     193+    ADMTEK_REG(Port_conf0_REG) =
     194+       SW_EN_BP_MASK | SW_EN_MC_MASK | SW_DISABLE_PORT_MASK;
     195+    for (i = 0; i < 500000; i++);
     196+    ADMTEK_REG(PHY_cntl2_REG) |= SW_PHY_AN_MASK | SW_PHY_NORMAL_MASK;
     197+    ADMTEK_REG(PHY_cntl3_REG) |= 0x400;
     198+    ADMTEK_REG(SW_Int_mask_REG) = SWITCH_INT_MASK;
     199+    ADMTEK_REG(SW_Int_st_REG) = SWITCH_INT_MASK;
     200+    ADMTEK_REG(Send_LBaddr_REG) = sw.tx_descs_dma;
     201+    ADMTEK_REG(Send_HBaddr_REG) = sw.tx_descs_dma;
     202+    ADMTEK_REG(Recv_LBaddr_REG) = sw.rx_descs_dma;
     203+    ADMTEK_REG(Recv_HBaddr_REG) = sw.rx_descs_dma;
     204+    ADMTEK_REG(VLAN_G1_REG) = 0;
     205+    ADMTEK_REG(VLAN_G2_REG) = 0;
     206+    ADMTEK_REG(CPUp_conf_REG) &= ~SW_CPU_PORT_DISABLE;
     207+
     208+    // setup vlans
     209+    for (i = 0; i < PORT_COUNT; ++i) {
     210+       unsigned long reg, shiftcnt;
     211+       if (i <= 3) {
     212+           shiftcnt = 8 * i;
     213+           reg = ADMTEK_REG(VLAN_G1_REG) & ~(VLAN_PORT_MASK << shiftcnt);
     214+           reg |= (0x40 | (1 << i)) << shiftcnt;
     215+           ADMTEK_REG(VLAN_G1_REG) = reg;
     216+       }
     217+       else {
     218+           shiftcnt = 8 * (i - 4);
     219+           reg = ADMTEK_REG(VLAN_G2_REG) & ~(VLAN_PORT_MASK << shiftcnt);
     220+           reg |= (0x40 | (1 << i)) << shiftcnt;
     221+           ADMTEK_REG(VLAN_G2_REG) = reg;
     222+       }
     223+    }
     224+}
     225+
     226+static void admtek_init_descs(void) {
     227+    unsigned i;
     228+
     229+    memset(sw.rx_descs, 0, sizeof(struct admtek_rx_desc) * RX_DESC_COUNT);
     230+    for (i = 0; i < RX_DESC_COUNT; ++i) {
     231+       sw.rx_descs[i].len = RX_BUF_SIZE;
     232+       sw.rx_descs[i].buf1 =
     233+           ((unsigned long)sw.rx_skbs[i]->data & DESC_ADDR_MASK) | DESC_OWN;
     234+    }
     235+    sw.rx_descs[RX_DESC_COUNT - 1].buf1 |= DESC_RING_END;
     236+
     237+    memset(sw.tx_descs, 0, sizeof(struct admtek_tx_desc) * TX_DESC_COUNT);
     238+    sw.tx_descs[TX_DESC_COUNT - 1].buf1 |= DESC_RING_END;
     239+
     240+    memset(sw.tx_skbs, 0, sizeof(struct sk_buff *) * TX_DESC_COUNT);
     241+}
     242+
     243+static void admtek_rx_tasklet(unsigned long dum) {
     244+    struct admtek_rx_desc *desc;
     245+    unsigned port;
     246+    struct net_device *dev;
     247+    struct admtek_dev_priv *priv;
     248+    unsigned len;
     249+    struct sk_buff *skb;
     250+    unsigned long flags;
     251+
     252+    spin_lock_irqsave(&sw.lock, flags);
     253+
     254+    while (1) {
     255+       desc = sw.rx_descs + sw.cur_rx;
     256+       if (desc->buf1 & DESC_OWN) break;
     257+
     258+       port = (desc->status & DESC_RX_PORT_MASK) >> DESC_RX_PORT_SHIFT;
     259+
     260+       dev = sw.devs[port];
     261+       priv = dev->priv;
     262+
     263+       len = ((desc->status & DESC_LEN_MASK) >> DESC_LEN_SHIFT) - 4;
     264+//     printk("rx status: %08lx, port: %u, len: %u, dev: %s\n",
     265+//            desc->status, port, len, dev->name);
     266+       if (!len || desc->status & DESC_RX_CSUM_ERR) {
     267+           printk("admtek: rx error\n");
     268+           priv->stats.rx_errors++;
     269+           priv->stats.rx_length_errors++;
     270+           goto next;
     271+       }
     272+
     273+       if (netif_running(dev)) {
     274+           skb = sw.rx_skbs[sw.cur_rx];
     275+           skb_put(skb, len);
     276+           skb->dev = dev;
     277+           skb->protocol = eth_type_trans(skb, dev);
     278+           skb->ip_summed = CHECKSUM_UNNECESSARY;
     279+
     280+           // only place we need to flush cache
     281+           dma_cache_wback_inv((unsigned long)skb->head, len);
     282+
     283+           dev->last_rx = jiffies;
     284+           priv->stats.rx_packets++;
     285+           priv->stats.rx_bytes += skb->len;
     286+           netif_rx(skb);
     287+           skb = dev_alloc_skb(RX_BUF_SIZE + 16);
     288+           if (skb) skb_reserve(skb, 2);
     289+           else {
     290+               printk("admtek: alloc rx skb failed\n");
     291+           }
     292+           sw.rx_skbs[sw.cur_rx] = skb;
     293+       }
     294+
     295+       if (sw.rx_skbs[sw.cur_rx]) {
     296+       next:
     297+           skb = sw.rx_skbs[sw.cur_rx];
     298+           desc->buf2 = 0;
     299+           desc->status = 0;
     300+           desc->len = RX_BUF_SIZE;
     301+           desc->buf1 = (desc->buf1 & DESC_RING_END) | DESC_OWN
     302+               | (((unsigned long)skb->data) & DESC_ADDR_MASK);
     303+       }
     304+       else {
     305+           printk("admtek: not enough mem\n");
     306+       }
     307+
     308+       ++sw.cur_rx;
     309+       if (sw.cur_rx >= RX_DESC_COUNT) sw.cur_rx = 0;
     310+    }
     311+    ADMTEK_REG(SW_Int_mask_REG) = (ADMTEK_REG(SW_Int_mask_REG) & ~RX_L_INT);
     312+    spin_unlock_irqrestore(&sw.lock, flags);
     313+}
     314+
     315+static void admtek_tx_tasklet(unsigned long dum) {
     316+    struct admtek_tx_desc *desc;
     317+    struct admtek_dev_priv *priv;
     318+    unsigned long flags;
     319+
     320+    spin_lock_irqsave(&sw.lock, flags);
     321+
     322+    while (1) {
     323+       desc = sw.tx_descs + sw.dirty_tx;
     324+       if (desc->buf1 & DESC_OWN) break;
     325+       if (sw.cur_tx == sw.dirty_tx) break;
     326+
     327+       priv = sw.devs[ffs(desc->ctrl) - 1]->priv;
     328+       if (priv->in_transmit >= TX_DESC_PER_PORT) {
     329+//         printk("%lu: start queue: %s, %u\n",
     330+//                jiffies, priv->dev->name, priv->in_transmit);
     331+           netif_start_queue(priv->dev);
     332+       }
     333+       --priv->in_transmit;
     334+
     335+       dev_kfree_skb_any(sw.tx_skbs[sw.dirty_tx]);
     336+       sw.tx_skbs[sw.dirty_tx] = NULL;
     337+
     338+       ++sw.dirty_tx;
     339+       if (sw.dirty_tx >= TX_DESC_COUNT) sw.dirty_tx = 0;
     340+    }
     341+
     342+    ADMTEK_REG(SW_Int_mask_REG) = (ADMTEK_REG(SW_Int_mask_REG) & ~TX_L_INT);
     343+    spin_unlock_irqrestore(&sw.lock, flags);
     344+}
     345+
     346+static void admtek_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
     347+    unsigned long status, mask;
     348+//    printk("admtek_interrupt\n");
     349+
     350+    spin_lock(&sw.lock);
     351+
     352+    mask = ADMTEK_REG(SW_Int_mask_REG);
     353+
     354+    // get status
     355+    status = ADMTEK_REG(SW_Int_st_REG);
     356+//    if (status & ~(RX_L_INT | TX_L_INT | PORT_STATUS_CHANGE_INT)) {
     357+//     printk("interrupt status: %08lx mask: %08lx\n", status, mask);
     358+//    }
     359+
     360+    // acknowledge
     361+    ADMTEK_REG(SW_Int_st_REG ) = status;
     362+
     363+    if (status & RX_L_INT) {
     364+       mask |= RX_L_INT;
     365+       tasklet_hi_schedule(&sw.rx_tasklet);
     366+    }
     367+    if (status & TX_L_INT) {
     368+       mask |= TX_L_INT;
     369+       tasklet_hi_schedule(&sw.tx_tasklet);
     370+    }
     371+    if (status & PORT_STATUS_CHANGE_INT) {
     372+       unsigned new_status = ADMTEK_REG(PHY_st_REG);
     373+       unsigned i;
     374+       for (i = 0; i < PORT_COUNT; ++i) {
     375+           if (!sw.devs[i] || !netif_running(sw.devs[i])) continue;
     376+           if (((new_status & (1 << i))) != ((sw.link_status & (1 << i)))) {
     377+               if ((new_status & (1 << i))) {
     378+                   printk("admtek: link up for %s\n", sw.devs[i]->name);
     379+                   netif_carrier_on(sw.devs[i]);
     380+               }
     381+               else {
     382+                   printk("admtek: link down for %s\n", sw.devs[i]->name);
     383+                   netif_carrier_off(sw.devs[i]);
     384+               }
     385+           }
     386+       }
     387+       sw.link_status = new_status;
     388+    }
     389+
     390+    ADMTEK_REG(SW_Int_mask_REG) = mask;
     391+    spin_unlock(&sw.lock);
     392+}
     393+
     394+
     395+static int admtek_open(struct net_device *dev) {
     396+    struct admtek_dev_priv *priv = dev->priv;
     397+    unsigned long reg;
     398+//    printk("admtek_open: %s\n", dev->name);
     399+
     400+    // set mac
     401+//    printk("port #%d mac = %02x:%02x:%02x:%02x:%02x:%02x\n", priv->port,
     402+//        dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
     403+//        dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
     404+
     405+    reg = (dev->dev_addr[5] << 24) | (dev->dev_addr[4] << 16) |
     406+       (dev->dev_addr[3] << 8) | dev->dev_addr[2];
     407+    ADMTEK_REG(MAC_wt1_REG) = reg;
     408+
     409+    reg = (dev->dev_addr[1] << 24) | (dev->dev_addr[0] << 16) |
     410+       (priv->port << SW_MAC_VLANID_SHIFT) | SW_MAC_WRITE | SW_MAC_VLANID_EN;
     411+    ADMTEK_REG(MAC_wt0_REG) = reg;
     412+
     413+    while (!(ADMTEK_REG(MAC_wt0_REG) & SW_MAC_WRITE_DONE));
     414+
     415+    reg = ADMTEK_REG(PHY_st_REG);
     416+    if ((reg & (1 << priv->port))) {
     417+       printk("admtek: initial link up for %s\n", dev->name);
     418+       netif_carrier_on(dev);
     419+       sw.link_status |= (1 << priv->port);
     420+    }
     421+    else {
     422+       printk("admtek: initial link down for %s\n", dev->name);
     423+       netif_carrier_off(dev);
     424+       sw.link_status &= ~(1 << priv->port);
     425+    }
     426+
     427+    // enable port
     428+    ADMTEK_REG(Port_conf0_REG) &= ~(1 << priv->port);
     429+
     430+    netif_start_queue(dev);
     431+    return 0;
     432+}
     433+
     434+static int admtek_stop(struct net_device *dev) {
     435+    struct admtek_dev_priv *priv = dev->priv;
     436+//    printk("admtek_stop: %s\n", dev->name);
     437+
     438+    netif_stop_queue(dev);
     439+
     440+    // disable port
     441+    ADMTEK_REG(Port_conf0_REG) |= (1 << priv->port);
     442+
     443+    return 0;
     444+}
     445+
     446+static void admtek_set_multicast_list(struct net_device *dev) {
     447+    struct admtek_dev_priv *priv = dev->priv;
     448+//    printk("admtek_set_multicast_list: %s\n", dev->name);
     449+
     450+    if (dev->flags & IFF_PROMISC) {
     451+       printk("admtek: enable promisc for %s\n", dev->name);
     452+       ADMTEK_REG(CPUp_conf_REG) &= ~((1 << priv->port) << 9);
     453+    }
     454+    else {
     455+       printk("admtek: disable promisc for %s\n", dev->name);
     456+       ADMTEK_REG(CPUp_conf_REG) |= ((1 << priv->port) << 9);
     457+    }
     458+
     459+}
     460+
     461+static int admtek_hard_start_xmit(struct sk_buff *skb,
     462+                                 struct net_device *dev) {
     463+    struct admtek_dev_priv *priv = dev->priv;
     464+    struct admtek_tx_desc *desc;
     465+    unsigned len;
     466+    unsigned long flags;
     467+//    printk("admtek_hard_start_xmit: %s\n", dev->name);
     468+
     469+    spin_lock_irqsave(&sw.lock, flags);
     470+
     471+    desc = sw.tx_descs + sw.cur_tx;
     472+    if (desc->buf1 & DESC_OWN) {
     473+       printk("admtek: queue not stopped when it should be\n");
     474+       dev_kfree_skb(skb);
     475+       priv->stats.tx_dropped++;
     476+       return 0;
     477+    }
     478+
     479+    sw.tx_skbs[sw.cur_tx] = skb;
     480+
     481+    desc->buf1 = (desc->buf1 & DESC_RING_END) |
     482+       ((unsigned long)skb->data & DESC_ADDR_MASK) | DESC_OWN;
     483+    len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
     484+    desc->ctrl = (len << DESC_LEN_SHIFT) | (1 << priv->port);
     485+    desc->len = len;
     486+
     487+    ADMTEK_REG(Send_trig_REG) = 1;
     488+
     489+    priv->stats.tx_packets++;
     490+    priv->stats.tx_bytes += len;
     491+    dev->trans_start = jiffies;
     492+
     493+    ++sw.cur_tx;
     494+    if (sw.cur_tx >= TX_DESC_COUNT) sw.cur_tx = 0;
     495+
     496+    priv->in_transmit++;
     497+    if (priv->in_transmit >= TX_DESC_PER_PORT) {
     498+//     printk("%lu: stop queue: %s, %u\n",
     499+//            jiffies, dev->name, priv->in_transmit);
     500+       netif_stop_queue(dev);
     501+    }
     502+
     503+    spin_unlock_irqrestore(&sw.lock, flags);
     504+    return 0;
     505+}
     506+
     507+static void admtek_get_drvinfo (struct net_device *dev,
     508+                               struct ethtool_drvinfo *info) {
     509+    strcpy(info->driver, "admtek");
     510+    strcpy(info->version, "1.0");
     511+}
     512+
     513+static int admtek_get_settings(struct net_device *dev,
     514+                              struct ethtool_cmd *cmd) {
     515+    struct admtek_dev_priv *priv = dev->priv;
     516+    unsigned long reg;
     517+    spin_lock_irq(&sw.lock);
     518+
     519+    // inspired from mii.c
     520+    cmd->supported =
     521+       (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
     522+        SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
     523+        SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
     524+    cmd->port = PORT_MII;
     525+    cmd->transceiver = XCVR_INTERNAL;
     526+    cmd->phy_address = 0;
     527+
     528+    cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
     529+    cmd->advertising |= ADVERTISED_10baseT_Half;
     530+    cmd->advertising |= ADVERTISED_10baseT_Full;
     531+    cmd->advertising |= ADVERTISED_100baseT_Half;
     532+    cmd->advertising |= ADVERTISED_100baseT_Full;
     533+
     534+    reg = ADMTEK_REG(PHY_cntl2_REG);
     535+    if ((reg & (1 << priv->port))) {
     536+       cmd->advertising |= ADVERTISED_Autoneg;
     537+       cmd->autoneg = AUTONEG_ENABLE;
     538+    }
     539+    else cmd->autoneg = AUTONEG_DISABLE;
     540+
     541+    reg = ADMTEK_REG(PHY_st_REG);
     542+    if ((reg & ((1 << 8) << priv->port))) cmd->speed = SPEED_100;
     543+    else cmd->speed = SPEED_10;
     544+    if ((reg & ((1 << 16) << priv->port))) cmd->duplex = DUPLEX_FULL;
     545+    else cmd->duplex = DUPLEX_HALF;
     546+
     547+    spin_unlock_irq(&sw.lock);
     548+    return 0;
     549+}
     550+
     551+static int admtek_set_settings(struct net_device *dev,
     552+                              struct ethtool_cmd *cmd) {
     553+    struct admtek_dev_priv *priv = dev->priv;
     554+    spin_lock_irq(&sw.lock);
     555+
     556+    // inspired from mii.c
     557+    if (cmd->speed != SPEED_10 && cmd->speed != SPEED_100)
     558+       return -EINVAL;
     559+    if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
     560+       return -EINVAL;
     561+    if (cmd->port != PORT_MII)
     562+       return -EINVAL;
     563+    if (cmd->transceiver != XCVR_INTERNAL)
     564+       return -EINVAL;
     565+    if (cmd->autoneg != AUTONEG_DISABLE && cmd->autoneg != AUTONEG_ENABLE)
     566+       return -EINVAL;
     567+
     568+    if (cmd->autoneg == AUTONEG_ENABLE) {
     569+       ADMTEK_REG(PHY_cntl2_REG) |= (1 << priv->port);
     570+       ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 5) << priv->port);
     571+       ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 10) << priv->port);
     572+    } else {
     573+       ADMTEK_REG(PHY_cntl2_REG) &= ~(1 << priv->port);
     574+
     575+       if (cmd->speed == SPEED_100) {
     576+           ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 5) << priv->port);
     577+       }
     578+       else {
     579+           ADMTEK_REG(PHY_cntl2_REG) &= ~((1 << 5) << priv->port);
     580+       }
     581+
     582+       if (cmd->duplex == DUPLEX_FULL) {
     583+           ADMTEK_REG(PHY_cntl2_REG) |= ((1 << 10) << priv->port);
     584+       }
     585+       else {
     586+           ADMTEK_REG(PHY_cntl2_REG) &= ~((1 << 10) << priv->port);
     587+       }
     588+    }
     589+
     590+    spin_unlock_irq(&sw.lock);
     591+    return 0;
     592+}
     593+
     594+static u32 admtek_get_link(struct net_device *dev) {
     595+    struct admtek_dev_priv *priv = dev->priv;
     596+
     597+    return !!(sw.link_status & (1 << priv->port));
     598+}
     599+
     600+
     601+static struct ethtool_ops admtek_ethtool_ops = {
     602+    .get_drvinfo       = admtek_get_drvinfo,
     603+    .get_settings      = admtek_get_settings,
     604+    .set_settings      = admtek_set_settings,
     605+    .get_link          = admtek_get_link,
     606+};
     607+
     608+static int admtek_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) {
     609+    return -EINVAL;
     610+}
     611+
     612+static struct net_device_stats *admtek_get_stats(struct net_device *dev) {
     613+    struct admtek_dev_priv *priv = dev->priv;
     614+//    printk("admtek_get_stats: %s\n", dev->name);
     615+    return &priv->stats;
     616+}
     617+
     618+static void admtek_tx_timeout(struct net_device *dev) {
     619+    unsigned i;
     620+    unsigned long flags;
     621+    printk("admtek_tx_timeout: %s\n", dev->name);
     622+
     623+    spin_lock_irqsave(&sw.lock, flags);
     624+
     625+    // disable interrupts
     626+    ADMTEK_REG(SW_Int_mask_REG) = SWITCH_INT_MASK;
     627+
     628+    admtek_init_engine();
     629+
     630+    for (i = 0; i < TX_DESC_COUNT; ++i) {
     631+       if (sw.tx_skbs[i]) dev_kfree_skb(sw.tx_skbs[i]);
     632+    }
     633+
     634+    admtek_init_descs();
     635+
     636+    // reenable ports
     637+    for (i = 0; i < PORT_COUNT; ++i) {
     638+       if (netif_running(sw.devs[i])) {
     639+           ADMTEK_REG(Port_conf0_REG) &= ~(1 << i);
     640+       }
     641+    }
     642+
     643+    // enable interrupts
     644+    ADMTEK_REG(SW_Int_mask_REG) = ~(RX_L_INT | TX_L_INT | RX_DESC_ERR_INT |
     645+                                   TX_DESC_ERR_INT | PORT_STATUS_CHANGE_INT);
     646+
     647+    spin_unlock_irqrestore(&sw.lock, flags);
     648+}
     649+
     650+
     651+static int admtek_init_dev(struct net_device *dev, unsigned port) {
     652+    struct admtek_dev_priv *priv = dev->priv;
     653+    int ret = 0;
     654+
     655+    SET_MODULE_OWNER(dev);
     656+    memcpy(dev->dev_addr, mips_mac_address, 6);
     657+
     658+    if (dev->dev_addr[5] + port > 255) ++dev->dev_addr[4];
     659+    dev->dev_addr[5] += port;
     660+
     661+    dev->open               = admtek_open;
     662+    dev->stop               = admtek_stop;
     663+    dev->set_multicast_list = admtek_set_multicast_list;
     664+    dev->hard_start_xmit    = admtek_hard_start_xmit;
     665+    dev->do_ioctl           = admtek_ioctl;
     666+    dev->get_stats          = admtek_get_stats;
     667+    dev->tx_timeout         = admtek_tx_timeout;
     668+    dev->watchdog_timeo     = 2 * HZ;
     669+    dev->irq                = SW_IRQ;
     670+    dev->ethtool_ops        = &admtek_ethtool_ops;
     671+
     672+    ret = register_netdev(dev);
     673+    if (ret) {
     674+       printk("admtek: register_netdev failed\n");
     675+       return ret;
     676+    }
     677+
     678+    priv->dev = dev;
     679+    priv->port = port;
     680+
     681+    return ret;
     682+}
     683+
     684+static void admtek_cleanup_dev(struct net_device *dev) {
     685+    struct admtek_dev_priv *priv = dev->priv;
     686+
     687+    if (priv->dev) unregister_netdevice(dev);
     688+
     689+    kfree(dev);
     690+}
     691+
     692+static void admtek_cleanup(void) {
     693+    unsigned i;
     694+    unsigned c;
     695+
     696+    // disable interrupts
     697+    ADMTEK_REG(SW_Int_mask_REG) = SWITCH_INT_MASK;
     698+
     699+    if (sw.irq) free_irq(SW_IRQ, &sw);
     700+
     701+    for (i = 0; i < PORT_COUNT; ++i) {
     702+       if (sw.devs[i]) admtek_cleanup_dev(sw.devs[i]);
     703+    }
     704+    if (sw.tx_skbs) {
     705+       for (i = 0; i < TX_DESC_COUNT; ++i) {
     706+           if (sw.tx_skbs[i]) dev_kfree_skb(sw.tx_skbs[i]);
     707+       }
     708+       kfree(sw.tx_skbs);
     709+    }
     710+    if (sw.tx_descs) {
     711+       c = TX_DESC_COUNT;
     712+       pci_free_consistent(NULL, sizeof(struct admtek_rx_desc) * c,
     713+                           sw.tx_descs, sw.tx_descs_dma);
     714+    }
     715+    if (sw.rx_skbs) {
     716+       for (i = 0; i < RX_DESC_COUNT; ++i) {
     717+           if (sw.rx_skbs[i]) dev_kfree_skb(sw.rx_skbs[i]);
     718+       }
     719+       kfree(sw.rx_skbs);
     720+    }
     721+    if (sw.rx_descs) {
     722+       c = RX_DESC_COUNT;
     723+       pci_free_consistent(NULL, sizeof(struct admtek_rx_desc) * c,
     724+                           sw.rx_descs, sw.rx_descs_dma);
     725+    }
     726+}
     727+
     728+static int __init admtek_init(void) {
     729+    unsigned i;
     730+
     731+    if (!is_rb100()) return 1;
     732+
     733+    printk("ADMTEK ethernet switch driver\n");
     734+    if (request_irq(SW_IRQ, admtek_interrupt, SA_SHIRQ,
     735+                   "ethernet switch", &sw)) {
     736+       printk("admtek: request irq failed\n");
     737+       goto err_out;
     738+    }
     739+    sw.irq = 1;
     740+
     741+    // alloc buffers
     742+    sw.rx_descs = pci_alloc_consistent(NULL, sizeof(struct admtek_rx_desc)
     743+                                      * RX_DESC_COUNT, &sw.rx_descs_dma);
     744+    if (!sw.rx_descs) {
     745+       printk("admtek: alloc rx descriptors failed\n");
     746+       goto err_out;
     747+    }
     748+
     749+    sw.rx_skbs = kmalloc(sizeof(struct sk_buff *) * RX_DESC_COUNT, GFP_KERNEL);
     750+    if (!sw.rx_skbs) {
     751+       printk("admtek: alloc rx skb ptr buf failed\n");
     752+       goto err_out;
     753+    }
     754+    memset(sw.rx_skbs, 0, sizeof(struct sk_buff *) * RX_DESC_COUNT);
     755+
     756+    for (i = 0; i < RX_DESC_COUNT; ++i) {
     757+       sw.rx_skbs[i] = dev_alloc_skb(RX_BUF_SIZE + 16);
     758+       if (!sw.rx_skbs[i]) {
     759+           printk("admtek: alloc rx skb failed\n");
     760+           goto err_out;
     761+       }
     762+       skb_reserve(sw.rx_skbs[i], 2);
     763+    }
     764+
     765+    sw.tx_descs = pci_alloc_consistent(NULL, sizeof(struct admtek_tx_desc)
     766+                                      * TX_DESC_COUNT, &sw.tx_descs_dma);
     767+    if (!sw.tx_descs) {
     768+       printk("admtek: alloc tx descriptors failed\n");
     769+       goto err_out;
     770+    }
     771+
     772+    sw.tx_skbs = kmalloc(sizeof(struct sk_buff *) * TX_DESC_COUNT, GFP_KERNEL);
     773+    if (!sw.tx_skbs) {
     774+       printk("admtek: alloc tx skb ptr buf failed\n");
     775+       goto err_out;
     776+    }
     777+
     778+    tasklet_init(&sw.rx_tasklet, admtek_rx_tasklet, (unsigned long)&sw);
     779+    tasklet_init(&sw.tx_tasklet, admtek_tx_tasklet, (unsigned long)&sw);
     780+    spin_lock_init(&sw.lock);
     781+
     782+    admtek_init_engine();
     783+
     784+    admtek_init_descs();
     785+
     786+    for (i = 0; i < PORT_COUNT; ++i) {
     787+       sw.devs[i] = alloc_etherdev(sizeof(struct admtek_dev_priv));
     788+       if (sw.devs[i] == NULL) {
     789+           printk("admtek: alloc_etherdev failed for port #%u\n", i);
     790+           goto err_out;
     791+       }
     792+
     793+       /* TODO: check for 5 port version */
     794+       if (i == 1) break;
     795+
     796+       if (admtek_init_dev(sw.devs[i], i)) {
     797+           printk("admtek: init failed for port #%u\n", i);
     798+           goto err_out;
     799+       }
     800+    }
     801+
     802+    // enable interrupts
     803+    ADMTEK_REG(SW_Int_mask_REG) = ~(RX_L_INT | TX_L_INT | RX_DESC_ERR_INT |
     804+                                   TX_DESC_ERR_INT | PORT_STATUS_CHANGE_INT);
     805+    return 0;
     806+err_out:
     807+    admtek_cleanup();
     808+    return -ENODEV;
     809+}
     810+
     811+static void __exit admtek_uninit(void) {
     812+    admtek_cleanup();
     813+}
     814+
     815+module_init(admtek_init);
     816+module_exit(admtek_uninit);
    1817diff -NaurB linux-2.4.33.3/drivers/net/Config.in linux-2.4.33.3.patched/drivers/net/Config.in
    2 --- linux-2.4.33.3/drivers/net/Config.in        2006-11-12 21:17:50.000000000 +0100
    3 +++ linux-2.4.33.3.patched/drivers/net/Config.in        2006-11-12 22:37:38.000000000 +0100
     818--- linux-2.4.33.3/drivers/net/Config.in        2006-11-15 10:12:14.000000000 +0100
     819+++ linux-2.4.33.3.patched/drivers/net/Config.in        2006-11-15 10:34:48.000000000 +0100
    4820@@ -30,6 +30,9 @@
    5821 comment 'Ethernet (10 or 100Mbit)'
     
    12828       dep_bool '  ARM EBSA110 AM79C961A support' CONFIG_ARM_AM79C961A $CONFIG_ARCH_EBSA110
    13829       tristate '  Cirrus Logic CS8900A support' CONFIG_ARM_CIRRUS
     830@@ -77,6 +80,12 @@
     831          bool '   Broadcom 5222 Dual Phy Support' CONFIG_BCM5222_DUAL_PHY
     832       fi
     833    fi
     834+   if [ "$CONFIG_MIPS_MIKROTIK" = "y" ]; then
     835+      tristate '  MIPS ADM5120 Ethernet Switch support' CONFIG_MIPS_AM5120_SW
     836+   fi
     837+   if [ "$CONFIG_SIBYTE_SB1xxx_SOC" = "y" ]; then
     838+      tristate '  SB1250 Ethernet support' CONFIG_NET_SB1250_MAC
     839+   fi
     840    if [ "$CONFIG_SGI_IP27" = "y" ]; then
     841       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
     842    fi
    14843diff -NaurB linux-2.4.33.3/drivers/net/korina.c linux-2.4.33.3.patched/drivers/net/korina.c
    15844--- linux-2.4.33.3/drivers/net/korina.c 1970-01-01 01:00:00.000000000 +0100
    16 +++ linux-2.4.33.3.patched/drivers/net/korina.c 2006-11-12 22:33:45.000000000 +0100
    17 @@ -0,0 +1,1725 @@
     845+++ linux-2.4.33.3.patched/drivers/net/korina.c 2006-11-15 10:34:48.000000000 +0100
     846@@ -0,0 +1,1727 @@
    18847+/*
    19848+************************************************************************************
     
    15632392+       int i, retval=0;
    15642393+
     2394+       if (!is_rb500()) return 1;
     2395+
    15652396+       for (i = 0; korina_iflist[i].iobase; i++) {
    15662397+               retval |= korina_probe(i);
     
    17422573+module_exit(korina_cleanup_module);
    17432574diff -NaurB linux-2.4.33.3/drivers/net/Makefile linux-2.4.33.3.patched/drivers/net/Makefile
    1744 --- linux-2.4.33.3/drivers/net/Makefile 2006-11-12 21:17:50.000000000 +0100
    1745 +++ linux-2.4.33.3.patched/drivers/net/Makefile 2006-11-12 22:38:07.000000000 +0100
    1746 @@ -244,6 +244,7 @@
     2575--- linux-2.4.33.3/drivers/net/Makefile 2006-11-15 10:12:14.000000000 +0100
     2576+++ linux-2.4.33.3.patched/drivers/net/Makefile 2006-11-15 10:34:48.000000000 +0100
     2577@@ -244,6 +244,8 @@
    17472578 obj-$(CONFIG_DL2K) += dl2k.o
    17482579 obj-$(CONFIG_R8169) += r8169.o
    17492580 obj-$(CONFIG_AMD8111_ETH) += amd8111e.o mii.o
    17502581+obj-$(CONFIG_KORINA) += korina.o mii.o
     2582+obj-$(CONFIG_MIPS_AM5120_SW) += admtek.o
    17512583 
    17522584 # non-drivers/net drivers who want mii lib
    17532585 obj-$(CONFIG_PCMCIA_SMC91C92) += mii.o
     2586diff -NaurB linux-2.4.33.3/drivers/net/natsemi.c linux-2.4.33.3.patched/drivers/net/natsemi.c
     2587--- linux-2.4.33.3/drivers/net/natsemi.c        2006-08-31 19:03:20.000000000 +0200
     2588+++ linux-2.4.33.3.patched/drivers/net/natsemi.c        2006-11-15 10:34:10.000000000 +0100
     2589@@ -190,8 +190,8 @@
     2590 static int debug = -1;
     2591 
     2592 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
     2593-static int max_interrupt_work = 20;
     2594-static int mtu;
     2595+static int max_interrupt_work = 40;
     2596+static int mtu = 0;
     2597 
     2598 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
     2599    This chip uses a 512 element hash table based on the Ethernet CRC.  */
     2600@@ -199,7 +199,10 @@
     2601 
     2602 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
     2603    Setting to > 1518 effectively disables this feature. */
     2604-static int rx_copybreak;
     2605+static int rx_copybreak = 0;
     2606+
     2607+/* Set the interrupt holdoff value in usec. */
     2608+static int intr_holdoff_value = 1000;
     2609 
     2610 /* Used to pass the media type, etc.
     2611    Both 'options[]' and 'full_duplex[]' should exist for driver
     2612@@ -217,9 +220,9 @@
     2613    Making the Tx ring too large decreases the effectiveness of channel
     2614    bonding and packet priority.
     2615    There are no ill effects from too-large receive rings. */
     2616-#define TX_RING_SIZE   16
     2617-#define TX_QUEUE_LEN   10 /* Limit ring entries actually used, min 4. */
     2618-#define RX_RING_SIZE   32
     2619+#define TX_RING_SIZE   32
     2620+#define TX_QUEUE_LEN   28 /* Limit ring entries actually used, min 4. */
     2621+#define RX_RING_SIZE   64
     2622 
     2623 /* Operational parameters that usually are not changed. */
     2624 /* Time in jiffies before concluding the transmitter is hung. */
     2625@@ -236,7 +239,8 @@
     2626 #define NATSEMI_REGS_SIZE      (NATSEMI_NREGS * sizeof(u32))
     2627 #define NATSEMI_EEPROM_SIZE    24 /* 12 16-bit values */
     2628 
     2629-#define PKT_BUF_SZ             1536 /* Size of each temporary Rx buffer. */
     2630+//#define PKT_BUF_SZ           1536 /* Size of each temporary Rx buffer. */
     2631+#define PKT_BUF_SZ             4036 /* Size of each temporary Rx buffer. */
     2632 
     2633 /* These identify the driver base version and may not be removed. */
     2634 static char version[] __devinitdata =
     2635@@ -254,6 +258,7 @@
     2636 MODULE_PARM(mtu, "i");
     2637 MODULE_PARM(debug, "i");
     2638 MODULE_PARM(rx_copybreak, "i");
     2639+MODULE_PARM(intr_holdoff_value, "i");
     2640 MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
     2641 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
     2642 MODULE_PARM_DESC(max_interrupt_work,
     2643@@ -262,6 +267,8 @@
     2644 MODULE_PARM_DESC(debug, "DP8381x default debug level");
     2645 MODULE_PARM_DESC(rx_copybreak,
     2646        "DP8381x copy breakpoint for copy-only-tiny-frames");
     2647+MODULE_PARM_DESC(intr_holdoff_value,
     2648+       "DP83816 interrupt holdoff in usec (DP83816 only)");
     2649 MODULE_PARM_DESC(options,
     2650        "DP8381x: Bits 0-3: media type, bit 17: full duplex");
     2651 MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)");
     2652@@ -597,6 +604,11 @@
     2653        PhyAddrMask             = 0xf,
     2654 };
     2655 
     2656+enum IntrHoldoff_bits {
     2657+       InteHoldoffTime         = 0xff,
     2658+       InteHoldoffControl      = 0x100,
     2659+};
     2660+
     2661 /* values we might find in the silicon revision register */
     2662 #define SRR_DP83815_C  0x0302
     2663 #define SRR_DP83815_D  0x0403
     2664@@ -674,6 +686,9 @@
     2665        unsigned int iosize;
     2666        spinlock_t lock;
     2667        u32 msg_enable;
     2668+
     2669+       int long_cable;
     2670+       int cable_magic_done;
     2671 };
     2672 
     2673 static int eeprom_read(long ioaddr, int location);
     2674@@ -1131,9 +1146,12 @@
     2675 {
     2676        struct netdev_private *np = dev->priv;
     2677 
     2678-       if (np->srr >= SRR_DP83816_A5)
     2679+       if (np->srr > SRR_DP83816_A5 || np->long_cable)
     2680                return;
     2681 
     2682+       np->cable_magic_done = 1;
     2683+       printk("natsemi: do cable magic\n");
     2684+
     2685        /*
     2686         * 100 MBit links with short cables can trip an issue with the chip.
     2687         * The problem manifests as lots of CRC errors and/or flickering
     2688@@ -1172,9 +1190,12 @@
     2689        u16 data;
     2690        struct netdev_private *np = dev->priv;
     2691 
     2692-       if (np->srr >= SRR_DP83816_A5)
     2693+       if (np->srr > SRR_DP83816_A5 || !np->cable_magic_done)
     2694                return;
     2695 
     2696+       np->cable_magic_done = 0;
     2697+       printk("natsemi: undo cable magic\n");
     2698+
     2699        writew(1, dev->base_addr + PGSEL);
     2700        /* make sure the lock bit is clear */
     2701        data = readw(dev->base_addr + DSPCFG);
     2702@@ -1294,7 +1315,8 @@
     2703        /* DRTH 0x10: start copying to memory if 128 bytes are in the fifo
     2704         * MXDMA 0: up to 256 byte bursts
     2705         */
     2706-       np->rx_config = RxMxdma_256 | 0x20;
     2707+//     np->rx_config = RxMxdma_256 | 0x20;
     2708+       np->rx_config = RxAcceptLong | RxMxdma_256 | 0x20;
     2709        writel(np->rx_config, ioaddr + RxConfig);
     2710 
     2711        /* Disable PME:
     2712@@ -1506,7 +1528,8 @@
     2713        /* 2) RX ring */
     2714        np->dirty_rx = 0;
     2715        np->cur_rx = RX_RING_SIZE;
     2716-       np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
     2717+       np->rx_buf_sz = PKT_BUF_SZ;
     2718+//     np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
     2719        np->oom = 0;
     2720        np->rx_head_desc = &np->rx_ring[0];
     2721 
     2722@@ -1691,6 +1714,7 @@
     2723        struct netdev_private *np = dev->priv;
     2724        long ioaddr = dev->base_addr;
     2725        int boguscnt = max_interrupt_work;
     2726+       int was_rx = 0;
     2727        unsigned int handled = 0;
     2728 
     2729        if (np->hands_off)
     2730@@ -1712,6 +1736,7 @@
     2731                if (intr_status &
     2732                   (IntrRxDone | IntrRxIntr | RxStatusFIFOOver |
     2733                    IntrRxErr | IntrRxOverrun)) {
     2734+                       was_rx++;
     2735                        netdev_rx(dev);
     2736                }
     2737 
     2738@@ -1736,6 +1761,13 @@
     2739                }
     2740        } while (1);
     2741 
     2742+        if (was_rx && (np->srr >= SRR_DP83816_A4))
     2743+          {
     2744+            /* set interrupt hold off. (only in DP83816) */
     2745+            writel(((intr_holdoff_value/100) & InteHoldoffTime),
     2746+                   dev->base_addr + IntrHoldoff);
     2747+          }
     2748+
     2749        if (netif_msg_intr(np))
     2750                printk(KERN_DEBUG "%s: exiting interrupt.\n", dev->name);
     2751 
     2752@@ -2122,6 +2154,20 @@
     2753                return 0;
     2754        }
     2755 
     2756+       case 0x12345678: {
     2757+               struct ethtool_value edata;
     2758+               if (copy_from_user(&edata, useraddr, sizeof(edata)))
     2759+                       return -EFAULT;
     2760+
     2761+               spin_lock_irq(&np->lock);
     2762+               undo_cable_magic(dev);
     2763+               np->long_cable = edata.data;
     2764+               do_cable_magic(dev);
     2765+               spin_unlock_irq(&np->lock);
     2766+
     2767+               return 0;
     2768+       }
     2769+
     2770        }
     2771 
     2772        return -EOPNOTSUPP;
     2773diff -NaurB linux-2.4.33.3/drivers/net/sundance.c linux-2.4.33.3.patched/drivers/net/sundance.c
     2774--- linux-2.4.33.3/drivers/net/sundance.c       2006-08-31 19:03:20.000000000 +0200
     2775+++ linux-2.4.33.3.patched/drivers/net/sundance.c       2006-11-15 10:34:16.000000000 +0100
     2776@@ -188,6 +188,8 @@
     2777 #include "compat.h"
     2778 #endif
     2779 
     2780+#define USE_IO_OPS 1
     2781+
     2782 /* These identify the driver base version and may not be removed. */
     2783 static char version[] __devinitdata =
     2784 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
     2785diff -NaurB linux-2.4.33.3/drivers/net/tulip/interrupt.c linux-2.4.33.3.patched/drivers/net/tulip/interrupt.c
     2786--- linux-2.4.33.3/drivers/net/tulip/interrupt.c        2006-08-31 19:03:20.000000000 +0200
     2787+++ linux-2.4.33.3.patched/drivers/net/tulip/interrupt.c        2006-11-15 10:34:19.000000000 +0100
     2788@@ -122,14 +122,36 @@
     2789        /* If we own the next entry, it is a new packet. Send it up. */
     2790        while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) {
     2791                s32 status = le32_to_cpu(tp->rx_ring[entry].status);
     2792+               short pkt_len;
     2793 
     2794                if (tulip_debug > 5)
     2795                        printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n",
     2796                                   dev->name, entry, status);
     2797                if (--rx_work_limit < 0)
     2798                        break;
     2799-               if ((status & 0x38008300) != 0x0300) {
     2800-                       if ((status & 0x38000300) != 0x0300) {
     2801+                       
     2802+               /*
     2803+                 Omit the four octet CRC from the length.
     2804+                 (May not be considered valid until we have
     2805+                 checked status for RxLengthOver2047 bits)
     2806+                */
     2807+               pkt_len = ((status >> 16) & 0x7ff) - 4;
     2808+
     2809+               /*
     2810+                 Maximum pkt_len is 1518 (1514 + vlan header)
     2811+                 Anything higher than this is always invalid
     2812+                 regardless of RxLengthOver2047 bits
     2813+               */
     2814+
     2815+               if ((status & (RxLengthOver2047 |
     2816+                              RxDescCRCError |
     2817+                              RxDescCollisionSeen |
     2818+                              RxDescRunt |
     2819+                              RxDescDescErr |
     2820+                              RxWholePkt))        != RxWholePkt
     2821+                   || pkt_len > 1518 ) {
     2822+                       if ((status & (RxLengthOver2047 |
     2823+                                      RxWholePkt))         != RxWholePkt) {
     2824                                /* Ingore earlier buffers. */
     2825                                if ((status & 0xffff) != 0x7fff) {
     2826                                        if (tulip_debug > 1)
     2827@@ -138,31 +160,21 @@
     2828                                                           dev->name, status);
     2829                                        tp->stats.rx_length_errors++;
     2830                                }
     2831-                       } else if (status & RxDescFatalErr) {
     2832+                       } else {
     2833                                /* There was a fatal error. */
     2834                                if (tulip_debug > 2)
     2835                                        printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n",
     2836                                                   dev->name, status);
     2837                                tp->stats.rx_errors++; /* end of a packet.*/
     2838-                               if (status & 0x0890) tp->stats.rx_length_errors++;
     2839+                               if (pkt_len > 1518 ||
     2840+                                   status & RxDescRunt) tp->stats.rx_length_errors++;
     2841                                if (status & 0x0004) tp->stats.rx_frame_errors++;
     2842                                if (status & 0x0002) tp->stats.rx_crc_errors++;
     2843                                if (status & 0x0001) tp->stats.rx_fifo_errors++;
     2844                        }
     2845                } else {
     2846-                       /* Omit the four octet CRC from the length. */
     2847-                       short pkt_len = ((status >> 16) & 0x7ff) - 4;
     2848                        struct sk_buff *skb;
     2849 
     2850-#ifndef final_version
     2851-                       if (pkt_len > 1518) {
     2852-                               printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n",
     2853-                                          dev->name, pkt_len, pkt_len);
     2854-                               pkt_len = 1518;
     2855-                               tp->stats.rx_length_errors++;
     2856-                       }
     2857-#endif
     2858-
     2859 #ifdef CONFIG_NET_HW_FLOWCONTROL
     2860                         drop = atomic_read(&netdev_dropping);
     2861                         if (drop)
     2862diff -NaurB linux-2.4.33.3/drivers/net/tulip/tulip.h linux-2.4.33.3.patched/drivers/net/tulip/tulip.h
     2863--- linux-2.4.33.3/drivers/net/tulip/tulip.h    2006-08-31 19:03:20.000000000 +0200
     2864+++ linux-2.4.33.3.patched/drivers/net/tulip/tulip.h    2006-11-15 10:34:19.000000000 +0100
     2865@@ -191,8 +191,40 @@
     2866 
     2867 enum desc_status_bits {
     2868        DescOwned = 0x80000000,
     2869-       RxDescFatalErr = 0x8000,
     2870+
     2871+        /*
     2872+          Error summary flag is logical or of 'CRC Error',
     2873+          'Collision Seen', 'Frame Too Long', 'Runt' and
     2874+          'Descriptor Error' flags generated within tulip chip.
     2875+       */
     2876+        RxDescErrorSummary = 0x8000,
     2877+       
     2878+       RxDescCRCError = 0x0002,
     2879+        RxDescCollisionSeen = 0x0040,
     2880+       
     2881+        /*
     2882+          'Frame Too Long' flag is set if packet length including CRC
     2883+          exceeds 1518.  However, a full sized VLAN tagged frame is
     2884+          1522 bytes including CRC.
     2885+         
     2886+          The tulip chip does not block oversized frames, and if this
     2887+          flag is set on a receive descriptor it does not indicate
     2888+          the frame has been truncated.  The receive descriptor also
     2889+          includes the actual length.  Therefore we can safety ignore
     2890+          this flag and check the length ourselves.
     2891+        */
     2892+        RxDescFrameTooLong = 0x0080,
     2893+       RxDescRunt = 0x0800,
     2894+       RxDescDescErr = 0x4000,
     2895        RxWholePkt = 0x0300,
     2896+       
     2897+       /*
     2898+         Top three bits of 14 bit frame length (status bits 27-29)
     2899+          should never be set as that would make frame over 2047 bytes.
     2900+         The Receive Watchdog flag (bit 4) may indicate the length is
     2901+          over 2048 and the length field is invalid.
     2902+       */
     2903+       RxLengthOver2047 = 0x38000010
     2904 };
     2905 
     2906 
     2907diff -NaurB linux-2.4.33.3/drivers/net/via-rhine.c linux-2.4.33.3.patched/drivers/net/via-rhine.c
     2908--- linux-2.4.33.3/drivers/net/via-rhine.c      2006-08-31 19:03:20.000000000 +0200
     2909+++ linux-2.4.33.3.patched/drivers/net/via-rhine.c      2006-11-15 10:33:56.000000000 +0100
     2910@@ -172,9 +172,9 @@
     2911    Making the Tx ring too large decreases the effectiveness of channel
     2912    bonding and packet priority.
     2913    There are no ill effects from too-large receive rings. */
     2914-#define TX_RING_SIZE   16
     2915-#define TX_QUEUE_LEN   10              /* Limit ring entries actually used.  */
     2916-#define RX_RING_SIZE   16
     2917+#define TX_RING_SIZE   128
     2918+#define TX_QUEUE_LEN   120             /* Limit ring entries actually used.  */
     2919+#define RX_RING_SIZE   128
     2920 
     2921 
     2922 /* Operational parameters that usually are not changed. */
     2923@@ -258,6 +258,31 @@
     2924 MODULE_PARM_DESC(options, "VIA Rhine: Bits 0-3: media type, bit 17: full duplex");
     2925 MODULE_PARM_DESC(full_duplex, "VIA Rhine full duplex setting(s) (1)");
     2926 
     2927+#ifdef CONFIG_MIPS_MIKROTIK
     2928+#undef USE_MEM
     2929+#undef USE_IO
     2930+#define USE_IO
     2931+
     2932+#undef readb
     2933+#undef readw
     2934+#undef readl
     2935+#undef writeb
     2936+#undef writew
     2937+#undef writel
     2938+
     2939+#include <asm/rb/pci.h>
     2940+#include <asm/io.h>
     2941+
     2942+#define readb(addr) pci_readb((unsigned long) (addr) + mips_io_port_base)
     2943+#define readw(addr) pci_readw((unsigned long) (addr) + mips_io_port_base)
     2944+#define readl(addr) pci_readl((unsigned long) (addr) + mips_io_port_base)
     2945+
     2946+#define writeb(b,addr) pci_writeb(b, (unsigned long) (addr) + mips_io_port_base)
     2947+#define writew(b,addr) pci_writew(b, (unsigned long) (addr) + mips_io_port_base)
     2948+#define writel(b,addr) pci_writel(b, (unsigned long) (addr) + mips_io_port_base)
     2949+
     2950+#endif
     2951+
     2952 /*
     2953                                Theory of Operation
     2954 
     2955@@ -510,6 +535,9 @@
     2956        unsigned char *tx_bufs;
     2957        dma_addr_t tx_bufs_dma;
     2958 
     2959+       struct tasklet_struct *rx_tasklet;
     2960+       struct tasklet_struct *tx_tasklet;
     2961+
     2962        struct pci_dev *pdev;
     2963        struct net_device_stats stats;
     2964        struct timer_list timer;        /* Media monitoring timer. */
     2965@@ -543,7 +571,9 @@
     2966 static int  via_rhine_start_tx(struct sk_buff *skb, struct net_device *dev);
     2967 static irqreturn_t via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
     2968 static void via_rhine_tx(struct net_device *dev);
     2969+static void via_rhine_tx_tasklet(unsigned long tx_data_dev);
     2970 static void via_rhine_rx(struct net_device *dev);
     2971+static void via_rhine_rx_tasklet(unsigned long rx_data_dev);
     2972 static void via_rhine_error(struct net_device *dev, int intr_status);
     2973 static void via_rhine_set_rx_mode(struct net_device *dev);
     2974 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
     2975@@ -567,7 +597,7 @@
     2976 static void wait_for_reset(struct net_device *dev, int chip_id, char *name)
     2977 {
     2978        long ioaddr = dev->base_addr;
     2979-       int boguscnt = 20;
     2980+       int boguscnt = 2000;
     2981 
     2982        IOSYNC;
     2983 
     2984@@ -611,7 +641,7 @@
     2985        int i;
     2986        outb(0x20, ioaddr + MACRegEEcsr);
     2987        /* Typically 2 cycles to reload. */
     2988-       for (i = 0; i < 150; i++)
     2989+       for (i = 0; i < 3000; i++)
     2990                if (! (inb(ioaddr + MACRegEEcsr) & 0x20))
     2991                        break;
     2992 }
     2993@@ -735,6 +765,7 @@
     2994        dev->base_addr = ioaddr;
     2995        wait_for_reset(dev, chip_id, shortname);
     2996 
     2997+#ifndef CONFIG_MIPS_MIKROTIK
     2998        /* Reload the station address from the EEPROM. */
     2999 #ifdef USE_IO
     3000        reload_eeprom(ioaddr);
     3001@@ -745,6 +776,7 @@
     3002           not known if that still works with the "win98-reboot" problem. */
     3003        enable_mmio(ioaddr0, chip_id);
     3004 #endif
     3005+#endif
     3006 
     3007        for (i = 0; i < 6; i++)
     3008                dev->dev_addr[i] = readb(ioaddr + StationAddr + i);
     3009@@ -874,6 +906,17 @@
     3010                }
     3011        }
     3012 
     3013+       np->rx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
     3014+       tasklet_init(np->rx_tasklet, via_rhine_rx_tasklet, (unsigned long)dev);
     3015+       tasklet_disable_nosync(np->rx_tasklet);
     3016+       np->tx_tasklet = kmalloc(sizeof(struct tasklet_struct), GFP_KERNEL);
     3017+       tasklet_init(np->tx_tasklet, via_rhine_tx_tasklet, (unsigned long)dev);
     3018+       tasklet_disable_nosync(np->tx_tasklet);
     3019+
     3020+       // shut down until somebody really needs it
     3021+       writeb(0x80, ioaddr + 0xa1);
     3022+       pci_set_power_state(np->pdev, 3);
     3023+
     3024        return 0;
     3025 
     3026 err_out_unmap:
     3027@@ -1091,9 +1134,11 @@
     3028 
     3029 static int mdio_read(struct net_device *dev, int phy_id, int regnum)
     3030 {
     3031+       struct netdev_private *np = dev->priv;
     3032        long ioaddr = dev->base_addr;
     3033        int boguscnt = 1024;
     3034 
     3035+       if (np->pdev->current_state) return 0;
     3036        /* Wait for a previous command to complete. */
     3037        while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0)
     3038                ;
     3039@@ -1113,6 +1158,7 @@
     3040        long ioaddr = dev->base_addr;
     3041        int boguscnt = 1024;
     3042 
     3043+       if (np->pdev->current_state) return;
     3044        if (phy_id == np->phys[0]) {
     3045                switch (regnum) {
     3046                case MII_BMCR:                                  /* Is user forcing speed/duplex? */
     3047@@ -1144,6 +1190,8 @@
     3048        long ioaddr = dev->base_addr;
     3049        int i;
     3050 
     3051+       pci_enable_device(np->pdev);
     3052+
     3053        /* Reset the chip. */
     3054        writew(CmdReset, ioaddr + ChipCmd);
     3055 
     3056@@ -1168,6 +1216,9 @@
     3057                           dev->name, readw(ioaddr + ChipCmd),
     3058                           mdio_read(dev, np->phys[0], MII_BMSR));
     3059 
     3060+       tasklet_enable(np->rx_tasklet);
     3061+       tasklet_enable(np->tx_tasklet);
     3062+
     3063        netif_start_queue(dev);
     3064 
     3065        /* Set the timer to check for link beat. */
     3066@@ -1367,7 +1418,6 @@
     3067        struct net_device *dev = dev_instance;
     3068        long ioaddr;
     3069        u32 intr_status;
     3070-       int boguscnt = max_interrupt_work;
     3071        int handled = 0;
     3072 
     3073        ioaddr = dev->base_addr;
     3074@@ -1409,13 +1459,11 @@
     3075                                   IntrTxUnderrun | IntrTxDescRace))
     3076                        via_rhine_error(dev, intr_status);
     3077 
     3078-               if (--boguscnt < 0) {
     3079-                       printk(KERN_WARNING "%s: Too much work at interrupt, "
     3080-                                  "status=%#8.8x.\n",
     3081-                                  dev->name, intr_status);
     3082+               if (debug > 3)
     3083+                       printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n",
     3084+                                  dev->name, readw(ioaddr + IntrStatus));
     3085                        break;
     3086                }
     3087-       }
     3088 
     3089        if (debug > 3)
     3090                printk(KERN_DEBUG "%s: exiting interrupt, status=%8.8x.\n",
     3091@@ -1428,9 +1476,28 @@
     3092 static void via_rhine_tx(struct net_device *dev)
     3093 {
     3094        struct netdev_private *np = dev->priv;
     3095+       long ioaddr = dev->base_addr;
     3096+
     3097+       spin_lock(&np->lock);
     3098+
     3099+       /* Disable TX interrupts by setting the interrupt mask */
     3100+       writew(readw(ioaddr + IntrEnable) & ~(IntrTxDone | IntrTxErrSummary),
     3101+                  ioaddr + IntrEnable);
     3102+
     3103+       tasklet_hi_schedule(np->tx_tasklet);
     3104+
     3105+       spin_unlock(&np->lock);
     3106+}
     3107+
     3108+static void via_rhine_tx_tasklet(unsigned long tx_data_dev)
     3109+{
     3110+       struct net_device *dev = (struct net_device *)tx_data_dev;
     3111+       struct netdev_private *np = dev->priv;
     3112+       long ioaddr = dev->base_addr;
     3113+
     3114        int txstatus = 0, entry = np->dirty_tx % TX_RING_SIZE;
     3115 
     3116-       spin_lock (&np->lock);
     3117+       spin_lock_irq(&np->lock);
     3118 
     3119        /* find and cleanup dirty tx descriptors */
     3120        while (np->dirty_tx != np->cur_tx) {
     3121@@ -1474,14 +1541,19 @@
     3122                                                         np->tx_skbuff_dma[entry],
     3123                                                         np->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
     3124                }
     3125-               dev_kfree_skb_irq(np->tx_skbuff[entry]);
     3126+               dev_kfree_skb_any(np->tx_skbuff[entry]);
     3127                np->tx_skbuff[entry] = NULL;
     3128                entry = (++np->dirty_tx) % TX_RING_SIZE;
     3129        }
     3130        if ((np->cur_tx - np->dirty_tx) < TX_QUEUE_LEN - 4)
     3131                netif_wake_queue (dev);
     3132 
     3133-       spin_unlock (&np->lock);
     3134+       spin_unlock_irq(&np->lock);
     3135+
     3136+       // Enable TX interrupts by setting the interrupt mask
     3137+       writew(readw(ioaddr + IntrEnable) |
     3138+                  (IntrTxDone | IntrTxErrSummary),
     3139+                  ioaddr + IntrEnable);
     3140 }
     3141 
     3142 /* This routine is logically part of the interrupt handler, but isolated
     3143@@ -1489,6 +1561,28 @@
     3144 static void via_rhine_rx(struct net_device *dev)
     3145 {
     3146        struct netdev_private *np = dev->priv;
     3147+       long ioaddr = dev->base_addr;
     3148+
     3149+       spin_lock(&np->lock);
     3150+
     3151+       /* Disable RX interrupts by setting the interrupt mask */
     3152+       writew(readw(ioaddr + IntrEnable) &
     3153+                  ~(IntrRxDone | IntrRxErr | IntrRxDropped | IntrRxWakeUp |
     3154+                        IntrRxEmpty | IntrRxNoBuf),
     3155+                  ioaddr + IntrEnable);
     3156+
     3157+       tasklet_hi_schedule(np->rx_tasklet);
     3158+
     3159+       spin_unlock(&np->lock);
     3160+}
     3161+
     3162+static void via_rhine_rx_tasklet(unsigned long rx_data_dev)
     3163+{
     3164+       struct net_device *dev = (struct net_device *)rx_data_dev;
     3165+       struct netdev_private *np = dev->priv;
     3166+       long ioaddr = dev->base_addr;
     3167+       u32 desc_status;
     3168+
     3169        int entry = np->cur_rx % RX_RING_SIZE;
     3170        int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
     3171 
     3172@@ -1498,10 +1592,11 @@
     3173        }
     3174 
     3175        /* If EOP is set on the next entry, it's a new packet. Send it up. */
     3176-       while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) {
     3177-               struct rx_desc *desc = np->rx_head_desc;
     3178-               u32 desc_status = le32_to_cpu(desc->rx_status);
     3179-               int data_size = desc_status >> 16;
     3180+       while (1) {
     3181+               int data_size;
     3182+               desc_status = le32_to_cpu(np->rx_head_desc->rx_status);
     3183+               if (desc_status & DescOwn) break;
     3184+               data_size = desc_status >> 16;
     3185 
     3186                if (debug > 4)
     3187                        printk(KERN_DEBUG "  via_rhine_rx() status is %8.8x.\n",
     3188@@ -1527,9 +1622,9 @@
     3189                                if (desc_status & 0x0004) np->stats.rx_frame_errors++;
     3190                                if (desc_status & 0x0002) {
     3191                                        /* this can also be updated outside the interrupt handler */
     3192-                                       spin_lock (&np->lock);
     3193+                                       spin_lock_irq(&np->lock);
     3194                                        np->stats.rx_crc_errors++;
     3195-                                       spin_unlock (&np->lock);
     3196+                                       spin_unlock_irq(&np->lock);
     3197                                }
     3198                        }
     3199                } else {
     3200@@ -1566,7 +1661,7 @@
     3201                                np->rx_skbuff[entry] = NULL;
     3202                                skb_put(skb, pkt_len);
     3203                                pci_unmap_single(np->pdev, np->rx_skbuff_dma[entry],
     3204-                                                                np->rx_buf_sz, PCI_DMA_FROMDEVICE);
     3205+                                                pkt_len, PCI_DMA_FROMDEVICE);
     3206                        }
     3207                        skb->protocol = eth_type_trans(skb, dev);
     3208                        netif_rx(skb);
     3209@@ -1596,6 +1691,12 @@
     3210                np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn);
     3211        }
     3212 
     3213+       // Enable RX interrupts by setting the interrupt mask
     3214+       writew(readw(ioaddr + IntrEnable) |
     3215+                  (IntrRxDone | IntrRxErr | IntrRxDropped | IntrRxWakeUp |
     3216+                       IntrRxEmpty | IntrRxNoBuf),
     3217+                  ioaddr + IntrEnable);
     3218+
     3219        /* Pre-emptively restart Rx engine. */
     3220        writew(readw(dev->base_addr + ChipCmd) | CmdRxOn | CmdRxDemand,
     3221                   dev->base_addr + ChipCmd);
     3222@@ -1866,6 +1967,9 @@
     3223 
     3224        del_timer_sync(&np->timer);
     3225 
     3226+       tasklet_disable(np->rx_tasklet);
     3227+       tasklet_disable(np->tx_tasklet);
     3228+
     3229        spin_lock_irq(&np->lock);
     3230 
     3231        netif_stop_queue(dev);
     3232@@ -1890,6 +1994,9 @@
     3233        free_tbufs(dev);
     3234        free_ring(dev);
     3235 
     3236+       writeb(0x80, ioaddr + 0xa1);
     3237+       pci_set_power_state(np->pdev, 3);
     3238+
     3239        return 0;
     3240 }
     3241 
     3242@@ -1897,6 +2004,7 @@
     3243 static void __devexit via_rhine_remove_one (struct pci_dev *pdev)
     3244 {
     3245        struct net_device *dev = pci_get_drvdata(pdev);
     3246+       struct netdev_private *np = dev->priv;
     3247 
     3248        unregister_netdev(dev);
     3249 
     3250@@ -1906,6 +2014,9 @@
     3251        iounmap((char *)(dev->base_addr));
     3252 #endif
     3253 
     3254+       kfree(np->rx_tasklet);
     3255+       kfree(np->tx_tasklet);
     3256+
     3257        free_netdev(dev);
     3258        pci_disable_device(pdev);
     3259        pci_set_drvdata(pdev, NULL);
    17543260diff -NaurB linux-2.4.33.3/include/asm-mips/rb/rb500_korina.h linux-2.4.33.3.patched/include/asm-mips/rb/rb500_korina.h
    17553261--- linux-2.4.33.3/include/asm-mips/rb/rb500_korina.h   1970-01-01 01:00:00.000000000 +0100
    1756 +++ linux-2.4.33.3.patched/include/asm-mips/rb/rb500_korina.h   2006-11-12 21:20:23.000000000 +0100
     3262+++ linux-2.4.33.3.patched/include/asm-mips/rb/rb500_korina.h   2006-11-15 10:33:51.000000000 +0100
    17573263@@ -0,0 +1,209 @@
    17583264+/* $Id: pciacacia.h,v 1.5 2001/05/01 10:09:17 carstenl Exp $
     
    19653471+
    19663472+
     3473diff -NaurB linux-2.4.33.3/net/ipv4/tcp_input.c linux-2.4.33.3.patched/net/ipv4/tcp_input.c
     3474--- linux-2.4.33.3/net/ipv4/tcp_input.c 2006-08-31 19:03:20.000000000 +0200
     3475+++ linux-2.4.33.3.patched/net/ipv4/tcp_input.c 2006-11-15 10:23:06.000000000 +0100
     3476@@ -70,6 +70,7 @@
     3477 #include <net/tcp.h>
     3478 #include <net/inet_common.h>
     3479 #include <linux/ipsec.h>
     3480+#include <asm/unaligned.h>
     3481 
     3482 int sysctl_tcp_timestamps = 1;
     3483 int sysctl_tcp_window_scaling = 1;
     3484@@ -2896,7 +2897,7 @@
     3485                                switch(opcode) {
     3486                                case TCPOPT_MSS:
     3487                                        if(opsize==TCPOLEN_MSS && th->syn && !estab) {
     3488-                                               u16 in_mss = ntohs(*(__u16 *)ptr);
     3489+                                               u16 in_mss = ntohs(get_unaligned((__u16 *)ptr));
     3490                                                if (in_mss) {
     3491                                                        if (tp->user_mss && tp->user_mss < in_mss)
     3492                                                                in_mss = tp->user_mss;
     3493@@ -2923,8 +2924,8 @@
     3494                                                if ((estab && tp->tstamp_ok) ||
     3495                                                    (!estab && sysctl_tcp_timestamps)) {
     3496                                                        tp->saw_tstamp = 1;
     3497-                                                       tp->rcv_tsval = ntohl(*(__u32 *)ptr);
     3498-                                                       tp->rcv_tsecr = ntohl(*(__u32 *)(ptr+4));
     3499+                                                       tp->rcv_tsval = ntohl(get_unaligned((__u32 *)ptr));
     3500+                                                       tp->rcv_tsecr = ntohl(get_unaligned((__u32 *)(ptr+4)));
     3501                                                }
     3502                                        }
     3503                                        break;
     3504@@ -2961,13 +2962,13 @@
     3505        } else if (tp->tstamp_ok &&
     3506                   th->doff == (sizeof(struct tcphdr)>>2)+(TCPOLEN_TSTAMP_ALIGNED>>2)) {
     3507                __u32 *ptr = (__u32 *)(th + 1);
     3508-               if (*ptr == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
     3509+               if (get_unaligned(ptr) == ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
     3510                                  | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) {
     3511                        tp->saw_tstamp = 1;
     3512                        ++ptr;
     3513-                       tp->rcv_tsval = ntohl(*ptr);
     3514+                       tp->rcv_tsval = ntohl(get_unaligned(ptr));
     3515                        ++ptr;
     3516-                       tp->rcv_tsecr = ntohl(*ptr);
     3517+                       tp->rcv_tsecr = ntohl(get_unaligned(ptr));
     3518                        return 1;
     3519                }
     3520        }
     3521@@ -4131,15 +4132,15 @@
     3522                        __u32 *ptr = (__u32 *)(th + 1);
     3523 
     3524                        /* No? Slow path! */
     3525-                       if (*ptr != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
     3526+                       if (get_unaligned(ptr) != ntohl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16)
     3527                                           | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP))
     3528                                goto slow_path;
     3529 
     3530                        tp->saw_tstamp = 1;
     3531                        ++ptr;
     3532-                       tp->rcv_tsval = ntohl(*ptr);
     3533+                       tp->rcv_tsval = ntohl(get_unaligned(ptr));
     3534                        ++ptr;
     3535-                       tp->rcv_tsecr = ntohl(*ptr);
     3536+                       tp->rcv_tsecr = ntohl(get_unaligned(ptr));
     3537 
     3538                        /* If PAWS failed, check it more carefully in slow path */
     3539                        if ((s32)(tp->rcv_tsval - tp->ts_recent) < 0)
  • target/linux/rb-2.4/patches/005-cfmips.patch

    r7a23d2e re1e379b  
    11diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/ata.c linux-2.4.33.3.patched/drivers/block/cf-mips/ata.c
    22--- linux-2.4.33.3/drivers/block/cf-mips/ata.c  1970-01-01 01:00:00.000000000 +0100
    3 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.c  2006-11-12 23:46:19.000000000 +0100
    4 @@ -0,0 +1,802 @@
     3+++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.c  2006-11-15 10:42:47.000000000 +0100
     4@@ -0,0 +1,862 @@
    55+#include <linux/kernel.h>      /* printk() */
    66+#include <linux/module.h>      /* module to be loadable */
     
    1414+#include <asm/rc32434/dev.h>
    1515+#include <asm/rc32434/gpio.h>
     16+#include <asm/rb/rb100.h>
    1617+
    1718+#include "ata.h"
     
    3132+#define RC32434_IRQ_CFRDY      (8 + 4 * 32 + RC32434_CF_GPIO_NUM)    /* 149 */
    3233+static GPIO_t rcgpio = (GPIO_t)GPIO_VirtualAddress;
     34+
     35+/* CFRDY is connected to GPIO4/INTX_1 */
     36+#define ADM5120_CF_GPIO_NUM    4
     37+#define ADM5120_CF_IRQ_LEVEL_BIT       0x20    /* GPIO4 = 0x20, GPIO2 = 0x10 */
     38+#define ADM5120_IRQ_CFRDY      INT_LVL_EXTIO_1
    3339+
    3440+static unsigned irq_cfrdy = 0;
     
    104110+}
    105111+
     112+static int
     113+adm5120_cfrdy(void)
     114+{
     115+       return ADM5120_SW_REG(GPIO_conf0_REG) & GPIO4_INPUT_MASK;
     116+}
     117+
    106118+static void
    107119+rc32434_prepare_cf_irq(void)
     
    113125+}
    114126+
     127+static void
     128+adm5120_prepare_cf_irq(void)
     129+{
     130+       /* interrupt on cf ready (not busy) */
     131+       ADM5120_INTC_REG(IRQ_LEVEL_REG) |= ADM5120_CF_IRQ_LEVEL_BIT;
     132+       // FIXME: how to clear interrupt status?
     133+}
     134+
    115135+static int
    116136+init_cfdev_base(void)
    117137+{
    118 +       printk("RB500 CF\n");
    119 +       DEV_t devt = (DEV_t)DEV_VirtualAddress;
    120 +
    121 +       if (devt->dev[1].devmask == 0) {
    122 +               printk(KERN_ERR
    123 +                      "DEV1 in Device Controller"
    124 +                      " is not mapped anywhere!\n");
     138+       if (is_rb500()) {
     139+               printk("RB500 CF\n");
     140+               DEV_t devt = (DEV_t)DEV_VirtualAddress;
     141+
     142+               if (devt->dev[1].devmask == 0) {
     143+                       printk(KERN_ERR
     144+                              "DEV1 in Device Controller"
     145+                              " is not mapped anywhere!\n");
     146+                       return 0;
     147+               }
     148+               /* setup CFRDY GPIO as input */
     149+               rcgpio->gpiofunc &= ~RC32434_CF_GPIO_BIT;
     150+               rcgpio->gpiocfg &= ~RC32434_CF_GPIO_BIT;
     151+
     152+               cfdev_base = devt->dev[1].devbase;
     153+               cfrdy = &rc32434_cfrdy;
     154+               prepare_cf_irq = &rc32434_prepare_cf_irq;
     155+               irq_cfrdy = RC32434_IRQ_CFRDY;
     156+               ilevel_addr = &rcgpio->gpioilevel;
     157+               ilevel_bit = RC32434_CF_GPIO_BIT;
     158+
     159+               printk(KERN_INFO
     160+                      "DC DEV1 base 0x%08lx ctrl 0x%08x tctrl 0x%08x"
     161+                      " cfrdy %d\n",
     162+                      cfdev_base,
     163+                      devt->dev[1].devc,
     164+                      devt->dev[1].devtc,
     165+                      (*cfrdy)());
     166+       }
     167+       else if (is_rb100()) {
     168+               printk("RB100 CF\n");
     169+
     170+               /* FIXME: enabling of EXTIO will be done by BIOS in future */
     171+               unsigned cmd = EXTIO_CS0_INT0_EN;
     172+               /* on RB100 WAIT is LOW all the time => read will hang */
     173+               if (ADM5120_SW_REG(GPIO_conf0_REG) & GPIO0_INPUT_MASK) {
     174+                       cmd |= EXTIO_WAIT_EN;
     175+               }
     176+               ADM5120_SW_REG(GPIO_conf2_REG) = cmd;
     177+               ADM5120_SW_REG(GPIO_conf0_REG) &= ~(1 <<
     178+                                                   (16 + ADM5120_CF_GPIO_NUM));
     179+
     180+               /* FIXME: timings will be set by BIOS in future - remove this */
     181+               writel(0x88, KSEG1ADDR(MPMC_BASE) | MPMC_SM_CONFIG2_REG);
     182+               writel(0x02, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITWEN2_REG);
     183+               writel(0x03, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITOEN2_REG);
     184+               writel(0x1a, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITRD2_REG);
     185+               writel(0x1d, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITPAGE2_REG);
     186+               writel(0x14, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITWR2_REG);
     187+               writel(0x09, KSEG1ADDR(MPMC_BASE) | MPMC_SM_WAITTURN2_REG);
     188+
     189+               cfdev_base = EXTIO0_BASE;
     190+               cfrdy = &adm5120_cfrdy;
     191+               prepare_cf_irq = &adm5120_prepare_cf_irq;
     192+               irq_cfrdy = ADM5120_IRQ_CFRDY;
     193+               ilevel_addr = (volatile U32 *)(KSEG1ADDR(INTC_BASE + IRQ_LEVEL_REG));
     194+               ilevel_bit = ADM5120_CF_IRQ_LEVEL_BIT;
     195+
     196+               printk(KERN_INFO
     197+                      "CF DEV base 0x%08lx cfrdy %d\n",
     198+                      cfdev_base,
     199+                      (*cfrdy)());
     200+       }
     201+       else {
     202+               printk(KERN_ERR "CF ERROR: unknown RouterBOARD type!\n");
    125203+               return 0;
    126204+       }
    127 +       /* setup CFRDY GPIO as input */
    128 +       rcgpio->gpiofunc &= ~RC32434_CF_GPIO_BIT;
    129 +       rcgpio->gpiocfg &= ~RC32434_CF_GPIO_BIT;
    130 +
    131 +       cfdev_base = devt->dev[1].devbase;
    132 +       cfrdy = &rc32434_cfrdy;
    133 +       prepare_cf_irq = &rc32434_prepare_cf_irq;
    134 +       irq_cfrdy = RC32434_IRQ_CFRDY;
    135 +       ilevel_addr = &rcgpio->gpioilevel;
    136 +       ilevel_bit = RC32434_CF_GPIO_BIT;
    137 +
    138 +       printk(KERN_INFO
    139 +              "DC DEV1 base 0x%08lx ctrl 0x%08x tctrl 0x%08x"
    140 +              " cfrdy %d\n",
    141 +              cfdev_base,
    142 +              devt->dev[1].devc,
    143 +              devt->dev[1].devtc,
    144 +              (*cfrdy)());
    145205+       return 1;
    146206+}
     
    807867diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/ata.h linux-2.4.33.3.patched/drivers/block/cf-mips/ata.h
    808868--- linux-2.4.33.3/drivers/block/cf-mips/ata.h  1970-01-01 01:00:00.000000000 +0100
    809 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.h  2006-11-12 23:44:49.000000000 +0100
     869+++ linux-2.4.33.3.patched/drivers/block/cf-mips/ata.h  2006-11-15 10:42:38.000000000 +0100
    810870@@ -0,0 +1,70 @@
    811871+#ifndef __CFMIPS_ATA_H__
     
    881941diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/bdev.c linux-2.4.33.3.patched/drivers/block/cf-mips/bdev.c
    882942--- linux-2.4.33.3/drivers/block/cf-mips/bdev.c 1970-01-01 01:00:00.000000000 +0100
    883 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/bdev.c 2006-11-12 23:44:49.000000000 +0100
    884 @@ -0,0 +1,294 @@
     943+++ linux-2.4.33.3.patched/drivers/block/cf-mips/bdev.c 2006-11-15 10:42:47.000000000 +0100
     944@@ -0,0 +1,298 @@
    885945+#include <linux/kernel.h>      /* printk() */
    886946+#include <linux/module.h>      /* module to be loadable */
     
    10641124+       DEBUGP(KERN_INFO "cf-mips module opened, minor %d\n", minor);
    10651125+       MOD_INC_USE_COUNT;
    1066 +       GPIO_t gpiot = (GPIO_t)GPIO_VirtualAddress;
    1067 +       /* dirty workaround to set CFRDY GPIO as an input
    1068 +        * when some other program sets it as an output
    1069 +        */
    1070 +       gpiot->gpiocfg &= ~(1 << 13);
     1126+       if (is_rb500()) {
     1127+               GPIO_t gpiot = (GPIO_t)GPIO_VirtualAddress;
     1128+               /* dirty workaround to set CFRDY GPIO as an input
     1129+                * when some other program sets it as an output
     1130+                */
     1131+               gpiot->gpiocfg &= ~(1 << 13);
     1132+       }
    10711133+       return 0;               /* success */
    10721134+}
     
    11071169+       int i;
    11081170+
     1171+       if (!is_rb500() && !is_rb100()) return -1;
     1172+
    11091173+       result = register_blkdev(MAJOR_NR, "cf-mips", &cf_bdops);
    11101174+       if (result < 0) {
     
    11791243diff -NaurB linux-2.4.33.3/drivers/block/cf-mips/Makefile linux-2.4.33.3.patched/drivers/block/cf-mips/Makefile
    11801244--- linux-2.4.33.3/drivers/block/cf-mips/Makefile       1970-01-01 01:00:00.000000000 +0100
    1181 +++ linux-2.4.33.3.patched/drivers/block/cf-mips/Makefile       2006-11-12 23:44:49.000000000 +0100
     1245+++ linux-2.4.33.3.patched/drivers/block/cf-mips/Makefile       2006-11-15 10:42:38.000000000 +0100
    11821246@@ -0,0 +1,5 @@
    11831247+O_TARGET := cf-mips.o
     
    11881252diff -NaurB linux-2.4.33.3/drivers/block/ll_rw_blk.c linux-2.4.33.3.patched/drivers/block/ll_rw_blk.c
    11891253--- linux-2.4.33.3/drivers/block/ll_rw_blk.c    2006-08-31 19:03:20.000000000 +0200
    1190 +++ linux-2.4.33.3.patched/drivers/block/ll_rw_blk.c    2006-11-12 23:44:49.000000000 +0100
     1254+++ linux-2.4.33.3.patched/drivers/block/ll_rw_blk.c    2006-11-15 10:42:38.000000000 +0100
    11911255@@ -32,6 +32,8 @@
    11921256 #include <linux/slab.h>
     
    12111275diff -NaurB linux-2.4.33.3/drivers/block/Makefile linux-2.4.33.3.patched/drivers/block/Makefile
    12121276--- linux-2.4.33.3/drivers/block/Makefile       2006-08-31 19:03:20.000000000 +0200
    1213 +++ linux-2.4.33.3.patched/drivers/block/Makefile       2006-11-12 23:44:49.000000000 +0100
     1277+++ linux-2.4.33.3.patched/drivers/block/Makefile       2006-11-15 10:42:38.000000000 +0100
    12141278@@ -32,7 +32,9 @@
    12151279 obj-$(CONFIG_BLK_DEV_UMEM)     += umem.o
     
    12231287 include $(TOPDIR)/Rules.make
    12241288diff -NaurB linux-2.4.33.3/init/do_mounts.c linux-2.4.33.3.patched/init/do_mounts.c
    1225 --- linux-2.4.33.3/init/do_mounts.c     2006-11-12 23:43:16.000000000 +0100
    1226 +++ linux-2.4.33.3.patched/init/do_mounts.c     2006-11-12 23:44:49.000000000 +0100
     1289--- linux-2.4.33.3/init/do_mounts.c     2006-11-15 10:12:12.000000000 +0100
     1290+++ linux-2.4.33.3.patched/init/do_mounts.c     2006-11-15 10:42:38.000000000 +0100
    12271291@@ -256,6 +256,7 @@
    12281292        { "ftld", 0x2c18 },
Note: See TracChangeset for help on using the changeset viewer.