/* A few user-configurable values. */
+#define xircom_debug debug
+#ifdef XIRCOM_DEBUG
+static int xircom_debug = XIRCOM_DEBUG;
+#else
+static int xircom_debug = 1;
+#endif
+
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work = 25;
#include <linux/config.h>
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/netdevice.h>
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("Xircom CBE-100 ethernet driver");
MODULE_LICENSE("GPL v2");
+MODULE_VERSION(DRV_VERSION);
-MODULE_PARM(debug, "i");
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(csr0, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+module_param(debug, int, 0);
+module_param(max_interrupt_work, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param(csr0, int, 0);
-#define RUN_AT(x) (jiffies + (x))
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
-#define xircom_debug debug
-#ifdef XIRCOM_DEBUG
-static int xircom_debug = XIRCOM_DEBUG;
-#else
-static int xircom_debug = 1;
-#endif
+#define RUN_AT(x) (jiffies + (x))
/*
Theory of Operation
int saved_if_port;
struct pci_dev *pdev;
spinlock_t lock;
-#ifdef CONFIG_PM
- u32 pci_state[16];
-#endif
};
static int mdio_read(struct net_device *dev, int phy_id, int location);
static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void set_rx_mode(struct net_device *dev);
static void check_duplex(struct net_device *dev);
+static struct ethtool_ops ops;
/* The Xircom cards are picky about when certain bits in CSR6 can be
*/
static void find_mii_transceivers(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
int phy, phy_idx;
if (media_cap[tp->default_port] & MediaIsMII) {
*/
static void transceiver_voodoo(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
long ioaddr = dev->base_addr;
/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
/* Clear the missed-packet counter. */
(volatile int)inl(ioaddr + CSR8);
- tp = dev->priv;
+ tp = netdev_priv(dev);
- tp->lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&tp->lock);
tp->pdev = pdev;
tp->chip_id = chip_idx;
/* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles. */
#endif
dev->tx_timeout = xircom_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ SET_ETHTOOL_OPS(dev, &ops);
transceiver_voodoo(dev);
static void
xircom_up(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
long ioaddr = dev->base_addr;
int i;
static int
xircom_open(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
if (request_irq(dev->irq, &xircom_interrupt, SA_SHIRQ, dev->name, dev))
return -EAGAIN;
static void xircom_tx_timeout(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
long ioaddr = dev->base_addr;
if (media_cap[dev->if_port] & MediaIsMII) {
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void xircom_init_ring(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
int i;
tp->tx_full = 0;
static int
xircom_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
int entry;
u32 flag;
static void xircom_media_change(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
long ioaddr = dev->base_addr;
u16 reg0, reg1, reg4, reg5;
u32 csr6 = inl(ioaddr + CSR6), newcsr6;
static void check_duplex(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
u16 reg0;
mdio_write(dev, tp->phys[0], MII_BMCR, BMCR_RESET);
static irqreturn_t xircom_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
{
struct net_device *dev = dev_instance;
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
long ioaddr = dev->base_addr;
int csr5, work_budget = max_interrupt_work;
int handled = 0;
static int
xircom_rx(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
int entry = tp->cur_rx % RX_RING_SIZE;
int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
int work_done = 0;
xircom_down(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
/* Disable interrupts by clearing the interrupt mask. */
outl(0, ioaddr + CSR7);
xircom_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
int i;
if (xircom_debug > 1)
static struct net_device_stats *xircom_get_stats(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
long ioaddr = dev->base_addr;
if (netif_device_present(dev))
return &tp->stats;
}
-
-static int xircom_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static int xircom_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
- struct ethtool_cmd ecmd;
- struct xircom_private *tp = dev->priv;
-
- if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
- return -EFAULT;
-
- switch (ecmd.cmd) {
- case ETHTOOL_GSET:
- ecmd.supported =
+ struct xircom_private *tp = netdev_priv(dev);
+ ecmd->supported =
SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
SUPPORTED_100baseT_Half |
SUPPORTED_Autoneg |
SUPPORTED_MII;
- ecmd.advertising = ADVERTISED_MII;
- if (tp->advertising[0] & ADVERTISE_10HALF)
- ecmd.advertising |= ADVERTISED_10baseT_Half;
- if (tp->advertising[0] & ADVERTISE_10FULL)
- ecmd.advertising |= ADVERTISED_10baseT_Full;
- if (tp->advertising[0] & ADVERTISE_100HALF)
- ecmd.advertising |= ADVERTISED_100baseT_Half;
- if (tp->advertising[0] & ADVERTISE_100FULL)
- ecmd.advertising |= ADVERTISED_100baseT_Full;
- if (tp->autoneg) {
- ecmd.advertising |= ADVERTISED_Autoneg;
- ecmd.autoneg = AUTONEG_ENABLE;
- } else
- ecmd.autoneg = AUTONEG_DISABLE;
-
- ecmd.port = PORT_MII;
- ecmd.transceiver = XCVR_INTERNAL;
- ecmd.phy_address = tp->phys[0];
- ecmd.speed = tp->speed100 ? SPEED_100 : SPEED_10;
- ecmd.duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
- ecmd.maxtxpkt = TX_RING_SIZE / 2;
- ecmd.maxrxpkt = 0;
-
- if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
+ ecmd->advertising = ADVERTISED_MII;
+ if (tp->advertising[0] & ADVERTISE_10HALF)
+ ecmd->advertising |= ADVERTISED_10baseT_Half;
+ if (tp->advertising[0] & ADVERTISE_10FULL)
+ ecmd->advertising |= ADVERTISED_10baseT_Full;
+ if (tp->advertising[0] & ADVERTISE_100HALF)
+ ecmd->advertising |= ADVERTISED_100baseT_Half;
+ if (tp->advertising[0] & ADVERTISE_100FULL)
+ ecmd->advertising |= ADVERTISED_100baseT_Full;
+ if (tp->autoneg) {
+ ecmd->advertising |= ADVERTISED_Autoneg;
+ ecmd->autoneg = AUTONEG_ENABLE;
+ } else
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ ecmd->port = PORT_MII;
+ ecmd->transceiver = XCVR_INTERNAL;
+ ecmd->phy_address = tp->phys[0];
+ ecmd->speed = tp->speed100 ? SPEED_100 : SPEED_10;
+ ecmd->duplex = tp->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
+ ecmd->maxtxpkt = TX_RING_SIZE / 2;
+ ecmd->maxrxpkt = 0;
+ return 0;
+}
- case ETHTOOL_SSET: {
- u16 autoneg, speed100, full_duplex;
-
- autoneg = (ecmd.autoneg == AUTONEG_ENABLE);
- speed100 = (ecmd.speed == SPEED_100);
- full_duplex = (ecmd.duplex == DUPLEX_FULL);
-
- tp->autoneg = autoneg;
- if (speed100 != tp->speed100 ||
- full_duplex != tp->full_duplex) {
- tp->speed100 = speed100;
- tp->full_duplex = full_duplex;
- /* change advertising bits */
- tp->advertising[0] &= ~(ADVERTISE_10HALF |
- ADVERTISE_10FULL |
- ADVERTISE_100HALF |
- ADVERTISE_100FULL |
- ADVERTISE_100BASE4);
- if (speed100) {
- if (full_duplex)
- tp->advertising[0] |= ADVERTISE_100FULL;
- else
- tp->advertising[0] |= ADVERTISE_100HALF;
- } else {
- if (full_duplex)
- tp->advertising[0] |= ADVERTISE_10FULL;
- else
- tp->advertising[0] |= ADVERTISE_10HALF;
- }
+static int xircom_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+ struct xircom_private *tp = netdev_priv(dev);
+ u16 autoneg, speed100, full_duplex;
+
+ autoneg = (ecmd->autoneg == AUTONEG_ENABLE);
+ speed100 = (ecmd->speed == SPEED_100);
+ full_duplex = (ecmd->duplex == DUPLEX_FULL);
+
+ tp->autoneg = autoneg;
+ if (speed100 != tp->speed100 ||
+ full_duplex != tp->full_duplex) {
+ tp->speed100 = speed100;
+ tp->full_duplex = full_duplex;
+ /* change advertising bits */
+ tp->advertising[0] &= ~(ADVERTISE_10HALF |
+ ADVERTISE_10FULL |
+ ADVERTISE_100HALF |
+ ADVERTISE_100FULL |
+ ADVERTISE_100BASE4);
+ if (speed100) {
+ if (full_duplex)
+ tp->advertising[0] |= ADVERTISE_100FULL;
+ else
+ tp->advertising[0] |= ADVERTISE_100HALF;
+ } else {
+ if (full_duplex)
+ tp->advertising[0] |= ADVERTISE_10FULL;
+ else
+ tp->advertising[0] |= ADVERTISE_10HALF;
}
- check_duplex(dev);
- return 0;
- }
-
- case ETHTOOL_GDRVINFO: {
- struct ethtool_drvinfo info;
- memset(&info, 0, sizeof(info));
- info.cmd = ecmd.cmd;
- strcpy(info.driver, DRV_NAME);
- strcpy(info.version, DRV_VERSION);
- *info.fw_version = 0;
- strcpy(info.bus_info, pci_name(tp->pdev));
- if (copy_to_user(useraddr, &info, sizeof(info)))
- return -EFAULT;
- return 0;
}
+ check_duplex(dev);
+ return 0;
+}
- default:
- return -EOPNOTSUPP;
- }
+static void xircom_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ struct xircom_private *tp = netdev_priv(dev);
+ strcpy(info->driver, DRV_NAME);
+ strcpy(info->version, DRV_VERSION);
+ strcpy(info->bus_info, pci_name(tp->pdev));
}
+static struct ethtool_ops ops = {
+ .get_settings = xircom_get_settings,
+ .set_settings = xircom_set_settings,
+ .get_drvinfo = xircom_get_drvinfo,
+};
/* Provide ioctl() calls to examine the MII xcvr state. */
static int xircom_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
u16 *data = (u16 *)&rq->ifr_ifru;
int phy = tp->phys[0] & 0x1f;
unsigned long flags;
switch(cmd) {
- case SIOCETHTOOL:
- return xircom_ethtool_ioctl(dev, rq->ifr_data);
-
/* Legacy mii-diag interface */
case SIOCGMIIPHY: /* Get address of MII PHY in use. */
if (tp->mii_cnt)
when re-entered but still correct. */
static void set_rx_mode(struct net_device *dev)
{
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
struct dev_mc_list *mclist;
long ioaddr = dev->base_addr;
int csr6 = inl(ioaddr + CSR6);
static int xircom_suspend(struct pci_dev *pdev, u32 state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
printk(KERN_INFO "xircom_suspend(%s)\n", dev->name);
if (tp->open)
xircom_down(dev);
- pci_save_state(pdev, tp->pci_state);
+ pci_save_state(pdev);
pci_disable_device(pdev);
pci_set_power_state(pdev, 3);
static int xircom_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct xircom_private *tp = dev->priv;
+ struct xircom_private *tp = netdev_priv(dev);
printk(KERN_INFO "xircom_resume(%s)\n", dev->name);
pci_set_power_state(pdev,0);
pci_enable_device(pdev);
- pci_restore_state(pdev, tp->pci_state);
+ pci_restore_state(pdev);
/* Bring the chip out of sleep mode.
Caution: Snooze mode does not work with some boards! */