#include <linux/rtnetlink.h>
#include <linux/mii.h>
#include <linux/crc32.h>
+#include <linux/bitops.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
-#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
MODULE_DESCRIPTION("National Semiconductor DP8381x series PCI Ethernet driver");
MODULE_LICENSE("GPL");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(mtu, "i");
-MODULE_PARM(debug, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+module_param(max_interrupt_work, int, 0);
+module_param(mtu, int, 0);
+module_param(debug, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
MODULE_PARM_DESC(max_interrupt_work,
"DP8381x maximum events handled per interrupt");
MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)");
#define DSPCFG_VAL 0x5040
#define SDCFG_VAL 0x008c /* set voltage thresholds for Signal Detect */
#define DSPCFG_LOCK 0x20 /* coefficient lock bit in DSPCFG */
+#define DSPCFG_COEF 0x1000 /* see coefficient (in TSTDAT) bit in DSPCFG */
#define TSTDAT_FIXED 0xe8 /* magic number for bad coefficients */
/* misc PCI space registers */
};
static void move_int_phy(struct net_device *dev, int addr);
-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 reg);
static void mdio_write(struct net_device *dev, int reg, u16 data);
static void init_phy_fixup(struct net_device *dev);
static void netdev_rx(struct net_device *dev);
static void netdev_tx_done(struct net_device *dev);
static int natsemi_change_mtu(struct net_device *dev, int new_mtu);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void natsemi_poll_controller(struct net_device *dev);
+#endif
static void __set_rx_mode(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
static void __get_stats(struct net_device *dev);
static int netdev_close(struct net_device *dev);
static int netdev_get_regs(struct net_device *dev, u8 *buf);
static int netdev_get_eeprom(struct net_device *dev, u8 *buf);
+static struct ethtool_ops ethtool_ops;
+
+static inline void __iomem *ns_ioaddr(struct net_device *dev)
+{
+ return (void __iomem *) dev->base_addr;
+}
static void move_int_phy(struct net_device *dev, int addr)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
int target = 31;
/*
target--;
if (target == np->phy_addr_external)
target--;
- writew(target, dev->base_addr + PhyCtrl);
- readw(dev->base_addr + PhyCtrl);
+ writew(target, ioaddr + PhyCtrl);
+ readw(ioaddr + PhyCtrl);
udelay(1);
}
struct netdev_private *np;
int i, option, irq, chip_idx = ent->driver_data;
static int find_cnt = -1;
- unsigned long ioaddr, iosize;
+ unsigned long iostart, iosize;
+ void __iomem *ioaddr;
const int pcibar = 1; /* PCI base address register */
int prev_eedata;
u32 tmp;
}
find_cnt++;
- ioaddr = pci_resource_start(pdev, pcibar);
+ iostart = pci_resource_start(pdev, pcibar);
iosize = pci_resource_len(pdev, pcibar);
irq = pdev->irq;
if (i)
goto err_pci_request_regions;
- ioaddr = (unsigned long) ioremap (ioaddr, iosize);
+ ioaddr = ioremap(iostart, iosize);
if (!ioaddr) {
i = -ENOMEM;
goto err_ioremap;
prev_eedata = eedata;
}
- dev->base_addr = ioaddr;
+ dev->base_addr = (unsigned long __force) ioaddr;
dev->irq = irq;
np = netdev_priv(dev);
* The address would be used to access a phy over the mii bus, but
* the internal phy is accessed through mapped registers.
*/
- if (readl(dev->base_addr + ChipConfig) & CfgExtPhy)
+ if (readl(ioaddr + ChipConfig) & CfgExtPhy)
dev->if_port = PORT_MII;
else
dev->if_port = PORT_TP;
dev->do_ioctl = &netdev_ioctl;
dev->tx_timeout = &tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ dev->poll_controller = &natsemi_poll_controller;
+#endif
+ SET_ETHTOOL_OPS(dev, ðtool_ops);
if (mtu)
dev->mtu = mtu;
if (netif_msg_drv(np)) {
printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ",
- dev->name, natsemi_pci_info[chip_idx].name, ioaddr,
+ dev->name, natsemi_pci_info[chip_idx].name, iostart,
pci_name(np->pci_dev));
for (i = 0; i < ETH_ALEN-1; i++)
printk("%02x:", dev->dev_addr[i]);
return 0;
err_register_netdev:
- iounmap ((void *) dev->base_addr);
+ iounmap(ioaddr);
err_ioremap:
pci_release_regions(pdev);
EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6),
};
-static int eeprom_read(long addr, int location)
+static int eeprom_read(void __iomem *addr, int location)
{
int i;
int retval = 0;
- long ee_addr = addr + EECtrl;
+ void __iomem *ee_addr = addr + EECtrl;
int read_cmd = location | EE_ReadCmd;
+
writel(EE_Write0, ee_addr);
/* Shift the read command bits out. */
/* clock transitions >= 20ns (25MHz)
* One readl should be good to PCI @ 100MHz
*/
-#define mii_delay(dev) readl(dev->base_addr + EECtrl)
+#define mii_delay(ioaddr) readl(ioaddr + EECtrl)
static int mii_getbit (struct net_device *dev)
{
int data;
+ void __iomem *ioaddr = ns_ioaddr(dev);
- writel(MII_ShiftClk, dev->base_addr + EECtrl);
- data = readl(dev->base_addr + EECtrl);
- writel(0, dev->base_addr + EECtrl);
- mii_delay(dev);
+ writel(MII_ShiftClk, ioaddr + EECtrl);
+ data = readl(ioaddr + EECtrl);
+ writel(0, ioaddr + EECtrl);
+ mii_delay(ioaddr);
return (data & MII_Data)? 1 : 0;
}
static void mii_send_bits (struct net_device *dev, u32 data, int len)
{
u32 i;
+ void __iomem *ioaddr = ns_ioaddr(dev);
for (i = (1 << (len-1)); i; i >>= 1)
{
u32 mdio_val = MII_Write | ((data & i)? MII_Data : 0);
- writel(mdio_val, dev->base_addr + EECtrl);
- mii_delay(dev);
- writel(mdio_val | MII_ShiftClk, dev->base_addr + EECtrl);
- mii_delay(dev);
+ writel(mdio_val, ioaddr + EECtrl);
+ mii_delay(ioaddr);
+ writel(mdio_val | MII_ShiftClk, ioaddr + EECtrl);
+ mii_delay(ioaddr);
}
- writel(0, dev->base_addr + EECtrl);
- mii_delay(dev);
+ writel(0, ioaddr + EECtrl);
+ mii_delay(ioaddr);
}
static int miiport_read(struct net_device *dev, int phy_id, int reg)
static int mdio_read(struct net_device *dev, int reg)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
/* The 83815 series has two ports:
* - an internal transceiver
* - an external mii bus
*/
if (dev->if_port == PORT_TP)
- return readw(dev->base_addr+BasicControl+(reg<<2));
+ return readw(ioaddr+BasicControl+(reg<<2));
else
return miiport_read(dev, np->phy_addr_external, reg);
}
static void mdio_write(struct net_device *dev, int reg, u16 data)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
/* The 83815 series has an internal transceiver; handle separately */
if (dev->if_port == PORT_TP)
- writew(data, dev->base_addr+BasicControl+(reg<<2));
+ writew(data, ioaddr+BasicControl+(reg<<2));
else
miiport_write(dev, np->phy_addr_external, reg, data);
}
static void init_phy_fixup(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem *ioaddr = ns_ioaddr(dev);
int i;
u32 cfg;
u16 tmp;
*/
}
mdio_write(dev, MII_BMCR, tmp);
- readl(dev->base_addr + ChipConfig);
+ readl(ioaddr + ChipConfig);
udelay(1);
/* find out what phy this is */
default:
break;
}
- cfg = readl(dev->base_addr + ChipConfig);
+ cfg = readl(ioaddr + ChipConfig);
if (cfg & CfgExtPhy)
return;
writew(1, ioaddr + PGSEL);
writew(PMDCSR_VAL, ioaddr + PMDCSR);
writew(TSTDAT_VAL, ioaddr + TSTDAT);
- np->dspcfg = DSPCFG_VAL;
+ np->dspcfg = (np->srr <= SRR_DP83815_C)?
+ DSPCFG_VAL : (DSPCFG_COEF | readw(ioaddr + DSPCFG));
writew(np->dspcfg, ioaddr + DSPCFG);
writew(SDCFG_VAL, ioaddr + SDCFG);
writew(0, ioaddr + PGSEL);
static int switch_port_external(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
u32 cfg;
- cfg = readl(dev->base_addr + ChipConfig);
+ cfg = readl(ioaddr + ChipConfig);
if (cfg & CfgExtPhy)
return 0;
}
/* 1) switch back to external phy */
- writel(cfg | (CfgExtPhy | CfgPhyDis), dev->base_addr + ChipConfig);
- readl(dev->base_addr + ChipConfig);
+ writel(cfg | (CfgExtPhy | CfgPhyDis), ioaddr + ChipConfig);
+ readl(ioaddr + ChipConfig);
udelay(1);
/* 2) reset the external phy: */
static int switch_port_internal(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
int i;
u32 cfg;
u16 bmcr;
- cfg = readl(dev->base_addr + ChipConfig);
+ cfg = readl(ioaddr + ChipConfig);
if (!(cfg &CfgExtPhy))
return 0;
}
/* 1) switch back to internal phy: */
cfg = cfg & ~(CfgExtPhy | CfgPhyDis);
- writel(cfg, dev->base_addr + ChipConfig);
- readl(dev->base_addr + ChipConfig);
+ writel(cfg, ioaddr + ChipConfig);
+ readl(ioaddr + ChipConfig);
udelay(1);
/* 2) reset the internal phy: */
- bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2));
- writel(bmcr | BMCR_RESET, dev->base_addr+BasicControl+(MII_BMCR<<2));
- readl(dev->base_addr + ChipConfig);
+ bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2));
+ writel(bmcr | BMCR_RESET, ioaddr+BasicControl+(MII_BMCR<<2));
+ readl(ioaddr + ChipConfig);
udelay(10);
for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
- bmcr = readw(dev->base_addr+BasicControl+(MII_BMCR<<2));
+ bmcr = readw(ioaddr+BasicControl+(MII_BMCR<<2));
if (!(bmcr & BMCR_RESET))
break;
udelay(10);
u16 pmatch[3];
u16 sopass[3];
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
/*
* Resetting the chip causes some registers to be lost.
*/
/* CFG */
- cfg = readl(dev->base_addr + ChipConfig) & CFG_RESET_SAVE;
+ cfg = readl(ioaddr + ChipConfig) & CFG_RESET_SAVE;
/* WCSR */
- wcsr = readl(dev->base_addr + WOLCmd) & WCSR_RESET_SAVE;
+ wcsr = readl(ioaddr + WOLCmd) & WCSR_RESET_SAVE;
/* RFCR */
- rfcr = readl(dev->base_addr + RxFilterAddr) & RFCR_RESET_SAVE;
+ rfcr = readl(ioaddr + RxFilterAddr) & RFCR_RESET_SAVE;
/* PMATCH */
for (i = 0; i < 3; i++) {
- writel(i*2, dev->base_addr + RxFilterAddr);
- pmatch[i] = readw(dev->base_addr + RxFilterData);
+ writel(i*2, ioaddr + RxFilterAddr);
+ pmatch[i] = readw(ioaddr + RxFilterData);
}
/* SOPAS */
for (i = 0; i < 3; i++) {
- writel(0xa+(i*2), dev->base_addr + RxFilterAddr);
- sopass[i] = readw(dev->base_addr + RxFilterData);
+ writel(0xa+(i*2), ioaddr + RxFilterAddr);
+ sopass[i] = readw(ioaddr + RxFilterData);
}
/* now whack the chip */
- writel(ChipReset, dev->base_addr + ChipCmd);
+ writel(ChipReset, ioaddr + ChipCmd);
for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
- if (!(readl(dev->base_addr + ChipCmd) & ChipReset))
+ if (!(readl(ioaddr + ChipCmd) & ChipReset))
break;
udelay(5);
}
}
/* restore CFG */
- cfg |= readl(dev->base_addr + ChipConfig) & ~CFG_RESET_SAVE;
+ cfg |= readl(ioaddr + ChipConfig) & ~CFG_RESET_SAVE;
/* turn on external phy if it was selected */
if (dev->if_port == PORT_TP)
cfg &= ~(CfgExtPhy | CfgPhyDis);
else
cfg |= (CfgExtPhy | CfgPhyDis);
- writel(cfg, dev->base_addr + ChipConfig);
+ writel(cfg, ioaddr + ChipConfig);
/* restore WCSR */
- wcsr |= readl(dev->base_addr + WOLCmd) & ~WCSR_RESET_SAVE;
- writel(wcsr, dev->base_addr + WOLCmd);
+ wcsr |= readl(ioaddr + WOLCmd) & ~WCSR_RESET_SAVE;
+ writel(wcsr, ioaddr + WOLCmd);
/* read RFCR */
- rfcr |= readl(dev->base_addr + RxFilterAddr) & ~RFCR_RESET_SAVE;
+ rfcr |= readl(ioaddr + RxFilterAddr) & ~RFCR_RESET_SAVE;
/* restore PMATCH */
for (i = 0; i < 3; i++) {
- writel(i*2, dev->base_addr + RxFilterAddr);
- writew(pmatch[i], dev->base_addr + RxFilterData);
+ writel(i*2, ioaddr + RxFilterAddr);
+ writew(pmatch[i], ioaddr + RxFilterData);
}
for (i = 0; i < 3; i++) {
- writel(0xa+(i*2), dev->base_addr + RxFilterAddr);
- writew(sopass[i], dev->base_addr + RxFilterData);
+ writel(0xa+(i*2), ioaddr + RxFilterAddr);
+ writew(sopass[i], ioaddr + RxFilterData);
}
/* restore RFCR */
- writel(rfcr, dev->base_addr + RxFilterAddr);
+ writel(rfcr, ioaddr + RxFilterAddr);
}
static void natsemi_reload_eeprom(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
int i;
- writel(EepromReload, dev->base_addr + PCIBusCfg);
+ writel(EepromReload, ioaddr + PCIBusCfg);
for (i=0;i<NATSEMI_HW_TIMEOUT;i++) {
udelay(50);
- if (!(readl(dev->base_addr + PCIBusCfg) & EepromReload))
+ if (!(readl(ioaddr + PCIBusCfg) & EepromReload))
break;
}
if (i==NATSEMI_HW_TIMEOUT) {
static void natsemi_stop_rxtx(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
struct netdev_private *np = netdev_priv(dev);
int i;
static int netdev_open(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
int i;
/* Reset the chip, just in case. */
static void do_cable_magic(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem *ioaddr = ns_ioaddr(dev);
if (dev->if_port != PORT_TP)
return;
* activity LED while idle. This process is based on instructions
* from engineers at National.
*/
- if (readl(dev->base_addr + ChipConfig) & CfgSpeed100) {
+ if (readl(ioaddr + ChipConfig) & CfgSpeed100) {
u16 data;
- writew(1, dev->base_addr + PGSEL);
+ writew(1, ioaddr + PGSEL);
/*
* coefficient visibility should already be enabled via
* DSPCFG | 0x1000
*/
- data = readw(dev->base_addr + TSTDAT) & 0xff;
+ data = readw(ioaddr + TSTDAT) & 0xff;
/*
* the value must be negative, and within certain values
* (these values all come from National)
struct netdev_private *np = netdev_priv(dev);
/* the bug has been triggered - fix the coefficient */
- writew(TSTDAT_FIXED, dev->base_addr + TSTDAT);
+ writew(TSTDAT_FIXED, ioaddr + TSTDAT);
/* lock the value */
- data = readw(dev->base_addr + DSPCFG);
+ data = readw(ioaddr + DSPCFG);
np->dspcfg = data | DSPCFG_LOCK;
- writew(np->dspcfg, dev->base_addr + DSPCFG);
+ writew(np->dspcfg, ioaddr + DSPCFG);
}
- writew(0, dev->base_addr + PGSEL);
+ writew(0, ioaddr + PGSEL);
}
}
{
u16 data;
struct netdev_private *np = netdev_priv(dev);
+ void __iomem * ioaddr = ns_ioaddr(dev);
if (dev->if_port != PORT_TP)
return;
if (np->srr >= SRR_DP83816_A5)
return;
- writew(1, dev->base_addr + PGSEL);
+ writew(1, ioaddr + PGSEL);
/* make sure the lock bit is clear */
- data = readw(dev->base_addr + DSPCFG);
+ data = readw(ioaddr + DSPCFG);
np->dspcfg = data & ~DSPCFG_LOCK;
- writew(np->dspcfg, dev->base_addr + DSPCFG);
- writew(0, dev->base_addr + PGSEL);
+ writew(np->dspcfg, ioaddr + DSPCFG);
+ writew(0, ioaddr + PGSEL);
}
static void check_link(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
int duplex;
u16 bmsr;
static void init_registers(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
init_phy_fixup(dev);
{
struct net_device *dev = (struct net_device *)data;
struct netdev_private *np = netdev_priv(dev);
+ void __iomem * ioaddr = ns_ioaddr(dev);
int next_tick = 5*HZ;
if (netif_msg_timer(np)) {
}
if (dev->if_port == PORT_TP) {
- long ioaddr = dev->base_addr;
u16 dspcfg;
spin_lock_irq(&np->lock);
refill_rx(dev);
enable_irq(dev->irq);
if (!np->oom) {
- writel(RxOn, dev->base_addr + ChipCmd);
+ writel(RxOn, ioaddr + ChipCmd);
} else {
next_tick = 1;
}
static void tx_timeout(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
disable_irq(dev->irq);
spin_lock_irq(&np->lock);
static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem * ioaddr = ns_ioaddr(dev);
unsigned entry;
/* Note: Ordering is important here, set the field with the
netif_stop_queue(dev);
}
/* Wake the potentially-idle transmit channel. */
- writel(TxOn, dev->base_addr + ChipCmd);
+ writel(TxOn, ioaddr + ChipCmd);
} else {
dev_kfree_skb_irq(skb);
np->stats.tx_dropped++;
{
struct net_device *dev = dev_instance;
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
int boguscnt = max_interrupt_work;
unsigned int handled = 0;
int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx;
s32 desc_status = le32_to_cpu(np->rx_head_desc->cmd_status);
unsigned int buflen = np->rx_buf_sz;
+ void __iomem * ioaddr = ns_ioaddr(dev);
/* If the driver owns the next entry it's a new packet. Send it up. */
while (desc_status < 0) { /* e.g. & DescOwn */
if (np->oom)
mod_timer(&np->timer, jiffies + 1);
else
- writel(RxOn, dev->base_addr + ChipCmd);
+ writel(RxOn, ioaddr + ChipCmd);
}
static void netdev_error(struct net_device *dev, int intr_status)
{
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
spin_lock(&np->lock);
if (intr_status & LinkChange) {
static void __get_stats(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
struct netdev_private *np = netdev_priv(dev);
/* The chip only need report frame silently dropped. */
return &np->stats;
}
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void natsemi_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ intr_handler(dev->irq, dev, NULL);
+ enable_irq(dev->irq);
+}
+#endif
+
#define HASH_TABLE 0x200
static void __set_rx_mode(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
struct netdev_private *np = netdev_priv(dev);
u8 mc_filter[64]; /* Multicast hash filter */
u32 rx_mode;
rx_mode = RxFilterEnable | AcceptBroadcast
| AcceptMulticast | AcceptMyPhys;
for (i = 0; i < 64; i += 2) {
- writew(HASH_TABLE + i, ioaddr + RxFilterAddr);
- writew((mc_filter[i+1]<<8) + mc_filter[i],
- ioaddr + RxFilterData);
+ writel(HASH_TABLE + i, ioaddr + RxFilterAddr);
+ writel((mc_filter[i + 1] << 8) + mc_filter[i],
+ ioaddr + RxFilterData);
}
}
writel(rx_mode, ioaddr + RxFilterAddr);
/* synchronized against open : rtnl_lock() held by caller */
if (netif_running(dev)) {
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
disable_irq(dev->irq);
spin_lock(&np->lock);
spin_unlock_irq(&np->lock);
}
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
struct netdev_private *np = netdev_priv(dev);
- u32 cmd;
-
- if (get_user(cmd, (u32 __user *)useraddr))
- return -EFAULT;
-
- switch (cmd) {
- /* get driver info */
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
- strncpy(info.driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);
- strncpy(info.version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);
- info.fw_version[0] = '\0';
- strncpy(info.bus_info, pci_name(np->pci_dev),
- ETHTOOL_BUSINFO_LEN);
- info.eedump_len = NATSEMI_EEPROM_SIZE;
- info.regdump_len = NATSEMI_REGS_SIZE;
- if (copy_to_user(useraddr, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- /* get settings */
- case ETHTOOL_GSET: {
- struct ethtool_cmd ecmd = { ETHTOOL_GSET };
- spin_lock_irq(&np->lock);
- netdev_get_ecmd(dev, &ecmd);
- spin_unlock_irq(&np->lock);
- if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
- }
- /* set settings */
- case ETHTOOL_SSET: {
- struct ethtool_cmd ecmd;
- int r;
- if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
- return -EFAULT;
- spin_lock_irq(&np->lock);
- r = netdev_set_ecmd(dev, &ecmd);
- spin_unlock_irq(&np->lock);
- return r;
- }
- /* get wake-on-lan */
- case ETHTOOL_GWOL: {
- struct ethtool_wolinfo wol = {ETHTOOL_GWOL};
- spin_lock_irq(&np->lock);
- netdev_get_wol(dev, &wol.supported, &wol.wolopts);
- netdev_get_sopass(dev, wol.sopass);
- spin_unlock_irq(&np->lock);
- if (copy_to_user(useraddr, &wol, sizeof(wol)))
- return -EFAULT;
- return 0;
- }
- /* set wake-on-lan */
- case ETHTOOL_SWOL: {
- struct ethtool_wolinfo wol;
- int r;
- if (copy_from_user(&wol, useraddr, sizeof(wol)))
- return -EFAULT;
- spin_lock_irq(&np->lock);
- netdev_set_wol(dev, wol.wolopts);
- r = netdev_set_sopass(dev, wol.sopass);
- spin_unlock_irq(&np->lock);
- return r;
- }
- /* get registers */
- case ETHTOOL_GREGS: {
- struct ethtool_regs regs;
- u8 regbuf[NATSEMI_REGS_SIZE];
- int r;
-
- if (copy_from_user(®s, useraddr, sizeof(regs)))
- return -EFAULT;
+ strncpy(info->driver, DRV_NAME, ETHTOOL_BUSINFO_LEN);
+ strncpy(info->version, DRV_VERSION, ETHTOOL_BUSINFO_LEN);
+ strncpy(info->bus_info, pci_name(np->pci_dev), ETHTOOL_BUSINFO_LEN);
+}
- if (regs.len > NATSEMI_REGS_SIZE) {
- regs.len = NATSEMI_REGS_SIZE;
- }
- regs.version = NATSEMI_REGS_VER;
- if (copy_to_user(useraddr, ®s, sizeof(regs)))
- return -EFAULT;
+static int get_regs_len(struct net_device *dev)
+{
+ return NATSEMI_REGS_SIZE;
+}
- useraddr += offsetof(struct ethtool_regs, data);
+static int get_eeprom_len(struct net_device *dev)
+{
+ return NATSEMI_EEPROM_SIZE;
+}
- spin_lock_irq(&np->lock);
- r = netdev_get_regs(dev, regbuf);
- spin_unlock_irq(&np->lock);
+static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ spin_lock_irq(&np->lock);
+ netdev_get_ecmd(dev, ecmd);
+ spin_unlock_irq(&np->lock);
+ return 0;
+}
- if (r)
- return r;
- if (copy_to_user(useraddr, regbuf, regs.len))
- return -EFAULT;
- return 0;
- }
- /* 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;
- }
- /* restart autonegotiation */
- case ETHTOOL_NWAY_RST: {
- int tmp;
- int r = -EINVAL;
- /* if autoneg is off, it's an error */
- tmp = mdio_read(dev, MII_BMCR);
- if (tmp & BMCR_ANENABLE) {
- tmp |= (BMCR_ANRESTART);
- mdio_write(dev, MII_BMCR, tmp);
- r = 0;
- }
- return r;
- }
- /* get link status */
- case ETHTOOL_GLINK: {
- struct ethtool_value edata = {ETHTOOL_GLINK};
- /* LSTATUS is latched low until a read - so read twice */
- mdio_read(dev, MII_BMSR);
- edata.data = (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
- if (copy_to_user(useraddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
- }
- /* get EEPROM */
- case ETHTOOL_GEEPROM: {
- struct ethtool_eeprom eeprom;
- u8 eebuf[NATSEMI_EEPROM_SIZE];
- int r;
+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 = netdev_set_ecmd(dev, ecmd);
+ spin_unlock_irq(&np->lock);
+ return res;
+}
- if (copy_from_user(&eeprom, useraddr, sizeof(eeprom)))
- return -EFAULT;
+static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ spin_lock_irq(&np->lock);
+ netdev_get_wol(dev, &wol->supported, &wol->wolopts);
+ netdev_get_sopass(dev, wol->sopass);
+ spin_unlock_irq(&np->lock);
+}
- if (eeprom.offset > eeprom.offset+eeprom.len)
- return -EINVAL;
+static int set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ int res;
+ spin_lock_irq(&np->lock);
+ netdev_set_wol(dev, wol->wolopts);
+ res = netdev_set_sopass(dev, wol->sopass);
+ spin_unlock_irq(&np->lock);
+ return res;
+}
- if ((eeprom.offset+eeprom.len) > NATSEMI_EEPROM_SIZE) {
- eeprom.len = NATSEMI_EEPROM_SIZE-eeprom.offset;
- }
- eeprom.magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
- if (copy_to_user(useraddr, &eeprom, sizeof(eeprom)))
- return -EFAULT;
+static void get_regs(struct net_device *dev, struct ethtool_regs *regs, void *buf)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ regs->version = NATSEMI_REGS_VER;
+ spin_lock_irq(&np->lock);
+ netdev_get_regs(dev, buf);
+ spin_unlock_irq(&np->lock);
+}
- useraddr += offsetof(struct ethtool_eeprom, data);
+static u32 get_msglevel(struct net_device *dev)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ return np->msg_enable;
+}
- spin_lock_irq(&np->lock);
- r = netdev_get_eeprom(dev, eebuf);
- spin_unlock_irq(&np->lock);
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ np->msg_enable = val;
+}
- if (r)
- return r;
- if (copy_to_user(useraddr, eebuf+eeprom.offset, eeprom.len))
- return -EFAULT;
- return 0;
+static int nway_reset(struct net_device *dev)
+{
+ int tmp;
+ int r = -EINVAL;
+ /* if autoneg is off, it's an error */
+ tmp = mdio_read(dev, MII_BMCR);
+ if (tmp & BMCR_ANENABLE) {
+ tmp |= (BMCR_ANRESTART);
+ mdio_write(dev, MII_BMCR, tmp);
+ r = 0;
}
+ return r;
+}
- }
+static u32 get_link(struct net_device *dev)
+{
+ /* LSTATUS is latched low until a read - so read twice */
+ mdio_read(dev, MII_BMSR);
+ return (mdio_read(dev, MII_BMSR)&BMSR_LSTATUS) ? 1:0;
+}
- return -EOPNOTSUPP;
+static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct netdev_private *np = netdev_priv(dev);
+ u8 eebuf[NATSEMI_EEPROM_SIZE];
+ int res;
+
+ eeprom->magic = PCI_VENDOR_ID_NS | (PCI_DEVICE_ID_NS_83815<<16);
+ spin_lock_irq(&np->lock);
+ res = netdev_get_eeprom(dev, eebuf);
+ spin_unlock_irq(&np->lock);
+ if (!res)
+ memcpy(data, eebuf+eeprom->offset, eeprom->len);
+ return res;
}
+static struct ethtool_ops ethtool_ops = {
+ .get_drvinfo = get_drvinfo,
+ .get_regs_len = get_regs_len,
+ .get_eeprom_len = get_eeprom_len,
+ .get_settings = get_settings,
+ .set_settings = set_settings,
+ .get_wol = get_wol,
+ .set_wol = set_wol,
+ .get_regs = get_regs,
+ .get_msglevel = get_msglevel,
+ .set_msglevel = set_msglevel,
+ .nway_reset = nway_reset,
+ .get_link = get_link,
+ .get_eeprom = get_eeprom,
+};
+
static int netdev_set_wol(struct net_device *dev, u32 newval)
{
struct netdev_private *np = netdev_priv(dev);
- u32 data = readl(dev->base_addr + WOLCmd) & ~WakeOptsSummary;
+ void __iomem * ioaddr = ns_ioaddr(dev);
+ u32 data = readl(ioaddr + WOLCmd) & ~WakeOptsSummary;
/* translate to bitmasks this chip understands */
if (newval & WAKE_PHY)
}
}
- writel(data, dev->base_addr + WOLCmd);
+ writel(data, ioaddr + WOLCmd);
return 0;
}
static int netdev_get_wol(struct net_device *dev, u32 *supported, u32 *cur)
{
struct netdev_private *np = netdev_priv(dev);
- u32 regval = readl(dev->base_addr + WOLCmd);
+ void __iomem * ioaddr = ns_ioaddr(dev);
+ u32 regval = readl(ioaddr + WOLCmd);
*supported = (WAKE_PHY | WAKE_UCAST | WAKE_MCAST | WAKE_BCAST
| WAKE_ARP | WAKE_MAGIC);
static int netdev_set_sopass(struct net_device *dev, u8 *newval)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem * ioaddr = ns_ioaddr(dev);
u16 *sval = (u16 *)newval;
u32 addr;
}
/* enable writing to these registers by disabling the RX filter */
- addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;
+ addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask;
addr &= ~RxFilterEnable;
- writel(addr, dev->base_addr + RxFilterAddr);
+ writel(addr, ioaddr + RxFilterAddr);
/* write the three words to (undocumented) RFCR vals 0xa, 0xc, 0xe */
- writel(addr | 0xa, dev->base_addr + RxFilterAddr);
- writew(sval[0], dev->base_addr + RxFilterData);
+ writel(addr | 0xa, ioaddr + RxFilterAddr);
+ writew(sval[0], ioaddr + RxFilterData);
- writel(addr | 0xc, dev->base_addr + RxFilterAddr);
- writew(sval[1], dev->base_addr + RxFilterData);
+ writel(addr | 0xc, ioaddr + RxFilterAddr);
+ writew(sval[1], ioaddr + RxFilterData);
- writel(addr | 0xe, dev->base_addr + RxFilterAddr);
- writew(sval[2], dev->base_addr + RxFilterData);
+ writel(addr | 0xe, ioaddr + RxFilterAddr);
+ writew(sval[2], ioaddr + RxFilterData);
/* re-enable the RX filter */
- writel(addr | RxFilterEnable, dev->base_addr + RxFilterAddr);
+ writel(addr | RxFilterEnable, ioaddr + RxFilterAddr);
return 0;
}
static int netdev_get_sopass(struct net_device *dev, u8 *data)
{
struct netdev_private *np = netdev_priv(dev);
+ void __iomem * ioaddr = ns_ioaddr(dev);
u16 *sval = (u16 *)data;
u32 addr;
}
/* read the three words from (undocumented) RFCR vals 0xa, 0xc, 0xe */
- addr = readl(dev->base_addr + RxFilterAddr) & ~RFCRAddressMask;
+ addr = readl(ioaddr + RxFilterAddr) & ~RFCRAddressMask;
- writel(addr | 0xa, dev->base_addr + RxFilterAddr);
- sval[0] = readw(dev->base_addr + RxFilterData);
+ writel(addr | 0xa, ioaddr + RxFilterAddr);
+ sval[0] = readw(ioaddr + RxFilterData);
- writel(addr | 0xc, dev->base_addr + RxFilterAddr);
- sval[1] = readw(dev->base_addr + RxFilterData);
+ writel(addr | 0xc, ioaddr + RxFilterAddr);
+ sval[1] = readw(ioaddr + RxFilterData);
- writel(addr | 0xe, dev->base_addr + RxFilterAddr);
- sval[2] = readw(dev->base_addr + RxFilterData);
+ writel(addr | 0xe, ioaddr + RxFilterAddr);
+ sval[2] = readw(ioaddr + RxFilterData);
- writel(addr, dev->base_addr + RxFilterAddr);
+ writel(addr, ioaddr + RxFilterAddr);
return 0;
}
int j;
u32 rfcr;
u32 *rbuf = (u32 *)buf;
+ void __iomem * ioaddr = ns_ioaddr(dev);
/* read non-mii page 0 of registers */
for (i = 0; i < NATSEMI_PG0_NREGS/2; i++) {
- rbuf[i] = readl(dev->base_addr + i*4);
+ rbuf[i] = readl(ioaddr + i*4);
}
/* read current mii registers */
rbuf[i] = mdio_read(dev, i & 0x1f);
/* read only the 'magic' registers from page 1 */
- writew(1, dev->base_addr + PGSEL);
- rbuf[i++] = readw(dev->base_addr + PMDCSR);
- rbuf[i++] = readw(dev->base_addr + TSTDAT);
- rbuf[i++] = readw(dev->base_addr + DSPCFG);
- rbuf[i++] = readw(dev->base_addr + SDCFG);
- writew(0, dev->base_addr + PGSEL);
+ writew(1, ioaddr + PGSEL);
+ rbuf[i++] = readw(ioaddr + PMDCSR);
+ rbuf[i++] = readw(ioaddr + TSTDAT);
+ rbuf[i++] = readw(ioaddr + DSPCFG);
+ rbuf[i++] = readw(ioaddr + SDCFG);
+ writew(0, ioaddr + PGSEL);
/* read RFCR indexed registers */
- rfcr = readl(dev->base_addr + RxFilterAddr);
+ rfcr = readl(ioaddr + RxFilterAddr);
for (j = 0; j < NATSEMI_RFDR_NREGS; j++) {
- writel(j*2, dev->base_addr + RxFilterAddr);
- rbuf[i++] = readw(dev->base_addr + RxFilterData);
+ writel(j*2, ioaddr + RxFilterAddr);
+ rbuf[i++] = readw(ioaddr + RxFilterData);
}
- writel(rfcr, dev->base_addr + RxFilterAddr);
+ writel(rfcr, ioaddr + RxFilterAddr);
/* the interrupt status is clear-on-read - see if we missed any */
if (rbuf[4] & rbuf[5]) {
{
int i;
u16 *ebuf = (u16 *)buf;
+ void __iomem * ioaddr = ns_ioaddr(dev);
/* eeprom_read reads 16 bits, and indexes by 16 bits */
for (i = 0; i < NATSEMI_EEPROM_SIZE/2; i++) {
- ebuf[i] = eeprom_read(dev->base_addr, i);
+ ebuf[i] = eeprom_read(ioaddr, i);
/* The EEPROM itself stores data bit-swapped, but eeprom_read
* reads it back "sanely". So we swap it back here in order to
* present it to userland as it is stored. */
struct netdev_private *np = netdev_priv(dev);
switch(cmd) {
- case SIOCETHTOOL:
- return netdev_ethtool_ioctl(dev, rq->ifr_data);
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
case SIOCDEVPRIVATE: /* for binary compat, remove in 2.5 */
data->phy_id = np->phy_addr_external;
static void enable_wol_mode(struct net_device *dev, int enable_intr)
{
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
struct netdev_private *np = netdev_priv(dev);
if (netif_msg_wol(np))
static int netdev_close(struct net_device *dev)
{
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
struct netdev_private *np = netdev_priv(dev);
if (netif_msg_ifdown(np))
static void __devexit natsemi_remove1 (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
+ void __iomem * ioaddr = ns_ioaddr(dev);
unregister_netdev (dev);
pci_release_regions (pdev);
- iounmap ((char *) dev->base_addr);
+ iounmap(ioaddr);
free_netdev (dev);
pci_set_drvdata(pdev, NULL);
}
* Interrupts must be disabled, otherwise hands_off can cause irq storms.
*/
-static int natsemi_suspend (struct pci_dev *pdev, u32 state)
+static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct netdev_private *np = netdev_priv(dev);
- long ioaddr = dev->base_addr;
+ void __iomem * ioaddr = ns_ioaddr(dev);
rtnl_lock();
if (netif_running (dev)) {