vserver 1.9.5.x5
[linux-2.6.git] / drivers / net / pcmcia / smc91c92_cs.c
index 49d60d9..85a1521 100644 (file)
@@ -66,7 +66,7 @@ static char *if_names[] = { "auto", "10baseT", "10base2"};
 MODULE_DESCRIPTION("SMC 91c92 series PCMCIA ethernet driver");
 MODULE_LICENSE("GPL");
 
-#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
+#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
 
 /*
   Transceiver/media type.
@@ -76,11 +76,6 @@ MODULE_LICENSE("GPL");
 */
 INT_MODULE_PARM(if_port, 0);
 
-/* Bit map of interrupts to choose from. */
-INT_MODULE_PARM(irq_mask, 0xdeb8);
-static int irq_list[4] = { -1 };
-MODULE_PARM(irq_list, "1-4i");
-
 #ifdef PCMCIA_DEBUG
 INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
 static const char *version =
@@ -120,7 +115,7 @@ struct smc_private {
     dev_node_t                 node;
     struct sk_buff             *saved_skb;
     int                                packets_waiting;
-    caddr_t                    base;
+    void                       __iomem *base;
     u_short                    cfg;
     struct timer_list          media;
     int                                watchdog, tx_err;
@@ -300,10 +295,11 @@ static int s9k_config(struct net_device *dev, struct ifmap *map);
 static void smc_set_xcvr(struct net_device *dev, int if_port);
 static void smc_reset(struct net_device *dev);
 static void media_check(u_long arg);
-static void mdio_sync(ioaddr_t addr);
+static void mdio_sync(kio_addr_t addr);
 static int mdio_read(struct net_device *dev, int phy_id, int loc);
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int value);
 static int smc_link_ok(struct net_device *dev);
+static struct ethtool_ops ethtool_ops;
 
 /*======================================================================
 
@@ -319,7 +315,7 @@ static dev_link_t *smc91c92_attach(void)
     struct smc_private *smc;
     dev_link_t *link;
     struct net_device *dev;
-    int i, ret;
+    int ret;
 
     DEBUG(0, "smc91c92_attach()\n");
 
@@ -336,12 +332,7 @@ static dev_link_t *smc91c92_attach(void)
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
     link->io.IOAddrLines = 4;
     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-    link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
-    if (irq_list[0] == -1)
-       link->irq.IRQInfo2 = irq_mask;
-    else
-       for (i = 0; i < 4; i++)
-           link->irq.IRQInfo2 |= 1 << irq_list[i];
+    link->irq.IRQInfo1 = IRQ_LEVEL_ID;
     link->irq.Handler = &smc_interrupt;
     link->irq.Instance = dev;
     link->conf.Attributes = CONF_ENABLE_IRQ;
@@ -357,6 +348,7 @@ static dev_link_t *smc91c92_attach(void)
     dev->open = &smc_open;
     dev->stop = &smc_close;
     dev->do_ioctl = &smc_ioctl;
+    SET_ETHTOOL_OPS(dev, &ethtool_ops);
 #ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = smc_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
@@ -372,7 +364,6 @@ static dev_link_t *smc91c92_attach(void)
     link->next = dev_list;
     dev_list = link;
     client_reg.dev_info = &dev_info;
-    client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
     client_reg.EventMask = CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
@@ -620,8 +611,8 @@ static void mot_config(dev_link_t *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
-    ioaddr_t iouart = link->io.BasePort2;
+    kio_addr_t ioaddr = dev->base_addr;
+    kio_addr_t iouart = link->io.BasePort2;
 
     /* Set UART base address and force map with COR bit 1 */
     writeb(iouart & 0xff,        smc->base + MOT_UART + CISREG_IOBASE_0);
@@ -640,7 +631,7 @@ static void mot_config(dev_link_t *link)
 static int mot_setup(dev_link_t *link)
 {
     struct net_device *dev = link->priv;
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     int i, wait, loop;
     u_int addr;
 
@@ -748,7 +739,7 @@ static int smc_setup(dev_link_t *link)
 static int osi_config(dev_link_t *link)
 {
     struct net_device *dev = link->priv;
-    static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+    static kio_addr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
     int i, j;
 
     link->conf.Attributes |= CONF_ENABLE_SPKR;
@@ -837,7 +828,7 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
 static int check_sig(dev_link_t *link)
 {
     struct net_device *dev = link->priv;
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     int width;
     u_short s;
 
@@ -901,7 +892,7 @@ static void smc91c92_config(dev_link_t *link)
     u_short buf[32];
     char *name;
     int i, j, rev;
-    ioaddr_t ioaddr;
+    kio_addr_t ioaddr;
     u_long mir;
 
     DEBUG(0, "smc91c92_config(0x%p)\n", link);
@@ -1022,6 +1013,7 @@ static void smc91c92_config(dev_link_t *link)
 
     link->dev = &smc->node;
     link->state &= ~DEV_CONFIG_PENDING;
+    SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 
     if (register_netdev(dev) != 0) {
        printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");
@@ -1179,7 +1171,7 @@ static int smc91c92_event(event_t event, int priority,
 #define MDIO_DATA_WRITE1       (MDIO_DIR_WRITE | MDIO_DATA_OUT)
 #define MDIO_DATA_READ         0x02
 
-static void mdio_sync(ioaddr_t addr)
+static void mdio_sync(kio_addr_t addr)
 {
     int bits;
     for (bits = 0; bits < 32; bits++) {
@@ -1190,7 +1182,7 @@ static void mdio_sync(ioaddr_t addr)
 
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
 {
-    ioaddr_t addr = dev->base_addr + MGMT;
+    kio_addr_t addr = dev->base_addr + MGMT;
     u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
     int i, retval = 0;
 
@@ -1210,7 +1202,7 @@ static int mdio_read(struct net_device *dev, int phy_id, int loc)
 
 static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
 {
-    ioaddr_t addr = dev->base_addr + MGMT;
+    kio_addr_t addr = dev->base_addr + MGMT;
     u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
     int i;
 
@@ -1236,7 +1228,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int loc, int value)
 #ifdef PCMCIA_DEBUG
 static void smc_dump(struct net_device *dev)
 {
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     u_short i, w, save;
     save = inw(ioaddr + BANK_SELECT);
     for (w = 0; w < 4; w++) {
@@ -1291,7 +1283,7 @@ static int smc_close(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
     dev_link_t *link = &smc->link;
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
 
     DEBUG(0, "%s: smc_close(), status %4.4x.\n",
          dev->name, inw(ioaddr + BANK_SELECT));
@@ -1328,7 +1320,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
 {
     struct smc_private *smc = netdev_priv(dev);
     struct sk_buff *skb = smc->saved_skb;
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     u_char packet_no;
 
     if (!skb) {
@@ -1392,7 +1384,7 @@ static void smc_hardware_send_packet(struct net_device * dev)
 static void smc_tx_timeout(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
 
     printk(KERN_NOTICE "%s: SMC91c92 transmit timed out, "
           "Tx_status %2.2x status %4.4x.\n",
@@ -1407,7 +1399,7 @@ static void smc_tx_timeout(struct net_device *dev)
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     u_short num_pages;
     short time_out, ir;
 
@@ -1473,7 +1465,7 @@ static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static void smc_tx_err(struct net_device * dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     int saved_packet = inw(ioaddr + PNR_ARR) & 0xff;
     int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f;
     int tx_status;
@@ -1517,7 +1509,7 @@ static void smc_tx_err(struct net_device * dev)
 static void smc_eph_irq(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     u_short card_stats, ephs;
 
     SMC_SELECT_BANK(0);
@@ -1552,7 +1544,7 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct net_device *dev = dev_id;
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr;
+    kio_addr_t ioaddr;
     u_short saved_bank, saved_pointer, mask, status;
     unsigned int handled = 1;
     char bogus_cnt = INTR_WORK;                /* Work we are willing to do. */
@@ -1670,7 +1662,7 @@ irq_done:
 static void smc_rx(struct net_device *dev)
 {
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     int rx_status;
     int packet_length; /* Caution: not frame length, rather words
                           to transfer from the chip. */
@@ -1776,7 +1768,7 @@ static void fill_multicast_tbl(int count, struct dev_mc_list *addrs,
 
 static void set_rx_mode(struct net_device *dev)
 {
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     struct smc_private *smc = netdev_priv(dev);
     u_int multicast_table[ 2 ] = { 0, };
     unsigned long flags;
@@ -1843,7 +1835,7 @@ static int s9k_config(struct net_device *dev, struct ifmap *map)
 static void smc_set_xcvr(struct net_device *dev, int if_port)
 {
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     u_short saved_bank;
 
     saved_bank = inw(ioaddr + BANK_SELECT);
@@ -1866,7 +1858,7 @@ static void smc_set_xcvr(struct net_device *dev, int if_port)
 
 static void smc_reset(struct net_device *dev)
 {
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     struct smc_private *smc = netdev_priv(dev);
     int i;
 
@@ -1943,7 +1935,7 @@ static void media_check(u_long arg)
 {
     struct net_device *dev = (struct net_device *) arg;
     struct smc_private *smc = netdev_priv(dev);
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     u_short i, media, saved_bank;
     u_short link;
 
@@ -2055,7 +2047,7 @@ reschedule:
 
 static int smc_link_ok(struct net_device *dev)
 {
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
     struct smc_private *smc = netdev_priv(dev);
 
     if (smc->cfg & CFG_MII_SELECT) {
@@ -2069,7 +2061,7 @@ static int smc_link_ok(struct net_device *dev)
 static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
     u16 tmp;
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
 
     ecmd->supported = (SUPPORTED_TP | SUPPORTED_AUI |
        SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full);
@@ -2091,7 +2083,7 @@ static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
 static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
     u16 tmp;
-    ioaddr_t ioaddr = dev->base_addr;
+    kio_addr_t ioaddr = dev->base_addr;
 
     if (ecmd->speed != SPEED_10)
        return -EINVAL;
@@ -2113,136 +2105,135 @@ static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
        tmp |= TCR_FDUPLX;
     else
        tmp &= ~TCR_FDUPLX;
-    outw(ioaddr + TCR, tmp);
+    outw(tmp, ioaddr + TCR);
        
     return 0;
 }
 
-static int smc_ethtool_ioctl (struct net_device *dev, void __user *useraddr)
+static int check_if_running(struct net_device *dev)
 {
-    u32 ethcmd;
-    struct smc_private *smc = netdev_priv(dev);
-
-    if (get_user(ethcmd, (u32 __user *)useraddr))
-       return -EFAULT;
-
-    switch (ethcmd) {
-
-    case ETHTOOL_GDRVINFO: {
-       struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-       strcpy(info.driver, DRV_NAME);
-       strcpy(info.version, DRV_VERSION);
-       if (copy_to_user(useraddr, &info, sizeof(info)))
-           return -EFAULT;
+       if (!netif_running(dev))
+               return -EINVAL;
        return 0;
-    }
+}
 
-    /* get settings */
-    case ETHTOOL_GSET: {
+static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+}
+
+static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct smc_private *smc = netdev_priv(dev);
+       kio_addr_t ioaddr = dev->base_addr;
+       u16 saved_bank = inw(ioaddr + BANK_SELECT);
        int ret;
-       struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+
+       SMC_SELECT_BANK(3);
        spin_lock_irq(&smc->lock);
        if (smc->cfg & CFG_MII_SELECT)
-           ret = mii_ethtool_gset(&smc->mii_if, &ecmd);
+               ret = mii_ethtool_gset(&smc->mii_if, ecmd);
        else
-           ret = smc_netdev_get_ecmd(dev, &ecmd);
+               ret = smc_netdev_get_ecmd(dev, ecmd);
        spin_unlock_irq(&smc->lock);
-       if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
-           return -EFAULT;
+       SMC_SELECT_BANK(saved_bank);
        return ret;
-    }
+}
 
-    /* set settings */
-    case ETHTOOL_SSET: {
+static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct smc_private *smc = netdev_priv(dev);
+       kio_addr_t ioaddr = dev->base_addr;
+       u16 saved_bank = inw(ioaddr + BANK_SELECT);
        int ret;
-       struct ethtool_cmd ecmd;
-       if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-           return -EFAULT;
+
+       SMC_SELECT_BANK(3);
        spin_lock_irq(&smc->lock);
        if (smc->cfg & CFG_MII_SELECT)
-           ret = mii_ethtool_sset(&smc->mii_if, &ecmd);
+               ret = mii_ethtool_sset(&smc->mii_if, ecmd);
        else
-           ret = smc_netdev_set_ecmd(dev, &ecmd);
+               ret = smc_netdev_set_ecmd(dev, ecmd);
        spin_unlock_irq(&smc->lock);
+       SMC_SELECT_BANK(saved_bank);
        return ret;
-    }
+}
 
-    /* get link status */
-    case ETHTOOL_GLINK: {
-       struct ethtool_value edata = { ETHTOOL_GLINK };
+static u32 smc_get_link(struct net_device *dev)
+{
+       struct smc_private *smc = netdev_priv(dev);
+       kio_addr_t ioaddr = dev->base_addr;
+       u16 saved_bank = inw(ioaddr + BANK_SELECT);
+       u32 ret;
+
+       SMC_SELECT_BANK(3);
        spin_lock_irq(&smc->lock);
-       edata.data = smc_link_ok(dev);
+       ret = smc_link_ok(dev);
        spin_unlock_irq(&smc->lock);
-       if (copy_to_user(useraddr, &edata, sizeof(edata)))
-           return -EFAULT;
-       return 0;
-    }
+       SMC_SELECT_BANK(saved_bank);
+       return ret;
+}
 
 #ifdef PCMCIA_DEBUG
-    /* get message-level */
-    case ETHTOOL_GMSGLVL: {
-       struct ethtool_value edata = { ETHTOOL_GMSGLVL };
-       edata.data = pc_debug;
-       if (copy_to_user(useraddr, &edata, sizeof(edata)))
-           return -EFAULT;
-       return 0;
-    }
+static u32 smc_get_msglevel(struct net_device *dev)
+{
+       return pc_debug;
+}
 
-    /* set message-level */
-    case ETHTOOL_SMSGLVL: {
-       struct ethtool_value edata;
-       if (copy_from_user(&edata, useraddr, sizeof(edata)))
-           return -EFAULT;
-       pc_debug = edata.data;
-       return 0;
-    }
+static void smc_set_msglevel(struct net_device *dev, u32 val)
+{
+       pc_debug = val;
+}
 #endif
-    /* restart autonegotiation */
-    case ETHTOOL_NWAY_RST: {
-       if (smc->cfg & CFG_MII_SELECT)
-           return mii_nway_restart(&smc->mii_if);
-       else
-           return -EOPNOTSUPP;
-    }
-
-    default:
-       break;
-    }
 
-    return -EOPNOTSUPP;
+static int smc_nway_reset(struct net_device *dev)
+{
+       struct smc_private *smc = netdev_priv(dev);
+       if (smc->cfg & CFG_MII_SELECT) {
+               kio_addr_t ioaddr = dev->base_addr;
+               u16 saved_bank = inw(ioaddr + BANK_SELECT);
+               int res;
+
+               SMC_SELECT_BANK(3);
+               res = mii_nway_restart(&smc->mii_if);
+               SMC_SELECT_BANK(saved_bank);
+
+               return res;
+       } else
+               return -EOPNOTSUPP;
 }
 
+static struct ethtool_ops ethtool_ops = {
+       .begin = check_if_running,
+       .get_drvinfo = smc_get_drvinfo,
+       .get_settings = smc_get_settings,
+       .set_settings = smc_set_settings,
+       .get_link = smc_get_link,
+#ifdef PCMCIA_DEBUG
+       .get_msglevel = smc_get_msglevel,
+       .set_msglevel = smc_set_msglevel,
+#endif
+       .nway_reset = smc_nway_reset,
+};
+
 static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    struct smc_private *smc = netdev_priv(dev);
-    struct mii_ioctl_data *mii;
-    int rc = 0;
-    u_short saved_bank;
-    ioaddr_t ioaddr = dev->base_addr;
-
-    mii = if_mii(rq);
-    if (!netif_running(dev))
-       return -EINVAL;
+       struct smc_private *smc = netdev_priv(dev);
+       struct mii_ioctl_data *mii = if_mii(rq);
+       int rc = 0;
+       u16 saved_bank;
+       kio_addr_t ioaddr = dev->base_addr;
 
-    switch (cmd) {
-    case SIOCETHTOOL:
-       saved_bank = inw(ioaddr + BANK_SELECT);
-       SMC_SELECT_BANK(3);
-       rc = smc_ethtool_ioctl(dev, rq->ifr_data);
-       SMC_SELECT_BANK(saved_bank);
-       break;
+       if (!netif_running(dev))
+               return -EINVAL;
 
-    default:
        spin_lock_irq(&smc->lock);
        saved_bank = inw(ioaddr + BANK_SELECT);
        SMC_SELECT_BANK(3);
        rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL);
        SMC_SELECT_BANK(saved_bank);
        spin_unlock_irq(&smc->lock);
-       break;
-    }
-
-    return rc;
+       return rc;
 }
 
 static struct pcmcia_driver smc91c92_cs_driver = {
@@ -2262,8 +2253,7 @@ static int __init init_smc91c92_cs(void)
 static void __exit exit_smc91c92_cs(void)
 {
        pcmcia_unregister_driver(&smc91c92_cs_driver);
-       while (dev_list != NULL)
-               smc91c92_detach(dev_list);
+       BUG_ON(dev_list != NULL);
 }
 
 module_init(init_smc91c92_cs);