X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fnet%2Fsun3lance.c;h=f8d46134dacaeaa16f66a2d98b8ce2faad4616f2;hb=7387273307139ebf8d7f7fb3bb79d1ca48bd71d6;hp=d4c0002b43db658f8099891afcc5f18bad53620a;hpb=8d3b33f67fdc0fb364a1ef6d8fbbea7c2e4e6c98;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index d4c0002..f8d4613 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c @@ -1,24 +1,24 @@ /* sun3lance.c: Ethernet driver for SUN3 Lance chip */ /* - Sun3 Lance ethernet driver, by Sam Creasey (sammy@users.qual.net). + Sun3 Lance ethernet driver, by Sam Creasey (sammy@users.qual.net). This driver is a part of the linux kernel, and is thus distributed under the GNU General Public License. - + The values used in LANCE_OBIO and LANCE_IRQ seem to be empirically true for the correct IRQ and address of the lance registers. They have not been widely tested, however. What we probably need is a "proper" way to search for a device in the sun3's prom, but, alas, - linux has no such thing. + linux has no such thing. This driver is largely based on atarilance.c, by Roman Hodek. Other sources of inspiration were the NetBSD sun3 am7990 driver, and the - linux sparc lance driver (sunlance.c). + linux sparc lance driver (sunlance.c). There are more assumptions made throughout this driver, it almost certainly still needs work, but it does work at least for RARP/BOOTP and mounting the root NFS filesystem. - + */ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.net)\n"; @@ -38,6 +38,7 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.ne #include #include +#include #include #include #include @@ -55,7 +56,7 @@ static char *version = "sun3lance.c: v1.2 1/12/2001 Sam Creasey (sammy@sammy.ne /* sun3/60 addr/irq for the lance chip. If your sun is different, change this. */ #define LANCE_OBIO 0x120000 -#define LANCE_IRQ IRQ3 +#define LANCE_IRQ IRQ_AUTO_3 /* Debug level: * 0 = silent, print only serious errors @@ -151,7 +152,6 @@ struct lance_private { struct lance_memory *mem; int new_rx, new_tx; /* The next free ring entry */ int old_tx, old_rx; /* ring entry to be processed */ - struct net_device_stats stats; /* These two must be longs for set_bit() */ long tx_full; long lock; @@ -237,10 +237,9 @@ static int lance_probe( struct net_device *dev); static int lance_open( struct net_device *dev ); static void lance_init_ring( struct net_device *dev ); static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); -static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp ); +static irqreturn_t lance_interrupt( int irq, void *dev_id); static int lance_rx( struct net_device *dev ); 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 ); /************************* End of Prototypes **************************/ @@ -273,7 +272,6 @@ struct net_device * __init sun3lance_probe(int unit) sprintf(dev->name, "eth%d", unit); netdev_boot_setup_check(dev); } - SET_MODULE_OWNER(dev); if (!lance_probe(dev)) goto out; @@ -286,7 +284,7 @@ struct net_device * __init sun3lance_probe(int unit) out1: #ifdef CONFIG_SUN3 - iounmap((void *)dev->base_addr); + iounmap((void __iomem *)dev->base_addr); #endif out: free_netdev(dev); @@ -294,14 +292,15 @@ out: } static int __init lance_probe( struct net_device *dev) -{ +{ unsigned long ioaddr; - + struct lance_private *lp; int i; static int did_version; volatile unsigned short *ioaddr_probe; unsigned short tmp1, tmp2; + DECLARE_MAC_BUF(mac); #ifdef CONFIG_SUN3 ioaddr = (unsigned long)ioremap(LANCE_OBIO, PAGE_SIZE); @@ -313,7 +312,7 @@ static int __init lance_probe( struct net_device *dev) /* test to see if there's really a lance here */ /* (CSRO_INIT shouldn't be readable) */ - + ioaddr_probe = (volatile unsigned short *)ioaddr; tmp1 = ioaddr_probe[0]; tmp2 = ioaddr_probe[1]; @@ -326,7 +325,7 @@ static int __init lance_probe( struct net_device *dev) ioaddr_probe[1] = tmp2; #ifdef CONFIG_SUN3 - iounmap((void *)ioaddr); + iounmap((void __iomem *)ioaddr); #endif return 0; } @@ -335,13 +334,27 @@ static int __init lance_probe( struct net_device *dev) /* XXX - leak? */ MEM = dvma_malloc_align(sizeof(struct lance_memory), 0x10000); + if (MEM == NULL) { +#ifdef CONFIG_SUN3 + iounmap((void __iomem *)ioaddr); +#endif + printk(KERN_WARNING "SUN3 Lance couldn't allocate DVMA memory\n"); + return 0; + } lp->iobase = (volatile unsigned short *)ioaddr; dev->base_addr = (unsigned long)ioaddr; /* informational only */ - REGA(CSR0) = CSR0_STOP; + REGA(CSR0) = CSR0_STOP; - request_irq(LANCE_IRQ, lance_interrupt, SA_INTERRUPT, "SUN3 Lance", dev); + if (request_irq(LANCE_IRQ, lance_interrupt, IRQF_DISABLED, "SUN3 Lance", dev) < 0) { +#ifdef CONFIG_SUN3 + iounmap((void __iomem *)ioaddr); +#endif + dvma_free((void *)MEM); + printk(KERN_WARNING "SUN3 Lance unable to allocate IRQ\n"); + return 0; + } dev->irq = (unsigned short)LANCE_IRQ; @@ -363,8 +376,7 @@ static int __init lance_probe( struct net_device *dev) MEM->init.hwaddr[4] = dev->dev_addr[5]; MEM->init.hwaddr[5] = dev->dev_addr[4]; - for( i = 0; i < 6; ++i ) - printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" ); + printk("%s\n", print_mac(mac, dev->dev_addr)); MEM->init.mode = 0x0000; MEM->init.filter[0] = 0x00000000; @@ -378,7 +390,7 @@ static int __init lance_probe( struct net_device *dev) DPRINTK(2, ("initaddr: %08lx rx_ring: %08lx tx_ring: %08lx\n", dvma_vtob(&(MEM->init)), dvma_vtob(MEM->rx_head), - (dvma_vtob(MEM->tx_head)))); + (dvma_vtob(MEM->tx_head)))); if (did_version++ == 0) printk( version ); @@ -387,15 +399,12 @@ static int __init lance_probe( struct net_device *dev) dev->open = &lance_open; dev->hard_start_xmit = &lance_start_xmit; dev->stop = &lance_close; - dev->get_stats = &lance_get_stats; dev->set_multicast_list = &set_multicast_list; dev->set_mac_address = NULL; // KLUDGE -- REMOVE ME set_bit(__LINK_STATE_PRESENT, &dev->state); - memset( &lp->stats, 0, sizeof(lp->stats) ); - return 1; } @@ -427,7 +436,7 @@ static int lance_open( struct net_device *dev ) DREG = CSR0_IDON | CSR0_STRT | CSR0_INEA; netif_start_queue(dev); - + DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); return( 0 ); @@ -449,7 +458,7 @@ static void lance_init_ring( struct net_device *dev ) for( i = 0; i < TX_RING_SIZE; i++ ) { MEM->tx_head[i].base = dvma_vtob(MEM->tx_data[i]); MEM->tx_head[i].flag = 0; - MEM->tx_head[i].base_hi = + MEM->tx_head[i].base_hi = (dvma_vtob(MEM->tx_data[i])) >>16; MEM->tx_head[i].length = 0; MEM->tx_head[i].misc = 0; @@ -458,7 +467,7 @@ static void lance_init_ring( struct net_device *dev ) for( i = 0; i < RX_RING_SIZE; i++ ) { MEM->rx_head[i].base = dvma_vtob(MEM->rx_data[i]); MEM->rx_head[i].flag = RMD1_OWN_CHIP; - MEM->rx_head[i].base_hi = + MEM->rx_head[i].base_hi = (dvma_vtob(MEM->rx_data[i])) >> 16; MEM->rx_head[i].buf_length = -PKT_BUF_SZ | 0xf000; MEM->rx_head[i].msg_length = 0; @@ -520,7 +529,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) * little endian mode. */ REGA(CSR3) = CSR3_BSWP; - lp->stats.tx_errors++; + dev->stats.tx_errors++; if(lance_debug >= 2) { int i; @@ -542,22 +551,22 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) lance_init_ring(dev); REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT; - + netif_start_queue(dev); dev->trans_start = jiffies; - + return 0; } - + /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ /* Block a timer-based transmit from overlapping with us by stopping the queue for a bit... */ - + netif_stop_queue(dev); - + if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) { printk( "%s: tx queue lock!.\n", dev->name); /* don't clear dev->tbusy flag. */ @@ -581,19 +590,14 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) /* Fill in a Tx ring entry */ #if 0 if (lance_debug >= 2) { - u_char *p; - int i; - printk( "%s: TX pkt %d type 0x%04x from ", dev->name, - lp->new_tx, ((u_short *)skb->data)[6]); - for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ ) - printk("%02x%s", *p++, i != 5 ? ":" : "" ); - printk(" to "); - for( p = (u_char *)skb->data, i = 0; i < 6; i++ ) - printk("%02x%s", *p++, i != 5 ? ":" : "" ); - printk(" data at 0x%08x len %d\n", (int)skb->data, - (int)skb->len ); + printk( "%s: TX pkt %d type 0x%04x" + " from %s to %s" + " data at 0x%08x len %d\n", + dev->name, lp->new_tx, ((u_short *)skb->data)[6], + DEV_ADDR(&skb->data[6]), DEV_ADDR(skb->data), + (int)skb->data, (int)skb->len ); } -#endif +#endif /* We're not prepared for the int until the last flags are set/reset. * And the int may happen already after setting the OWN_CHIP... */ local_irq_save(flags); @@ -614,13 +618,13 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) head->length = (-len) | 0xf000; head->misc = 0; - memcpy( PKTBUF_ADDR(head), (void *)skb->data, skb->len ); + skb_copy_from_linear_data(skb, PKTBUF_ADDR(head), skb->len); if (len != skb->len) memset(PKTBUF_ADDR(head) + skb->len, 0, len-skb->len); head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP; lp->new_tx = (lp->new_tx + 1) & TX_RING_MOD_MASK; - lp->stats.tx_bytes += skb->len; + dev->stats.tx_bytes += skb->len; /* Trigger an immediate send poll. */ REGA(CSR0) = CSR0_INEA | CSR0_TDMD | CSR0_STRT; @@ -632,7 +636,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) lp->lock = 0; if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) == - TMD1_OWN_HOST) + TMD1_OWN_HOST) netif_start_queue(dev); local_irq_restore(flags); @@ -642,7 +646,7 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ) /* The LANCE interrupt handler. */ -static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) +static irqreturn_t lance_interrupt( int irq, void *dev_id) { struct net_device *dev = dev_id; struct lance_private *lp = netdev_priv(dev); @@ -657,10 +661,10 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) if (in_interrupt) DPRINTK( 2, ( "%s: Re-entering the interrupt handler.\n", dev->name )); in_interrupt = 1; - + still_more: flush_cache_all(); - + AREG = CSR0; csr0 = DREG; @@ -680,32 +684,32 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) // if(lance_debug >= 3) { // int i; -// +// // printk("%s: tx int\n", dev->name); -// +// // for(i = 0; i < TX_RING_SIZE; i++) // printk("ring %d flag=%04x\n", i, // MEM->tx_head[i].flag); // } - + while( old_tx != lp->new_tx) { - struct lance_tx_head *head = &(MEM->tx_head[old_tx]); - + struct lance_tx_head *head = &(MEM->tx_head[old_tx]); + DPRINTK(3, ("on tx_ring %d\n", old_tx)); if (head->flag & TMD1_OWN_CHIP) break; /* It still hasn't been Txed */ - + if (head->flag & TMD1_ERR) { int status = head->misc; - lp->stats.tx_errors++; - if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; - if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; - if (status & TMD3_LCOL) lp->stats.tx_window_errors++; + dev->stats.tx_errors++; + if (status & TMD3_RTRY) dev->stats.tx_aborted_errors++; + if (status & TMD3_LCAR) dev->stats.tx_carrier_errors++; + if (status & TMD3_LCOL) dev->stats.tx_window_errors++; if (status & (TMD3_UFLO | TMD3_BUFF)) { - lp->stats.tx_fifo_errors++; + dev->stats.tx_fifo_errors++; printk("%s: Tx FIFO error\n", - dev->name); + dev->name); REGA(CSR0) = CSR0_STOP; REGA(CSR3) = CSR3_BSWP; lance_init_ring(dev); @@ -713,12 +717,12 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) return IRQ_HANDLED; } } else if(head->flag & (TMD1_ENP | TMD1_STP)) { - + head->flag &= ~(TMD1_ENP | TMD1_STP); if(head->flag & (TMD1_ONE | TMD1_MORE)) - lp->stats.collisions++; - - lp->stats.tx_packets++; + dev->stats.collisions++; + + dev->stats.tx_packets++; DPRINTK(3, ("cleared tx ring %d\n", old_tx)); } old_tx = (old_tx +1) & TX_RING_MOD_MASK; @@ -736,10 +740,10 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp) if (csr0 & CSR0_RINT) /* Rx interrupt */ lance_rx( dev ); - + /* Log misc errors. */ - if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */ - if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */ + if (csr0 & CSR0_BABL) dev->stats.tx_errors++; /* Tx babble. */ + if (csr0 & CSR0_MISS) dev->stats.rx_errors++; /* Missed a Rx frame. */ if (csr0 & CSR0_MERR) { DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), " "status %04x.\n", dev->name, csr0 )); @@ -778,18 +782,18 @@ static int lance_rx( struct net_device *dev ) while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) { struct lance_rx_head *head = &(MEM->rx_head[entry]); int status = head->flag; - + if (status != (RMD1_ENP|RMD1_STP)) { /* There was an error. */ /* There is a tricky error noted by John Murphy, - to Russ Nelson: Even with + to Russ Nelson: Even with full-sized buffers it's possible for a jabber packet to use two buffers, with only the last correctly noting the error. */ if (status & RMD1_ENP) /* Only count a general error at the */ - lp->stats.rx_errors++; /* end of a packet.*/ - if (status & RMD1_FRAM) lp->stats.rx_frame_errors++; - if (status & RMD1_OFLO) lp->stats.rx_over_errors++; - if (status & RMD1_CRC) lp->stats.rx_crc_errors++; - if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++; + dev->stats.rx_errors++; /* end of a packet.*/ + if (status & RMD1_FRAM) dev->stats.rx_frame_errors++; + if (status & RMD1_OFLO) dev->stats.rx_over_errors++; + if (status & RMD1_CRC) dev->stats.rx_crc_errors++; + if (status & RMD1_BUFF) dev->stats.rx_fifo_errors++; head->flag &= (RMD1_ENP|RMD1_STP); } else { /* Malloc up new buffer, compatible with net-3. */ @@ -799,15 +803,15 @@ static int lance_rx( struct net_device *dev ) if (pkt_len < 60) { printk( "%s: Runt packet!\n", dev->name ); - lp->stats.rx_errors++; + dev->stats.rx_errors++; } else { skb = dev_alloc_skb( pkt_len+2 ); if (skb == NULL) { DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n", dev->name )); - - lp->stats.rx_dropped++; + + dev->stats.rx_dropped++; head->msg_length = 0; head->flag |= RMD1_OWN_CHIP; lp->new_rx = (lp->new_rx+1) & @@ -816,13 +820,14 @@ static int lance_rx( struct net_device *dev ) #if 0 if (lance_debug >= 3) { - u_char *data = PKTBUF_ADDR(head), *p; - printk( "%s: RX pkt %d type 0x%04x from ", dev->name, entry, ((u_short *)data)[6]); - for( p = &data[6], i = 0; i < 6; i++ ) - printk("%02x%s", *p++, i != 5 ? ":" : "" ); - printk(" to "); - for( p = data, i = 0; i < 6; i++ ) - printk("%02x%s", *p++, i != 5 ? ":" : "" ); + u_char *data = PKTBUF_ADDR(head); + DECLARE_MAC_BUF(mac); + DECLARE_MAC_BUF(mac2) + printk("%s: RX pkt %d type 0x%04x" + " from %s to %s", + dev->name, lp->new_tx, ((u_short *)data)[6], + print_mac(mac, &data[6]), print_mac(mac2, data)); + printk(" data %02x %02x %02x %02x %02x %02x %02x %02x " "len %d at %08x\n", data[15], data[16], data[17], data[18], @@ -833,22 +838,20 @@ static int lance_rx( struct net_device *dev ) if (lance_debug >= 3) { u_char *data = PKTBUF_ADDR(head); printk( "%s: RX pkt %d type 0x%04x len %d\n ", dev->name, entry, ((u_short *)data)[6], pkt_len); - } + } - skb->dev = dev; skb_reserve( skb, 2 ); /* 16 byte align */ skb_put( skb, pkt_len ); /* Make room */ -// memcpy( skb->data, PKTBUF_ADDR(head), pkt_len ); - eth_copy_and_sum(skb, + skb_copy_to_linear_data(skb, PKTBUF_ADDR(head), - pkt_len, 0); + pkt_len); skb->protocol = eth_type_trans( skb, dev ); 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; } } @@ -885,14 +888,6 @@ static int lance_close( struct net_device *dev ) } -static struct net_device_stats *lance_get_stats( struct net_device *dev ) -{ - struct lance_private *lp = netdev_priv(dev); - - return &lp->stats; -} - - /* Set or clear the multicast filter for this adaptor. num_addrs == -1 Promiscuous mode, receive all packets num_addrs == 0 Normal mode, clear multicast list @@ -914,7 +909,7 @@ static void set_multicast_list( struct net_device *dev ) if (dev->flags & IFF_PROMISC) { /* Log any net taps. */ - DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name )); + DPRINTK( 3, ( "%s: Promiscuous mode enabled.\n", dev->name )); REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */ } else { short multicast_table[4]; @@ -944,7 +939,7 @@ static void set_multicast_list( struct net_device *dev ) static struct net_device *sun3lance_dev; -int init_module(void) +int __init init_module(void) { sun3lance_dev = sun3lance_probe(-1); if (IS_ERR(sun3lance_dev)) @@ -952,11 +947,11 @@ int init_module(void) return 0; } -void cleanup_module(void) +void __exit cleanup_module(void) { unregister_netdev(sun3lance_dev); #ifdef CONFIG_SUN3 - iounmap((void *)sun3lance_dev->base_addr); + iounmap((void __iomem *)sun3lance_dev->base_addr); #endif free_netdev(sun3lance_dev); }