]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/net/pcmcia/fmvj18x_cs.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/dlm
[karo-tx-linux.git] / drivers / net / pcmcia / fmvj18x_cs.c
index 69d916daa7bbb313440dbd4c2827a6779a715376..81e6660a433ad9dcd892d3aebf5d3a885ce5e334 100644 (file)
@@ -100,7 +100,6 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t fjn_interrupt(int irq, void *dev_id);
 static void fjn_rx(struct net_device *dev);
 static void fjn_reset(struct net_device *dev);
-static struct net_device_stats *fjn_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
 static void fjn_tx_timeout(struct net_device *dev);
 static const struct ethtool_ops netdev_ethtool_ops;
@@ -118,13 +117,13 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
 typedef struct local_info_t {
        struct pcmcia_device    *p_dev;
     dev_node_t node;
-    struct net_device_stats stats;
     long open_time;
     uint tx_started:1;
     uint tx_queue;
     u_short tx_queue_len;
     cardtype_t cardtype;
     u_short sent;
+    u_char __iomem *base;
 } local_info_t;
 
 #define MC_FILTERBREAK 64
@@ -228,6 +227,18 @@ typedef struct local_info_t {
 #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
 #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
 
+static const struct net_device_ops fjn_netdev_ops = {
+       .ndo_open               = fjn_open,
+       .ndo_stop               = fjn_close,
+       .ndo_start_xmit         = fjn_start_xmit,
+       .ndo_tx_timeout         = fjn_tx_timeout,
+       .ndo_set_config         = fjn_config,
+       .ndo_set_multicast_list = set_rx_mode,
+       .ndo_change_mtu         = eth_change_mtu,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
 static int fmvj18x_probe(struct pcmcia_device *link)
 {
     local_info_t *lp;
@@ -242,6 +253,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     lp = netdev_priv(dev);
     link->priv = dev;
     lp->p_dev = link;
+    lp->base = NULL;
 
     /* The io structure describes IO port mapping */
     link->io.NumPorts1 = 32;
@@ -258,17 +270,9 @@ static int fmvj18x_probe(struct pcmcia_device *link)
     link->conf.Attributes = CONF_ENABLE_IRQ;
     link->conf.IntType = INT_MEMORY_AND_IO;
 
-    /* The FMVJ18x specific entries in the device structure. */
-    dev->hard_start_xmit = &fjn_start_xmit;
-    dev->set_config = &fjn_config;
-    dev->get_stats = &fjn_get_stats;
-    dev->set_multicast_list = &set_rx_mode;
-    dev->open = &fjn_open;
-    dev->stop = &fjn_close;
-#ifdef HAVE_TX_TIMEOUT
-    dev->tx_timeout = fjn_tx_timeout;
+    dev->netdev_ops = &fjn_netdev_ops;
     dev->watchdog_timeo = TX_TIMEOUT;
-#endif
+
     SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
 
     return fmvj18x_config(link);
@@ -348,7 +352,6 @@ static int fmvj18x_config(struct pcmcia_device *link)
     cardtype_t cardtype;
     char *card_name = "unknown";
     u_char *node_id;
-    DECLARE_MAC_BUF(mac);
 
     DEBUG(0, "fmvj18x_config(0x%p)\n", link);
 
@@ -443,8 +446,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
     dev->irq = link->irq.AssignedIRQ;
     dev->base_addr = link->io.BasePort1;
 
-    if (link->io.BasePort2 != 0)
-       fmvj18x_setup_mfc(link);
+    if (link->io.BasePort2 != 0) {
+       ret = fmvj18x_setup_mfc(link);
+       if (ret != 0) goto failed;
+    }
 
     ioaddr = dev->base_addr;
 
@@ -539,9 +544,9 @@ static int fmvj18x_config(struct pcmcia_device *link)
 
     /* print current configuration */
     printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, "
-          "hw_addr %s\n",
+          "hw_addr %pM\n",
           dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", 
-          dev->base_addr, dev->irq, print_mac(mac, dev->dev_addr));
+          dev->base_addr, dev->irq, dev->dev_addr);
 
     return 0;
     
@@ -611,10 +616,10 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 {
     win_req_t req;
     memreq_t mem;
-    u_char __iomem *base;
-    int i, j;
+    int i;
     struct net_device *dev = link->priv;
     unsigned int ioaddr;
+    local_info_t *lp = netdev_priv(dev);
 
     /* Allocate a small memory window */
     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -626,25 +631,32 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
        return -1;
     }
 
-    base = ioremap(req.Base, req.Size);
+    lp->base = ioremap(req.Base, req.Size);
+    if (lp->base == NULL) {
+       printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
+       return -1;
+    }
+
     mem.Page = 0;
     mem.CardOffset = 0;
-    pcmcia_map_mem_page(link->win, &mem);
-
+    i = pcmcia_map_mem_page(link->win, &mem);
+    if (i != 0) {
+       iounmap(lp->base);
+       lp->base = NULL;
+       cs_error(link, MapMemPage, i);
+       return -1;
+    }
+    
     ioaddr = dev->base_addr;
-    writeb(0x47, base+0x800);  /* Config Option Register of LAN */
-    writeb(0x0, base+0x802);   /* Config and Status Register */
+    writeb(0x47, lp->base+0x800);      /* Config Option Register of LAN */
+    writeb(0x0,  lp->base+0x802);      /* Config and Status Register */
 
-    writeb(ioaddr & 0xff, base+0x80a);         /* I/O Base(Low) of LAN */
-    writeb((ioaddr >> 8) & 0xff, base+0x80c);  /* I/O Base(High) of LAN */
+    writeb(ioaddr & 0xff, lp->base+0x80a);       /* I/O Base(Low) of LAN */
+    writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
    
-    writeb(0x45, base+0x820);  /* Config Option Register of Modem */
-    writeb(0x8, base+0x822);   /* Config and Status Register */
+    writeb(0x45, lp->base+0x820);      /* Config Option Register of Modem */
+    writeb(0x8,  lp->base+0x822);      /* Config and Status Register */
 
-    iounmap(base);
-    j = pcmcia_release_window(link->win);
-    if (j != 0)
-       cs_error(link, ReleaseWindow, j);
     return 0;
 
 }
@@ -652,8 +664,25 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
 
 static void fmvj18x_release(struct pcmcia_device *link)
 {
-       DEBUG(0, "fmvj18x_release(0x%p)\n", link);
-       pcmcia_disable_device(link);
+
+    struct net_device *dev = link->priv;
+    local_info_t *lp = netdev_priv(dev);
+    u_char __iomem *tmp;
+    int j;
+
+    DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+
+    if (lp->base != NULL) {
+       tmp = lp->base;
+       lp->base = NULL;    /* set NULL before iounmap */
+       iounmap(tmp);
+       j = pcmcia_release_window(link->win);
+       if (j != 0)
+           cs_error(link, ReleaseWindow, j);
+    }
+
+    pcmcia_disable_device(link);
+
 }
 
 static int fmvj18x_suspend(struct pcmcia_device *link)
@@ -766,7 +795,7 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
        fjn_rx(dev);
     }
     if (tx_stat & F_TMT_RDY) {
-       lp->stats.tx_packets += lp->sent ;
+       dev->stats.tx_packets += lp->sent ;
         lp->sent = 0 ;
        if (lp->tx_queue) {
            outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
@@ -784,6 +813,13 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
 
     outb(D_TX_INTR, ioaddr + TX_INTR);
     outb(D_RX_INTR, ioaddr + RX_INTR);
+
+    if (lp->base != NULL) {
+       /* Ack interrupt for multifunction card */
+       writeb(0x01, lp->base+0x802);
+       writeb(0x09, lp->base+0x822);
+    }
+
     return IRQ_HANDLED;
 
 } /* fjn_interrupt */
@@ -806,7 +842,7 @@ static void fjn_tx_timeout(struct net_device *dev)
           htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
           htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
           htons(inw(ioaddr +14)));
-    lp->stats.tx_errors++;
+    dev->stats.tx_errors++;
     /* ToDo: We should try to restart the adaptor... */
     local_irq_disable();
     fjn_reset(dev);
@@ -846,7 +882,7 @@ static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        DEBUG(4, "%s: Transmitting a packet of length %lu.\n",
              dev->name, (unsigned long)skb->len);
-       lp->stats.tx_bytes += skb->len;
+       dev->stats.tx_bytes += skb->len;
 
        /* Disable both interrupts. */
        outw(0x0000, ioaddr + TX_INTR);
@@ -974,7 +1010,6 @@ static void fjn_reset(struct net_device *dev)
 
 static void fjn_rx(struct net_device *dev)
 {
-    struct local_info_t *lp = netdev_priv(dev);
     unsigned int ioaddr = dev->base_addr;
     int boguscount = 10;       /* 5 -> 10: by agy 19940922 */
 
@@ -993,11 +1028,11 @@ static void fjn_rx(struct net_device *dev)
        }
 #endif
        if ((status & 0xF0) != 0x20) {  /* There was an error. */
-           lp->stats.rx_errors++;
-           if (status & F_LEN_ERR) lp->stats.rx_length_errors++;
-           if (status & F_ALG_ERR) lp->stats.rx_frame_errors++;
-           if (status & F_CRC_ERR) lp->stats.rx_crc_errors++;
-           if (status & F_OVR_FLO) lp->stats.rx_over_errors++;
+           dev->stats.rx_errors++;
+           if (status & F_LEN_ERR) dev->stats.rx_length_errors++;
+           if (status & F_ALG_ERR) dev->stats.rx_frame_errors++;
+           if (status & F_CRC_ERR) dev->stats.rx_crc_errors++;
+           if (status & F_OVR_FLO) dev->stats.rx_over_errors++;
        } else {
            u_short pkt_len = inw(ioaddr + DATAPORT);
            /* Malloc up new buffer. */
@@ -1007,7 +1042,7 @@ static void fjn_rx(struct net_device *dev)
                printk(KERN_NOTICE "%s: The FMV-18x claimed a very "
                       "large packet, size %d.\n", dev->name, pkt_len);
                outb(F_SKP_PKT, ioaddr + RX_SKIP);
-               lp->stats.rx_errors++;
+               dev->stats.rx_errors++;
                break;
            }
            skb = dev_alloc_skb(pkt_len+2);
@@ -1015,7 +1050,7 @@ static void fjn_rx(struct net_device *dev)
                printk(KERN_NOTICE "%s: Memory squeeze, dropping "
                       "packet (len %d).\n", dev->name, pkt_len);
                outb(F_SKP_PKT, ioaddr + RX_SKIP);
-               lp->stats.rx_dropped++;
+               dev->stats.rx_dropped++;
                break;
            }
 
@@ -1036,9 +1071,8 @@ static void fjn_rx(struct net_device *dev)
 #endif
 
            netif_rx(skb);
-           dev->last_rx = jiffies;
-           lp->stats.rx_packets++;
-           lp->stats.rx_bytes += pkt_len;
+           dev->stats.rx_packets++;
+           dev->stats.rx_bytes += pkt_len;
        }
        if (--boguscount <= 0)
            break;
@@ -1158,14 +1192,6 @@ static int fjn_close(struct net_device *dev)
 
 /*====================================================================*/
 
-static struct net_device_stats *fjn_get_stats(struct net_device *dev)
-{
-    local_info_t *lp = netdev_priv(dev);
-    return &lp->stats;
-} /* fjn_get_stats */
-
-/*====================================================================*/
-
 /*
   Set the multicast/promiscuous mode for this adaptor.
 */