linux/ixp4xx: add kernel 2.6.36 preliminary support
[openwrt.git] / target / linux / amazon / files / drivers / net / amazon_sw.c
index d19db6e..54a7062 100644 (file)
@@ -38,6 +38,7 @@
 
 // copyright 2007 john crispin <blogic@openwrt.org>
 // copyright 2007 felix fietkau <nbd@openwrt.org>
+// copyright 2009 hauke mehrtens <hauke@hauke-m.de>
 
 
 // TODO
@@ -85,6 +86,7 @@
 #include <linux/ethtool.h>
 #include <asm/checksum.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 
 #include <asm/amazon/amazon.h>
 #include <asm/amazon/amazon_dma.h>
@@ -105,10 +107,7 @@ module_param(timeout, int, 0);
 int switch_init(struct net_device *dev);
 void switch_tx_timeout(struct net_device *dev);
 
-struct net_device switch_devs[2] = {
-       {init:switch_init,},
-       {init:switch_init,}
-};
+static struct net_device *switch_devs[2];
 
 int add_mac_table_entry(u64 entry_value)
 {
@@ -266,7 +265,7 @@ static int __init ethaddr_setup(char *line)
                if (line)
                        line = (*ep) ? ep + 1 : ep;
        }
-       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]);
+       printk(KERN_INFO "amazon_mii0: mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]);
        return 0;
 }
 
@@ -274,7 +273,7 @@ __setup("ethaddr=", ethaddr_setup);
 
 static void open_rx_dma(struct net_device *dev)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        struct dma_device_info *dma_dev = priv->dma_device;
        int i;
 
@@ -286,7 +285,7 @@ static void open_rx_dma(struct net_device *dev)
 #ifdef CONFIG_NET_HW_FLOWCONTROL
 static void close_rx_dma(struct net_device *dev)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        struct dma_device_info *dma_dev = priv->dma_device;
        int i;
 
@@ -306,7 +305,7 @@ void amazon_xon(struct net_device *dev)
 
 int switch_open(struct net_device *dev)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        if (!strcmp(dev->name, "eth1")) {
                priv->mdio_phy_addr = PHY0_ADDR;
        }
@@ -314,7 +313,7 @@ int switch_open(struct net_device *dev)
 
 #ifdef CONFIG_NET_HW_FLOWCONTROL
        if ((priv->fc_bit = netdev_register_fc(dev, amazon_xon)) == 0) {
-               printk("Hardware Flow Control register fails\n");
+               printk(KERN_WARNING "amazon_mii0: Hardware Flow Control register fails\n");
        }
 #endif
 
@@ -325,7 +324,7 @@ int switch_open(struct net_device *dev)
 int switch_release(struct net_device *dev)
 {
        int i;
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        struct dma_device_info *dma_dev = priv->dma_device;
 
        for (i = 0; i < dma_dev->num_tx_chan; i++)
@@ -348,7 +347,7 @@ int switch_release(struct net_device *dev)
 
 void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
 #ifdef CONFIG_NET_HW_FLOWCONTROL
        int mit_sel = 0;
 #endif
@@ -381,7 +380,7 @@ void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
 
 int asmlinkage switch_hw_tx(char *buf, int len, struct net_device *dev)
 {
-       struct switch_priv *priv = dev->priv;
+       struct switch_priv *priv = netdev_priv(dev);
        struct dma_device_info *dma_dev = priv->dma_device;
 
        dma_dev->current_tx_chan = 0;
@@ -392,7 +391,7 @@ int asmlinkage switch_tx(struct sk_buff *skb, struct net_device *dev)
 {
        int len;
        char *data;
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
 
        len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
        data = skb->data;
@@ -411,7 +410,7 @@ int asmlinkage switch_tx(struct sk_buff *skb, struct net_device *dev)
 
 void switch_tx_timeout(struct net_device *dev)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        priv->stats.tx_errors++;
        netif_wake_queue(dev);
        return;
@@ -419,7 +418,7 @@ void switch_tx_timeout(struct net_device *dev)
 
 void negotiate(struct net_device *dev)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        unsigned short data = get_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG);
 
        data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);
@@ -470,7 +469,7 @@ void negotiate(struct net_device *dev)
 
 void set_duplex(struct net_device *dev, enum duplex new_duplex)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        if (new_duplex != priv->current_duplex) {
                priv->current_duplex = new_duplex;
                negotiate(dev);
@@ -479,14 +478,14 @@ void set_duplex(struct net_device *dev, enum duplex new_duplex)
 
 void set_speed(struct net_device *dev, unsigned long speed)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        priv->current_speed_selection = speed;
        negotiate(dev);
 }
 
 static int switch_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        struct ethtool_cmd ecmd;
 
        if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
@@ -642,7 +641,7 @@ int switch_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 struct net_device_stats *switch_stats(struct net_device *dev)
 {
-       struct switch_priv *priv = (struct switch_priv *) dev->priv;
+       struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
        return &priv->stats;
 }
 
@@ -663,18 +662,18 @@ int switch_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
        len = dma_device_read(dma_dev, &buf, (void **) &skb);
 
        if (len >= 0x600) {
-               printk("packet too large %d\n", len);
+               printk(KERN_WARNING "amazon_mii0: packet too large %d\n", len);
                goto switch_hw_receive_err_exit;
        }
 
        /* remove CRC */
        len -= 4;
        if (skb == NULL) {
-               printk("cannot restore pointer\n");
+               printk(KERN_WARNING "amazon_mii0: cannot restore pointer\n");
                goto switch_hw_receive_err_exit;
        }
        if (len > (skb->end - skb->tail)) {
-               printk("BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
+               printk(KERN_WARNING "amazon_mii0: BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
                goto switch_hw_receive_err_exit;
        }
        skb_put(skb, len);
@@ -692,7 +691,7 @@ int dma_intr_handler(struct dma_device_info *dma_dev, int status)
 {
        struct net_device *dev;
 
-       dev = switch_devs + (u32) dma_dev->priv;
+       dev = dma_dev->priv;
        switch (status) {
        case RCV_INT:
                switch_hw_receive(dev, dma_dev);
@@ -735,19 +734,18 @@ int dma_buffer_free(u8 * dataptr, void *opt)
        return OK;
 }
 
-int init_dma_device(_dma_device_info * dma_dev)
+int init_dma_device(_dma_device_info * dma_dev, struct net_device *dev)
 {
        int i;
        int num_tx_chan, num_rx_chan;
        if (strcmp(dma_dev->device_name, "switch1") == 0) {
                num_tx_chan = 1;
                num_rx_chan = 2;
-               dma_dev->priv = (void *) 0;
        } else {
                num_tx_chan = 1;
                num_rx_chan = 2;
-               dma_dev->priv = (void *) 1;
        }
+       dma_dev->priv = dev;
 
        dma_dev->weight = 1;
        dma_dev->num_tx_chan = num_tx_chan;
@@ -780,6 +778,17 @@ int switch_set_mac_address(struct net_device *dev, void *p)
        return OK;
 }
 
+static const struct net_device_ops amazon_mii_ops = {
+       .ndo_init               = switch_init,
+       .ndo_open               = switch_open,
+       .ndo_stop               = switch_release,
+       .ndo_start_xmit         = switch_tx,
+       .ndo_do_ioctl           = switch_ioctl,
+       .ndo_get_stats          = switch_stats,
+       .ndo_change_mtu         = switch_change_mtu,
+       .ndo_set_mac_address            = switch_set_mac_address,
+       .ndo_tx_timeout         = switch_tx_timeout,
+};
 
 int switch_init(struct net_device *dev)
 {
@@ -788,32 +797,18 @@ int switch_init(struct net_device *dev)
        int result;
        struct switch_priv *priv;
        ether_setup(dev);                       /* assign some of the fields */
-       printk("%s up using ", dev->name);
-       dev->open = switch_open;
-       dev->stop = switch_release;
-       dev->hard_start_xmit = switch_tx;
-       dev->do_ioctl = switch_ioctl;
-       dev->get_stats = switch_stats;
-       dev->change_mtu = switch_change_mtu;
-       dev->set_mac_address = switch_set_mac_address;
-       dev->tx_timeout = switch_tx_timeout;
+       printk(KERN_INFO "amazon_mii0: %s up using ", dev->name);
        dev->watchdog_timeo = timeout;
 
-       SET_MODULE_OWNER(dev);
-
-       dev->priv = kmalloc(sizeof(struct switch_priv), GFP_KERNEL);
-       if (dev->priv == NULL)
-               return -ENOMEM;
-       memset(dev->priv, 0, sizeof(struct switch_priv));
-       priv = dev->priv;
+       priv = netdev_priv(dev);
        priv->dma_device = (struct dma_device_info *) kmalloc(sizeof(struct dma_device_info), GFP_KERNEL);
-       if ((dev - switch_devs) == 0) {
+       if (priv->num == 0) {
                sprintf(priv->dma_device->device_name, "switch1");
-       } else if ((dev - switch_devs) == 1) {
+       } else if (priv->num == 1) {
                sprintf(priv->dma_device->device_name, "switch2");
        }
        printk("\"%s\"\n", priv->dma_device->device_name);
-       init_dma_device(priv->dma_device);
+       init_dma_device(priv->dma_device, dev);
        result = dma_device_register(priv->dma_device);
 
        /* read the mac address from the mac table and put them into the mac table. */
@@ -827,25 +822,29 @@ int switch_init(struct net_device *dev)
                dev->dev_addr[2] = 0xda;
                dev->dev_addr[3] = 0x86;
                dev->dev_addr[4] = 0x23;
-               dev->dev_addr[5] = 0x74 + (unsigned char) (dev - switch_devs);
+               dev->dev_addr[5] = 0x74 + (unsigned char) priv->num;
        } else {
                for (i = 0; i < 6; i++) {
                        dev->dev_addr[i] = my_ethaddr[i];
                }
-               dev->dev_addr[5] += +(unsigned char) (dev - switch_devs);
+               dev->dev_addr[5] += +(unsigned char) priv->num;
        }
        return OK;
 }
 
-int switch_init_module(void)
+static int amazon_mii_probe(struct platform_device *dev)
 {
        int i = 0, result, device_present = 0;
+       struct switch_priv *priv;
 
        for (i = 0; i < AMAZON_SW_INT_NO; i++) {
-               sprintf(switch_devs[i].name, "eth%d", i);
-
-               if ((result = register_netdev(switch_devs + i)))
-                       printk("error %i registering device \"%s\"\n", result, switch_devs[i].name);
+               switch_devs[i] = alloc_etherdev(sizeof(struct switch_priv));
+               switch_devs[i]->netdev_ops = &amazon_mii_ops;
+               strcpy(switch_devs[i]->name, "eth%d");
+               priv = (struct switch_priv *) netdev_priv(switch_devs[i]);
+               priv->num = i;
+               if ((result = register_netdev(switch_devs[i])))
+                       printk(KERN_WARNING "amazon_mii0: error %i registering device \"%s\"\n", result, switch_devs[i]->name);
                else
                        device_present++;
        }
@@ -853,24 +852,48 @@ int switch_init_module(void)
        return device_present ? 0 : -ENODEV;
 }
 
-void switch_cleanup(void)
+static int amazon_mii_remove(struct platform_device *dev)
 {
        int i;
        struct switch_priv *priv;
        for (i = 0; i < AMAZON_SW_INT_NO; i++) {
-               priv = switch_devs[i].priv;
+               priv = netdev_priv(switch_devs[i]);
                if (priv->dma_device) {
                        dma_device_unregister(priv->dma_device);
                        kfree(priv->dma_device);
                }
-               kfree(switch_devs[i].priv);
-               unregister_netdev(switch_devs + i);
+               kfree(netdev_priv(switch_devs[i]));
+               unregister_netdev(switch_devs[i]);
        }
-       return;
+       return 0;
+}
+
+static struct platform_driver amazon_mii_driver = {
+       .probe = amazon_mii_probe,
+       .remove = amazon_mii_remove,
+       .driver = {
+               .name = "amazon_mii0",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init amazon_mii_init(void)
+{
+       int ret = platform_driver_register(&amazon_mii_driver);
+       if (ret)
+               printk(KERN_WARNING "amazon_mii0: Error registering platfom driver!\n");
+       return ret;
 }
 
-module_init(switch_init_module);
-module_exit(switch_cleanup);
+static void __exit amazon_mii_cleanup(void)
+{
+       platform_driver_unregister(&amazon_mii_driver);
+}
+
+module_init(amazon_mii_init);
+module_exit(amazon_mii_cleanup);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Wu Qi Ming");
+MODULE_DESCRIPTION("ethernet driver for AMAZON boards");
+
This page took 0.035108 seconds and 4 git commands to generate.