X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Flance.c;h=a3843320dbe1df8efdebf7aef1d12e77e197a280;hb=refs%2Fheads%2Fvserver;hp=fc1f9e90264daca69dff682d656d66ecd023e1ec;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/net/lance.c b/drivers/net/lance.c index fc1f9e902..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,19 +31,23 @@ 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 Get rid of check_region, check kmalloc return in lance_probe1 Arnaldo Carvalho de Melo - 11/01/2001 + + Reworked detection, added support for Racal InterLan EtherBlaster cards + 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 @@ -53,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 @@ -62,6 +67,26 @@ static unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, static int lance_probe1(struct net_device *dev, int ioaddr, int irq, int options); static int __init do_lance_probe(struct net_device *dev); + +static struct card { + char id_offset14; + char id_offset15; +} cards[] = { + { //"normal" + .id_offset14 = 0x57, + .id_offset15 = 0x57, + }, + { //NI6510EB + .id_offset14 = 0x52, + .id_offset15 = 0x44, + }, + { //Racal InterLan EtherBlaster + .id_offset14 = 0x52, + .id_offset15 = 0x49, + }, +}; +#define NUM_CARDS 3 + #ifdef LANCE_DEBUG static int lance_debug = LANCE_DEBUG; #else @@ -274,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 */ @@ -304,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; @@ -332,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; @@ -346,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); } @@ -380,13 +402,20 @@ static int __init do_lance_probe(struct net_device *dev) "lance-probe"); if (r) { - /* Detect "normal" 0x57 0x57 and the NI6510EB 0x52 0x44 - signatures w/ minimal I/O reads */ - char offset15, offset14 = inb(ioaddr + 14); - - if ((offset14 == 0x52 || offset14 == 0x57) && - ((offset15 = inb(ioaddr + 15)) == 0x57 || - offset15 == 0x44)) { + /* Detect the card with minimal I/O reads */ + char offset14 = inb(ioaddr + 14); + int card; + for (card = 0; card < NUM_CARDS; ++card) + if (cards[card].id_offset14 == offset14) + break; + if (card < NUM_CARDS) {/*yes, the first byte matches*/ + char offset15 = inb(ioaddr + 15); + for (card = 0; card < NUM_CARDS; ++card) + if ((cards[card].id_offset14 == offset14) && + (cards[card].id_offset15 == offset15)) + break; + } + if (card < NUM_CARDS) { /*Signature OK*/ result = lance_probe1(dev, ioaddr, 0, 0); if (!result) { struct lance_private *lp = dev->priv; @@ -402,6 +431,7 @@ static int __init do_lance_probe(struct net_device *dev) return -ENODEV; } +#ifndef MODULE struct net_device * __init lance_probe(int unit) { struct net_device *dev = alloc_etherdev(0); @@ -416,16 +446,12 @@ 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); } +#endif static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options) { @@ -439,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); @@ -501,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; @@ -626,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); @@ -691,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) @@ -704,7 +738,7 @@ out_lp: return err; } - + static int lance_open(struct net_device *dev) { @@ -768,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. */ @@ -793,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; @@ -802,7 +836,7 @@ lance_purge_ring(struct net_device *dev) /* Free all the skbuffs in the Rx and Tx queues. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = lp->rx_skbuff[i]; - lp->rx_skbuff[i] = 0; + lp->rx_skbuff[i] = NULL; lp->rx_ring[i].base = 0; /* Not owned by LANCE chip. */ if (skb) dev_kfree_skb_any(skb); @@ -818,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; @@ -834,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) @@ -846,7 +880,7 @@ lance_init_ring(struct net_device *dev, int gfp) /* The Tx buffer address is filled in as needed, but we do need to clear the upper ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) { - lp->tx_skbuff[i] = 0; + lp->tx_skbuff[i] = NULL; lp->tx_ring[i].base = 0; } @@ -935,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; @@ -980,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); @@ -1019,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 */ @@ -1051,7 +1078,7 @@ lance_interrupt(int irq, void *dev_id, struct pt_regs * regs) in the bounce buffer. */ if (lp->tx_skbuff[entry]) { dev_kfree_skb_irq(lp->tx_skbuff[entry]); - lp->tx_skbuff[entry] = 0; + lp->tx_skbuff[entry] = NULL; } dirty_tx++; } @@ -1110,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; @@ -1128,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); @@ -1142,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; @@ -1249,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 {