]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/dm9000.c
net drivers: fix platform driver hotplug/coldplug
[linux-2.6-omap-h63xx.git] / drivers / net / dm9000.c
index d0cd7f945fde9350df355cec5568a68eb29f3b78..e6fe2614ea6dc3a9f2db6928cce6393b75498475 100644 (file)
@@ -142,6 +142,7 @@ 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_ioctl(struct net_device *dev, struct ifreq *req, int cmd);
 
 static void dm9000_init_dm9000(struct net_device *);
 
@@ -332,6 +333,16 @@ static void dm9000_poll_controller(struct net_device *dev)
 }
 #endif
 
+static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+       board_info_t *dm = to_dm9000_board(dev);
+
+       if (!netif_running(dev))
+               return -EINVAL;
+
+       return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL);
+}
+
 /* ethtool ops */
 
 static void dm9000_get_drvinfo(struct net_device *dev,
@@ -405,6 +416,9 @@ static int dm9000_get_eeprom(struct net_device *dev,
        if ((len & 1) != 0 || (offset & 1) != 0)
                return -EINVAL;
 
+       if (dm->flags & DM9000_PLATF_NO_EEPROM)
+               return -ENOENT;
+
        ee->magic = DM_EEPROM_MAGIC;
 
        for (i = 0; i < len; i += 2)
@@ -426,6 +440,9 @@ static int dm9000_set_eeprom(struct net_device *dev,
        if ((len & 1) != 0 || (offset & 1) != 0)
                return -EINVAL;
 
+       if (dm->flags & DM9000_PLATF_NO_EEPROM)
+               return -ENOENT;
+
        if (ee->magic != DM_EEPROM_MAGIC)
                return -EINVAL;
 
@@ -492,6 +509,7 @@ dm9000_probe(struct platform_device *pdev)
        struct dm9000_plat_data *pdata = pdev->dev.platform_data;
        struct board_info *db;  /* Point a board information structure */
        struct net_device *ndev;
+       const unsigned char *mac_src;
        unsigned long base;
        int ret = 0;
        int iosize;
@@ -626,7 +644,7 @@ dm9000_probe(struct platform_device *pdev)
        dm9000_reset(db);
 
        /* try two times, DM9000 sometimes gets the first read wrong */
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < 8; i++) {
                id_val  = ior(db, DM9000_VIDL);
                id_val |= (u32)ior(db, DM9000_VIDH) << 8;
                id_val |= (u32)ior(db, DM9000_PIDL) << 16;
@@ -655,6 +673,7 @@ dm9000_probe(struct platform_device *pdev)
        ndev->stop               = &dm9000_stop;
        ndev->set_multicast_list = &dm9000_hash_table;
        ndev->ethtool_ops        = &dm9000_ethtool_ops;
+       ndev->do_ioctl           = &dm9000_ioctl;
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
        ndev->poll_controller    = &dm9000_poll_controller;
@@ -669,13 +688,16 @@ dm9000_probe(struct platform_device *pdev)
        db->mii.mdio_read    = dm9000_phy_read;
        db->mii.mdio_write   = dm9000_phy_write;
 
+       mac_src = "eeprom";
+
        /* try reading the node address from the attached EEPROM */
        for (i = 0; i < 6; i += 2)
                dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);
 
        if (!is_valid_ether_addr(ndev->dev_addr)) {
                /* try reading from mac */
-
+               
+               mac_src = "chip";
                for (i = 0; i < 6; i++)
                        ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
        }
@@ -689,9 +711,9 @@ dm9000_probe(struct platform_device *pdev)
 
        if (ret == 0) {
                DECLARE_MAC_BUF(mac);
-               printk("%s: dm9000 at %p,%p IRQ %d MAC: %s\n",
+               printk("%s: dm9000 at %p,%p IRQ %d MAC: %s (%s)\n",
                       ndev->name,  db->io_addr, db->io_data, ndev->irq,
-                      print_mac(mac, ndev->dev_addr));
+                      print_mac(mac, ndev->dev_addr), mac_src);
        }
        return 0;
 
@@ -776,8 +798,6 @@ dm9000_init_dm9000(struct net_device *dev)
        /* Set address filter table */
        dm9000_hash_table(dev);
 
-       /* Activate DM9000 */
-       iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
        /* Enable TX/RX interrupt mask */
        iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
 
@@ -948,7 +968,7 @@ dm9000_interrupt(int irq, void *dev_id)
 struct dm9000_rxhdr {
        u8      RxPktReady;
        u8      RxStatus;
-       u16     RxLen;
+       __le16  RxLen;
 } __attribute__((__packed__));
 
 /*
@@ -1100,6 +1120,12 @@ dm9000_read_eeprom(board_info_t *db, int offset, u8 *to)
 {
        unsigned long flags;
 
+       if (db->flags & DM9000_PLATF_NO_EEPROM) {
+               to[0] = 0xff;
+               to[1] = 0xff;
+               return;
+       }
+
        mutex_lock(&db->addr_lock);
 
        spin_lock_irqsave(&db->lock, flags);
@@ -1134,6 +1160,9 @@ dm9000_write_eeprom(board_info_t *db, int offset, u8 *data)
 {
        unsigned long flags;
 
+       if (db->flags & DM9000_PLATF_NO_EEPROM)
+               return;
+
        mutex_lock(&db->addr_lock);
 
        spin_lock_irqsave(&db->lock, flags);
@@ -1166,6 +1195,7 @@ dm9000_hash_table(struct net_device *dev)
        int i, oft;
        u32 hash_val;
        u16 hash_table[4];
+       u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;
        unsigned long flags;
 
        dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -1182,6 +1212,12 @@ dm9000_hash_table(struct net_device *dev)
        /* broadcast address */
        hash_table[3] = 0x8000;
 
+       if (dev->flags & IFF_PROMISC)
+               rcr |= RCR_PRMSC;
+
+       if (dev->flags & IFF_ALLMULTI)
+               rcr |= RCR_ALL;
+
        /* the multicast address in Hash Table : 64 bits */
        for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
                hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
@@ -1194,6 +1230,7 @@ dm9000_hash_table(struct net_device *dev)
                iow(db, oft++, hash_table[i] >> 8);
        }
 
+       iow(db, DM9000_RCR, rcr);
        spin_unlock_irqrestore(&db->lock, flags);
 }
 
@@ -1381,3 +1418,4 @@ module_exit(dm9000_cleanup);
 MODULE_AUTHOR("Sascha Hauer, Ben Dooks");
 MODULE_DESCRIPTION("Davicom DM9000 network driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:dm9000");