linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / net / tulip / winbond-840.c
index eba9083..5b1af39 100644 (file)
                        Copyright (C) 2001 Manfred Spraul
        * ethtool support (jgarzik)
        * Replace some MII-related magic numbers with constants (jgarzik)
-
+  
        TODO:
        * enable pci_power_off
        * Wake-On-LAN
 */
-
+  
 #define DRV_NAME       "winbond-840"
 #define DRV_VERSION    "1.01-d"
 #define DRV_RELDATE    "Nov-17-2001"
@@ -57,7 +57,7 @@ c-help-name: Winbond W89c840 PCI Ethernet support
 c-help-symbol: CONFIG_WINBOND_840
 c-help: This driver is for the Winbond W89c840 chip.  It also works with
 c-help: the TX9882 chip on the Compex RL100-ATX board.
-c-help: More specific information and updates are available from
+c-help: More specific information and updates are available from 
 c-help: http://www.scyld.com/network/drivers.html
 */
 
@@ -138,7 +138,7 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #include <asm/irq.h>
 
 /* These identify the driver base version and may not be removed. */
-static char version[] =
+static char version[] __devinitdata =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " (2.4 port) " DRV_RELDATE "  Donald Becker <becker@scyld.com>\n"
 KERN_INFO "  http://www.scyld.com/network/drivers.html\n";
 
@@ -207,38 +207,53 @@ Test with 'ping -s 10000' on a fast computer.
 
 */
 
-
+\f
 
 /*
   PCI probe table.
 */
-enum chip_capability_flags {
-       CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8,
+enum pci_id_flags_bits {
+        /* Set PCI command register bits before calling probe1(). */
+        PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+        /* Read and map the single following PCI BAR. */
+        PCI_ADDR0=0<<4, PCI_ADDR1=1<<4, PCI_ADDR2=2<<4, PCI_ADDR3=3<<4,
+        PCI_ADDR_64BITS=0x100, PCI_NO_ACPI_WAKE=0x200, PCI_NO_MIN_LATENCY=0x400,
 };
+enum chip_capability_flags {
+       CanHaveMII=1, HasBrokenTx=2, AlwaysFDX=4, FDXOnNoMII=8,};
+#ifdef USE_IO_OPS
+#define W840_FLAGS (PCI_USES_IO | PCI_ADDR0 | PCI_USES_MASTER)
+#else
+#define W840_FLAGS (PCI_USES_MEM | PCI_ADDR1 | PCI_USES_MASTER)
+#endif
 
-static const struct pci_device_id w840_pci_tbl[] = {
+static struct pci_device_id w840_pci_tbl[] = {
        { 0x1050, 0x0840, PCI_ANY_ID, 0x8153,     0, 0, 0 },
        { 0x1050, 0x0840, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
        { 0x11f6, 0x2011, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
-       { }
+       { 0, }
 };
 MODULE_DEVICE_TABLE(pci, w840_pci_tbl);
 
-enum {
-       netdev_res_size         = 128,  /* size of PCI BAR resource */
-};
-
 struct pci_id_info {
         const char *name;
-        int drv_flags;         /* Driver use, intended as capability flags. */
+        struct match_info {
+                int     pci, pci_mask, subsystem, subsystem_mask;
+                int revision, revision_mask;                            /* Only 8 bits. */
+        } id;
+        enum pci_id_flags_bits pci_flags;
+        int io_size;                            /* Needed for I/O region check or ioremap(). */
+        int drv_flags;                          /* Driver use, intended as capability flags. */
 };
-
-static const struct pci_id_info pci_id_tbl[] __devinitdata = {
-       {                               /* Sometime a Level-One switch card. */
-         "Winbond W89c840",    CanHaveMII | HasBrokenTx | FDXOnNoMII},
-       { "Winbond W89c840",    CanHaveMII | HasBrokenTx},
-       { "Compex RL100-ATX",   CanHaveMII | HasBrokenTx},
-       { }     /* terminate list. */
+static struct pci_id_info pci_id_tbl[] = {
+       {"Winbond W89c840",                     /* Sometime a Level-One switch card. */
+        { 0x08401050, 0xffffffff, 0x81530000, 0xffff0000 },
+        W840_FLAGS, 128, CanHaveMII | HasBrokenTx | FDXOnNoMII},
+       {"Winbond W89c840", { 0x08401050, 0xffffffff, },
+        W840_FLAGS, 128, CanHaveMII | HasBrokenTx},
+       {"Compex RL100-ATX", { 0x201111F6, 0xffffffff,},
+        W840_FLAGS, 128, CanHaveMII | HasBrokenTx},
+       {NULL,},                                        /* 0 terminated list. */
 };
 
 /* This driver was written to use PCI memory space, however some x86 systems
@@ -359,7 +374,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static struct ethtool_ops netdev_ethtool_ops;
 static int  netdev_close(struct net_device *dev);
 
-
+\f
 
 static int __devinit w840_probe1 (struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
@@ -396,7 +411,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
 #ifdef USE_IO_OPS
        bar = 0;
 #endif
-       ioaddr = pci_iomap(pdev, bar, netdev_res_size);
+       ioaddr = pci_iomap(pdev, bar, pci_id_tbl[chip_idx].io_size);
        if (!ioaddr)
                goto err_out_free_res;
 
@@ -419,7 +434,7 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
        np->mii_if.mdio_read = mdio_read;
        np->mii_if.mdio_write = mdio_write;
        np->base_addr = ioaddr;
-
+       
        pci_set_drvdata(pdev, dev);
 
        if (dev->mem_start)
@@ -495,7 +510,7 @@ err_out_netdev:
        return -ENODEV;
 }
 
-
+\f
 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.  These are
    often serial bit streams generated by the host processor.
    The example below is for the common 93c46 EEPROM, 64 16 bit words. */
@@ -645,7 +660,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
        return;
 }
 
-
+\f
 static int netdev_open(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
@@ -655,7 +670,7 @@ static int netdev_open(struct net_device *dev)
        iowrite32(0x00000001, ioaddr + PCIBusCfg);              /* Reset */
 
        netif_device_detach(dev);
-       i = request_irq(dev->irq, &intr_handler, IRQF_SHARED, dev->name, dev);
+       i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
        if (i)
                goto out_err;
 
@@ -716,7 +731,7 @@ static int update_link(struct net_device *dev)
                                dev->name, np->phys[0]);
                netif_carrier_on(dev);
        }
-
+       
        if ((np->mii & ~0xf) == MII_DAVICOM_DM9101) {
                /* If the link partner doesn't support autonegotiation
                 * the MII detects it's abilities with the "parallel detection".
@@ -746,7 +761,7 @@ static int update_link(struct net_device *dev)
                result |= 0x20000000;
        if (result != np->csr6 && debug)
                printk(KERN_INFO "%s: Setting %dMBit-%s-duplex based on MII#%d\n",
-                                dev->name, fasteth ? 100 : 10,
+                                dev->name, fasteth ? 100 : 10, 
                                duplex ? "full" : "half", np->phys[0]);
        return result;
 }
@@ -835,7 +850,7 @@ static void init_rxtx_rings(struct net_device *dev)
                        break;
                skb->dev = dev;                 /* Mark as being used by this device. */
                np->rx_addr[i] = pci_map_single(np->pci_dev,skb->data,
-                                       np->rx_buf_sz,PCI_DMA_FROMDEVICE);
+                                       skb->len,PCI_DMA_FROMDEVICE);
 
                np->rx_ring[i].buffer1 = np->rx_addr[i];
                np->rx_ring[i].status = DescOwn;
@@ -932,7 +947,7 @@ static void init_registers(struct net_device *dev)
        iowrite32(i, ioaddr + PCIBusCfg);
 
        np->csr6 = 0;
-       /* 128 byte Tx threshold;
+       /* 128 byte Tx threshold; 
                Transmit on; Receive on; */
        update_csr6(dev, 0x00022002 | update_link(dev) | __set_rx_mode(dev));
 
@@ -1301,7 +1316,7 @@ static int netdev_rx(struct net_device *dev)
                        skb->dev = dev;                 /* Mark as being used by this device. */
                        np->rx_addr[entry] = pci_map_single(np->pci_dev,
                                                        skb->data,
-                                                       np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+                                                       skb->len, PCI_DMA_FROMDEVICE);
                        np->rx_ring[entry].buffer1 = np->rx_addr[entry];
                }
                wmb();
@@ -1569,7 +1584,7 @@ static int netdev_close(struct net_device *dev)
 static void __devexit w840_remove1 (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-
+       
        if (dev) {
                struct netdev_private *np = netdev_priv(dev);
                unregister_netdev(dev);
@@ -1590,11 +1605,11 @@ static void __devexit w840_remove1 (struct pci_dev *pdev)
  * - get_stats:
  *     spin_lock_irq(np->lock), doesn't touch hw if not present
  * - hard_start_xmit:
- *     synchronize_irq + netif_tx_disable;
+ *     netif_stop_queue + spin_unlock_wait(&dev->xmit_lock);
  * - tx_timeout:
- *     netif_device_detach + netif_tx_disable;
+ *     netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  * - set_multicast_list
- *     netif_device_detach + netif_tx_disable;
+ *     netif_device_detach + spin_unlock_wait(&dev->xmit_lock);
  * - interrupt handler
  *     doesn't touch hw if not present, synchronize_irq waits for
  *     running instances of the interrupt handler.
@@ -1620,16 +1635,17 @@ static int w840_suspend (struct pci_dev *pdev, pm_message_t state)
                netif_device_detach(dev);
                update_csr6(dev, 0);
                iowrite32(0, ioaddr + IntrEnable);
+               netif_stop_queue(dev);
                spin_unlock_irq(&np->lock);
 
+               spin_unlock_wait(&dev->xmit_lock);
                synchronize_irq(dev->irq);
-               netif_tx_disable(dev);
        
                np->stats.rx_missed_errors += ioread32(ioaddr + RxMissed) & 0xffff;
 
                /* no more hardware accesses behind this line. */
 
-               BUG_ON(np->csr6);
+               if (np->csr6) BUG();
                if (ioread32(ioaddr + IntrEnable)) BUG();
 
                /* pci_power_off(pdev, -1); */