X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fsundance.c;h=698568e751daf512aaed32902f36b818354db3f3;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=e5069fca1792027be6985b58b65b132ca48aba9e;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c index e5069fca1..698568e75 100644 --- a/drivers/net/sundance.c +++ b/drivers/net/sundance.c @@ -16,86 +16,13 @@ Support and updates available at http://www.scyld.com/network/sundance.html - - - Version LK1.01a (jgarzik): - - Replace some MII-related magic numbers with constants - - Version LK1.02 (D-Link): - - Add new board to PCI ID list - - Fix multicast bug - - Version LK1.03 (D-Link): - - New Rx scheme, reduce Rx congestion - - Option to disable flow control - - Version LK1.04 (D-Link): - - Tx timeout recovery - - More support for ethtool. - - Version LK1.04a: - - Remove unused/constant members from struct pci_id_info - (which then allows removal of 'drv_flags' from private struct) - (jgarzik) - - If no phy is found, fail to load that board (jgarzik) - - Always start phy id scan at id 1 to avoid problems (Donald Becker) - - Autodetect where mii_preable_required is needed, - default to not needed. (Donald Becker) - - Version LK1.04b: - - Remove mii_preamble_required module parameter (Donald Becker) - - Add per-interface mii_preamble_required (setting is autodetected) - (Donald Becker) - - Remove unnecessary cast from void pointer (jgarzik) - - Re-align comments in private struct (jgarzik) - - Version LK1.04c (jgarzik): - - Support bitmapped message levels (NETIF_MSG_xxx), and the - two ethtool ioctls that get/set them - - Don't hand-code MII ethtool support, use standard API/lib - - Version LK1.04d: - - Merge from Donald Becker's sundance.c: (Jason Lunz) - * proper support for variably-sized MTUs - * default to PIO, to fix chip bugs - - Add missing unregister_netdev (Jason Lunz) - - Add CONFIG_SUNDANCE_MMIO config option (jgarzik) - - Better rx buf size calculation (Donald Becker) - - Version LK1.05 (D-Link): - - Fix DFE-580TX packet drop issue (for DL10050C) - - Fix reset_tx logic - - Version LK1.06 (D-Link): - - Fix crash while unloading driver - - Versin LK1.06b (D-Link): - - New tx scheme, adaptive tx_coalesce - - Version LK1.07 (D-Link): - - Fix tx bugs in big-endian machines - - Remove unused max_interrupt_work module parameter, the new - NAPI-like rx scheme doesn't need it. - - Remove redundancy get_stats() in intr_handler(), those - I/O access could affect performance in ARM-based system - - Add Linux software VLAN support - - Version LK1.08 (D-Link): - - Fix bug of custom mac address - (StationAddr register only accept word write) - - Version LK1.09 (D-Link): - - Fix the flowctrl bug. - - Set Pause bit in MII ANAR if flow control enabled. - - Version LK1.09a (ICPlus): - - Add the delay time in reading the contents of EEPROM + [link no longer provides useful info -jgarzik] */ #define DRV_NAME "sundance" -#define DRV_VERSION "1.01+LK1.09a" -#define DRV_RELDATE "10-Jul-2003" +#define DRV_VERSION "1.1" +#define DRV_RELDATE "27-Jun-2006" /* The user-configurable values. @@ -103,7 +30,7 @@ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ /* Maximum number of multicast addresses to filter (vs. rx-all-multicast). Typical is a 64 element hash table based on the Ethernet CRC. */ -static int multicast_filter_limit = 32; +static const int multicast_filter_limit = 32; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. @@ -148,15 +75,6 @@ static char *media[MAX_UNITS]; #define TX_TIMEOUT (4*HZ) #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ -#ifndef __KERNEL__ -#define __KERNEL__ -#endif -#if !defined(__OPTIMIZE__) -#warning You must compile this file with the correct options! -#warning See the last lines of the source file. -#error You must compile this driver with "-O". -#endif - /* Include files, designed to support most kernel versions 2.0.0 and later. */ #include #include @@ -171,9 +89,9 @@ static char *media[MAX_UNITS]; #include #include #include +#include #include #include /* Processor type for cache alignment. */ -#include #include #include #include @@ -189,7 +107,7 @@ static char *media[MAX_UNITS]; #endif /* These identify the driver base version and may not be removed. */ -static char version[] __devinitdata = +static char version[] = KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker\n" KERN_INFO " http://www.scyld.com/network/sundance.html\n"; @@ -197,10 +115,10 @@ MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("Sundance Alta Ethernet driver"); MODULE_LICENSE("GPL"); -MODULE_PARM(debug, "i"); -MODULE_PARM(rx_copybreak, "i"); -MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "s"); -MODULE_PARM(flowctrl, "i"); +module_param(debug, int, 0); +module_param(rx_copybreak, int, 0); +module_param_array(media, charp, NULL, 0); +module_param(flowctrl, int, 0); MODULE_PARM_DESC(debug, "Sundance Alta debug level (0-5)"); MODULE_PARM_DESC(rx_copybreak, "Sundance Alta copy breakpoint for copy-only-tiny-frames"); MODULE_PARM_DESC(flowctrl, "Sundance Alta flow control [0|1]"); @@ -272,8 +190,10 @@ IV. Notes IVb. References The Sundance ST201 datasheet, preliminary version. -http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html -http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html +The Kendin KS8723 datasheet, preliminary version. +The ICplus IP100 datasheet, preliminary version. +http://www.scyld.com/expert/100mbps.html +http://www.scyld.com/expert/NWay.html IVc. Errata @@ -284,14 +204,15 @@ IVc. Errata #define USE_IO_OPS 1 #endif -static struct pci_device_id sundance_pci_tbl[] = { - {0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0}, - {0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1}, - {0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2}, - {0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3}, - {0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4}, - {0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5}, - {0,} +static const struct pci_device_id sundance_pci_tbl[] = { + { 0x1186, 0x1002, 0x1186, 0x1002, 0, 0, 0 }, + { 0x1186, 0x1002, 0x1186, 0x1003, 0, 0, 1 }, + { 0x1186, 0x1002, 0x1186, 0x1012, 0, 0, 2 }, + { 0x1186, 0x1002, 0x1186, 0x1040, 0, 0, 3 }, + { 0x1186, 0x1002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, + { 0x13F0, 0x0201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, + { 0x13F0, 0x0200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 }, + { } }; MODULE_DEVICE_TABLE(pci, sundance_pci_tbl); @@ -302,32 +223,19 @@ enum { struct pci_id_info { const char *name; }; -static struct pci_id_info pci_id_tbl[] = { +static const struct pci_id_info pci_id_tbl[] __devinitdata = { {"D-Link DFE-550TX FAST Ethernet Adapter"}, {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"}, {"D-Link DFE-580TX 4 port Server Adapter"}, {"D-Link DFE-530TXS FAST Ethernet Adapter"}, {"D-Link DL10050-based FAST Ethernet Adapter"}, {"Sundance Technology Alta"}, - {0,}, /* 0 terminated list. */ + {"IC Plus Corporation IP100A FAST Ethernet Adapter"}, + { } /* terminate list. */ }; /* This driver was written to use PCI memory space, however x86-oriented hardware often uses I/O space accesses. */ -#ifdef USE_IO_OPS -#undef readb -#undef readw -#undef readl -#undef writeb -#undef writew -#undef writel -#define readb inb -#define readw inw -#define readl inl -#define writeb outb -#define writew outw -#define writel outl -#endif /* Offsets to the device registers. Unlike software-only systems, device drivers interact with complex hardware. @@ -489,6 +397,7 @@ struct netdev_private { int mii_preamble_required; unsigned char phys[MII_CNT]; /* MII device addresses, only first one used. */ struct pci_dev *pci_dev; + void __iomem *base; unsigned char pci_rev_id; }; @@ -499,7 +408,7 @@ struct netdev_private { LinkChange) static int change_mtu(struct net_device *dev, int new_mtu); -static int eeprom_read(long ioaddr, int location); +static int eeprom_read(void __iomem *ioaddr, int location); static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int netdev_open(struct net_device *dev); @@ -520,8 +429,26 @@ static int __set_mac_addr(struct net_device *dev); static struct net_device_stats *get_stats(struct net_device *dev); static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct net_device *dev); +static struct ethtool_ops ethtool_ops; - +static void sundance_reset(struct net_device *dev, unsigned long reset_cmd) +{ + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base + ASICCtrl; + int countdown; + + /* ST201 documentation states ASICCtrl is a 32bit register */ + iowrite32 (reset_cmd | ioread32 (ioaddr), ioaddr); + /* ST201 documentation states reset can take up to 1 ms */ + countdown = 10 + 1; + while (ioread32 (ioaddr) & (ResetBusy << 16)) { + if (--countdown == 0) { + printk(KERN_WARNING "%s : reset not completed !!\n", dev->name); + break; + } + udelay(100); + } +} static int __devinit sundance_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent) @@ -532,10 +459,16 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, int chip_idx = ent->driver_data; int irq; int i; - long ioaddr; + void __iomem *ioaddr; u16 mii_ctl; void *ring_space; dma_addr_t ring_dma; +#ifdef USE_IO_OPS + int bar = 0; +#else + int bar = 1; +#endif + int phy, phy_idx = 0; /* when built into the kernel, we only print version if device is found */ @@ -560,23 +493,20 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, if (pci_request_regions(pdev, DRV_NAME)) goto err_out_netdev; -#ifdef USE_IO_OPS - ioaddr = pci_resource_start(pdev, 0); -#else - ioaddr = pci_resource_start(pdev, 1); - ioaddr = (long) ioremap (ioaddr, netdev_io_size); + ioaddr = pci_iomap(pdev, bar, netdev_io_size); if (!ioaddr) goto err_out_res; -#endif for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET)); + memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - dev->base_addr = ioaddr; + dev->base_addr = (unsigned long)ioaddr; dev->irq = irq; - np = dev->priv; + np = netdev_priv(dev); + np->base = ioaddr; np->pci_dev = pdev; np->chip_id = chip_idx; np->msg_enable = (1 << debug) - 1; @@ -609,6 +539,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, dev->get_stats = &get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &netdev_ioctl; + SET_ETHTOOL_OPS(dev, ðtool_ops); dev->tx_timeout = &tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; dev->change_mtu = &change_mtu; @@ -620,39 +551,41 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, if (i) goto err_out_unmap_rx; - printk(KERN_INFO "%s: %s at 0x%lx, ", + printk(KERN_INFO "%s: %s at %p, ", dev->name, pci_id_tbl[chip_idx].name, ioaddr); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); - if (1) { - int phy, phy_idx = 0; - np->phys[0] = 1; /* Default setting */ - np->mii_preamble_required++; - for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) { - int mii_status = mdio_read(dev, phy, MII_BMSR); - if (mii_status != 0xffff && mii_status != 0x0000) { - np->phys[phy_idx++] = phy; - np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE); - if ((mii_status & 0x0040) == 0) - np->mii_preamble_required++; - printk(KERN_INFO "%s: MII PHY found at address %d, status " - "0x%4.4x advertising %4.4x.\n", - dev->name, phy, mii_status, np->mii_if.advertising); - } - } - np->mii_preamble_required--; - - if (phy_idx == 0) { - printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n", - dev->name, readl(ioaddr + ASICCtrl)); - goto err_out_unregister; + np->phys[0] = 1; /* Default setting */ + np->mii_preamble_required++; + /* + * It seems some phys doesn't deal well with address 0 being accessed + * first, so leave address zero to the end of the loop (32 & 31). + */ + for (phy = 1; phy <= 32 && phy_idx < MII_CNT; phy++) { + int phyx = phy & 0x1f; + int mii_status = mdio_read(dev, phyx, MII_BMSR); + if (mii_status != 0xffff && mii_status != 0x0000) { + np->phys[phy_idx++] = phyx; + np->mii_if.advertising = mdio_read(dev, phyx, MII_ADVERTISE); + if ((mii_status & 0x0040) == 0) + np->mii_preamble_required++; + printk(KERN_INFO "%s: MII PHY found at address %d, status " + "0x%4.4x advertising %4.4x.\n", + dev->name, phyx, mii_status, np->mii_if.advertising); } + } + np->mii_preamble_required--; - np->mii_if.phy_id = np->phys[0]; + if (phy_idx == 0) { + printk(KERN_INFO "%s: No MII transceiver found, aborting. ASIC status %x\n", + dev->name, ioread32(ioaddr + ASICCtrl)); + goto err_out_unregister; } + np->mii_if.phy_id = np->phys[0]; + /* Parse override configuration */ np->an_enable = 1; if (card_idx < MAX_UNITS) { @@ -683,7 +616,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, } /* Fibre PHY? */ - if (readl (ioaddr + ASICCtrl) & 0x80) { + if (ioread32 (ioaddr + ASICCtrl) & 0x80) { /* Default 100Mbps Full */ if (np->an_enable) { np->speed = 100; @@ -712,10 +645,10 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev, /* Perhaps move the reset here? */ /* Reset the chip to erase previous misconfiguration. */ if (netif_msg_hw(np)) - printk("ASIC Control is %x.\n", readl(ioaddr + ASICCtrl)); - writew(0x007f, ioaddr + ASICCtrl + 2); + printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl)); + iowrite16(0x00ff, ioaddr + ASICCtrl + 2); if (netif_msg_hw(np)) - printk("ASIC Control is now %x.\n", readl(ioaddr + ASICCtrl)); + printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl)); card_idx++; return 0; @@ -728,10 +661,8 @@ err_out_unmap_tx: pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma); err_out_cleardev: pci_set_drvdata(pdev, NULL); -#ifndef USE_IO_OPS - iounmap((void *)ioaddr); + pci_iounmap(pdev, ioaddr); err_out_res: -#endif pci_release_regions(pdev); err_out_netdev: free_netdev (dev); @@ -748,16 +679,16 @@ static int change_mtu(struct net_device *dev, int new_mtu) return 0; } -#define eeprom_delay(ee_addr) readl(ee_addr) +#define eeprom_delay(ee_addr) ioread32(ee_addr) /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */ -static int __devinit eeprom_read(long ioaddr, int location) +static int __devinit eeprom_read(void __iomem *ioaddr, int location) { int boguscnt = 10000; /* Typical 1900 ticks. */ - writew(0x0200 | (location & 0xff), ioaddr + EECtrl); + iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl); do { eeprom_delay(ioaddr + EECtrl); - if (! (readw(ioaddr + EECtrl) & 0x8000)) { - return readw(ioaddr + EEData); + if (! (ioread16(ioaddr + EECtrl) & 0x8000)) { + return ioread16(ioaddr + EEData); } } while (--boguscnt > 0); return 0; @@ -770,7 +701,7 @@ static int __devinit eeprom_read(long ioaddr, int location) The maximum data clock rate is 2.5 Mhz. The minimum timing is usually met by back-to-back 33Mhz PCI cycles. */ -#define mdio_delay() readb(mdio_addr) +#define mdio_delay() ioread8(mdio_addr) enum mii_reg_bits { MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004, @@ -781,23 +712,23 @@ enum mii_reg_bits { /* Generate the preamble required for initial synchronization and a few older transceivers. */ -static void mdio_sync(long mdio_addr) +static void mdio_sync(void __iomem *mdio_addr) { int bits = 32; /* Establish sync by sending at least 32 logic ones. */ while (--bits >= 0) { - writeb(MDIO_WRITE1, mdio_addr); + iowrite8(MDIO_WRITE1, mdio_addr); mdio_delay(); - writeb(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); + iowrite8(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr); mdio_delay(); } } static int mdio_read(struct net_device *dev, int phy_id, int location) { - struct netdev_private *np = dev->priv; - long mdio_addr = dev->base_addr + MIICtrl; + struct netdev_private *np = netdev_priv(dev); + void __iomem *mdio_addr = np->base + MIICtrl; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int i, retval = 0; @@ -808,17 +739,17 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) for (i = 15; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writeb(dataval, mdio_addr); + iowrite8(dataval, mdio_addr); mdio_delay(); - writeb(dataval | MDIO_ShiftClk, mdio_addr); + iowrite8(dataval | MDIO_ShiftClk, mdio_addr); mdio_delay(); } /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) { - writeb(MDIO_EnbIn, mdio_addr); + iowrite8(MDIO_EnbIn, mdio_addr); mdio_delay(); - retval = (retval << 1) | ((readb(mdio_addr) & MDIO_Data) ? 1 : 0); - writeb(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); + retval = (retval << 1) | ((ioread8(mdio_addr) & MDIO_Data) ? 1 : 0); + iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); mdio_delay(); } return (retval>>1) & 0xffff; @@ -826,8 +757,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location) static void mdio_write(struct net_device *dev, int phy_id, int location, int value) { - struct netdev_private *np = dev->priv; - long mdio_addr = dev->base_addr + MIICtrl; + struct netdev_private *np = netdev_priv(dev); + void __iomem *mdio_addr = np->base + MIICtrl; int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value; int i; @@ -838,16 +769,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val for (i = 31; i >= 0; i--) { int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0; - writeb(dataval, mdio_addr); + iowrite8(dataval, mdio_addr); mdio_delay(); - writeb(dataval | MDIO_ShiftClk, mdio_addr); + iowrite8(dataval | MDIO_ShiftClk, mdio_addr); mdio_delay(); } /* Clear out extra bits. */ for (i = 2; i > 0; i--) { - writeb(MDIO_EnbIn, mdio_addr); + iowrite8(MDIO_EnbIn, mdio_addr); mdio_delay(); - writeb(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); + iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr); mdio_delay(); } return; @@ -855,13 +786,13 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val static int netdev_open(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; int i; /* Do we need to reset the chip??? */ - i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); + i = request_irq(dev->irq, &intr_handler, IRQF_SHARED, dev->name, dev); if (i) return i; @@ -870,45 +801,45 @@ static int netdev_open(struct net_device *dev) dev->name, dev->irq); init_ring(dev); - writel(np->rx_ring_dma, ioaddr + RxListPtr); + iowrite32(np->rx_ring_dma, ioaddr + RxListPtr); /* The Tx list pointer is written as packets are queued. */ /* Initialize other registers. */ __set_mac_addr(dev); #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) - writew(dev->mtu + 18, ioaddr + MaxFrameSize); + iowrite16(dev->mtu + 18, ioaddr + MaxFrameSize); #else - writew(dev->mtu + 14, ioaddr + MaxFrameSize); + iowrite16(dev->mtu + 14, ioaddr + MaxFrameSize); #endif if (dev->mtu > 2047) - writel(readl(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl); + iowrite32(ioread32(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl); /* Configure the PCI bus bursts and FIFO thresholds. */ if (dev->if_port == 0) dev->if_port = np->default_port; - np->mcastlock = (spinlock_t) SPIN_LOCK_UNLOCKED; + spin_lock_init(&np->mcastlock); set_rx_mode(dev); - writew(0, ioaddr + IntrEnable); - writew(0, ioaddr + DownCounter); + iowrite16(0, ioaddr + IntrEnable); + iowrite16(0, ioaddr + DownCounter); /* Set the chip to poll every N*320nsec. */ - writeb(100, ioaddr + RxDMAPollPeriod); - writeb(127, ioaddr + TxDMAPollPeriod); + iowrite8(100, ioaddr + RxDMAPollPeriod); + iowrite8(127, ioaddr + TxDMAPollPeriod); /* Fix DFE-580TX packet drop issue */ if (np->pci_rev_id >= 0x14) - writeb(0x01, ioaddr + DebugCtrl1); + iowrite8(0x01, ioaddr + DebugCtrl1); netif_start_queue(dev); - writew (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); + iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); if (netif_msg_ifup(np)) printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x " "MAC Control %x, %4.4x %4.4x.\n", - dev->name, readl(ioaddr + RxStatus), readb(ioaddr + TxStatus), - readl(ioaddr + MACCtrl0), - readw(ioaddr + MACCtrl1), readw(ioaddr + MACCtrl0)); + dev->name, ioread32(ioaddr + RxStatus), ioread8(ioaddr + TxStatus), + ioread32(ioaddr + MACCtrl0), + ioread16(ioaddr + MACCtrl1), ioread16(ioaddr + MACCtrl0)); /* Set the timer to check for link beat. */ init_timer(&np->timer); @@ -918,15 +849,15 @@ static int netdev_open(struct net_device *dev) add_timer(&np->timer); /* Enable interrupts by setting the interrupt mask. */ - writew(DEFAULT_INTR, ioaddr + IntrEnable); + iowrite16(DEFAULT_INTR, ioaddr + IntrEnable); return 0; } static void check_duplex(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA); int negotiated = mii_lpa & np->mii_if.advertising; int duplex; @@ -934,7 +865,7 @@ static void check_duplex(struct net_device *dev) /* Force media */ if (!np->an_enable || mii_lpa == 0xffff) { if (np->mii_if.full_duplex) - writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex, + iowrite16 (ioread16 (ioaddr + MACCtrl0) | EnbFullDuplex, ioaddr + MACCtrl0); return; } @@ -947,22 +878,22 @@ static void check_duplex(struct net_device *dev) printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d " "negotiated capability %4.4x.\n", dev->name, duplex ? "full" : "half", np->phys[0], negotiated); - writew(readw(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0); + iowrite16(ioread16(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0); } } static void netdev_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; int next_tick = 10*HZ; if (netif_msg_timer(np)) { printk(KERN_DEBUG "%s: Media selection timer tick, intr status %4.4x, " "Tx %x Rx %x.\n", - dev->name, readw(ioaddr + IntrEnable), - readb(ioaddr + TxStatus), readl(ioaddr + RxStatus)); + dev->name, ioread16(ioaddr + IntrEnable), + ioread8(ioaddr + TxStatus), ioread32(ioaddr + RxStatus)); } check_duplex(dev); np->timer.expires = jiffies + next_tick; @@ -971,17 +902,17 @@ static void netdev_timer(unsigned long data) static void tx_timeout(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; unsigned long flag; netif_stop_queue(dev); tasklet_disable(&np->tx_tasklet); - writew(0, ioaddr + IntrEnable); + iowrite16(0, ioaddr + IntrEnable); printk(KERN_WARNING "%s: Transmit timed out, TxStatus %2.2x " "TxFrameId %2.2x," - " resetting...\n", dev->name, readb(ioaddr + TxStatus), - readb(ioaddr + TxFrameId)); + " resetting...\n", dev->name, ioread8(ioaddr + TxStatus), + ioread8(ioaddr + TxFrameId)); { int i; @@ -995,7 +926,7 @@ static void tx_timeout(struct net_device *dev) le32_to_cpu(np->tx_ring[i].frag[0].length)); } printk(KERN_DEBUG "TxListPtr=%08x netif_queue_stopped=%d\n", - readl(dev->base_addr + TxListPtr), + ioread32(np->base + TxListPtr), netif_queue_stopped(dev)); printk(KERN_DEBUG "cur_tx=%d(%02x) dirty_tx=%d(%02x)\n", np->cur_tx, np->cur_tx % TX_RING_SIZE, @@ -1016,7 +947,7 @@ static void tx_timeout(struct net_device *dev) if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { netif_wake_queue(dev); } - writew(DEFAULT_INTR, ioaddr + IntrEnable); + iowrite16(DEFAULT_INTR, ioaddr + IntrEnable); tasklet_enable(&np->tx_tasklet); } @@ -1024,7 +955,7 @@ static void tx_timeout(struct net_device *dev) /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void init_ring(struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int i; np->cur_rx = np->cur_tx = 0; @@ -1039,7 +970,7 @@ static void init_ring(struct net_device *dev) ((i+1)%RX_RING_SIZE)*sizeof(*np->rx_ring)); np->rx_ring[i].status = 0; np->rx_ring[i].frag[0].length = 0; - np->rx_skbuff[i] = 0; + np->rx_skbuff[i] = NULL; } /* Fill in the Rx buffers. Handle allocation failure gracefully. */ @@ -1051,14 +982,14 @@ static void init_ring(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* 16 byte align the IP header. */ np->rx_ring[i].frag[0].addr = cpu_to_le32( - pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, + pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); np->rx_ring[i].frag[0].length = cpu_to_le32(np->rx_buf_sz | LastFrag); } np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); for (i = 0; i < TX_RING_SIZE; i++) { - np->tx_skbuff[i] = 0; + np->tx_skbuff[i] = NULL; np->tx_ring[i].status = 0; } return; @@ -1067,7 +998,7 @@ static void init_ring(struct net_device *dev) static void tx_poll (unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unsigned head = np->cur_task % TX_RING_SIZE; struct netdev_desc *txdesc = &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE]; @@ -1085,16 +1016,16 @@ static void tx_poll (unsigned long data) /* Indicate the latest descriptor of tx ring */ txdesc->status |= cpu_to_le32(DescIntrOnTx); - if (readl (dev->base_addr + TxListPtr) == 0) - writel (np->tx_ring_dma + head * sizeof(struct netdev_desc), - dev->base_addr + TxListPtr); + if (ioread32 (np->base + TxListPtr) == 0) + iowrite32 (np->tx_ring_dma + head * sizeof(struct netdev_desc), + np->base + TxListPtr); return; } static int start_tx (struct sk_buff *skb, struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); struct netdev_desc *txdesc; unsigned entry; @@ -1136,18 +1067,18 @@ start_tx (struct sk_buff *skb, struct net_device *dev) static int reset_tx (struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; struct sk_buff *skb; int i; int irq = in_interrupt(); /* Reset tx logic, TxListPtr will be cleaned */ - writew (TxDisable, ioaddr + MACCtrl1); - writew (TxReset | DMAReset | FIFOReset | NetworkReset, + iowrite16 (TxDisable, ioaddr + MACCtrl1); + iowrite16 (TxReset | DMAReset | FIFOReset | NetworkReset, ioaddr + ASICCtrl + 2); for (i=50; i > 0; i--) { - if ((readw(ioaddr + ASICCtrl + 2) & ResetBusy) == 0) + if ((ioread16(ioaddr + ASICCtrl + 2) & ResetBusy) == 0) break; mdelay(1); } @@ -1162,13 +1093,13 @@ reset_tx (struct net_device *dev) dev_kfree_skb_irq (skb); else dev_kfree_skb (skb); - np->tx_skbuff[i] = 0; + np->tx_skbuff[i] = NULL; np->stats.tx_dropped++; } } np->cur_tx = np->dirty_tx = 0; np->cur_task = 0; - writew (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); + iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1); return 0; } @@ -1177,19 +1108,17 @@ reset_tx (struct net_device *dev) static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) { struct net_device *dev = (struct net_device *)dev_instance; - struct netdev_private *np; - long ioaddr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; int hw_frame_id; int tx_cnt; int tx_status; int handled = 0; - ioaddr = dev->base_addr; - np = dev->priv; do { - int intr_status = readw(ioaddr + IntrStatus); - writew(intr_status, ioaddr + IntrStatus); + int intr_status = ioread16(ioaddr + IntrStatus); + iowrite16(intr_status, ioaddr + IntrStatus); if (netif_msg_intr(np)) printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", @@ -1201,47 +1130,59 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs handled = 1; if (intr_status & (IntrRxDMADone)) { - writew(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), + iowrite16(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone), ioaddr + IntrEnable); if (np->budget < 0) np->budget = RX_BUDGET; tasklet_schedule(&np->rx_tasklet); } if (intr_status & (IntrTxDone | IntrDrvRqst)) { - tx_status = readw (ioaddr + TxStatus); + tx_status = ioread16 (ioaddr + TxStatus); for (tx_cnt=32; tx_status & 0x80; --tx_cnt) { if (netif_msg_tx_done(np)) printk ("%s: Transmit status is %2.2x.\n", dev->name, tx_status); if (tx_status & 0x1e) { + if (netif_msg_tx_err(np)) + printk("%s: Transmit error status %4.4x.\n", + dev->name, tx_status); np->stats.tx_errors++; if (tx_status & 0x10) np->stats.tx_fifo_errors++; if (tx_status & 0x08) np->stats.collisions++; + if (tx_status & 0x04) + np->stats.tx_fifo_errors++; if (tx_status & 0x02) np->stats.tx_window_errors++; - /* This reset has not been verified!. */ - if (tx_status & 0x10) { /* Reset the Tx. */ - np->stats.tx_fifo_errors++; - spin_lock(&np->lock); - reset_tx(dev); - spin_unlock(&np->lock); + /* + ** This reset has been verified on + ** DFE-580TX boards ! phdm@macqel.be. + */ + if (tx_status & 0x10) { /* TxUnderrun */ + unsigned short txthreshold; + + txthreshold = ioread16 (ioaddr + TxStartThresh); + /* Restart Tx FIFO and transmitter */ + sundance_reset(dev, (NetworkReset|FIFOReset|TxReset) << 16); + iowrite16 (txthreshold, ioaddr + TxStartThresh); + /* No need to reset the Tx pointer here */ } - if (tx_status & 0x1e) /* Restart the Tx. */ - writew (TxEnable, - ioaddr + MACCtrl1); + /* Restart the Tx. */ + iowrite16 (TxEnable, ioaddr + MACCtrl1); } /* Yup, this is a documentation bug. It cost me *hours*. */ - writew (0, ioaddr + TxStatus); - tx_status = readw (ioaddr + TxStatus); - if (tx_cnt < 0) + iowrite16 (0, ioaddr + TxStatus); + if (tx_cnt < 0) { + iowrite32(5000, ioaddr + DownCounter); break; + } + tx_status = ioread16 (ioaddr + TxStatus); } hw_frame_id = (tx_status >> 8) & 0xff; } else { - hw_frame_id = readb(ioaddr + TxFrameId); + hw_frame_id = ioread8(ioaddr + TxFrameId); } if (np->pci_rev_id >= 0x14) { @@ -1265,7 +1206,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs np->tx_ring[entry].frag[0].addr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq (np->tx_skbuff[entry]); - np->tx_skbuff[entry] = 0; + np->tx_skbuff[entry] = NULL; np->tx_ring[entry].frag[0].addr = 0; np->tx_ring[entry].frag[0].length = 0; } @@ -1284,7 +1225,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs np->tx_ring[entry].frag[0].addr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq (np->tx_skbuff[entry]); - np->tx_skbuff[entry] = 0; + np->tx_skbuff[entry] = NULL; np->tx_ring[entry].frag[0].addr = 0; np->tx_ring[entry].frag[0].length = 0; } @@ -1302,18 +1243,17 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs } while (0); if (netif_msg_intr(np)) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", - dev->name, readw(ioaddr + IntrStatus)); - writel(5000, ioaddr + DownCounter); + dev->name, ioread16(ioaddr + IntrStatus)); return IRQ_RETVAL(handled); } static void rx_poll(unsigned long data) { struct net_device *dev = (struct net_device *)data; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry = np->cur_rx % RX_RING_SIZE; int boguscnt = np->budget; - long ioaddr = dev->base_addr; + void __iomem *ioaddr = np->base; int received = 0; /* If EOP is set on the next entry, it's a new packet. Send it up. */ @@ -1365,7 +1305,7 @@ static void rx_poll(unsigned long data) np->rx_buf_sz, PCI_DMA_FROMDEVICE); - eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); + eth_copy_and_sum(skb, np->rx_skbuff[entry]->data, pkt_len, 0); pci_dma_sync_single_for_device(np->pci_dev, desc->frag[0].addr, np->rx_buf_sz, @@ -1390,7 +1330,7 @@ static void rx_poll(unsigned long data) np->cur_rx = entry; refill_rx (dev); np->budget -= received; - writew(DEFAULT_INTR, ioaddr + IntrEnable); + iowrite16(DEFAULT_INTR, ioaddr + IntrEnable); return; not_done: @@ -1407,7 +1347,7 @@ not_done: static void refill_rx (struct net_device *dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); int entry; int cnt = 0; @@ -1424,7 +1364,7 @@ static void refill_rx (struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ np->rx_ring[entry].frag[0].addr = cpu_to_le32( - pci_map_single(np->pci_dev, skb->tail, + pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE)); } /* Perhaps we need not reset this field. */ @@ -1437,8 +1377,8 @@ static void refill_rx (struct net_device *dev) } static void netdev_error(struct net_device *dev, int intr_status) { - long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; u16 mii_ctl, mii_advertise, mii_lpa; int speed; @@ -1474,9 +1414,9 @@ static void netdev_error(struct net_device *dev, int intr_status) } check_duplex (dev); if (np->flowctrl && np->mii_if.full_duplex) { - writew(readw(ioaddr + MulticastFilter1+2) | 0x0200, + iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200, ioaddr + MulticastFilter1+2); - writew(readw(ioaddr + MACCtrl0) | EnbFlowCtrl, + iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl, ioaddr + MACCtrl0); } } @@ -1492,36 +1432,36 @@ static void netdev_error(struct net_device *dev, int intr_status) static struct net_device_stats *get_stats(struct net_device *dev) { - struct netdev_private *np = dev->priv; - long ioaddr = dev->base_addr; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; int i; /* We should lock this segment of code for SMP eventually, although the vulnerability window is very small and statistics are non-critical. */ /* The chip only need report frame silently dropped. */ - np->stats.rx_missed_errors += readb(ioaddr + RxMissed); - np->stats.tx_packets += readw(ioaddr + TxFramesOK); - np->stats.rx_packets += readw(ioaddr + RxFramesOK); - np->stats.collisions += readb(ioaddr + StatsLateColl); - np->stats.collisions += readb(ioaddr + StatsMultiColl); - np->stats.collisions += readb(ioaddr + StatsOneColl); - np->stats.tx_carrier_errors += readb(ioaddr + StatsCarrierError); - readb(ioaddr + StatsTxDefer); + np->stats.rx_missed_errors += ioread8(ioaddr + RxMissed); + np->stats.tx_packets += ioread16(ioaddr + TxFramesOK); + np->stats.rx_packets += ioread16(ioaddr + RxFramesOK); + np->stats.collisions += ioread8(ioaddr + StatsLateColl); + np->stats.collisions += ioread8(ioaddr + StatsMultiColl); + np->stats.collisions += ioread8(ioaddr + StatsOneColl); + np->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError); + ioread8(ioaddr + StatsTxDefer); for (i = StatsTxDefer; i <= StatsMcastRx; i++) - readb(ioaddr + i); - np->stats.tx_bytes += readw(ioaddr + TxOctetsLow); - np->stats.tx_bytes += readw(ioaddr + TxOctetsHigh) << 16; - np->stats.rx_bytes += readw(ioaddr + RxOctetsLow); - np->stats.rx_bytes += readw(ioaddr + RxOctetsHigh) << 16; + ioread8(ioaddr + i); + np->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow); + np->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16; + np->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow); + np->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16; return &np->stats; } static void set_rx_mode(struct net_device *dev) { - long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; u16 mc_filter[4]; /* Multicast hash filter */ u32 rx_mode; int i; @@ -1551,129 +1491,114 @@ static void set_rx_mode(struct net_device *dev) } rx_mode = AcceptBroadcast | AcceptMultiHash | AcceptMyPhys; } else { - writeb(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode); + iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode); return; } if (np->mii_if.full_duplex && np->flowctrl) mc_filter[3] |= 0x0200; for (i = 0; i < 4; i++) - writew(mc_filter[i], ioaddr + MulticastFilter0 + i*2); - writeb(rx_mode, ioaddr + RxMode); + iowrite16(mc_filter[i], ioaddr + MulticastFilter0 + i*2); + iowrite8(rx_mode, ioaddr + RxMode); } static int __set_mac_addr(struct net_device *dev) { + struct netdev_private *np = netdev_priv(dev); u16 addr16; addr16 = (dev->dev_addr[0] | (dev->dev_addr[1] << 8)); - writew(addr16, dev->base_addr + StationAddr); + iowrite16(addr16, np->base + StationAddr); addr16 = (dev->dev_addr[2] | (dev->dev_addr[3] << 8)); - writew(addr16, dev->base_addr + StationAddr+2); + iowrite16(addr16, np->base + StationAddr+2); addr16 = (dev->dev_addr[4] | (dev->dev_addr[5] << 8)); - writew(addr16, dev->base_addr + StationAddr+4); + iowrite16(addr16, np->base + StationAddr+4); return 0; } - -static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr) +static int check_if_running(struct net_device *dev) { - struct netdev_private *np = dev->priv; - u32 ethcmd; - - if (copy_from_user(ðcmd, useraddr, sizeof(ethcmd))) - return -EFAULT; - - switch (ethcmd) { - /* get constant driver settings/info */ - case ETHTOOL_GDRVINFO: { - struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO}; - strcpy(info.driver, DRV_NAME); - strcpy(info.version, DRV_VERSION); - strcpy(info.bus_info, pci_name(np->pci_dev)); - memset(&info.fw_version, 0, sizeof(info.fw_version)); - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; - } + if (!netif_running(dev)) + return -EINVAL; + return 0; +} - /* get media settings */ - case ETHTOOL_GSET: { - struct ethtool_cmd ecmd = { ETHTOOL_GSET }; - spin_lock_irq(&np->lock); - mii_ethtool_gset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - if (copy_to_user(useraddr, &ecmd, sizeof(ecmd))) - return -EFAULT; - return 0; - } - /* set media settings */ - case ETHTOOL_SSET: { - int r; - struct ethtool_cmd ecmd; - if (copy_from_user(&ecmd, useraddr, sizeof(ecmd))) - return -EFAULT; - spin_lock_irq(&np->lock); - r = mii_ethtool_sset(&np->mii_if, &ecmd); - spin_unlock_irq(&np->lock); - return r; - } +static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + struct netdev_private *np = netdev_priv(dev); + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, pci_name(np->pci_dev)); +} - /* restart autonegotiation */ - case ETHTOOL_NWAY_RST: { - return mii_nway_restart(&np->mii_if); - } +static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + spin_lock_irq(&np->lock); + mii_ethtool_gset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return 0; +} - /* get link status */ - case ETHTOOL_GLINK: { - struct ethtool_value edata = {ETHTOOL_GLINK}; - edata.data = mii_link_ok(&np->mii_if); - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } +static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) +{ + struct netdev_private *np = netdev_priv(dev); + int res; + spin_lock_irq(&np->lock); + res = mii_ethtool_sset(&np->mii_if, ecmd); + spin_unlock_irq(&np->lock); + return res; +} - /* get message-level */ - case ETHTOOL_GMSGLVL: { - struct ethtool_value edata = {ETHTOOL_GMSGLVL}; - edata.data = np->msg_enable; - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; - } - /* set message-level */ - case ETHTOOL_SMSGLVL: { - struct ethtool_value edata; - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - np->msg_enable = edata.data; - return 0; - } +static int nway_reset(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_nway_restart(&np->mii_if); +} - default: - return -EOPNOTSUPP; +static u32 get_link(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return mii_link_ok(&np->mii_if); +} - } +static u32 get_msglevel(struct net_device *dev) +{ + struct netdev_private *np = netdev_priv(dev); + return np->msg_enable; } +static void set_msglevel(struct net_device *dev, u32 val) +{ + struct netdev_private *np = netdev_priv(dev); + np->msg_enable = val; +} + +static struct ethtool_ops ethtool_ops = { + .begin = check_if_running, + .get_drvinfo = get_drvinfo, + .get_settings = get_settings, + .set_settings = set_settings, + .nway_reset = nway_reset, + .get_link = get_link, + .get_msglevel = get_msglevel, + .set_msglevel = set_msglevel, + .get_perm_addr = ethtool_op_get_perm_addr, +}; + static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; int rc; int i; - long ioaddr = dev->base_addr; if (!netif_running(dev)) return -EINVAL; - if (cmd == SIOCETHTOOL) - rc = netdev_ethtool_ioctl(dev, rq->ifr_data); - - else { - spin_lock_irq(&np->lock); - rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); - spin_unlock_irq(&np->lock); - } + spin_lock_irq(&np->lock); + rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL); + spin_unlock_irq(&np->lock); switch (cmd) { case SIOCDEVPRIVATE: for (i=0; itx_ring[i].frag[0].length)); } printk(KERN_DEBUG "TxListPtr=%08x netif_queue_stopped=%d\n", - readl(dev->base_addr + TxListPtr), + ioread32(np->base + TxListPtr), netif_queue_stopped(dev)); printk(KERN_DEBUG "cur_tx=%d(%02x) dirty_tx=%d(%02x)\n", np->cur_tx, np->cur_tx % TX_RING_SIZE, np->dirty_tx, np->dirty_tx % TX_RING_SIZE); printk(KERN_DEBUG "cur_rx=%d dirty_rx=%d\n", np->cur_rx, np->dirty_rx); printk(KERN_DEBUG "cur_task=%d\n", np->cur_task); - printk(KERN_DEBUG "TxStatus=%04x\n", readw(ioaddr + TxStatus)); + printk(KERN_DEBUG "TxStatus=%04x\n", ioread16(ioaddr + TxStatus)); return 0; } @@ -1704,8 +1629,8 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int netdev_close(struct net_device *dev) { - long ioaddr = dev->base_addr; - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); + void __iomem *ioaddr = np->base; struct sk_buff *skb; int i; @@ -1714,17 +1639,17 @@ static int netdev_close(struct net_device *dev) if (netif_msg_ifdown(np)) { printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %2.2x " "Rx %4.4x Int %2.2x.\n", - dev->name, readb(ioaddr + TxStatus), - readl(ioaddr + RxStatus), readw(ioaddr + IntrStatus)); + dev->name, ioread8(ioaddr + TxStatus), + ioread32(ioaddr + RxStatus), ioread16(ioaddr + IntrStatus)); printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d, Rx %d / %d.\n", dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx); } /* Disable interrupts by clearing the interrupt mask. */ - writew(0x0000, ioaddr + IntrEnable); + iowrite16(0x0000, ioaddr + IntrEnable); /* Stop the chip's Tx and Rx processes. */ - writew(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1); + iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1); /* Wait and kill tasklet */ tasklet_kill(&np->rx_tasklet); @@ -1762,7 +1687,7 @@ static int netdev_close(struct net_device *dev) np->rx_ring[i].frag[0].addr, np->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(skb); - np->rx_skbuff[i] = 0; + np->rx_skbuff[i] = NULL; } } for (i = 0; i < TX_RING_SIZE; i++) { @@ -1772,7 +1697,7 @@ static int netdev_close(struct net_device *dev) np->tx_ring[i].frag[0].addr, skb->len, PCI_DMA_TODEVICE); dev_kfree_skb(skb); - np->tx_skbuff[i] = 0; + np->tx_skbuff[i] = NULL; } } @@ -1784,17 +1709,15 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev) struct net_device *dev = pci_get_drvdata(pdev); if (dev) { - struct netdev_private *np = dev->priv; + struct netdev_private *np = netdev_priv(dev); unregister_netdev(dev); pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring, np->rx_ring_dma); pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma); + pci_iounmap(pdev, np->base); pci_release_regions(pdev); -#ifndef USE_IO_OPS - iounmap((char *)(dev->base_addr)); -#endif free_netdev(dev); pci_set_drvdata(pdev, NULL); }