ne: Add NEEDS_PORTLIST to control ISA auto-probe
[safe/jmp/linux-2.6] / drivers / net / dm9000.c
index 5fddc0f..0e33853 100644 (file)
  *                        net_device_stats
  *                      * introduced tx_timeout function
  *                      * reworked locking
+ *
+ *       01-Jul-2005   Ben Dooks <ben@simtec.co.uk>
+ *                     * fixed spinlock call without pointer
+ *                     * ensure spinlock is initialised
  */
 
 #include <linux/module.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/skbuff.h>
-#include <linux/version.h>
 #include <linux/spinlock.h>
 #include <linux/crc32.h>
 #include <linux/mii.h>
 #include <linux/dm9000.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 
 #include <asm/delay.h>
 #include <asm/irq.h>
@@ -144,11 +148,10 @@ typedef struct board_info {
 } board_info_t;
 
 /* function declaration ------------------------------------- */
-static int dm9000_probe(struct device *);
+static int dm9000_probe(struct platform_device *);
 static int dm9000_open(struct net_device *);
 static int dm9000_start_xmit(struct sk_buff *, struct net_device *);
 static int dm9000_stop(struct net_device *);
-static int dm9000_do_ioctl(struct net_device *, struct ifreq *, int);
 
 
 static void dm9000_timer(unsigned long);
@@ -156,7 +159,7 @@ static void dm9000_init_dm9000(struct net_device *);
 
 static struct net_device_stats *dm9000_get_stats(struct net_device *);
 
-static irqreturn_t dm9000_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t dm9000_interrupt(int, void *);
 
 static int dm9000_phy_read(struct net_device *dev, int phyaddr_unsused, int reg);
 static void dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg,
@@ -322,7 +325,7 @@ static void dm9000_timeout(struct net_device *dev)
 
        /* Save previous register address */
        reg_save = readb(db->io_addr);
-       spin_lock_irqsave(db->lock,flags);
+       spin_lock_irqsave(&db->lock,flags);
 
        netif_stop_queue(dev);
        dm9000_reset(db);
@@ -333,9 +336,20 @@ static void dm9000_timeout(struct net_device *dev)
 
        /* Restore previous register address */
        writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(db->lock,flags);
+       spin_unlock_irqrestore(&db->lock,flags);
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ *Used by netconsole
+ */
+static void dm9000_poll_controller(struct net_device *dev)
+{
+       disable_irq(dev->irq);
+       dm9000_interrupt(dev->irq,dev);
+       enable_irq(dev->irq);
+}
+#endif
 
 /* dm9000_release_board
  *
@@ -363,8 +377,8 @@ dm9000_release_board(struct platform_device *pdev, struct board_info *db)
                kfree(db->data_req);
        }
 
-       if (db->addr_res != NULL) {
-               release_resource(db->addr_res);
+       if (db->addr_req != NULL) {
+               release_resource(db->addr_req);
                kfree(db->addr_req);
        }
 }
@@ -375,9 +389,8 @@ dm9000_release_board(struct platform_device *pdev, struct board_info *db)
  * Search DM9000 board, allocate space and register it
  */
 static int
-dm9000_probe(struct device *dev)
+dm9000_probe(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
        struct dm9000_plat_data *pdata = pdev->dev.platform_data;
        struct board_info *db;  /* Point a board information structure */
        struct net_device *ndev;
@@ -387,8 +400,6 @@ dm9000_probe(struct device *dev)
        int i;
        u32 id_val;
 
-       printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
-
        /* Init network device */
        ndev = alloc_etherdev(sizeof (struct board_info));
        if (!ndev) {
@@ -397,7 +408,7 @@ dm9000_probe(struct device *dev)
        }
 
        SET_MODULE_OWNER(ndev);
-       SET_NETDEV_DEV(ndev, dev);
+       SET_NETDEV_DEV(ndev, &pdev->dev);
 
        PRINTK2("dm9000_probe()");
 
@@ -405,13 +416,12 @@ dm9000_probe(struct device *dev)
        db = (struct board_info *) ndev->priv;
        memset(db, 0, sizeof (*db));
 
+       spin_lock_init(&db->lock);
+
        if (pdev->num_resources < 2) {
                ret = -ENODEV;
                goto out;
-       }
-
-       switch (pdev->num_resources) {
-       case 2:
+       } else if (pdev->num_resources == 2) {
                base = pdev->resource[0].start;
 
                if (!request_mem_region(base, 4, ndev->name)) {
@@ -421,17 +431,16 @@ dm9000_probe(struct device *dev)
 
                ndev->base_addr = base;
                ndev->irq = pdev->resource[1].start;
-               db->io_addr = (void *)base;
-               db->io_data = (void *)(base + 4);
-
-               break;
+               db->io_addr = (void __iomem *)base;
+               db->io_data = (void __iomem *)(base + 4);
 
-       case 3:
+       } else {
                db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
                db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 
-               if (db->addr_res == NULL || db->data_res == NULL) {
+               if (db->addr_res == NULL || db->data_res == NULL ||
+                   db->irq_res == NULL) {
                        printk(KERN_ERR PFX "insufficient resources\n");
                        ret = -ENOENT;
                        goto out;
@@ -480,7 +489,6 @@ dm9000_probe(struct device *dev)
 
                /* ensure at least we have a default set of IO routines */
                dm9000_set_io(db, iosize);
-
        }
 
        /* check to see if anything is being over-ridden */
@@ -541,7 +549,9 @@ dm9000_probe(struct device *dev)
        ndev->stop               = &dm9000_stop;
        ndev->get_stats          = &dm9000_get_stats;
        ndev->set_multicast_list = &dm9000_hash_table;
-       ndev->do_ioctl           = &dm9000_do_ioctl;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       ndev->poll_controller    = &dm9000_poll_controller;
+#endif
 
 #ifdef DM9000_PROGRAM_EEPROM
        program_eeprom(db);
@@ -563,11 +573,18 @@ dm9000_probe(struct device *dev)
        for (i = 0; i < 6; i++)
                ndev->dev_addr[i] = db->srom[i];
 
+       if (!is_valid_ether_addr(ndev->dev_addr)) {
+               /* try reading from mac */
+
+               for (i = 0; i < 6; i++)
+                       ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
+       }
+
        if (!is_valid_ether_addr(ndev->dev_addr))
                printk("%s: Invalid ethernet MAC address.  Please "
                       "set using ifconfig\n", ndev->name);
 
-       dev_set_drvdata(dev, ndev);
+       platform_set_drvdata(pdev, ndev);
        ret = register_netdev(ndev);
 
        if (ret == 0) {
@@ -584,7 +601,7 @@ dm9000_probe(struct device *dev)
        printk("%s: not found (%d).\n", CARDNAME, ret);
 
        dm9000_release_board(pdev, db);
-       kfree(ndev);
+       free_netdev(ndev);
 
        return ret;
 }
@@ -600,7 +617,7 @@ dm9000_open(struct net_device *dev)
 
        PRINTK2("entering dm9000_open\n");
 
-       if (request_irq(dev->irq, &dm9000_interrupt, SA_SHIRQ, dev->name, dev))
+       if (request_irq(dev->irq, &dm9000_interrupt, IRQF_SHARED, dev->name, dev))
                return -EAGAIN;
 
        /* Initialize DM9000 board */
@@ -612,7 +629,7 @@ dm9000_open(struct net_device *dev)
 
        /* set and active a timer process */
        init_timer(&db->timer);
-       db->timer.expires  = DM9000_TIMER_WUT * 2;
+       db->timer.expires  = DM9000_TIMER_WUT;
        db->timer.data     = (unsigned long) dev;
        db->timer.function = &dm9000_timer;
        add_timer(&db->timer);
@@ -662,7 +679,6 @@ dm9000_init_dm9000(struct net_device *dev)
        db->tx_pkt_cnt = 0;
        db->queue_pkt_len = 0;
        dev->trans_start = 0;
-       spin_lock_init(&db->lock);
 }
 
 /*
@@ -766,7 +782,7 @@ dm9000_stop(struct net_device *ndev)
  * receive the packet to upper layer, free the transmitted packet
  */
 
-void
+static void
 dm9000_tx_done(struct net_device *dev, board_info_t * db)
 {
        int tx_status = ior(db, DM9000_NSR);    /* Got TX status */
@@ -788,7 +804,7 @@ dm9000_tx_done(struct net_device *dev, board_info_t * db)
 }
 
 static irqreturn_t
-dm9000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+dm9000_interrupt(int irq, void *dev_id)
 {
        struct net_device *dev = dev_id;
        board_info_t *db;
@@ -845,15 +861,6 @@ dm9000_get_stats(struct net_device *dev)
        return &db->stats;
 }
 
-/*
- *  Process the upper socket ioctl command
- */
-static int
-dm9000_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       PRINTK1("entering %s\n",__FUNCTION__);
-       return 0;
-}
 
 /*
  *  A periodic timer routine
@@ -864,21 +871,11 @@ dm9000_timer(unsigned long data)
 {
        struct net_device *dev = (struct net_device *) data;
        board_info_t *db = (board_info_t *) dev->priv;
-       u8 reg_save;
-       unsigned long flags;
 
        PRINTK3("dm9000_timer()\n");
 
-       spin_lock_irqsave(db->lock,flags);
-       /* Save previous register address */
-       reg_save = readb(db->io_addr);
-
        mii_check_media(&db->mii, netif_msg_link(db), 0);
 
-       /* Restore previous register address */
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(db->lock,flags);
-
        /* Set timer again */
        db->timer.expires = DM9000_TIMER_WUT;
        add_timer(&db->timer);
@@ -957,7 +954,6 @@ dm9000_rx(struct net_device *dev)
                /* Move data from DM9000 */
                if (GoodPacket
                    && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
-                       skb->dev = dev;
                        skb_reserve(skb, 2);
                        rdptr = (u8 *) skb_put(skb, RxLen - 4);
 
@@ -1098,9 +1094,14 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
 {
        board_info_t *db = (board_info_t *) dev->priv;
        unsigned long flags;
+       unsigned int reg_save;
        int ret;
 
        spin_lock_irqsave(&db->lock,flags);
+
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
@@ -1111,6 +1112,9 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
        /* The read data keeps on REG_0D & REG_0E */
        ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
 
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+
        spin_unlock_irqrestore(&db->lock,flags);
 
        return ret;
@@ -1124,9 +1128,13 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
 {
        board_info_t *db = (board_info_t *) dev->priv;
        unsigned long flags;
+       unsigned long reg_save;
 
        spin_lock_irqsave(&db->lock,flags);
 
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
        /* Fill the phyxcer register into REG_0C */
        iow(db, DM9000_EPAR, DM9000_PHY | reg);
 
@@ -1138,15 +1146,18 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value)
        udelay(500);            /* Wait write complete */
        iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer write command */
 
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+
        spin_unlock_irqrestore(&db->lock,flags);
 }
 
 static int
-dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
+dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
 {
-       struct net_device *ndev = dev_get_drvdata(dev);
+       struct net_device *ndev = platform_get_drvdata(dev);
 
-       if (ndev && level == SUSPEND_DISABLE) {
+       if (ndev) {
                if (netif_running(ndev)) {
                        netif_device_detach(ndev);
                        dm9000_shutdown(ndev);
@@ -1156,12 +1167,12 @@ dm9000_drv_suspend(struct device *dev, u32 state, u32 level)
 }
 
 static int
-dm9000_drv_resume(struct device *dev, u32 level)
+dm9000_drv_resume(struct platform_device *dev)
 {
-       struct net_device *ndev = dev_get_drvdata(dev);
+       struct net_device *ndev = platform_get_drvdata(dev);
        board_info_t *db = (board_info_t *) ndev->priv;
 
-       if (ndev && level == RESUME_ENABLE) {
+       if (ndev) {
 
                if (netif_running(ndev)) {
                        dm9000_reset(db);
@@ -1174,25 +1185,26 @@ dm9000_drv_resume(struct device *dev, u32 level)
 }
 
 static int
-dm9000_drv_remove(struct device *dev)
+dm9000_drv_remove(struct platform_device *pdev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct net_device *ndev = dev_get_drvdata(dev);
+       struct net_device *ndev = platform_get_drvdata(pdev);
 
-       dev_set_drvdata(dev, NULL);
+       platform_set_drvdata(pdev, NULL);
 
        unregister_netdev(ndev);
        dm9000_release_board(pdev, (board_info_t *) ndev->priv);
-       kfree(ndev);            /* free device structure */
+       free_netdev(ndev);              /* free device structure */
 
        PRINTK1("clean_module() exit\n");
 
        return 0;
 }
 
-static struct device_driver dm9000_driver = {
-       .name    = "dm9000",
-       .bus     = &platform_bus_type,
+static struct platform_driver dm9000_driver = {
+       .driver = {
+               .name    = "dm9000",
+               .owner   = THIS_MODULE,
+       },
        .probe   = dm9000_probe,
        .remove  = dm9000_drv_remove,
        .suspend = dm9000_drv_suspend,
@@ -1202,13 +1214,15 @@ static struct device_driver dm9000_driver = {
 static int __init
 dm9000_init(void)
 {
-       return driver_register(&dm9000_driver); /* search board and register */
+       printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
+
+       return platform_driver_register(&dm9000_driver);        /* search board and register */
 }
 
 static void __exit
 dm9000_cleanup(void)
 {
-       driver_unregister(&dm9000_driver);
+       platform_driver_unregister(&dm9000_driver);
 }
 
 module_init(dm9000_init);