X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Flance.c;h=a3843320dbe1df8efdebf7aef1d12e77e197a280;hb=refs%2Fheads%2Fvserver;hp=f04d0a82cf3b847b6e7aacf87a215703b62fbf84;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/net/lance.c b/drivers/net/lance.c index f04d0a82c..a3843320d 100644 --- a/drivers/net/lance.c +++ b/drivers/net/lance.c @@ -19,7 +19,7 @@ - alignment problem with 1.3.* kernel and some minor changes. Thomas Bogendoerfer (tsbogend@bigbug.franken.de): - added support for Linux/Alpha, but removed most of it, because - it worked only for the PCI chip. + it worked only for the PCI chip. - added hook for the 32bit lance driver - added PCnetPCI II (79C970A) to chip table Paul Gortmaker (gpg109@rsphy1.anu.edu.au): @@ -31,7 +31,7 @@ before unregister_netdev() which caused NULL pointer reference later in the chain (in rtnetlink_fill_ifinfo()) -- Mika Kuoppala - + Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from the 2.1 version of the old driver - Alan Cox @@ -42,11 +42,12 @@ Vesselin Kostadinov - 22/4/2004 */ -static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n"; +static const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n"; #include #include #include +#include #include #include #include @@ -56,8 +57,9 @@ static const char version[] = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker #include #include #include +#include +#include -#include #include #include @@ -297,27 +299,16 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_ static unsigned char lance_need_isa_bounce_buffers = 1; static int lance_open(struct net_device *dev); -static void lance_init_ring(struct net_device *dev, int mode); +static void lance_init_ring(struct net_device *dev, gfp_t mode); static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev); static int lance_rx(struct net_device *dev); -static irqreturn_t lance_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static irqreturn_t lance_interrupt(int irq, void *dev_id); static int lance_close(struct net_device *dev); static struct net_device_stats *lance_get_stats(struct net_device *dev); static void set_multicast_list(struct net_device *dev); static void lance_tx_timeout (struct net_device *dev); - -static void cleanup_card(struct net_device *dev) -{ - struct lance_private *lp = dev->priv; - if (dev->dma != 4) - free_dma(dev->dma); - release_region(dev->base_addr, LANCE_TOTAL_SIZE); - kfree(lp->tx_bounce_buffs); - kfree((void*)lp->rx_buffs); - kfree(lp); -} #ifdef MODULE #define MAX_CARDS 8 /* Max number of interfaces (cards) per module */ @@ -327,16 +318,16 @@ static int io[MAX_CARDS]; static int dma[MAX_CARDS]; static int irq[MAX_CARDS]; -MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i"); -MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i"); -MODULE_PARM(lance_debug, "i"); +module_param_array(io, int, NULL, 0); +module_param_array(dma, int, NULL, 0); +module_param_array(irq, int, NULL, 0); +module_param(lance_debug, int, 0); MODULE_PARM_DESC(io, "LANCE/PCnet I/O base address(es),required"); MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)"); MODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)"); MODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)"); -int init_module(void) +int __init init_module(void) { struct net_device *dev; int this_dev, found = 0; @@ -355,11 +346,8 @@ int init_module(void) dev->base_addr = io[this_dev]; dev->dma = dma[this_dev]; if (do_lance_probe(dev) == 0) { - if (register_netdev(dev) == 0) { - dev_lance[found++] = dev; - continue; - } - cleanup_card(dev); + dev_lance[found++] = dev; + continue; } free_netdev(dev); break; @@ -369,14 +357,25 @@ int init_module(void) return -ENXIO; } -void cleanup_module(void) +static void cleanup_card(struct net_device *dev) +{ + struct lance_private *lp = dev->priv; + if (dev->dma != 4) + free_dma(dev->dma); + release_region(dev->base_addr, LANCE_TOTAL_SIZE); + kfree(lp->tx_bounce_buffs); + kfree((void*)lp->rx_buffs); + kfree(lp); +} + +void __exit cleanup_module(void) { int this_dev; for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) { struct net_device *dev = dev_lance[this_dev]; if (dev) { - unregister_netdev(dev); + unregister_netdev(dev); cleanup_card(dev); free_netdev(dev); } @@ -447,12 +446,7 @@ struct net_device * __init lance_probe(int unit) err = do_lance_probe(dev); if (err) goto out; - err = register_netdev(dev); - if (err) - goto out1; return dev; -out1: - cleanup_card(dev); out: free_netdev(dev); return ERR_PTR(err); @@ -471,20 +465,25 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int static int did_version; /* Already printed version info. */ unsigned long flags; int err = -ENOMEM; + void __iomem *bios; /* First we look for special cases. Check for HP's on-board ethernet by looking for 'HP' in the BIOS. There are two HP versions, check the BIOS for the configuration port. This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com. */ - if (isa_readw(0x000f0102) == 0x5048) { + bios = ioremap(0xf00f0, 0x14); + if (!bios) + return -ENOMEM; + if (readw(bios + 0x12) == 0x5048) { static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360}; - int hp_port = (isa_readl(0x000f00f1) & 1) ? 0x499 : 0x99; + int hp_port = (readl(bios + 1) & 1) ? 0x499 : 0x99; /* We can have boards other than the built-in! Verify this is on-board. */ if ((inb(hp_port) & 0xc0) == 0x80 && ioaddr_table[inb(hp_port) & 3] == ioaddr) hp_builtin = hp_port; } + iounmap(bios); /* We also recognize the HP Vectra on-board here, but check below. */ hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 && inb(ioaddr+2) == 0x09); @@ -533,7 +532,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int dev->base_addr = ioaddr; /* Make certain the data structures used by the LANCE are aligned and DMAble. */ - + lp = kmalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); if(lp==NULL) return -ENODEV; @@ -658,7 +657,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */ if (request_dma(dma, chipname)) continue; - + flags=claim_dma_lock(); set_dma_mode(dma, DMA_MODE_CASCADE); enable_dma(dma); @@ -723,6 +722,9 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int dev->tx_timeout = lance_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + err = register_netdev(dev); + if (err) + goto out_dma; return 0; out_dma: if (dev->dma != 4) @@ -736,7 +738,7 @@ out_lp: return err; } - + static int lance_open(struct net_device *dev) { @@ -800,7 +802,7 @@ lance_open(struct net_device *dev) while (i++ < 100) if (inw(ioaddr+LANCE_DATA) & 0x0100) break; - /* + /* * We used to clear the InitDone bit, 0x0100, here but Mark Stockton * reports that doing so triggers a bug in the '974. */ @@ -825,7 +827,7 @@ lance_open(struct net_device *dev) restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com */ -static void +static void lance_purge_ring(struct net_device *dev) { struct lance_private *lp = dev->priv; @@ -850,7 +852,7 @@ lance_purge_ring(struct net_device *dev) /* Initialize the LANCE Rx and Tx rings. */ static void -lance_init_ring(struct net_device *dev, int gfp) +lance_init_ring(struct net_device *dev, gfp_t gfp) { struct lance_private *lp = dev->priv; int i; @@ -866,7 +868,7 @@ lance_init_ring(struct net_device *dev, int gfp) lp->rx_skbuff[i] = skb; if (skb) { skb->dev = dev; - rx_buff = skb->tail; + rx_buff = skb->data; } else rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp); if (rx_buff == NULL) @@ -967,12 +969,11 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) /* The old LANCE chips doesn't automatically pad buffers to min. size. */ if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { if (skb->len < ETH_ZLEN) { - skb = skb_padto(skb, ETH_ZLEN); - if (skb == NULL) + if (skb_padto(skb, ETH_ZLEN)) goto out; lp->tx_ring[entry].length = -ETH_ZLEN; } - else + else lp->tx_ring[entry].length = -skb->len; } else lp->tx_ring[entry].length = -skb->len; @@ -1012,22 +1013,16 @@ out: } /* The LANCE interrupt handler. */ -static irqreturn_t -lance_interrupt(int irq, void *dev_id, struct pt_regs * regs) +static irqreturn_t lance_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; struct lance_private *lp; int csr0, ioaddr, boguscnt=10; int must_restart; - if (dev == NULL) { - printk ("lance_interrupt(): irq %d for unknown device.\n", irq); - return IRQ_NONE; - } - ioaddr = dev->base_addr; lp = dev->priv; - + spin_lock (&lp->devlock); outw(0x00, dev->base_addr + LANCE_ADDR); @@ -1051,7 +1046,7 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs) while (dirty_tx < lp->cur_tx) { int entry = dirty_tx & TX_RING_MOD_MASK; int status = lp->tx_ring[entry].base; - + if (status < 0) break; /* It still hasn't been Txed */ @@ -1142,7 +1137,7 @@ lance_rx(struct net_device *dev) struct lance_private *lp = dev->priv; int entry = lp->cur_rx & RX_RING_MOD_MASK; int i; - + /* If we own the next entry, it's a new packet. Send it up. */ while (lp->rx_ring[entry].base >= 0) { int status = lp->rx_ring[entry].base >> 24; @@ -1160,12 +1155,12 @@ lance_rx(struct net_device *dev) if (status & 0x04) lp->stats.rx_fifo_errors++; lp->rx_ring[entry].base &= 0x03ffffff; } - else + else { /* Malloc up new buffer, compatible with net3. */ short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4; struct sk_buff *skb; - + if(pkt_len<60) { printk("%s: Runt packet!\n",dev->name); @@ -1174,14 +1169,14 @@ lance_rx(struct net_device *dev) else { skb = dev_alloc_skb(pkt_len+2); - if (skb == NULL) + if (skb == NULL) { printk("%s: Memory squeeze, deferring packet.\n", dev->name); for (i=0; i < RX_RING_SIZE; i++) if (lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].base < 0) break; - if (i > RX_RING_SIZE -2) + if (i > RX_RING_SIZE -2) { lp->stats.rx_dropped++; lp->rx_ring[entry].base |= 0x80000000; @@ -1281,8 +1276,6 @@ static void set_multicast_list(struct net_device *dev) outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance. */ if (dev->flags&IFF_PROMISC) { - /* Log any net taps. */ - printk("%s: Promiscuous mode enabled.\n", dev->name); outw(15, ioaddr+LANCE_ADDR); outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */ } else {