Commit 9eb76e9f authored by Anton Blanchard's avatar Anton Blanchard

Merge samba.org:/scratch/anton/linux-2.5

into samba.org:/scratch/anton/tmp3
parents e16687d5 23dabca3
......@@ -492,16 +492,16 @@ config MIPS_GT96100ETH
help
Say Y here to support the Ethernet subsystem on your GT96100 card.
config MIPS_AU1000_ENET
config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
depends on NET_ETHERNET && MIPS_AU1000
depends on NET_ETHERNET && SOC_AU1X00
help
If you have an Alchemy Semi AU1000 ethernet controller
on an SGI MIPS system, say Y. Otherwise, say N.
If you have an Alchemy Semi AU1X00 based system
say Y. Otherwise, say N.
config NET_SB1250_MAC
tristate "SB1250 Ethernet support"
depends on NET_ETHERNET && SIBYTE_SB1250
depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC
config SGI_IOC3_ETH
bool "SGI IOC3 Ethernet"
......@@ -511,6 +511,10 @@ config SGI_IOC3_ETH
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
config SGI_O2MACE_ETH
tristate "SGI O2 MACE Fast Ethernet support"
depends on NET_ETHERNET && SGI_IP32=y
config STNIC
tristate "National DP83902AV support"
depends on NET_ETHERNET && SUPERH
......@@ -1391,6 +1395,10 @@ config CS89x0
<file:Documentation/networking/net-modules.txt>. The module will be
called cs89x.
config TC35815
tristate "TOSHIBA TC35815 Ethernet support"
depends on NET_PCI && PCI
config DGRS
tristate "Digi Intl. RightSwitch SE-X support"
depends on NET_PCI && (PCI || EISA)
......@@ -1839,14 +1847,14 @@ config DE620
The module will be called de620.
config SGISEEQ
bool "SGI Seeq ethernet controller support"
tristate "SGI Seeq ethernet controller support"
depends on NET_ETHERNET && SGI_IP22
help
Say Y here if you have an Seeq based Ethernet network card. This is
used in many Silicon Graphics machines.
config DECLANCE
bool "DEC LANCE ethernet controller support"
tristate "DEC LANCE ethernet controller support"
depends on NET_ETHERNET && DECSTATION
help
This driver is for the series of Ethernet controllers produced by
......
......@@ -117,6 +117,7 @@ obj-$(CONFIG_SUN3_82586) += sun3_82586.o
obj-$(CONFIG_SUN3LANCE) += sun3lance.o
obj-$(CONFIG_DEFXX) += defxx.o
obj-$(CONFIG_SGISEEQ) += sgiseeq.o
obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
obj-$(CONFIG_AT1700) += at1700.o
obj-$(CONFIG_FMV18X) += fmv18x.o
obj-$(CONFIG_EL1) += 3c501.o
......@@ -156,7 +157,7 @@ obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
obj-$(CONFIG_EQUALIZER) += eql.o
obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o
obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
obj-$(CONFIG_MIPS_AU1000_ENET) += au1000_eth.o
obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_BAGETLANCE) += bagetlance.o
obj-$(CONFIG_DECLANCE) += declance.o
......
......@@ -24,6 +24,7 @@ obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o
obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o
obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o
obj-$(CONFIG_PCNET32) += crc32.o
obj-$(CONFIG_SGI_IOC3_ETH) += crc32.o
obj-$(CONFIG_SIS900) += crc32.o
obj-$(CONFIG_SMC9194) += crc32.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += crc32.o
......
......@@ -82,7 +82,6 @@ extern int sonic_probe(struct net_device *);
extern int SK_init(struct net_device *);
extern int seeq8005_probe(struct net_device *);
extern int smc_init( struct net_device * );
extern int sgiseeq_probe(struct net_device *);
extern int atarilance_probe(struct net_device *);
extern int sun3lance_probe(struct net_device *);
extern int sun3_82586_probe(struct net_device *);
......@@ -343,14 +342,6 @@ static struct devprobe m68k_probes[] __initdata = {
{NULL, 0},
};
static struct devprobe sgi_probes[] __initdata = {
#ifdef CONFIG_SGISEEQ
{sgiseeq_probe, 0},
#endif
{NULL, 0},
};
static struct devprobe mips_probes[] __initdata = {
#ifdef CONFIG_MIPS_JAZZ_SONIC
{sonic_probe, 0},
......@@ -385,8 +376,6 @@ static int __init ethif_probe(struct net_device *dev)
return 0;
if (probe_list(dev, mips_probes) == 0)
return 0;
if (probe_list(dev, sgi_probes) == 0)
return 0;
if (probe_list(dev, eisa_probes) == 0)
return 0;
if (probe_list(dev, mca_probes) == 0)
......
......@@ -3026,9 +3026,6 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return 0;
case ETHTOOL_SSET:
if(!capable(CAP_NET_ADMIN))
return -EPERM;
link = readl(&regs->GigLnkState);
if (link & LNK_1000MB)
speed = SPEED_1000;
......
/*
*
* Alchemy Semi Au1000 ethernet driver
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
......@@ -20,16 +17,8 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
*
*/
#ifndef __mips__
#error This driver only works with MIPS architectures!
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
......@@ -125,7 +114,7 @@ static struct {
},
au1100_iflist[NUM_INTERFACES] = {
{AU1000_ETH0_BASE, AU1000_ETH0_IRQ},
{NULL, NULL}
{0, 0}
};
static char version[] __devinitdata =
......@@ -152,13 +141,6 @@ static unsigned char au1000_mac_addr[6] __devinitdata = {
* code.
*/
static char *phy_link[] =
{"unknown",
"10Base2", "10BaseT",
"AUI",
"100BaseT", "100BaseTX", "100BaseFX"
};
int bcm_5201_init(struct net_device *dev, int phy_addr)
{
s16 data;
......@@ -184,6 +166,11 @@ int bcm_5201_init(struct net_device *dev, int phy_addr)
data &= ~MII_FDX_LED;
mdio_write(dev, phy_addr, MII_INT, data);
/* Enable TX LED instead of FDX */
data = mdio_read(dev, phy_addr, MII_INT);
data &= ~MII_FDX_LED;
mdio_write(dev, phy_addr, MII_INT, data);
if (au1000_debug > 4) dump_mii(dev, phy_addr);
return 0;
}
......@@ -640,7 +627,7 @@ static int __init au1000_init_module(void)
int prid;
int base_addr, irq;
prid = read_32bit_cp0_register(CP0_PRID);
prid = read_c0_prid();
for (i=0; i<NUM_INTERFACES; i++) {
if ( (prid & 0xffff0000) == 0x00030000 ) {
base_addr = au1000_iflist[i].port;
......@@ -675,10 +662,11 @@ au1000_probe1(struct net_device *dev, long ioaddr, int irq, int port_num)
char *pmac, *argptr;
char ethaddr[6];
if (!request_region(ioaddr, MAC_IOSIZE, "Au1000 ENET"))
if (!request_region(PHYSADDR(ioaddr), MAC_IOSIZE, "Au1000 ENET"))
return -ENODEV;
if (version_printed++ == 0) printk(version);
if (version_printed++ == 0)
printk(version);
if (!dev)
dev = init_etherdev(NULL, sizeof(struct au1000_private));
......@@ -816,7 +804,7 @@ au1000_probe1(struct net_device *dev, long ioaddr, int irq, int port_num)
return 0;
free_region:
release_region(ioaddr, MAC_IOSIZE);
release_region(PHYSADDR(ioaddr), MAC_IOSIZE);
unregister_netdev(dev);
if (aup->vaddr)
dma_free((void *)aup->vaddr,
......@@ -1047,8 +1035,9 @@ static void au1000_tx_ack(struct net_device *dev)
ptxd = aup->tx_dma_ring[aup->tx_tail];
while (ptxd->buff_stat & TX_T_DONE) {
update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_tail] & 0x3ff);
ptxd->buff_stat &= ~TX_T_DONE;
aup->tx_len[aup->tx_tail] = 0;
ptxd->len = 0;
au_sync();
......@@ -1088,7 +1077,8 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
return 1;
}
else if (buff_stat & TX_T_DONE) {
update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_head] & 0x3ff);
aup->tx_len[aup->tx_head] = 0;
ptxd->len = 0;
}
......@@ -1103,11 +1093,13 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
for (i=skb->len; i<MAC_MIN_PKT_SIZE; i++) {
((char *)pDB->vaddr)[i] = 0;
}
aup->tx_len[aup->tx_head] = MAC_MIN_PKT_SIZE;
ptxd->len = MAC_MIN_PKT_SIZE;
}
else
else {
aup->tx_len[aup->tx_head] = skb->len;
ptxd->len = skb->len;
}
ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
au_sync();
dev_kfree_skb(skb);
......@@ -1244,6 +1236,8 @@ static void au1000_tx_timeout(struct net_device *dev)
printk(KERN_ERR "%s: au1000_tx_timeout: dev=%p\n", dev->name, dev);
reset_mac(dev);
au1000_init(dev);
dev->trans_start = jiffies;
netif_wake_queue(dev);
}
static void set_rx_mode(struct net_device *dev)
......@@ -1269,7 +1263,8 @@ static void set_rx_mode(struct net_device *dev)
mc_filter[1] = mc_filter[0] = 0;
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter);
set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr)>>26,
mc_filter);
}
aup->mac->multi_hash_high = mc_filter[1];
aup->mac->multi_hash_low = mc_filter[0];
......@@ -1287,6 +1282,7 @@ static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
switch(cmd) {
case SIOCGMIIPHY: /* Get the address of the PHY in use. */
data[0] = PHY_ADDRESS;
return 0;
case SIOCGMIIREG: /* Read the specified MII register. */
//data[3] = mdio_read(ioaddr, data[0], data[1]);
......@@ -1295,8 +1291,10 @@ static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
case SIOCSMIIREG: /* Write the specified MII register */
if (!capable(CAP_NET_ADMIN))
return -EPERM;
//mdio_write(ioaddr, data[0], data[1], data[2]);
return 0;
default:
return -EOPNOTSUPP;
}
......
/*
*
* Alchemy Semi Au1000 ethernet driver include file
*
* Author: Pete Popov <ppopov@mvista.com>
*
* Copyright 2001 MontaVista Software Inc.
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
......@@ -20,11 +17,8 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
*
*/
#include <linux/config.h>
#define NUM_INTERFACES 2
......@@ -203,6 +197,7 @@ struct au1000_private {
db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA];
int tx_len[NUM_TX_DMA];
db_dest_t *rx_db_inuse[NUM_RX_DMA];
db_dest_t *tx_db_inuse[NUM_TX_DMA];
u32 rx_head;
......
......@@ -5,6 +5,8 @@
*
* adopted from sunlance.c by Richard van den Berg
*
* Copyright (C) 2002, 2003 Maciej W. Rozycki
*
* additional sources:
* - PMAD-AA TURBOchannel Ethernet Module Functional Specification,
* Revision 1.2
......@@ -21,71 +23,66 @@
* v0.004: lance-regs is pointing at the right addresses, added prom
* check. First start of address mapping and DMA.
*
* v0.005: started to play around with LANCE-DMA. This driver will not work
* for non IOASIC lances. HK
* v0.005: started to play around with LANCE-DMA. This driver will not
* work for non IOASIC lances. HK
*
* v0.006: added pointer arrays to lance_private and setup routine for them
* in dec_lance_init. HK
* v0.006: added pointer arrays to lance_private and setup routine for
* them in dec_lance_init. HK
*
* v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access
* the init block. This looks like one (short) word at a time, but the smallest
* amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here.
* Changed lance_init_block accordingly. The 16-16 padding for the buffers
* v0.007: Big shit. The LANCE seems to use a different DMA mechanism to
* access the init block. This looks like one (short) word at a
* time, but the smallest amount the IOASIC can transfer is a
* (long) word. So we have a 2-2 padding here. Changed
* lance_init_block accordingly. The 16-16 padding for the buffers
* seems to be correct. HK
*
* v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer
*/
#undef DEBUG_DRIVER
static char *version =
"declance.c: v0.008 by Linux Mips DECstation task force\n";
static char *lancestr = "LANCE";
/*
* card types
* v0.008: mods to make PMAX_LANCE work. 01/09/1999 triemer
*
* v0.009: Module support fixes, multiple interfaces support, various
* bits. macro
*/
#define ASIC_LANCE 1
#define PMAD_LANCE 2
#define PMAX_LANCE 3
#include <linux/config.h>
#include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/if_ether.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <asm/addrspace.h>
#include <asm/dec/interrupts.h>
#include <asm/dec/ioasic_ints.h>
#include <asm/dec/ioasic.h>
#include <asm/dec/ioasic_addrs.h>
#include <asm/dec/kn01.h>
#include <asm/dec/machtype.h>
#include <asm/dec/tc.h>
#include <asm/dec/kn01.h>
#include <asm/wbflush.h>
#include <asm/addrspace.h>
#include <asm/system.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/hdreg.h>
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/slab.h>
#include <linux/user.h>
#include <linux/utsname.h>
#include <linux/a.out.h>
#include <linux/tty.h>
#include <linux/delay.h>
#include <linux/crc32.h>
#include <asm/io.h>
#include <linux/etherdevice.h>
static char version[] __devinitdata =
"declance.c: v0.009 by Linux MIPS DECstation task force\n";
MODULE_AUTHOR("Linux MIPS DECstation task force");
MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver");
MODULE_LICENSE("GPL");
/*
* card types
*/
#define ASIC_LANCE 1
#define PMAD_LANCE 2
#define PMAX_LANCE 3
#ifndef CONFIG_TC
unsigned long system_base;
unsigned long dmaptr;
#endif
static int type;
#define LE_CSR0 0
#define LE_CSR1 1
......@@ -160,8 +157,6 @@ static int type;
#define TX_BUFF_SIZE PKT_BUF_SZ
#undef TEST_HITS
#define DEBUG_DRIVER 1
#define ZERO 0
/* The DS2000/3000 have a linear 64 KB buffer.
......@@ -184,11 +179,10 @@ struct lance_rx_desc {
unsigned char rmd1_hadr; /* high address of packet */
unsigned char rmd1_bits; /* descriptor bits */
short gap1;
short length; /* This length is 2s complement (negative)!
* Buffer length
*/
short length; /* 2s complement (negative!)
of buffer length */
short gap2;
unsigned short mblength; /* This is the actual number of bytes received */
unsigned short mblength; /* actual number of bytes received */
short gap3;
};
......@@ -198,7 +192,8 @@ struct lance_tx_desc {
unsigned char tmd1_hadr; /* high address of packet */
unsigned char tmd1_bits; /* descriptor bits */
short gap1;
short length; /* Length is 2s complement (negative)! */
short length; /* 2s complement (negative!)
of buffer length */
short gap2;
unsigned short misc;
short gap3;
......@@ -207,17 +202,15 @@ struct lance_tx_desc {
/* First part of the LANCE initialization block, described in databook. */
struct lance_init_block {
unsigned short mode; /* Pre-set mode (reg. 15) */
unsigned short mode; /* pre-set mode (reg. 15) */
short gap0;
unsigned char phys_addr[12]; /* Physical ethernet address
* only 0, 1, 4, 5, 8, 9 are valid
* 2, 3, 6, 7, 10, 11 are gaps
*/
unsigned short filter[8]; /* Multicast filter.
* only 0, 2, 4, 6 are valid
* 1, 3, 5, 7 are gaps
*/
unsigned char phys_addr[12]; /* physical ethernet address
only 0, 1, 4, 5, 8, 9 are valid
2, 3, 6, 7, 10, 11 are gaps */
unsigned short filter[8]; /* multicast filter
only 0, 2, 4, 6 are valid
1, 3, 5, 7 are gaps */
/* Receive and transmit ring base, along with extra bits. */
unsigned short rx_ptr; /* receive descriptor addr */
......@@ -228,7 +221,7 @@ struct lance_init_block {
short gap3;
unsigned short tx_len; /* transmit len and high addr */
short gap4;
char gap5[16];
short gap5[8];
/* The buffer descriptors */
struct lance_rx_desc brx_ring[RX_RING_SIZE];
......@@ -247,10 +240,12 @@ struct lance_init_block {
#define LANCE_ADDR(x) (PHYSADDR(x) >> 1)
struct lance_private {
char *name;
struct net_device *next;
int type;
int slot;
int dma_irq;
volatile struct lance_regs *ll;
volatile struct lance_init_block *init_block;
volatile unsigned long *dma_ptr_reg;
spinlock_t lock;
......@@ -261,8 +256,6 @@ struct lance_private {
unsigned short busmaster_regval;
struct net_device *dev; /* Backpointer */
struct lance_private *next_module;
struct timer_list multicast_timer;
/* Pointers to the ring buffers as seen from the CPU */
......@@ -292,16 +285,12 @@ struct lance_regs {
int dec_lance_debug = 2;
/*
#ifdef MODULE
static struct lance_private *root_lance_dev = NULL;
#endif
*/
static struct net_device *root_lance_dev;
static inline void writereg(volatile unsigned short *regptr, short value)
{
*regptr = value;
wbflush();
iob();
}
/* Load the CSR registers */
......@@ -330,7 +319,7 @@ static void load_csrs(struct lance_private *lp)
* Our specialized copy routines
*
*/
void cp_to_buf(void *to, const void *from, __kernel_size_t len)
void cp_to_buf(const int type, void *to, const void *from, int len)
{
unsigned short *tp, *fp, clen;
unsigned char *rtp, *rfp;
......@@ -381,10 +370,10 @@ void cp_to_buf(void *to, const void *from, __kernel_size_t len)
}
}
wbflush();
iob();
}
void cp_from_buf(void *to, unsigned char *from, int len)
void cp_from_buf(const int type, void *to, const void *from, int len)
{
unsigned short *tp, *fp, clen;
unsigned char *rtp, *rfp;
......@@ -509,7 +498,7 @@ static void lance_init_ring(struct net_device *dev)
if (i < 3 && ZERO)
printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]);
}
wbflush();
iob();
}
static int init_restart_lance(struct lance_private *lp)
......@@ -556,17 +545,16 @@ static int lance_rx(struct net_device *dev)
printk("[");
for (i = 0; i < RX_RING_SIZE; i++) {
if (i == lp->rx_new)
printk("%s",
ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X");
printk("%s", ib->brx_ring[i].rmd1_bits &
LE_R1_OWN ? "_" : "X");
else
printk("%s",
ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1");
printk("%s", ib->brx_ring[i].rmd1_bits &
LE_R1_OWN ? "." : "1");
}
printk("]");
}
#endif
for (rd = &ib->brx_ring[lp->rx_new];
!((bits = rd->rmd1_bits) & LE_R1_OWN);
rd = &ib->brx_ring[lp->rx_new]) {
......@@ -608,8 +596,8 @@ static int lance_rx(struct net_device *dev)
skb_reserve(skb, 2); /* 16 byte align */
skb_put(skb, len); /* make room */
cp_from_buf(skb->data,
(char *) lp->rx_buf_ptr_cpu[lp->rx_new],
cp_from_buf(lp->type, skb->data,
(char *)lp->rx_buf_ptr_cpu[lp->rx_new],
len);
skb->protocol = eth_type_trans(skb, dev);
......@@ -709,6 +697,14 @@ static void lance_tx(struct net_device *dev)
spin_unlock(&lp->lock);
}
static void lance_dma_merr_int(const int irq, void *dev_id,
struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
printk("%s: DMA error\n", dev->name);
}
static irqreturn_t
lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
{
......@@ -741,19 +737,8 @@ lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
lp->stats.rx_errors++;
if (csr0 & LE_C0_MERR) {
volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR);
printk("%s: Memory error, status %04x\n", dev->name, csr0);
if (int_stat & LANCE_DMA_MEMRDERR) {
printk("%s: DMA error\n", dev->name);
int_stat |= LANCE_DMA_MEMRDERR;
/*
* re-enable LANCE DMA
*/
*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
wbflush();
}
writereg(&ll->rdp, LE_C0_STOP);
lance_init_ring(dev);
......@@ -800,10 +785,30 @@ static int lance_open(struct net_device *dev)
netif_start_queue(dev);
/* Associate IRQ with lance_interrupt */
if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) {
printk("Lance: Can't get irq %d\n", dev->irq);
if (request_irq(dev->irq, &lance_interrupt, 0, "lance", dev)) {
printk("lance: Can't get IRQ %d\n", dev->irq);
return -EAGAIN;
}
if (lp->dma_irq >= 0) {
unsigned long flags;
if (request_irq(lp->dma_irq, &lance_dma_merr_int, 0,
"lance error", dev)) {
free_irq(dev->irq, dev);
printk("lance: Can't get DMA IRQ %d\n", lp->dma_irq);
return -EAGAIN;
}
spin_lock_irqsave(&ioasic_ssr_lock, flags);
fast_mb();
/* Enable I/O ASIC LANCE DMA. */
ioasic_write(IO_REG_SSR,
ioasic_read(IO_REG_SSR) | IO_SSR_LANCE_DMA_EN);
fast_mb();
spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
}
status = init_restart_lance(lp);
......@@ -827,7 +832,22 @@ static int lance_close(struct net_device *dev)
writereg(&ll->rap, LE_CSR0);
writereg(&ll->rdp, LE_C0_STOP);
free_irq(dev->irq, (void *) dev);
if (lp->dma_irq >= 0) {
unsigned long flags;
spin_lock_irqsave(&ioasic_ssr_lock, flags);
fast_mb();
/* Disable I/O ASIC LANCE DMA. */
ioasic_write(IO_REG_SSR,
ioasic_read(IO_REG_SSR) & ~IO_SSR_LANCE_DMA_EN);
fast_iob();
spin_unlock_irqrestore(&ioasic_ssr_lock, flags);
free_irq(lp->dma_irq, dev);
}
free_irq(dev->irq, dev);
/*
MOD_DEC_USE_COUNT;
*/
......@@ -886,7 +906,8 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
ib->btx_ring[entry].length = (-len);
ib->btx_ring[entry].misc = 0;
cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen);
cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data,
skblen);
/* Clear the slack of the packet, do I need this? */
/* For a firewall it's a good idea - AC */
......@@ -926,7 +947,7 @@ static void lance_load_multicast(struct net_device *dev)
volatile u16 *mcast_table = (u16 *) & ib->filter;
struct dev_mc_list *dmi = dev->mc_list;
char *addrs;
int i, j, bit, byte;
int i;
u32 crc;
/* set all multicast bits */
......@@ -952,7 +973,7 @@ static void lance_load_multicast(struct net_device *dev)
if (!(*addrs & 1))
continue;
crc = ether_crc_le(6, addrs);
crc = ether_crc_le(ETH_ALEN, addrs);
crc = crc >> 26;
mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf);
}
......@@ -1001,7 +1022,7 @@ static void lance_set_multicast_retry(unsigned long _opaque)
lance_set_multicast(dev);
}
static int __init dec_lance_init(struct net_device *dev, const int type)
static int __init dec_lance_init(const int type, const int slot)
{
static unsigned version_printed;
struct net_device *dev;
......@@ -1013,25 +1034,29 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
#ifndef CONFIG_TC
system_base = KN01_LANCE_BASE;
#else
int slot;
#endif
if (dec_lance_debug && version_printed++ == 0)
printk(version);
dev = init_etherdev(0, sizeof(struct lance_private));
dev = init_etherdev(NULL, sizeof(struct lance_private));
if (!dev)
return -ENOMEM;
SET_MODULE_OWNER(dev);
/* init_etherdev ensures the data structures used by the LANCE are aligned. */
/*
* init_etherdev ensures the data structures used by the LANCE
* are aligned.
*/
lp = (struct lance_private *) dev->priv;
spin_lock_init(&lp->lock);
lp->type = type;
lp->slot = slot;
switch (type) {
#ifdef CONFIG_TC
case ASIC_LANCE:
dev->base_addr = system_base + LANCE;
dev->base_addr = system_base + IOASIC_LANCE;
/* buffer space for the on-board LANCE shared memory */
/*
......@@ -1039,78 +1064,101 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
*/
dev->mem_start = KSEG1ADDR(0x00020000);
dev->mem_end = dev->mem_start + 0x00020000;
dev->irq = ETHER;
esar_base = system_base + ESAR;
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
esar_base = system_base + IOASIC_ESAR;
/* Workaround crash with booting KN04 2.1k from Disk */
memset(dev->mem_start, 0, dev->mem_end - dev->mem_start);
memset((void *)dev->mem_start, 0,
dev->mem_end - dev->mem_start);
/*
* setup the pointer arrays, this sucks [tm] :-(
*/
for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU
+ 2 * i * RX_BUFF_SIZE);
lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
+ i * RX_BUFF_SIZE);
lp->rx_buf_ptr_cpu[i] =
(char *)(dev->mem_start + BUF_OFFSET_CPU +
2 * i * RX_BUFF_SIZE);
lp->rx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
}
for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU
+ 2 * RX_RING_SIZE * RX_BUFF_SIZE
+ 2 * i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
+ RX_RING_SIZE * RX_BUFF_SIZE
+ i * TX_BUFF_SIZE);
lp->tx_buf_ptr_cpu[i] =
(char *)(dev->mem_start + BUF_OFFSET_CPU +
2 * RX_RING_SIZE * RX_BUFF_SIZE +
2 * i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
}
/*
* setup and enable IOASIC LANCE DMA
*/
lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P);
*(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3;
*(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16);
wbflush();
/* Setup I/O ASIC LANCE DMA. */
lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR];
ioasic_write(IO_REG_LANCE_DMA_P,
PHYSADDR(dev->mem_start) << 3);
break;
case PMAD_LANCE:
slot = search_tc_card("PMAD-AA");
claim_tc_card(slot);
dev->mem_start = get_tc_base_addr(slot);
dev->base_addr = dev->mem_start + 0x100000;
dev->irq = get_tc_irq_nr(slot);
esar_base = dev->mem_start + 0x1c0002;
lp->dma_irq = -1;
for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_buf_ptr_cpu[i] =
(char *)(dev->mem_start + BUF_OFFSET_CPU +
i * RX_BUFF_SIZE);
lp->rx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
}
for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_buf_ptr_cpu[i] =
(char *)(dev->mem_start + BUF_OFFSET_CPU +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
}
break;
#endif
case PMAX_LANCE:
dev->irq = ETHER;
dev->irq = dec_interrupt[DEC_IRQ_LANCE];
dev->base_addr = KN01_LANCE_BASE;
dev->mem_start = KN01_LANCE_BASE + 0x01000000;
esar_base = KN01_RTC_BASE + 1;
lp->dma_irq = -1;
/*
* setup the pointer arrays, this sucks [tm] :-(
*/
for (i = 0; i < RX_RING_SIZE; i++) {
lp->rx_buf_ptr_cpu[i] =
(char *) (dev->mem_start + BUF_OFFSET_CPU
+ 2 * i * RX_BUFF_SIZE);
(char *)(dev->mem_start + BUF_OFFSET_CPU +
2 * i * RX_BUFF_SIZE);
lp->rx_buf_ptr_lnc[i] =
(char *) (BUF_OFFSET_LNC
+ i * RX_BUFF_SIZE);
(char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE);
}
for (i = 0; i < TX_RING_SIZE; i++) {
lp->tx_buf_ptr_cpu[i] =
(char *) (dev->mem_start + BUF_OFFSET_CPU
+ 2 * RX_RING_SIZE * RX_BUFF_SIZE
+ 2 * i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC
+ RX_RING_SIZE * RX_BUFF_SIZE
+ i * TX_BUFF_SIZE);
(char *)(dev->mem_start + BUF_OFFSET_CPU +
2 * RX_RING_SIZE * RX_BUFF_SIZE +
2 * i * TX_BUFF_SIZE);
lp->tx_buf_ptr_lnc[i] =
(char *)(BUF_OFFSET_LNC +
RX_RING_SIZE * RX_BUFF_SIZE +
i * TX_BUFF_SIZE);
}
break;
default:
printk("declance_init called with unknown type\n");
ret = -ENODEV;
......@@ -1140,6 +1188,9 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
}
}
lp->next = root_lance_dev;
root_lance_dev = dev;
/* Copy the ethernet address to the device structure, later to the
* lance initialization block so the lance gets it every time it's
* (re)initialized.
......@@ -1162,7 +1213,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
printk(" irq = %d\n", dev->irq);
lp->dev = dev;
dev->open = &lance_open;
dev->stop = &lance_close;
dev->hard_start_xmit = &lance_start_xmit;
......@@ -1174,8 +1224,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
/* lp->ll is the location of the registers for lance card */
lp->ll = ll;
lp->name = lancestr;
/* busmaster_regval (CSR3) should be zero according to the PMAD-AA
* specification.
*/
......@@ -1183,8 +1231,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
dev->dma = 0;
ether_setup(dev);
/* We cannot sleep if the chip is busy during a
* multicast list update event, because such events
* can occur from interrupts (ex. IPv6). So we
......@@ -1194,11 +1240,6 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
lp->multicast_timer.data = (unsigned long) dev;
lp->multicast_timer.function = &lance_set_multicast_retry;
#ifdef MODULE
dev->ifindex = dev_new_index();
lp->next_module = root_lance_dev;
root_lance_dev = lp;
#endif
return 0;
err_out:
......@@ -1211,61 +1252,51 @@ static int __init dec_lance_init(struct net_device *dev, const int type)
/* Find all the lance cards on the system and initialize them */
static int __init dec_lance_probe(void)
{
struct net_device *dev = NULL;
static int called;
#ifdef MODULE
root_lance_dev = NULL;
#endif
int count = 0;
/* Scan slots for PMAD-AA cards first. */
#ifdef CONFIG_TC
int slot = -1;
if (TURBOCHANNEL) {
if (IOASIC && !called) {
called = 1;
type = ASIC_LANCE;
} else {
if ((slot = search_tc_card("PMAD-AA")) >= 0) {
type = PMAD_LANCE;
} else {
return -ENODEV;
}
int slot;
while ((slot = search_tc_card("PMAD-AA")) >= 0) {
if (dec_lance_init(PMAD_LANCE, slot) < 0)
break;
count++;
}
} else {
if (!called) {
called = 1;
type = PMAX_LANCE;
} else {
return -ENODEV;
}
#endif
/* Then handle onboard devices. */
if (dec_interrupt[DEC_IRQ_LANCE] >= 0) {
if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) {
#ifdef CONFIG_TC
if (dec_lance_init(ASIC_LANCE, -1) >= 0)
count++;
#endif
} else if (!TURBOCHANNEL) {
if (dec_lance_init(PMAX_LANCE, -1) >= 0)
count++;
}
#else
if (!called && !TURBOCHANNEL) {
called = 1;
type = PMAX_LANCE;
} else {
return -ENODEV;
}
#endif
return dec_lance_init(dev, type);
return (count > 0) ? 0 : -ENODEV;
}
static void __exit dec_lance_cleanup(void)
{
#ifdef MODULE
struct lance_private *lp;
while (root_lance_dev) {
lp = root_lance_dev->next_module;
struct net_device *dev = root_lance_dev;
struct lance_private *lp = (struct lance_private *)dev->priv;
unregister_netdev(root_lance_dev->dev);
kfree(root_lance_dev->dev);
root_lance_dev = lp;
#ifdef CONFIG_TC
if (lp->slot >= 0)
release_tc_card(lp->slot);
#endif
root_lance_dev = lp->next;
unregister_netdev(dev);
kfree(dev);
}
#endif /* MODULE */
}
module_init(dec_lance_probe);
......
......@@ -3424,10 +3424,6 @@ e100_ethtool_set_settings(struct net_device *dev, struct ifreq *ifr)
int ethtool_new_speed_duplex;
struct ethtool_cmd ecmd;
if (!capable(CAP_NET_ADMIN)) {
return -EPERM;
}
bdp = dev->priv;
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) {
return -EFAULT;
......@@ -3545,8 +3541,6 @@ e100_ethtool_gregs(struct net_device *dev, struct ifreq *ifr)
void *addr = ifr->ifr_data;
u16 mdi_reg;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
bdp = dev->priv;
if(copy_from_user(&regs, addr, sizeof(regs)))
......@@ -3574,9 +3568,6 @@ e100_ethtool_nway_rst(struct net_device *dev, struct ifreq *ifr)
{
struct e100_private *bdp;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
bdp = dev->priv;
if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) &&
......@@ -3632,9 +3623,6 @@ e100_ethtool_eeprom(struct net_device *dev, struct ifreq *ifr)
void *ptr;
u8 *eeprom_data_bytes = (u8 *)eeprom_data;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
bdp = dev->priv;
if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd)))
......@@ -3912,9 +3900,6 @@ e100_ethtool_wol(struct net_device *dev, struct ifreq *ifr)
struct ethtool_wolinfo wolinfo;
int res = 0;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
bdp = dev->priv;
if (copy_from_user(&wolinfo, ifr->ifr_data, sizeof (wolinfo))) {
......
......@@ -1289,8 +1289,6 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
}
case ETHTOOL_SSET: {
struct ethtool_cmd ecmd;
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&ecmd, addr, sizeof(ecmd)))
return -EFAULT;
return e1000_ethtool_sset(adapter, &ecmd);
......@@ -1363,8 +1361,6 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
return 0;
}
case ETHTOOL_NWAY_RST: {
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(netif_running(netdev)) {
e1000_down(adapter);
e1000_up(adapter);
......@@ -1393,8 +1389,6 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
}
case ETHTOOL_SWOL: {
struct ethtool_wolinfo wol;
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&wol, addr, sizeof(wol)) != 0)
return -EFAULT;
return e1000_ethtool_swol(adapter, &wol);
......@@ -1436,9 +1430,6 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
case ETHTOOL_SEEPROM: {
struct ethtool_eeprom eeprom;
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&eeprom, addr, sizeof(eeprom)))
return -EFAULT;
......@@ -1470,9 +1461,6 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
} test = { {ETHTOOL_TEST} };
int err;
if(!capable(CAP_NET_ADMIN))
return -EPERM;
if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test)))
return -EFAULT;
......
......@@ -116,6 +116,7 @@ static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
......@@ -670,7 +671,7 @@ static int __devinit speedo_found1(struct pci_dev *pdev,
if (tx_ring_space == NULL)
return -1;
dev = init_etherdev(NULL, sizeof(struct speedo_private));
dev = alloc_etherdev(sizeof(struct speedo_private));
if (dev == NULL) {
printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n");
pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma);
......@@ -687,6 +688,10 @@ static int __devinit speedo_found1(struct pci_dev *pdev,
else
option = 0;
rtnl_lock();
if (dev_alloc_name(dev, dev->name) < 0)
goto err_free_unlock;
/* Read the station address EEPROM before doing the reset.
Nominally his should even be done before accepting the device, but
then we wouldn't have a device name with which to report the error.
......@@ -881,7 +886,16 @@ static int __devinit speedo_found1(struct pci_dev *pdev,
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &speedo_ioctl;
if (register_netdevice(dev))
goto err_free_unlock;
rtnl_unlock();
return 0;
err_free_unlock:
rtnl_unlock();
kfree(dev);
return -1;
}
static void do_slow_command(struct net_device *dev, int cmd)
......
......@@ -3,8 +3,6 @@
* Author: MontaVista Software, Inc.
* stevel@mvista.com or source@mvista.com
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
......@@ -18,8 +16,6 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
* Ethernet driver for the MIPS GT96100 Advanced Communication Controller.
*
* Revision history
......@@ -32,18 +28,7 @@
* gt96100_cleanup_module(), and other general code cleanups
* <stevel@mvista.com>.
*/
#ifndef __OPTIMIZE__
#error You must compile this file with the correct options!
#error See the last lines of the source file.
#error You must compile this driver with "-O".
#endif
#ifndef __mips__
#error This driver only works with MIPS architectures!
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
......
......@@ -5,7 +5,7 @@
*
* Driver for SGI's IOC3 based Ethernet cards as found in the PCI card.
*
* Copyright (C) 1999, 2000, 2001 Ralf Baechle
* Copyright (C) 1999, 2000, 2001, 2003 Ralf Baechle
* Copyright (C) 1995, 1999, 2000, 2001 by Silicon Graphics, Inc.
*
* References:
......@@ -36,7 +36,7 @@
#include <linux/pci.h>
#include <linux/crc32.h>
#ifdef CONFIG_SERIAL
#ifdef CONFIG_SERIAL_8250
#include <linux/serial.h>
#include <asm/serial.h>
#define IOC3_BAUD (22000000 / (3*16))
......@@ -377,82 +377,6 @@ static void ioc3_get_eaddr_nic(struct ioc3_private *ip)
ip->dev->dev_addr[i - 2] = nic[i];
}
#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
/*
* Get the ether-address on SN1 nodes
*/
static void ioc3_get_eaddr_sn(struct ioc3_private *ip)
{
int ibrick_mac_addr_get(nasid_t, char *);
struct ioc3 *ioc3 = ip->regs;
nasid_t nasid_of_ioc3;
char io7eaddr[20];
long mac;
int err_val;
/*
* err_val = ibrick_mac_addr_get(get_nasid(), io7eaddr );
*
* BAD!! The above call uses get_nasid() and assumes that
* the ioc3 pointed to by struct ioc3 is hooked up to the
* cbrick that we're running on. The proper way to make this call
* is to figure out which nasid the ioc3 is connected to
* and use that to call ibrick_mac_addr_get. Below is
* a hack to do just that.
*/
/*
* Get the nasid of the ioc3 from the ioc3's base addr.
* FIXME: the 8 at the end assumes we're in memory mode,
* not node mode (for that, we'd change it to a 9).
* Is there a call to extract this info from a physical
* addr somewhere in an sn header file already? If so,
* we should probably use that, or restructure this routine
* to use pci_dev and generic numa nodeid getting stuff.
*/
nasid_of_ioc3 = (((unsigned long)ioc3 >> 33) & ~(-1 << 8));
err_val = ibrick_mac_addr_get(nasid_of_ioc3, io7eaddr );
if (err_val) {
/* Couldn't read the eeprom; try OSLoadOptions. */
printk("WARNING: ibrick_mac_addr_get failed: %d\n", err_val);
/* this is where we hardwire the mac address
* 1st ibrick had 08:00:69:11:34:75
* 2nd ibrick had 08:00:69:11:35:35
*
* Eagan Machines:
* mankato1 08:00:69:11:BE:95
* warroad 08:00:69:11:bd:60
* duron 08:00:69:11:34:60
*
* an easy way to get the mac address is to hook
* up an ip35, then from L1 do 'cti serial'
* and then look for MAC line XXX THIS DOESN"T QUITE WORK!!
*/
printk("ioc3_get_eaddr: setting ethernet address to:\n -----> ");
ip->dev->dev_addr[0] = 0x8;
ip->dev->dev_addr[1] = 0x0;
ip->dev->dev_addr[2] = 0x69;
ip->dev->dev_addr[3] = 0x11;
ip->dev->dev_addr[4] = 0x34;
ip->dev->dev_addr[5] = 0x60;
}
else {
long simple_strtol(const char *,char **,unsigned int);
mac = simple_strtol(io7eaddr, (char **)0, 16);
ip->dev->dev_addr[0] = (mac >> 40) & 0xff;
ip->dev->dev_addr[1] = (mac >> 32) & 0xff;
ip->dev->dev_addr[2] = (mac >> 24) & 0xff;
ip->dev->dev_addr[3] = (mac >> 16) & 0xff;
ip->dev->dev_addr[4] = (mac >> 8) & 0xff;
ip->dev->dev_addr[5] = mac & 0xff;
}
}
#endif
/*
* Ok, this is hosed by design. It's necessary to know what machine the
* NIC is in in order to know how to read the NIC address. We also have
......@@ -460,30 +384,15 @@ static void ioc3_get_eaddr_sn(struct ioc3_private *ip)
*/
static void ioc3_get_eaddr(struct ioc3_private *ip)
{
void (*do_get_eaddr)(struct ioc3_private *ip) = NULL;
int i;
/*
* We should also use this code for PCI cards, no matter what host
* machine but how to know that we're a PCI card?
*/
#ifdef CONFIG_SGI_IP27
do_get_eaddr = ioc3_get_eaddr_nic;
#endif
#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2)
do_get_eaddr = ioc3_get_eaddr_sn;
#endif
if (!do_get_eaddr) {
printk(KERN_ERR "Don't know how to read MAC address of this "
"IOC3 NIC\n");
return;
}
ioc3_get_eaddr_nic(ip);
printk("Ethernet address is ");
for (i = 0; i < 6; i++) {
printk("%02x", ip->dev->dev_addr[i]);
if (i < 7)
if (i < 5)
printk(":");
}
printk(".\n");
......@@ -588,7 +497,7 @@ ioc3_rx(struct ioc3_private *ip)
ip->stats.rx_frame_errors++;
next:
ip->rx_skbs[n_entry] = new_skb;
rxr[n_entry] = cpu_to_be32((0xa5UL << 56) |
rxr[n_entry] = cpu_to_be64((0xa5UL << 56) |
((unsigned long) rxb & TO_PHYS_MASK));
rxb->w0 = 0; /* Clear valid flag */
n_entry = (n_entry + 1) & 511; /* Update erpir */
......@@ -1550,7 +1459,7 @@ static int __devinit ioc3_probe(struct pci_dev *pdev,
}
ip->regs = ioc3;
#ifdef CONFIG_SERIAL
#ifdef CONFIG_SERIAL_8250
ioc3_serial_probe(pdev, ioc3);
#endif
......@@ -1613,6 +1522,7 @@ static void __devexit ioc3_remove_one (struct pci_dev *pdev)
struct ioc3_private *ip = dev->priv;
struct ioc3 *ioc3 = ip->regs;
unregister_netdev(dev);
iounmap(ioc3);
pci_release_regions(pdev);
kfree(dev);
......@@ -1844,9 +1754,6 @@ static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EFAULT;
return 0;
} else if (ecmd.cmd == ETHTOOL_SSET) {
if (!capable(CAP_NET_ADMIN))
return -EPERM;
/* Verify the settings we care about. */
if (ecmd.autoneg != AUTONEG_ENABLE &&
ecmd.autoneg != AUTONEG_DISABLE)
......
......@@ -289,6 +289,10 @@ config TOSHIBA_FIR
<file:Documentation/modules.txt>.
The module will be called donauboe.
config AU1000_FIR
tristate "Alchemy Au1000 SIR/FIR"
depends on MIPS_AU1000 && IRDA
config SMC_IRCC_OLD
tristate "SMC IrCC (old driver) (EXPERIMENTAL)"
depends on EXPERIMENTAL && IRDA
......
......@@ -28,6 +28,7 @@ obj-$(CONFIG_LITELINK_DONGLE) += litelink.o
obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin.o
obj-$(CONFIG_EP7211_IR) += ep7211_ir.o
obj-$(CONFIG_MCP2120_DONGLE) += mcp2120.o
obj-$(CONFIG_AU1000_FIR) += au1k_ir.o
obj-$(CONFIG_ACT200L_DONGLE) += act200l.o
obj-$(CONFIG_MA600_DONGLE) += ma600.o
# New SIR drivers
......
/*
*
* Alchemy Semi Au1000 IrDA driver
*
* Copyright 2001 MontaVista Software Inc.
* Author: MontaVista Software, Inc.
* ppopov@mvista.com or source@mvista.com
*
* ########################################################################
*
* This program is free software; you can distribute it and/or modify it
* under the terms of the GNU General Public License (Version 2) as
* published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*
* ########################################################################
*
*
*/
#ifndef __mips__
#error This driver only works with MIPS architectures!
#endif
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/au1000.h>
#include <asm/pb1000.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
#include <net/irda/wrapper.h>
#include <net/irda/irda_device.h>
#include "net/irda/au1000_ircc.h"
static int au1k_irda_net_init(struct net_device *);
static int au1k_irda_start(struct net_device *);
static int au1k_irda_stop(struct net_device *dev);
static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *);
static int au1k_irda_rx(struct net_device *);
static void au1k_irda_interrupt(int, void *, struct pt_regs *);
static void au1k_tx_timeout(struct net_device *);
static struct net_device_stats *au1k_irda_stats(struct net_device *);
static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int);
static int au1k_irda_set_speed(struct net_device *dev, int speed);
static void *dma_alloc(size_t, dma_addr_t *);
static void dma_free(void *, size_t);
static int qos_mtt_bits = 0x07; /* 1 ms or more */
static struct net_device *ir_devs[NUM_IR_IFF];
static char version[] __devinitdata =
"au1k_ircc:1.0 ppopov@mvista.com\n";
#define RUN_AT(x) (jiffies + (x))
static spinlock_t ir_lock = SPIN_LOCK_UNLOCKED;
/*
* IrDA peripheral bug. You have to read the register
* twice to get the right value.
*/
u32 read_ir_reg(u32 addr)
{
readl(addr);
return readl(addr);
}
/*
* Buffer allocation/deallocation routines. The buffer descriptor returned
* has the virtual and dma address of a buffer suitable for
* both, receive and transmit operations.
*/
static db_dest_t *GetFreeDB(struct au1k_private *aup)
{
db_dest_t *pDB;
pDB = aup->pDBfree;
if (pDB) {
aup->pDBfree = pDB->pnext;
}
return pDB;
}
static void ReleaseDB(struct au1k_private *aup, db_dest_t *pDB)
{
db_dest_t *pDBfree = aup->pDBfree;
if (pDBfree)
pDBfree->pnext = pDB;
aup->pDBfree = pDB;
}
/*
DMA memory allocation, derived from pci_alloc_consistent.
However, the Au1000 data cache is coherent (when programmed
so), therefore we return KSEG0 address, not KSEG1.
*/
static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
{
void *ret;
int gfp = GFP_ATOMIC | GFP_DMA;
ret = (void *) __get_free_pages(gfp, get_order(size));
if (ret != NULL) {
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret);
ret = KSEG0ADDR(ret);
}
return ret;
}
static void dma_free(void *vaddr, size_t size)
{
vaddr = KSEG0ADDR(vaddr);
free_pages((unsigned long) vaddr, get_order(size));
}
static void
setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base)
{
int i;
for (i=0; i<NUM_IR_DESC; i++) {
aup->rx_ring[i] = (volatile ring_dest_t *)
(rx_base + sizeof(ring_dest_t)*i);
}
for (i=0; i<NUM_IR_DESC; i++) {
aup->tx_ring[i] = (volatile ring_dest_t *)
(tx_base + sizeof(ring_dest_t)*i);
}
}
/*
* Device has already been stopped at this point.
*/
static void au1k_irda_net_uninit(struct net_device *dev)
{
dev->hard_start_xmit = NULL;
dev->open = NULL;
dev->stop = NULL;
dev->do_ioctl = NULL;
dev->get_stats = NULL;
dev->priv = NULL;
}
static int au1k_irda_init(void)
{
static unsigned version_printed = 0;
struct net_device *dev;
int err;
if (version_printed++ == 0) printk(version);
rtnl_lock();
dev = dev_alloc("irda%d", &err);
if (dev) {
dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */
dev->init = au1k_irda_net_init;
dev->uninit = au1k_irda_net_uninit;
err = register_netdevice(dev);
if (err)
kfree(dev);
else
ir_devs[0] = dev;
printk(KERN_INFO "IrDA: Registered device %s\n", dev->name);
}
rtnl_unlock();
return err;
}
static int au1k_irda_init_iobuf(iobuff_t *io, int size)
{
io->head = kmalloc(size, GFP_KERNEL);
if (io->head != NULL) {
io->truesize = size;
io->in_frame = FALSE;
io->state = OUTSIDE_FRAME;
io->data = io->head;
}
return io->head ? 0 : -ENOMEM;
}
static int au1k_irda_net_init(struct net_device *dev)
{
struct au1k_private *aup = NULL;
int i, retval = 0, err;
db_dest_t *pDB, *pDBfree;
unsigned long temp;
dev->priv = kmalloc(sizeof(struct au1k_private), GFP_KERNEL);
if (dev->priv == NULL) {
retval = -ENOMEM;
goto out;
}
memset(dev->priv, 0, sizeof(struct au1k_private));
aup = dev->priv;
err = au1k_irda_init_iobuf(&aup->rx_buff, 14384);
if (err)
goto out;
dev->open = au1k_irda_start;
dev->hard_start_xmit = au1k_irda_hard_xmit;
dev->stop = au1k_irda_stop;
dev->get_stats = au1k_irda_stats;
dev->do_ioctl = au1k_irda_ioctl;
dev->tx_timeout = au1k_tx_timeout;
irda_device_setup(dev);
irda_init_max_qos_capabilies(&aup->qos);
/* The only value we must override it the baudrate */
aup->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000 |(IR_4000000 << 8);
aup->qos.min_turn_time.bits = qos_mtt_bits;
irda_qos_bits_to_value(&aup->qos);
/* Tx ring follows rx ring + 512 bytes */
/* we need a 1k aligned buffer */
aup->rx_ring[0] = (ring_dest_t *)
dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp);
/* allocate the data buffers */
aup->db[0].vaddr =
(void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp);
if (!aup->db[0].vaddr || !aup->rx_ring[0]) {
retval = -ENOMEM;
goto out;
}
setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512);
pDBfree = NULL;
pDB = aup->db;
for (i=0; i<(2*NUM_IR_DESC); i++) {
pDB->pnext = pDBfree;
pDBfree = pDB;
pDB->vaddr =
(u32 *)((unsigned)aup->db[0].vaddr + MAX_BUF_SIZE*i);
pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
pDB++;
}
aup->pDBfree = pDBfree;
/* attach a data buffer to each descriptor */
for (i=0; i<NUM_IR_DESC; i++) {
pDB = GetFreeDB(aup);
if (!pDB) goto out;
aup->rx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
aup->rx_db_inuse[i] = pDB;
}
for (i=0; i<NUM_IR_DESC; i++) {
pDB = GetFreeDB(aup);
if (!pDB) goto out;
aup->tx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff);
aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff);
aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff);
aup->tx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff);
aup->tx_ring[i]->count_0 = 0;
aup->tx_ring[i]->count_1 = 0;
aup->tx_ring[i]->flags = 0;
aup->tx_db_inuse[i] = pDB;
}
return 0;
out:
if (aup->db[0].vaddr)
dma_free((void *)aup->db[0].vaddr,
MAX_BUF_SIZE * 2*NUM_IR_DESC);
if (aup->rx_ring[0])
kfree((void *)aup->rx_ring[0]);
if (aup->rx_buff.head)
kfree(aup->rx_buff.head);
if (dev->priv != NULL)
kfree(dev->priv);
unregister_netdevice(dev);
printk(KERN_ERR "%s: au1k_init_module failed. Returns %d\n",
dev->name, retval);
return retval;
}
static int au1k_init(struct net_device *dev)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
int i;
u32 control;
u32 ring_address;
/* bring the device out of reset */
control = 0xe; /* coherent, clock enable, one half system clock */
#ifndef CONFIG_CPU_LITTLE_ENDIAN
control |= 1;
#endif
aup->tx_head = 0;
aup->tx_tail = 0;
aup->rx_head = 0;
for (i=0; i<NUM_IR_DESC; i++) {
aup->rx_ring[i]->flags = AU_OWN;
}
writel(control, IR_INTERFACE_CONFIG);
au_sync_delay(10);
writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE); /* disable PHY */
au_sync_delay(1);
writel(MAX_BUF_SIZE, IR_MAX_PKT_LEN);
ring_address = (u32)virt_to_phys((void *)aup->rx_ring[0]);
writel(ring_address >> 26, IR_RING_BASE_ADDR_H);
writel((ring_address >> 10) & 0xffff, IR_RING_BASE_ADDR_L);
writel(RING_SIZE_64<<8 | RING_SIZE_64<<12, IR_RING_SIZE);
writel(1<<2 | IR_ONE_PIN, IR_CONFIG_2); /* 48MHz */
writel(0, IR_RING_ADDR_CMPR);
au1k_irda_set_speed(dev, 9600);
return 0;
}
static int au1k_irda_start(struct net_device *dev)
{
int retval;
char hwname[32];
struct au1k_private *aup = (struct au1k_private *) dev->priv;
MOD_INC_USE_COUNT;
if ((retval = au1k_init(dev))) {
printk(KERN_ERR "%s: error in au1k_init\n", dev->name);
MOD_DEC_USE_COUNT;
return retval;
}
if ((retval = request_irq(AU1000_IRDA_TX_INT, &au1k_irda_interrupt,
0, dev->name, dev))) {
printk(KERN_ERR "%s: unable to get IRQ %d\n",
dev->name, dev->irq);
MOD_DEC_USE_COUNT;
return retval;
}
if ((retval = request_irq(AU1000_IRDA_RX_INT, &au1k_irda_interrupt,
0, dev->name, dev))) {
free_irq(AU1000_IRDA_TX_INT, dev);
printk(KERN_ERR "%s: unable to get IRQ %d\n",
dev->name, dev->irq);
MOD_DEC_USE_COUNT;
return retval;
}
/* Give self a hardware name */
sprintf(hwname, "Au1000 SIR/FIR");
aup->irlap = irlap_open(dev, &aup->qos, hwname);
netif_start_queue(dev);
writel(read_ir_reg(IR_CONFIG_2) | 1<<8, IR_CONFIG_2); /* int enable */
aup->timer.expires = RUN_AT((3*HZ));
aup->timer.data = (unsigned long)dev;
return 0;
}
static int au1k_irda_stop(struct net_device *dev)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
/* disable interrupts */
writel(read_ir_reg(IR_CONFIG_2) & ~(1<<8), IR_CONFIG_2);
writel(0, IR_CONFIG_1);
writel(0, IR_INTERFACE_CONFIG); /* disable clock */
au_sync();
if (aup->irlap) {
irlap_close(aup->irlap);
aup->irlap = NULL;
}
netif_stop_queue(dev);
del_timer(&aup->timer);
/* disable the interrupt */
free_irq(AU1000_IRDA_TX_INT, dev);
free_irq(AU1000_IRDA_RX_INT, dev);
MOD_DEC_USE_COUNT;
return 0;
}
static void __exit au1k_irda_exit(void)
{
struct net_device *dev = ir_devs[0];
struct au1k_private *aup = (struct au1k_private *) dev->priv;
if (!dev) {
printk(KERN_ERR "au1k_ircc no dev found\n");
return;
}
if (aup->db[0].vaddr) {
dma_free((void *)aup->db[0].vaddr,
MAX_BUF_SIZE * 2*NUM_IR_DESC);
aup->db[0].vaddr = 0;
}
if (aup->rx_ring[0]) {
dma_free((void *)aup->rx_ring[0],
2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)));
aup->rx_ring[0] = 0;
}
rtnl_lock();
unregister_netdevice(dev);
rtnl_unlock();
ir_devs[0] = 0;
}
static inline void
update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
struct net_device_stats *ps = &aup->stats;
ps->tx_packets++;
ps->tx_bytes += pkt_len;
if (status & IR_TX_ERROR) {
ps->tx_errors++;
ps->tx_aborted_errors++;
}
}
static void au1k_tx_ack(struct net_device *dev)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
volatile ring_dest_t *ptxd;
ptxd = aup->tx_ring[aup->tx_tail];
while (!(ptxd->flags & AU_OWN) && (aup->tx_tail != aup->tx_head)) {
update_tx_stats(dev, ptxd->flags,
ptxd->count_1<<8 | ptxd->count_0);
ptxd->count_0 = 0;
ptxd->count_1 = 0;
au_sync();
aup->tx_tail = (aup->tx_tail + 1) & (NUM_IR_DESC - 1);
ptxd = aup->tx_ring[aup->tx_tail];
if (aup->tx_full) {
aup->tx_full = 0;
netif_wake_queue(dev);
}
}
if (aup->tx_tail == aup->tx_head) {
if (aup->newspeed) {
au1k_irda_set_speed(dev, aup->newspeed);
aup->newspeed = 0;
}
else {
writel(read_ir_reg(IR_CONFIG_1) & ~IR_TX_ENABLE,
IR_CONFIG_1);
au_sync();
writel(read_ir_reg(IR_CONFIG_1) | IR_RX_ENABLE,
IR_CONFIG_1);
writel(0, IR_RING_PROMPT);
au_sync();
}
}
}
/*
* Au1000 transmit routine.
*/
static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
int speed = irda_get_next_speed(skb);
volatile ring_dest_t *ptxd;
u32 len;
u32 flags;
db_dest_t *pDB;
if (speed != aup->speed && speed != -1) {
aup->newspeed = speed;
}
if ((skb->len == 0) && (aup->newspeed)) {
if (aup->tx_tail == aup->tx_head) {
au1k_irda_set_speed(dev, speed);
aup->newspeed = 0;
}
dev_kfree_skb(skb);
return 0;
}
ptxd = aup->tx_ring[aup->tx_head];
flags = ptxd->flags;
if (flags & AU_OWN) {
printk(KERN_INFO "%s: tx_full\n", dev->name);
netif_stop_queue(dev);
aup->tx_full = 1;
return 1;
}
else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) {
printk(KERN_INFO "%s: tx_full\n", dev->name);
netif_stop_queue(dev);
aup->tx_full = 1;
return 1;
}
pDB = aup->tx_db_inuse[aup->tx_head];
#if 0
if (read_ir_reg(IR_RX_BYTE_CNT) != 0) {
printk("tx warning: rx byte cnt %x\n",
read_ir_reg(IR_RX_BYTE_CNT));
}
#endif
if (aup->speed == 4000000) {
/* FIR */
memcpy((void *)pDB->vaddr, skb->data, skb->len);
ptxd->count_0 = skb->len & 0xff;
ptxd->count_1 = (skb->len >> 8) & 0xff;
}
else {
/* SIR */
len = async_wrap_skb(skb, (u8 *)pDB->vaddr, MAX_BUF_SIZE);
ptxd->count_0 = len & 0xff;
ptxd->count_1 = (len >> 8) & 0xff;
ptxd->flags |= IR_DIS_CRC;
}
ptxd->flags |= AU_OWN;
au_sync();
writel(read_ir_reg(IR_CONFIG_1) | IR_TX_ENABLE, IR_CONFIG_1);
writel(0, IR_RING_PROMPT);
au_sync();
dev_kfree_skb(skb);
aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1);
dev->trans_start = jiffies;
return 0;
}
static inline void
update_rx_stats(struct net_device *dev, u32 status, u32 count)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
struct net_device_stats *ps = &aup->stats;
ps->rx_packets++;
if (status & IR_RX_ERROR) {
ps->rx_errors++;
if (status & (IR_PHY_ERROR|IR_FIFO_OVER))
ps->rx_missed_errors++;
if (status & IR_MAX_LEN)
ps->rx_length_errors++;
if (status & IR_CRC_ERROR)
ps->rx_crc_errors++;
}
else
ps->rx_bytes += count;
}
/*
* Au1000 receive routine.
*/
static int au1k_irda_rx(struct net_device *dev)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
struct sk_buff *skb;
volatile ring_dest_t *prxd;
u32 flags, count;
db_dest_t *pDB;
prxd = aup->rx_ring[aup->rx_head];
flags = prxd->flags;
while (!(flags & AU_OWN)) {
pDB = aup->rx_db_inuse[aup->rx_head];
count = prxd->count_1<<8 | prxd->count_0;
if (!(flags & IR_RX_ERROR)) {
/* good frame */
update_rx_stats(dev, flags, count);
skb=alloc_skb(count+1,GFP_ATOMIC);
if (skb == NULL) {
aup->stats.rx_dropped++;
continue;
}
skb_reserve(skb, 1);
if (aup->speed == 4000000)
skb_put(skb, count);
else
skb_put(skb, count-2);
memcpy(skb->data, (void *)pDB->vaddr, count-2);
skb->dev = dev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
prxd->count_0 = 0;
prxd->count_1 = 0;
}
prxd->flags |= AU_OWN;
aup->rx_head = (aup->rx_head + 1) & (NUM_IR_DESC - 1);
writel(0, IR_RING_PROMPT);
au_sync();
/* next descriptor */
prxd = aup->rx_ring[aup->rx_head];
flags = prxd->flags;
dev->last_rx = jiffies;
}
return 0;
}
void au1k_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
if (dev == NULL) {
printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
return;
}
writel(0, IR_INT_CLEAR); /* ack irda interrupts */
au1k_irda_rx(dev);
au1k_tx_ack(dev);
}
/*
* The Tx ring has been full longer than the watchdog timeout
* value. The transmitter must be hung?
*/
static void au1k_tx_timeout(struct net_device *dev)
{
u32 speed;
struct au1k_private *aup = (struct au1k_private *) dev->priv;
printk(KERN_ERR "%s: tx timeout\n", dev->name);
speed = aup->speed;
aup->speed = 0;
au1k_irda_set_speed(dev, speed);
aup->tx_full = 0;
netif_wake_queue(dev);
}
/*
* Set the IrDA communications speed.
*/
static int
au1k_irda_set_speed(struct net_device *dev, int speed)
{
unsigned long flags;
struct au1k_private *aup = (struct au1k_private *) dev->priv;
u32 control;
int ret = 0, timeout = 10, i;
volatile ring_dest_t *ptxd;
if (speed == aup->speed)
return ret;
spin_lock_irqsave(&ir_lock, flags);
/* disable PHY first */
writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE);
/* disable RX/TX */
writel(read_ir_reg(IR_CONFIG_1) & ~(IR_RX_ENABLE|IR_TX_ENABLE),
IR_CONFIG_1);
au_sync_delay(1);
while (read_ir_reg(IR_ENABLE) & (IR_RX_STATUS | IR_TX_STATUS)) {
mdelay(1);
if (!timeout--) {
printk(KERN_ERR "%s: rx/tx disable timeout\n",
dev->name);
break;
}
}
/* disable DMA */
writel(read_ir_reg(IR_CONFIG_1) & ~IR_DMA_ENABLE, IR_CONFIG_1);
au_sync_delay(1);
/*
* After we disable tx/rx. the index pointers
* go back to zero.
*/
aup->tx_head = aup->tx_tail = aup->rx_head = 0;
for (i=0; i<NUM_IR_DESC; i++) {
ptxd = aup->tx_ring[i];
ptxd->flags = 0;
ptxd->count_0 = 0;
ptxd->count_1 = 0;
}
for (i=0; i<NUM_IR_DESC; i++) {
ptxd = aup->rx_ring[i];
ptxd->count_0 = 0;
ptxd->count_1 = 0;
ptxd->flags = AU_OWN;
}
if (speed == 4000000)
writel(1<<13, CPLD_AUX1);
else
writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1);
switch (speed) {
case 9600:
writel(11<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 19200:
writel(5<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 38400:
writel(2<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 57600:
writel(1<<10 | 12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 115200:
writel(12<<5, IR_WRITE_PHY_CONFIG);
writel(IR_SIR_MODE, IR_CONFIG_1);
break;
case 4000000:
writel(0xF, IR_WRITE_PHY_CONFIG);
writel(IR_FIR|IR_DMA_ENABLE|IR_RX_ENABLE, IR_CONFIG_1);
break;
default:
printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed);
ret = -EINVAL;
break;
}
aup->speed = speed;
writel(read_ir_reg(IR_ENABLE) | 0x8000, IR_ENABLE);
au_sync();
control = read_ir_reg(IR_ENABLE);
writel(0, IR_RING_PROMPT);
au_sync();
if (control & (1<<14)) {
printk(KERN_ERR "%s: configuration error\n", dev->name);
}
else {
if (control & (1<<11))
printk(KERN_INFO "%s Valid SIR config\n", dev->name);
if (control & (1<<12))
printk(KERN_INFO "%s Valid MIR config\n", dev->name);
if (control & (1<<13))
printk(KERN_INFO "%s Valid FIR config\n", dev->name);
if (control & (1<<10))
printk(KERN_INFO "%s TX enabled\n", dev->name);
if (control & (1<<9))
printk(KERN_INFO "%s RX enabled\n", dev->name);
}
spin_unlock_irqrestore(&ir_lock, flags);
return ret;
}
static int
au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
{
struct if_irda_req *rq = (struct if_irda_req *)ifreq;
struct au1k_private *aup = dev->priv;
int ret = -EOPNOTSUPP;
switch (cmd) {
case SIOCSBANDWIDTH:
if (capable(CAP_NET_ADMIN)) {
/*
* We are unable to set the speed if the
* device is not running.
*/
if (aup->open)
ret = au1k_irda_set_speed(dev,
rq->ifr_baudrate);
else {
printk(KERN_ERR "%s ioctl: !netif_running\n",
dev->name);
ret = 0;
}
}
break;
case SIOCSMEDIABUSY:
ret = -EPERM;
if (capable(CAP_NET_ADMIN)) {
irda_device_set_media_busy(dev, TRUE);
ret = 0;
}
break;
case SIOCGRECEIVING:
rq->ifr_receiving = 0;
break;
default:
break;
}
return ret;
}
static struct net_device_stats *au1k_irda_stats(struct net_device *dev)
{
struct au1k_private *aup = (struct au1k_private *) dev->priv;
return &aup->stats;
}
#ifdef MODULE
MODULE_AUTHOR("Pete Popov <ppopov@mvista.com>");
MODULE_DESCRIPTION("Au1000 IrDA Device Driver");
module_init(au1k_irda_init);
module_exit(au1k_irda_exit);
#endif /* MODULE */
......@@ -448,8 +448,6 @@ ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
case ETHTOOL_SSET:{
struct ethtool_cmd ecmd;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&ecmd, addr, sizeof (ecmd)))
return -EFAULT;
return ixgb_ethtool_sset(adapter, &ecmd);
......@@ -482,9 +480,6 @@ ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
#endif /* ETHTOOL_GREGS */
case ETHTOOL_NWAY_RST:{
IXGB_DBG("ETHTOOL_NWAY_RST\n");
if (!capable(CAP_NET_ADMIN))
return -EPERM;
ixgb_down(adapter);
ixgb_up(adapter);
......@@ -539,9 +534,6 @@ ixgb_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr)
struct ethtool_eeprom eeprom;
IXGB_DBG("ETHTOOL_SEEPROM\n");
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&eeprom, addr, sizeof (eeprom)))
return -EFAULT;
......
/*
* meth.c -- O2 Builtin 10/100 Ethernet driver
*
* Copyright (C) 2001 Ilya Volynets
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/kernel.h> /* printk() */
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/interrupt.h> /* mark_bh */
#include <linux/pci.h>
#include <linux/in.h>
#include <linux/netdevice.h> /* struct device, and other headers */
#include <linux/etherdevice.h> /* eth_type_trans */
#include <linux/ip.h> /* struct iphdr */
#include <linux/tcp.h> /* struct tcphdr */
#include <linux/skbuff.h>
#include <linux/mii.h> /*MII definitions */
#include <asm/ip32/crime.h>
#include <asm/ip32/mace.h>
#include <asm/ip32/ip32_ints.h>
#include "meth.h"
#include <linux/in6.h>
#include <asm/checksum.h>
#ifndef MFE_DEBUG
#define MFE_DEBUG 0
#endif
#if MFE_DEBUG>=1
#define DPRINTK(str,args...) printk (KERN_DEBUG "meth(%ld): %s: " str, jiffies, __FUNCTION__ , ## args)
#define MFE_RX_DEBUG 2
#else
#define DPRINTK(str,args...)
#define MFE_RX_DEBUG 0
#endif
static const char *version="meth.c: Ilya Volynets (ilya@theIlya.com)";
static const char *meth_str="SGI O2 Fast Ethernet";
MODULE_AUTHOR("Ilya Volynets");
MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver");
/* This is a load-time options */
/*static int eth = 0;
MODULE_PARM(eth, "i");*/
#define HAVE_TX_TIMEOUT
/* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */
#define TX_TIMEOUT (400*HZ/1000)
#ifdef HAVE_TX_TIMEOUT
static int timeout = TX_TIMEOUT;
MODULE_PARM(timeout, "i");
#endif
int meth_eth;
/*
* This structure is private to each device. It is used to pass
* packets in and out, so there is place for a packet
*/
typedef struct meth_private {
struct net_device_stats stats;
volatile struct meth_regs *regs;
u64 mode; /* in-memory copy of MAC control register */
int phy_addr; /* address of phy, used by mdio_* functions, initialized in mdio_probe*/
tx_packet *tx_ring;
dma_addr_t tx_ring_dma;
int free_space;
struct sk_buff *tx_skbs[TX_RING_ENTRIES];
dma_addr_t tx_skb_dmas[TX_RING_ENTRIES];
int tx_read,tx_write;
int tx_count;
rx_packet *rx_ring[RX_RING_ENTRIES];
dma_addr_t rx_ring_dmas[RX_RING_ENTRIES];
int rx_write;
spinlock_t meth_lock;
} meth_private;
extern struct net_device meth_devs[];
void meth_tx_timeout (struct net_device *dev);
void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs);
/* global, initialized in ip32-setup.c */
char o2meth_eaddr[8]={0,0,0,0,0,0,0,0};
static inline void load_eaddr(struct net_device *dev,
volatile struct meth_regs *regs)
{
int i;
DPRINTK("Loading MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
(int)o2meth_eaddr[0]&0xFF,(int)o2meth_eaddr[1]&0xFF,(int)o2meth_eaddr[2]&0xFF,
(int)o2meth_eaddr[3]&0xFF,(int)o2meth_eaddr[4]&0xFF,(int)o2meth_eaddr[5]&0xFF);
//memcpy(dev->dev_addr,o2meth_eaddr+2,6);
for (i=0; i<6; i++)
dev->dev_addr[i]=o2meth_eaddr[i];
regs->mac_addr= //dev->dev_addr[0]|(dev->dev_addr[1]<<8)|
//dev->dev_addr[2]<<16|(dev->dev_addr[3]<<24)|
//dev->dev_addr[4]<<32|(dev->dev_addr[5]<<40);
(*(u64*)o2meth_eaddr)>>16;
DPRINTK("MAC, finally is %0lx\n",regs->mac_addr);
}
/*
*Waits for BUSY status of mdio bus to clear
*/
#define WAIT_FOR_PHY(___regs, ___rval) \
while((___rval=___regs->phy_data)&MDIO_BUSY){ \
udelay(25); \
}
/*read phy register, return value read */
static int mdio_read(meth_private *priv,int phyreg)
{
volatile meth_regs* regs=priv->regs;
volatile u32 rval;
WAIT_FOR_PHY(regs,rval)
regs->phy_registers=(priv->phy_addr<<5)|(phyreg&0x1f);
udelay(25);
regs->phy_trans_go=1;
udelay(25);
WAIT_FOR_PHY(regs,rval)
return rval&MDIO_DATA_MASK;
}
/*write phy register */
static void mdio_write(meth_private* priv,int pfyreg,int val)
{
volatile meth_regs* regs=priv->regs;
int rval;
/// DPRINTK("Trying to write value %i to reguster %i\n",val, pfyreg);
spin_lock_irq(&priv->meth_lock);
WAIT_FOR_PHY(regs,rval)
regs->phy_registers=(priv->phy_addr<<5)|(pfyreg&0x1f);
regs->phy_data=val;
udelay(25);
WAIT_FOR_PHY(regs,rval)
spin_unlock_irq(&priv->meth_lock);
}
/* Modify phy register using given mask and value */
static void mdio_update(meth_private* priv,int phyreg, int val, int mask)
{
int rval;
DPRINTK("RMW value %i to PHY register %i with mask %i\n",val,phyreg,mask);
rval=mdio_read(priv,phyreg);
rval=(rval&~mask)|(val&mask);
mdio_write(priv,phyreg,rval);
}
/* handle errata data on MDIO bus */
//static void mdio_errata(meth_private *priv)
//{
/* Hmmm... what the hell is phyerrata? does it come from sys init parameters in IRIX */
//}
static int mdio_probe(meth_private *priv)
{
int i, p2, p3;
DPRINTK("Detecting PHY kind\n");
/* check if phy is detected already */
if(priv->phy_addr>=0&&priv->phy_addr<32)
return 0;
spin_lock_irq(&priv->meth_lock);
for (i=0;i<32;++i){
priv->phy_addr=(char)i;
p2=mdio_read(priv,2);
#ifdef MFE_DEBUG
p3=mdio_read(priv,3);
switch ((p2<<12)|(p3>>4)){
case PHY_QS6612X:
DPRINTK("PHY is QS6612X\n");
break;
case PHY_ICS1889:
DPRINTK("PHY is ICS1889\n");
break;
case PHY_ICS1890:
DPRINTK("PHY is ICS1890\n");
break;
case PHY_DP83840:
DPRINTK("PHY is DP83840\n");
break;
}
#endif
if(p2!=0xffff&&p2!=0x0000){
DPRINTK("PHY code: %x\n",(p2<<12)|(p3>>4));
break;
}
}
spin_unlock_irq(&priv->meth_lock);
if(priv->phy_addr<32) {
return 0;
}
DPRINTK("Oopsie! PHY is not known!\n");
priv->phy_addr=-1;
return -ENODEV;
}
static void meth_check_link(struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
int mii_partner = mdio_read(priv, 5);
int mii_advertising = mdio_read(priv, 4);
int negotiated = mii_advertising & mii_partner;
int duplex, speed;
if (mii_partner == 0xffff)
return;
duplex = ((negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040)?METH_PHY_FDX:0;
speed = (negotiated & 0x0380)?METH_100MBIT:0;
if ((priv->mode & METH_PHY_FDX) ^ duplex)
{
DPRINTK("Setting %s-duplex\n", duplex ? "full" : "half");
if (duplex)
priv->mode |= METH_PHY_FDX;
else
priv->mode &= ~METH_PHY_FDX;
priv->regs->mac_ctrl = priv->mode;
}
if ((priv->mode & METH_100MBIT) ^ speed)
{
DPRINTK("Setting %dMbs mode\n", speed ? 100 : 10);
if (duplex)
priv->mode |= METH_100MBIT;
else
priv->mode &= ~METH_100MBIT;
priv->regs->mac_ctrl = priv->mode;
}
}
static int meth_init_tx_ring(meth_private *priv)
{
/* Init TX ring */
DPRINTK("Initializing TX ring\n");
priv->tx_ring = (tx_packet *) pci_alloc_consistent(NULL,TX_RING_BUFFER_SIZE,&(priv->tx_ring_dma));
if(!priv->tx_ring)
return -ENOMEM;
memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE);
priv->tx_count = priv->tx_read = priv->tx_write = 0;
priv->regs->tx_ring_base = priv->tx_ring_dma;
priv->free_space = TX_RING_ENTRIES;
/* Now init skb save area */
memset(priv->tx_skbs,0,sizeof(priv->tx_skbs));
memset(priv->tx_skb_dmas,0,sizeof(priv->tx_skb_dmas));
DPRINTK("Done with TX ring init\n");
return 0;
}
static int meth_init_rx_ring(meth_private *priv)
{
int i;
DPRINTK("Initializing RX ring\n");
for(i=0;i<RX_RING_ENTRIES;i++){
DPRINTK("\t1:\t%i\t",i);
/*if(!(priv->rx_ring[i]=get_free_page(GFP_KERNEL)))
return -ENOMEM;
DPRINTK("\t2:\t%i\n",i);*/
priv->rx_ring[i]=(rx_packet*)pci_alloc_consistent(NULL,METH_RX_BUFF_SIZE,&(priv->rx_ring_dmas[i]));
/* I'll need to re-sync it after each RX */
DPRINTK("\t%p\n",priv->rx_ring[i]);
priv->regs->rx_fifo=priv->rx_ring_dmas[i];
}
priv->rx_write = 0;
DPRINTK("Done with RX ring\n");
return 0;
}
static void meth_free_tx_ring(meth_private *priv)
{
int i;
/* Remove any pending skb */
for (i = 0; i < TX_RING_ENTRIES; i++) {
if (priv->tx_skbs[i])
dev_kfree_skb(priv->tx_skbs[i]);
priv->tx_skbs[i] = NULL;
}
pci_free_consistent(NULL,
TX_RING_BUFFER_SIZE,
priv->tx_ring,
priv->tx_ring_dma);
}
static void meth_free_rx_ring(meth_private *priv)
{
int i;
for(i=0;i<RX_RING_ENTRIES;i++)
pci_free_consistent(NULL,
METH_RX_BUFF_SIZE,
priv->rx_ring[i],
priv->rx_ring_dmas[i]);
}
int meth_reset(struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
/* Reset card */
priv->regs->mac_ctrl = SGI_MAC_RESET;
priv->regs->mac_ctrl = 0;
udelay(25);
DPRINTK("MAC control after reset: %016lx\n", priv->regs->mac_ctrl);
/* Load ethernet address */
load_eaddr(dev, priv->regs);
/* Should load some "errata", but later */
/* Check for device */
if(mdio_probe(priv) < 0) {
DPRINTK("Unable to find PHY\n");
return -ENODEV;
}
/* Initial mode -- 10|Half-duplex|Accept normal packets */
priv->mode=METH_ACCEPT_MCAST|METH_DEFAULT_IPG;
if(dev->flags | IFF_PROMISC)
priv->mode |= METH_PROMISC;
priv->regs->mac_ctrl = priv->mode;
/* Autonegociate speed and duplex mode */
meth_check_link(dev);
/* Now set dma control, but don't enable DMA, yet */
priv->regs->dma_ctrl= (4 << METH_RX_OFFSET_SHIFT) |
(RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT);
return(0);
}
/*============End Helper Routines=====================*/
/*
* Open and close
*/
int meth_open(struct net_device *dev)
{
meth_private *priv=dev->priv;
volatile meth_regs *regs=priv->regs;
MOD_INC_USE_COUNT;
/* Start DMA */
regs->dma_ctrl|=
METH_DMA_TX_EN|/*METH_DMA_TX_INT_EN|*/
METH_DMA_RX_EN|METH_DMA_RX_INT_EN;
if(request_irq(dev->irq,meth_interrupt,SA_SHIRQ,meth_str,dev)){
printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq);
return -EAGAIN;
}
netif_start_queue(dev);
DPRINTK("Opened... DMA control=0x%08lx\n", regs->dma_ctrl);
return 0;
}
int meth_release(struct net_device *dev)
{
netif_stop_queue(dev); /* can't transmit any more */
/* shut down dma */
((meth_private*)(dev->priv))->regs->dma_ctrl&=
~(METH_DMA_TX_EN|METH_DMA_TX_INT_EN|
METH_DMA_RX_EN|METH_DMA_RX_INT_EN);
free_irq(dev->irq, dev);
MOD_DEC_USE_COUNT;
return 0;
}
/*
* Configuration changes (passed on by ifconfig)
*/
int meth_config(struct net_device *dev, struct ifmap *map)
{
if (dev->flags & IFF_UP) /* can't act on a running interface */
return -EBUSY;
/* Don't allow changing the I/O address */
if (map->base_addr != dev->base_addr) {
printk(KERN_WARNING "meth: Can't change I/O address\n");
return -EOPNOTSUPP;
}
/* Allow changing the IRQ */
if (map->irq != dev->irq) {
printk(KERN_WARNING "meth: Can't change IRQ\n");
return -EOPNOTSUPP;
}
DPRINTK("Configured\n");
/* ignore other fields */
return 0;
}
/*
* Receive a packet: retrieve, encapsulate and pass over to upper levels
*/
void meth_rx(struct net_device* dev)
{
struct sk_buff *skb;
struct meth_private *priv = (struct meth_private *) dev->priv;
rx_packet *rxb;
DPRINTK("RX...\n");
// TEMP while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){
while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){
int len=rxb->status.parsed.rx_len - 4; /* omit CRC */
DPRINTK("(%i)\n",priv->rx_write);
/* length sanity check */
if(len < 60 || len > 1518) {
printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x.\n",
dev->name, priv->rx_write, rxb->status.raw);
priv->stats.rx_errors++;
priv->stats.rx_length_errors++;
}
if(!(rxb->status.raw&METH_RX_STATUS_ERRORS)){
skb=alloc_skb(len+2,GFP_ATOMIC);/* Should be atomic -- we are in interrupt */
if(!skb){
/* Ouch! No memory! Drop packet on the floor */
DPRINTK("!!!>>>Ouch! Not enough Memory for RX buffer!\n");
priv->stats.rx_dropped++;
} else {
skb_reserve(skb, 2); /* align IP on 16B boundary */
memcpy(skb_put(skb, len), rxb->buf, len);
/* Write metadata, and then pass to the receive level */
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
//skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
DPRINTK("passing packet\n");
DPRINTK("len = %d rxb->status = %x\n",
len, rxb->status.raw);
netif_rx(skb);
dev->last_rx = jiffies;
priv->stats.rx_packets++;
priv->stats.rx_bytes+=len;
DPRINTK("There we go... Whew...\n");
}
}
priv->regs->rx_fifo=priv->rx_ring_dmas[priv->rx_write];
rxb->status.raw=0;
priv->rx_write=(priv->rx_write+1)&(RX_RING_ENTRIES-1);
}
}
static int meth_tx_full(struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
return(priv->tx_count >= TX_RING_ENTRIES-1);
}
void meth_tx_cleanup(struct net_device* dev, int rptr)
{
meth_private *priv=dev->priv;
tx_packet* status;
struct sk_buff *skb;
spin_lock(&priv->meth_lock);
/* Stop DMA */
priv->regs->dma_ctrl &= ~(METH_DMA_TX_INT_EN);
while(priv->tx_read != rptr){
skb = priv->tx_skbs[priv->tx_read];
status = &priv->tx_ring[priv->tx_read];
if(!status->header.res.sent)
break;
if(status->header.raw & METH_TX_STATUS_DONE) {
priv->stats.tx_packets++;
priv->stats.tx_bytes += skb->len;
}
dev_kfree_skb_irq(skb);
priv->tx_skbs[priv->tx_read] = NULL;
status->header.raw = 0;
priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1);
priv->tx_count --;
}
/* wake up queue if it was stopped */
if (netif_queue_stopped(dev) && ! meth_tx_full(dev)) {
netif_wake_queue(dev);
}
spin_unlock(priv->meth_lock);
}
/*
* The typical interrupt entry point
*/
void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs)
{
struct meth_private *priv;
union {
u32 reg; /*Whole status register */
struct {
u32 : 2,
rx_seq : 5,
tx_read : 9,
rx_read : 8,
int_mask: 8;
} parsed;
} status;
/*
* As usual, check the "device" pointer for shared handlers.
* Then assign "struct device *dev"
*/
struct net_device *dev = (struct net_device *)dev_id;
/* ... and check with hw if it's really ours */
if (!dev /*paranoid*/ ) return;
/* Lock the device */
priv = (struct meth_private *) dev->priv;
status.reg = priv->regs->int_flags;
DPRINTK("Interrupt, status %08x...\n",status.reg);
if (status.parsed.int_mask & METH_INT_RX_THRESHOLD) {
/* send it to meth_rx for handling */
meth_rx(dev);
}
if (status.parsed.int_mask & (METH_INT_TX_EMPTY|METH_INT_TX_PKT)) {
/* a transmission is over: free the skb */
meth_tx_cleanup(dev, status.parsed.tx_read);
}
/* check for errors too... */
if (status.parsed.int_mask & (METH_INT_TX_LINK_FAIL))
printk(KERN_WARNING "meth: link failure\n");
if (status.parsed.int_mask & (METH_INT_MEM_ERROR))
printk(KERN_WARNING "meth: memory error\n");
if (status.parsed.int_mask & (METH_INT_TX_ABORT))
printk(KERN_WARNING "meth: aborted\n");
DPRINTK("Interrupt handling done...\n");
priv->regs->int_flags=status.reg&0xff; /* clear interrupts */
}
/*
* Transmits packets that fit into TX descriptor (are <=120B)
*/
static void meth_tx_short_prepare(meth_private* priv, struct sk_buff* skb)
{
tx_packet *desc=&priv->tx_ring[priv->tx_write];
int len = (skb->len<ETH_ZLEN)?ETH_ZLEN:skb->len;
DPRINTK("preparing short packet\n");
/* maybe I should set whole thing to 0 first... */
memcpy(desc->data.dt+(120-len),skb->data,skb->len);
if(skb->len < len)
memset(desc->data.dt+120-len+skb->len,0,len-skb->len);
desc->header.raw=METH_TX_CMD_INT_EN|(len-1)|((128-len)<<16);
DPRINTK("desc=%016lx\n",desc->header.raw);
}
#define TX_CATBUF1 BIT(25)
static void meth_tx_1page_prepare(meth_private* priv, struct sk_buff* skb)
{
tx_packet *desc=&priv->tx_ring[priv->tx_write];
void *buffer_data = (void *)(((u64)skb->data + 7ULL) & (~7ULL));
int unaligned_len = (int)((u64)buffer_data - (u64)skb->data);
int buffer_len = skb->len - unaligned_len;
dma_addr_t catbuf;
DPRINTK("preparing 1 page...\n");
DPRINTK("length=%d data=%p\n", skb->len, skb->data);
DPRINTK("unaligned_len=%d\n", unaligned_len);
DPRINTK("buffer_data=%p buffer_len=%d\n",
buffer_data,
buffer_len);
desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|(skb->len-1);
/* unaligned part */
if(unaligned_len){
memcpy(desc->data.dt+(120-unaligned_len),
skb->data, unaligned_len);
desc->header.raw |= (128-unaligned_len) << 16;
}
/* first page */
catbuf = pci_map_single(NULL,
buffer_data,
buffer_len,
PCI_DMA_TODEVICE);
DPRINTK("catbuf=%x\n", catbuf);
desc->data.cat_buf[0].form.start_addr = catbuf >> 3;
desc->data.cat_buf[0].form.len = buffer_len-1;
DPRINTK("desc=%016lx\n",desc->header.raw);
DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw);
}
#define TX_CATBUF2 BIT(26)
static void meth_tx_2page_prepare(meth_private* priv, struct sk_buff* skb)
{
tx_packet *desc=&priv->tx_ring[priv->tx_write];
void *buffer1_data = (void *)(((u64)skb->data + 7ULL) & (~7ULL));
void *buffer2_data = (void *)PAGE_ALIGN((u64)skb->data);
int unaligned_len = (int)((u64)buffer1_data - (u64)skb->data);
int buffer1_len = (int)((u64)buffer2_data - (u64)buffer1_data);
int buffer2_len = skb->len - buffer1_len - unaligned_len;
dma_addr_t catbuf1, catbuf2;
DPRINTK("preparing 2 pages... \n");
DPRINTK("length=%d data=%p\n", skb->len, skb->data);
DPRINTK("unaligned_len=%d\n", unaligned_len);
DPRINTK("buffer1_data=%p buffer1_len=%d\n",
buffer1_data,
buffer1_len);
DPRINTK("buffer2_data=%p buffer2_len=%d\n",
buffer2_data,
buffer2_len);
desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|TX_CATBUF2|(skb->len-1);
/* unaligned part */
if(unaligned_len){
memcpy(desc->data.dt+(120-unaligned_len),
skb->data, unaligned_len);
desc->header.raw |= (128-unaligned_len) << 16;
}
/* first page */
catbuf1 = pci_map_single(NULL,
buffer1_data,
buffer1_len,
PCI_DMA_TODEVICE);
DPRINTK("catbuf1=%x\n", catbuf1);
desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3;
desc->data.cat_buf[0].form.len = buffer1_len-1;
/* second page */
catbuf2 = pci_map_single(NULL,
buffer2_data,
buffer2_len,
PCI_DMA_TODEVICE);
DPRINTK("catbuf2=%x\n", catbuf2);
desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3;
desc->data.cat_buf[1].form.len = buffer2_len-1;
DPRINTK("desc=%016lx\n",desc->header.raw);
DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw);
DPRINTK("cat_buf[1].raw=%016lx\n",desc->data.cat_buf[1].raw);
}
void meth_add_to_tx_ring(meth_private *priv, struct sk_buff* skb)
{
DPRINTK("Transmitting data...\n");
if(skb->len <= 120) {
/* Whole packet fits into descriptor */
meth_tx_short_prepare(priv,skb);
} else if(PAGE_ALIGN((u64)skb->data) !=
PAGE_ALIGN((u64)skb->data+skb->len-1)) {
/* Packet crosses page boundary */
meth_tx_2page_prepare(priv,skb);
} else {
/* Packet is in one page */
meth_tx_1page_prepare(priv,skb);
}
/* Remember the skb, so we can free it at interrupt time */
priv->tx_skbs[priv->tx_write] = skb;
priv->tx_write = (priv->tx_write+1) & (TX_RING_ENTRIES-1);
priv->regs->tx_info.wptr = priv->tx_write;
priv->tx_count ++;
/* Enable DMA transfer */
priv->regs->dma_ctrl |= METH_DMA_TX_INT_EN;
}
/*
* Transmit a packet (called by the kernel)
*/
int meth_tx(struct sk_buff *skb, struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
spin_lock_irq(&priv->meth_lock);
meth_add_to_tx_ring(priv, skb);
dev->trans_start = jiffies; /* save the timestamp */
/* If TX ring is full, tell the upper layer to stop sending packets */
if (meth_tx_full(dev)) {
DPRINTK("TX full: stopping\n");
netif_stop_queue(dev);
}
spin_unlock_irq(&priv->meth_lock);
return 0;
}
/*
* Deal with a transmit timeout.
*/
void meth_tx_timeout (struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
printk(KERN_WARNING "%s: transmit timed out\n", dev->name);
/* Protect against concurrent rx interrupts */
spin_lock_irq(&priv->meth_lock);
/* Try to reset the adaptor. */
meth_reset(dev);
priv->stats.tx_errors++;
/* Clear all rings */
meth_free_tx_ring(priv);
meth_free_rx_ring(priv);
meth_init_tx_ring(priv);
meth_init_rx_ring(priv);
/* Restart dma */
priv->regs->dma_ctrl|=METH_DMA_TX_EN|METH_DMA_RX_EN|METH_DMA_RX_INT_EN;
/* Enable interrupt */
spin_unlock_irq(&priv->meth_lock);
dev->trans_start = jiffies;
netif_wake_queue(dev);
return;
}
/*
* Ioctl commands
*/
int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
DPRINTK("ioctl\n");
return 0;
}
/*
* Return statistics to the caller
*/
struct net_device_stats *meth_stats(struct net_device *dev)
{
struct meth_private *priv = (struct meth_private *) dev->priv;
return &priv->stats;
}
/*
* The init function (sometimes called probe).
* It is invoked by register_netdev()
*/
int meth_init(struct net_device *dev)
{
meth_private *priv;
int ret;
/*
* Then, assign other fields in dev, using ether_setup() and some
* hand assignments
*/
ether_setup(dev); /* assign some of the fields */
dev->open = meth_open;
dev->stop = meth_release;
dev->set_config = meth_config;
dev->hard_start_xmit = meth_tx;
dev->do_ioctl = meth_ioctl;
dev->get_stats = meth_stats;
#ifdef HAVE_TX_TIMEOUT
dev->tx_timeout = meth_tx_timeout;
dev->watchdog_timeo = timeout;
#endif
dev->irq = MACE_ETHERNET_IRQ;
SET_MODULE_OWNER(dev);
/*
* Then, allocate the priv field. This encloses the statistics
* and a few private fields.
*/
priv = kmalloc(sizeof(struct meth_private), GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
dev->priv=priv;
memset(priv, 0, sizeof(struct meth_private));
spin_lock_init(&((struct meth_private *) dev->priv)->meth_lock);
/*
* Make the usual checks: check_region(), probe irq, ... -ENODEV
* should be returned if no device found. No resource should be
* grabbed: this is done on open().
*/
priv->regs=(meth_regs*)SGI_MFE;
dev->base_addr=SGI_MFE;
priv->phy_addr = -1; /* No phy is known yet... */
/* Initialize the hardware */
if((ret=meth_reset(dev)) < 0)
return ret;
/* Allocate the ring buffers */
if((ret=meth_init_tx_ring(priv))<0||(ret=meth_init_rx_ring(priv))<0){
meth_free_tx_ring(priv);
meth_free_rx_ring(priv);
return ret;
}
printk("SGI O2 Fast Ethernet rev. %ld\n", priv->regs->mac_ctrl >> 29);
return 0;
}
/*
* The devices
*/
struct net_device meth_devs[1] = {
{ init: meth_init, } /* init, nothing more */
};
/*
* Finally, the module stuff
*/
int meth_init_module(void)
{
int result, device_present = 0;
strcpy(meth_devs[0].name, "eth%d");
if ( (result = register_netdev(meth_devs)) )
printk("meth: error %i registering device \"%s\"\n",
result, meth_devs->name);
else device_present++;
#ifndef METH_DEBUG
EXPORT_NO_SYMBOLS;
#endif
return device_present ? 0 : -ENODEV;
}
void meth_cleanup(void)
{
kfree(meth_devs->priv);
unregister_netdev(meth_devs);
return;
}
module_init(meth_init_module);
module_exit(meth_cleanup);
/*
* snull.h -- definitions for the network module
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*/
/* version dependencies have been confined to a separate file */
#define SGI_MFE (MACE_BASE+MACE_ENET)
/* (0xBF280000)*/
/* Tunable parameters */
#define TX_RING_ENTRIES 64 /* 64-512?*/
#define RX_RING_ENTRIES 16 /* Do not change */
/* Internal constants */
#define TX_RING_BUFFER_SIZE (TX_RING_ENTRIES*sizeof(tx_packet))
#define RX_BUFFER_SIZE 1546 /* ethenet packet size */
#define METH_RX_BUFF_SIZE 4096
#define RX_BUFFER_OFFSET (sizeof(rx_status_vector)+2) /* staus vector + 2 bytes of padding */
#define RX_BUCKET_SIZE 256
/* For more detailed explanations of what each field menas,
see Nick's great comments to #defines below (or docs, if
you are lucky enough toget hold of them :)*/
/* tx status vector is written over tx command header upon
dma completion. */
typedef struct tx_status_vector {
u64 sent:1; /* always set to 1...*/
u64 pad0:34;/* always set to 0 */
u64 flags:9; /*I'm too lazy to specify each one separately at the moment*/
u64 col_retry_cnt:4; /*collision retry count*/
u64 len:16; /*Transmit length in bytes*/
} tx_status_vector;
/*
* Each packet is 128 bytes long.
* It consists of header, 0-3 concatination
* buffer pointers and up to 120 data bytes.
*/
typedef struct tx_packet_hdr {
u64 pad1:36; /*should be filled with 0 */
u64 cat_ptr3_valid:1, /*Concatination pointer valid flags*/
cat_ptr2_valid:1,
cat_ptr1_valid:1;
u64 tx_int_flag:1; /*Generate TX intrrupt when packet has been sent*/
u64 term_dma_flag:1; /*Terminate transmit DMA on transmit abort conditions*/
u64 data_offset:7; /*Starting byte offset in ring data block*/
u64 data_len:16; /*Length of valid data in bytes-1*/
} tx_packet_hdr;
typedef union tx_cat_ptr {
struct {
u64 pad2:16; /* should be 0 */
u64 len:16; /*length of buffer data - 1*/
u64 start_addr:29; /*Physical starting address*/
u64 pad1:3; /* should be zero */
} form;
u64 raw;
} tx_cat_ptr;
typedef struct tx_packet {
union {
tx_packet_hdr header;
tx_status_vector res;
u64 raw;
}header;
union {
tx_cat_ptr cat_buf[3];
char dt[120];
} data;
} tx_packet;
typedef union rx_status_vector {
struct {
u64 pad1:1;/*fill it with ones*/
u64 pad2:15;/*fill with 0*/
u64 ip_chk_sum:16;
u64 seq_num:5;
u64 mac_addr_match:1;
u64 mcast_addr_match:1;
u64 carrier_event_seen:1;
u64 bad_packet:1;
u64 long_event_seen:1;
u64 invalid_preamble:1;
u64 broadcast:1;
u64 multicast:1;
u64 crc_error:1;
u64 huh:1;/*???*/
u64 rx_code_violation:1;
u64 rx_len:16;
} parsed;
u64 raw;
} rx_status_vector;
typedef struct rx_packet {
rx_status_vector status;
u64 pad[3]; /* For whatever reason, there needs to be 4 double-word offset */
u16 pad2;
char buf[METH_RX_BUFF_SIZE-sizeof(rx_status_vector)-3*sizeof(u64)-sizeof(u16)];/* data */
} rx_packet;
typedef struct meth_regs {
u64 mac_ctrl; /*0x00,rw,31:0*/
u64 int_flags; /*0x08,rw,30:0*/
u64 dma_ctrl; /*0x10,rw,15:0*/
u64 timer; /*0x18,rw,5:0*/
u64 int_tx; /*0x20,wo,0:0*/
u64 int_rx; /*0x28,wo,9:4*/
struct {
u32 tx_info_pad;
u32 rptr:16,wptr:16;
} tx_info; /*0x30,rw,31:0*/
u64 tx_info_al; /*0x38,rw,31:0*/
struct {
u32 rx_buff_pad1;
u32 rx_buff_pad2:8,
wptr:8,
rptr:8,
depth:8;
} rx_buff; /*0x40,ro,23:0*/
u64 rx_buff_al1; /*0x48,ro,23:0*/
u64 rx_buff_al2; /*0x50,ro,23:0*/
u64 int_update; /*0x58,wo,31:0*/
u32 phy_data_pad;
u32 phy_data; /*0x60,rw,16:0*/
u32 phy_reg_pad;
u32 phy_registers; /*0x68,rw,9:0*/
u64 phy_trans_go; /*0x70,wo,0:0*/
u64 backoff_seed; /*0x78,wo,10:0*/
u64 imq_reserved[4];/*0x80,ro,64:0(x4)*/
/*===================================*/
u64 mac_addr; /*0xA0,rw,47:0, I think it's MAC address, but I'm not sure*/
u64 mcast_addr; /*0xA8,rw,47:0, This seems like secondary MAC address*/
u64 mcast_filter; /*0xB0,rw,63:0*/
u64 tx_ring_base; /*0xB8,rw,31:13*/
/* Following are read-only debugging info register */
u64 tx_pkt1_hdr; /*0xC0,ro,63:0*/
u64 tx_pkt1_ptr[3]; /*0xC8,ro,63:0(x3)*/
u64 tx_pkt2_hdr; /*0xE0,ro,63:0*/
u64 tx_pkt2_ptr[3]; /*0xE8,ro,63:0(x3)*/
/*===================================*/
u32 rx_pad;
u32 rx_fifo;
u64 reserved[31];
}meth_regs;
/* Bits in METH_MAC */
#define SGI_MAC_RESET BIT(0) /* 0: MAC110 active in run mode, 1: Global reset signal to MAC110 core is active */
#define METH_PHY_FDX BIT(1) /* 0: Disable full duplex, 1: Enable full duplex */
#define METH_PHY_LOOP BIT(2) /* 0: Normal operation, follows 10/100mbit and M10T/MII select, 1: loops internal MII bus */
/* selects ignored */
#define METH_100MBIT BIT(3) /* 0: 10meg mode, 1: 100meg mode */
#define METH_PHY_MII BIT(4) /* 0: MII selected, 1: SIA selected */
/* Note: when loopback is set this bit becomes collision control. Setting this bit will */
/* cause a collision to be reported. */
/* Bits 5 and 6 are used to determine the the Destination address filter mode */
#define METH_ACCEPT_MY 0 /* 00: Accept PHY address only */
#define METH_ACCEPT_MCAST 0x20 /* 01: Accept physical, broadcast, and multicast filter matches only */
#define METH_ACCEPT_AMCAST 0x40 /* 10: Accept physical, broadcast, and all multicast packets */
#define METH_PROMISC 0x60 /* 11: Promiscious mode */
#define METH_PHY_LINK_FAIL BIT(7) /* 0: Link failure detection disabled, 1: Hardware scans for link failure in PHY */
#define METH_MAC_IPG 0x1ffff00
#define METH_DEFAULT_IPG ((17<<15) | (11<<22) | (21<<8))
/* 0x172e5c00 */ /* 23, 23, 23 */ /*0x54A9500 *//*21,21,21*/
/* Bits 8 through 14 are used to determine Inter-Packet Gap between "Back to Back" packets */
/* The gap depends on the clock speed of the link, 80ns per increment for 100baseT, 800ns */
/* per increment for 10BaseT */
/* Bits 15 through 21 are used to determine IPGR1 */
/* Bits 22 through 28 are used to determine IPGR2 */
#define METH_REV_SHIFT 29 /* Bits 29 through 31 are used to determine the revision */
/* 000: Inital revision */
/* 001: First revision, Improved TX concatenation */
/* DMA control bits */
#define METH_RX_OFFSET_SHIFT 12 /* Bits 12:14 of DMA control register indicate starting offset of packet data for RX operation */
#define METH_RX_DEPTH_SHIFT 4 /* Bits 8:4 define RX fifo depth -- when # of RX fifo entries != depth, interrupt is generted */
#define METH_DMA_TX_EN BIT(1) /* enable TX DMA */
#define METH_DMA_TX_INT_EN BIT(0) /* enable TX Buffer Empty interrupt */
#define METH_DMA_RX_EN BIT(15) /* Enable RX */
#define METH_DMA_RX_INT_EN BIT(9) /* Enable interrupt on RX packet */
/* RX status bits */
#define METH_RX_ST_RCV_CODE_VIOLATION BIT(16)
#define METH_RX_ST_DRBL_NBL BIT(17)
#define METH_RX_ST_CRC_ERR BIT(18)
#define METH_RX_ST_MCAST_PKT BIT(19)
#define METH_RX_ST_BCAST_PKT BIT(20)
#define METH_RX_ST_INV_PREAMBLE_CTX BIT(21)
#define METH_RX_ST_LONG_EVT_SEEN BIT(22)
#define METH_RX_ST_BAD_PACKET BIT(23)
#define METH_RX_ST_CARRIER_EVT_SEEN BIT(24)
#define METH_RX_ST_MCAST_FILTER_MATCH BIT(25)
#define METH_RX_ST_PHYS_ADDR_MATCH BIT(26)
#define METH_RX_STATUS_ERRORS \
( \
METH_RX_ST_RCV_CODE_VIOLATION| \
METH_RX_ST_CRC_ERR| \
METH_RX_ST_INV_PREAMBLE_CTX| \
METH_RX_ST_LONG_EVT_SEEN| \
METH_RX_ST_BAD_PACKET| \
METH_RX_ST_CARRIER_EVT_SEEN \
)
/* Bits in METH_INT */
/* Write _1_ to corresponding bit to clear */
#define METH_INT_TX_EMPTY BIT(0) /* 0: No interrupt pending, 1: The TX ring buffer is empty */
#define METH_INT_TX_PKT BIT(1) /* 0: No interrupt pending */
/* 1: A TX message had the INT request bit set, the packet has been sent. */
#define METH_INT_TX_LINK_FAIL BIT(2) /* 0: No interrupt pending, 1: PHY has reported a link failure */
#define METH_INT_MEM_ERROR BIT(3) /* 0: No interrupt pending */
/* 1: A memory error occurred durring DMA, DMA stopped, Fatal */
#define METH_INT_TX_ABORT BIT(4) /* 0: No interrupt pending, 1: The TX aborted operation, DMA stopped, FATAL */
#define METH_INT_RX_THRESHOLD BIT(5) /* 0: No interrupt pending, 1: Selected receive threshold condition Valid */
#define METH_INT_RX_UNDERFLOW BIT(6) /* 0: No interrupt pending, 1: FIFO was empty, packet could not be queued */
#define METH_INT_RX_OVERFLOW BIT(7) /* 0: No interrupt pending, 1: DMA FIFO Overflow, DMA stopped, FATAL */
#define METH_INT_RX_RPTR_MASK 0x0001F00 /* Bits 8 through 12 alias of RX read-pointer */
/* Bits 13 through 15 are always 0. */
#define METH_INT_TX_RPTR_MASK 0x1FF0000 /* Bits 16 through 24 alias of TX read-pointer */
#define METH_INT_SEQ_MASK 0x2E000000 /* Bits 25 through 29 are the starting seq number for the message at the */
/* top of the queue */
#define METH_ERRORS ( \
METH_INT_RX_OVERFLOW| \
METH_INT_RX_UNDERFLOW| \
METH_INT_MEM_ERROR| \
METH_INT_TX_ABORT)
#define METH_INT_MCAST_HASH BIT(30) /* If RX DMA is enabled the hash select logic output is latched here */
/* TX status bits */
#define METH_TX_STATUS_DONE BIT(23) /* Packet was transmitted successfully */
/* Tx command header bits */
#define METH_TX_CMD_INT_EN BIT(24) /* Generate TX interrupt when packet is sent */
/* Phy MDIO interface busy flag */
#define MDIO_BUSY BIT(16)
#define MDIO_DATA_MASK 0xFFFF
/* PHY defines */
#define PHY_QS6612X 0x0181441 /* Quality TX */
#define PHY_ICS1889 0x0015F41 /* ICS FX */
#define PHY_ICS1890 0x0015F42 /* ICS TX */
#define PHY_DP83840 0x20005C0 /* National TX */
......@@ -211,7 +211,6 @@ enum Window4 { /* Window 4: Xcvr/media bits. */
struct el3_private {
dev_link_t link;
struct net_device dev;
dev_node_t node;
struct net_device_stats stats;
u16 advertising, partner; /* NWay media advertisement */
......@@ -291,13 +290,12 @@ static dev_link_t *tc574_attach(void)
flush_stale_links();
/* Create the PC card device object. */
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp)
dev = alloc_etherdev(sizeof(struct el3_private));
if (!dev)
return NULL;
memset(lp, 0, sizeof(*lp));
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
lp = dev->priv;
link = &lp->link;
link->priv = dev;
init_timer(&link->release);
link->release.function = &tc574_release;
......@@ -312,6 +310,7 @@ static dev_link_t *tc574_attach(void)
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
......@@ -323,7 +322,6 @@ static dev_link_t *tc574_attach(void)
dev->get_stats = &el3_get_stats;
dev->do_ioctl = &el3_ioctl;
dev->set_multicast_list = &set_rx_mode;
ether_setup(dev);
dev->open = &el3_open;
dev->stop = &el3_close;
#ifdef HAVE_TX_TIMEOUT
......@@ -364,7 +362,7 @@ static dev_link_t *tc574_attach(void)
static void tc574_detach(dev_link_t *link)
{
struct el3_private *lp = link->priv;
struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "3c574_detach(0x%p)\n", link);
......@@ -390,8 +388,8 @@ static void tc574_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
if (link->dev)
unregister_netdev(&lp->dev);
kfree(lp);
unregister_netdev(dev);
kfree(dev);
} /* tc574_detach */
......@@ -407,8 +405,8 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
static void tc574_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
struct el3_private *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
struct el3_private *lp = dev->priv;
tuple_t tuple;
cisparse_t parse;
unsigned short buf[32];
......@@ -599,8 +597,7 @@ static int tc574_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
struct el3_private *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
DEBUG(1, "3c574_event(0x%06x)\n", event);
......@@ -856,7 +853,7 @@ static int el3_open(struct net_device *dev)
tc574_reset(dev);
lp->media.function = &media_check;
lp->media.data = (unsigned long)lp;
lp->media.data = (unsigned long) dev;
lp->media.expires = jiffies + HZ;
add_timer(&lp->media);
......@@ -939,8 +936,8 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* The EL3 interrupt handler. */
static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct el3_private *lp = dev_id;
struct net_device *dev = &lp->dev;
struct net_device *dev = (struct net_device *) dev_id;
struct el3_private *lp = dev->priv;
ioaddr_t ioaddr, status;
int work_budget = max_interrupt_work;
int handled = 0;
......@@ -1032,8 +1029,8 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
static void media_check(unsigned long arg)
{
struct el3_private *lp = (struct el3_private *)arg;
struct net_device *dev = &lp->dev;
struct net_device *dev = (struct net_device *) arg;
struct el3_private *lp = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
unsigned long flags;
unsigned short /* cable, */ media, partner;
......
......@@ -106,7 +106,6 @@ enum RxFilter {
struct el3_private {
dev_link_t link;
struct net_device dev;
dev_node_t node;
struct net_device_stats stats;
/* For transceiver monitoring */
......@@ -213,14 +212,14 @@ static dev_link_t *tc589_attach(void)
flush_stale_links();
/* Create new ethernet device */
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
spin_lock_init(&lp->lock);
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
dev = alloc_etherdev(sizeof(struct el3_private));
if (!dev)
return NULL;
lp = dev->priv;
link = &lp->link;
link->priv = dev;
spin_lock_init(&lp->lock);
init_timer(&link->release);
link->release.function = &tc589_release;
link->release.data = (unsigned long)link;
......@@ -234,6 +233,7 @@ static dev_link_t *tc589_attach(void)
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
link->irq.Handler = &el3_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
......@@ -246,7 +246,6 @@ static dev_link_t *tc589_attach(void)
dev->set_config = &el3_config;
dev->get_stats = &el3_get_stats;
dev->set_multicast_list = &set_multicast_list;
ether_setup(dev);
dev->open = &el3_open;
dev->stop = &el3_close;
#ifdef HAVE_TX_TIMEOUT
......@@ -288,7 +287,7 @@ static dev_link_t *tc589_attach(void)
static void tc589_detach(dev_link_t *link)
{
struct el3_private *lp = link->priv;
struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "3c589_detach(0x%p)\n", link);
......@@ -314,8 +313,8 @@ static void tc589_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
if (link->dev)
unregister_netdev(&lp->dev);
kfree(lp);
unregister_netdev(dev);
kfree(dev);
} /* tc589_detach */
......@@ -333,8 +332,8 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
static void tc589_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
struct el3_private *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
struct el3_private *lp = dev->priv;
tuple_t tuple;
cisparse_t parse;
u16 buf[32], *phys_addr;
......@@ -487,8 +486,7 @@ static int tc589_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
struct el3_private *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
DEBUG(1, "3c589_event(0x%06x)\n", event);
......@@ -738,7 +736,7 @@ static int el3_open(struct net_device *dev)
tc589_reset(dev);
init_timer(&lp->media);
lp->media.function = &media_check;
lp->media.data = (unsigned long)lp;
lp->media.data = (unsigned long) dev;
lp->media.expires = jiffies + HZ;
add_timer(&lp->media);
......@@ -818,8 +816,8 @@ static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* The EL3 interrupt handler. */
static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct el3_private *lp = dev_id;
struct net_device *dev = &lp->dev;
struct net_device *dev = (struct net_device *) dev_id;
struct el3_private *lp = dev->priv;
ioaddr_t ioaddr, status;
int i = 0, handled = 1;
......@@ -903,8 +901,8 @@ static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static void media_check(unsigned long arg)
{
struct el3_private *lp = (struct el3_private *)(arg);
struct net_device *dev = &lp->dev;
struct net_device *dev = (struct net_device *)(arg);
struct el3_private *lp = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
u16 media, errs;
unsigned long flags;
......
......@@ -130,7 +130,6 @@ typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
*/
typedef struct local_info_t {
dev_link_t link;
struct net_device dev;
dev_node_t node;
struct net_device_stats stats;
long open_time;
......@@ -273,11 +272,12 @@ static dev_link_t *fmvj18x_attach(void)
flush_stale_links();
/* Make up a FMVJ18x specific data structure */
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
dev = alloc_etherdev(sizeof(local_info_t));
if (!dev)
return NULL;
lp = dev->priv;
link = &lp->link;
link->priv = dev;
init_timer(&link->release);
link->release.function = &fmvj18x_release;
......@@ -297,6 +297,7 @@ static dev_link_t *fmvj18x_attach(void)
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
link->irq.Handler = &fjn_interrupt;
link->irq.Instance = dev;
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
......@@ -309,7 +310,6 @@ static dev_link_t *fmvj18x_attach(void)
dev->set_config = &fjn_config;
dev->get_stats = &fjn_get_stats;
dev->set_multicast_list = &set_rx_mode;
ether_setup(dev);
dev->open = &fjn_open;
dev->stop = &fjn_close;
#ifdef HAVE_TX_TIMEOUT
......@@ -344,7 +344,7 @@ static dev_link_t *fmvj18x_attach(void)
static void fmvj18x_detach(dev_link_t *link)
{
local_info_t *lp = link->priv;
struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
......@@ -371,8 +371,8 @@ static void fmvj18x_detach(dev_link_t *link)
/* Unlink device structure, free pieces */
*linkp = link->next;
if (link->dev)
unregister_netdev(&lp->dev);
kfree(lp);
unregister_netdev(dev);
kfree(dev);
} /* fmvj18x_detach */
......@@ -423,8 +423,8 @@ static int ungermann_try_io_port(dev_link_t *link)
static void fmvj18x_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
local_info_t *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
local_info_t *lp = dev->priv;
tuple_t tuple;
cisparse_t parse;
u_short buf[32];
......@@ -704,8 +704,7 @@ static int fmvj18x_setup_mfc(dev_link_t *link)
memreq_t mem;
u_char *base;
int i, j;
local_info_t *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
ioaddr_t ioaddr;
/* Allocate a small memory window */
......@@ -776,8 +775,7 @@ static int fmvj18x_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
local_info_t *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
......@@ -847,8 +845,8 @@ module_exit(exit_fmvj18x_cs);
static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
local_info_t *lp = dev_id;
struct net_device *dev = &lp->dev;
struct net_device *dev = dev_id;
local_info_t *lp = dev->priv;
ioaddr_t ioaddr;
unsigned short tx_stat, rx_stat;
......
......@@ -359,7 +359,6 @@ typedef struct _mace_statistics {
typedef struct _mace_private {
dev_link_t link;
struct net_device dev;
dev_node_t node;
struct net_device_stats linux_stats; /* Linux statistics counters */
mace_statistics mace_stats; /* MACE chip statistics counters */
......@@ -476,11 +475,12 @@ static dev_link_t *nmclan_attach(void)
flush_stale_links();
/* Create new ethernet device */
lp = kmalloc(sizeof(*lp), GFP_KERNEL);
if (!lp) return NULL;
memset(lp, 0, sizeof(*lp));
link = &lp->link; dev = &lp->dev;
link->priv = dev->priv = link->irq.Instance = lp;
dev = alloc_etherdev(sizeof(mace_private));
if (!dev)
return NULL;
lp = dev->priv;
link = &lp->link;
link->priv = dev;
init_timer(&link->release);
link->release.function = &nmclan_release;
......@@ -496,6 +496,7 @@ static dev_link_t *nmclan_attach(void)
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
link->irq.Handler = &mace_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
......@@ -510,7 +511,6 @@ static dev_link_t *nmclan_attach(void)
dev->get_stats = &mace_get_stats;
dev->set_multicast_list = &set_multicast_list;
dev->do_ioctl = &mace_ioctl;
ether_setup(dev);
dev->open = &mace_open;
dev->stop = &mace_close;
#ifdef HAVE_TX_TIMEOUT
......@@ -550,7 +550,7 @@ nmclan_detach
static void nmclan_detach(dev_link_t *link)
{
mace_private *lp = link->priv;
struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "nmclan_detach(0x%p)\n", link);
......@@ -576,8 +576,8 @@ static void nmclan_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
if (link->dev)
unregister_netdev(&lp->dev);
kfree(lp);
unregister_netdev(dev);
kfree(dev);
} /* nmclan_detach */
......@@ -710,8 +710,8 @@ while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
static void nmclan_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
mace_private *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;;
mace_private *lp = dev->priv;
tuple_t tuple;
cisparse_t parse;
u_char buf[64];
......@@ -836,8 +836,7 @@ static int nmclan_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
mace_private *lp = link->priv;
struct net_device *dev = &lp->dev;
struct net_device *dev = link->priv;
DEBUG(1, "nmclan_event(0x%06x)\n", event);
......@@ -1145,8 +1144,8 @@ mace_interrupt
---------------------------------------------------------------------------- */
static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
mace_private *lp = (mace_private *)dev_id;
struct net_device *dev = &lp->dev;
struct net_device *dev = (struct net_device *) dev_id;
mace_private *lp = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
int status;
int IntrCnt = MACE_MAX_IR_ITERATIONS;
......
......@@ -113,7 +113,6 @@ static dev_link_t *dev_list;
struct smc_private {
dev_link_t link;
struct net_device dev;
spinlock_t lock;
u_short manfid;
u_short cardid;
......@@ -344,10 +343,13 @@ static dev_link_t *smc91c92_attach(void)
flush_stale_links();
/* Create new ethernet device */
smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL);
if (!smc) return NULL;
memset(smc, 0, sizeof(struct smc_private));
link = &smc->link; dev = &smc->dev;
dev = alloc_etherdev(sizeof(struct smc_private));
if (!dev)
return NULL;
smc = dev->priv;
link = &smc->link;
link->priv = dev;
spin_lock_init(&smc->lock);
init_timer(&link->release);
link->release.function = &smc91c92_release;
......@@ -363,6 +365,7 @@ static dev_link_t *smc91c92_attach(void)
for (i = 0; i < 4; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
link->irq.Handler = &smc_interrupt;
link->irq.Instance = dev;
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
......@@ -373,7 +376,6 @@ static dev_link_t *smc91c92_attach(void)
dev->get_stats = &smc_get_stats;
dev->set_config = &s9k_config;
dev->set_multicast_list = &set_rx_mode;
ether_setup(dev);
dev->open = &smc_open;
dev->stop = &smc_close;
dev->do_ioctl = &smc_ioctl;
......@@ -381,7 +383,6 @@ static dev_link_t *smc91c92_attach(void)
dev->tx_timeout = smc_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
#endif
dev->priv = link->priv = link->irq.Instance = smc;
smc->mii_if.dev = dev;
smc->mii_if.mdio_read = mdio_read;
......@@ -421,7 +422,7 @@ static dev_link_t *smc91c92_attach(void)
static void smc91c92_detach(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = link->priv;
dev_link_t **linkp;
DEBUG(0, "smc91c92_detach(0x%p)\n", link);
......@@ -447,8 +448,8 @@ static void smc91c92_detach(dev_link_t *link)
/* Unlink device structure, free bits */
*linkp = link->next;
if (link->dev)
unregister_netdev(&smc->dev);
kfree(smc);
unregister_netdev(dev);
kfree(dev);
} /* smc91c92_detach */
......@@ -502,7 +503,8 @@ static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
static int mhz_3288_power(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = link->priv;
struct smc_private *smc = dev->priv;
u_char tmp;
/* Read the ISR twice... */
......@@ -523,8 +525,8 @@ static int mhz_3288_power(dev_link_t *link)
static int mhz_mfc_config(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
struct smc_private *smc = dev->priv;
tuple_t tuple;
cisparse_t parse;
u_char buf[255];
......@@ -590,8 +592,7 @@ static int mhz_mfc_config(dev_link_t *link)
static int mhz_setup(dev_link_t *link)
{
client_handle_t handle = link->handle;
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
u_char buf[255], *station_addr;
......@@ -638,8 +639,8 @@ static int mhz_setup(dev_link_t *link)
static void mot_config(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
struct smc_private *smc = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
ioaddr_t iouart = link->io.BasePort2;
......@@ -659,8 +660,7 @@ static void mot_config(dev_link_t *link)
static int mot_setup(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
ioaddr_t ioaddr = dev->base_addr;
int i, wait, loop;
u_int addr;
......@@ -694,8 +694,7 @@ static int mot_setup(dev_link_t *link)
static int smc_config(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
u_char buf[255];
......@@ -727,8 +726,7 @@ static int smc_config(dev_link_t *link)
static int smc_setup(dev_link_t *link)
{
client_handle_t handle = link->handle;
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
tuple_t tuple;
cisparse_t parse;
cistpl_lan_node_id_t *node_id;
......@@ -755,7 +753,6 @@ static int smc_setup(dev_link_t *link)
return 0;
}
}
/* Try the third string in the Version 1 Version/ID tuple. */
tuple.DesiredTuple = CISTPL_VERS_1;
if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)
......@@ -771,8 +768,7 @@ static int smc_setup(dev_link_t *link)
static int osi_config(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
int i, j;
......@@ -806,8 +802,7 @@ static int osi_config(dev_link_t *link)
static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
{
client_handle_t handle = link->handle;
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
tuple_t tuple;
u_char buf[255];
int i;
......@@ -862,8 +857,7 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid)
static int check_sig(dev_link_t *link)
{
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
ioaddr_t ioaddr = dev->base_addr;
int width;
u_short s;
......@@ -921,8 +915,8 @@ if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; }
static void smc91c92_config(dev_link_t *link)
{
client_handle_t handle = link->handle;
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
struct smc_private *smc = dev->priv;
tuple_t tuple;
cisparse_t parse;
u_short buf[32];
......@@ -1090,7 +1084,6 @@ static void smc91c92_config(dev_link_t *link)
static void smc91c92_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
struct smc_private *smc = link->priv;
DEBUG(0, "smc91c92_release(0x%p)\n", link);
......@@ -1105,6 +1098,8 @@ static void smc91c92_release(u_long arg)
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
if (link->win) {
struct net_device *dev = link->priv;
struct smc_private *smc = dev->priv;
iounmap(smc->base);
CardServices(ReleaseWindow, link->win);
}
......@@ -1126,8 +1121,8 @@ static int smc91c92_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
struct smc_private *smc = link->priv;
struct net_device *dev = &smc->dev;
struct net_device *dev = link->priv;
struct smc_private *smc = dev->priv;
int i;
DEBUG(1, "smc91c92_event(0x%06x)\n", event);
......@@ -1302,7 +1297,7 @@ static int smc_open(struct net_device *dev)
smc_reset(dev);
init_timer(&smc->media);
smc->media.function = &media_check;
smc->media.data = (u_long)smc;
smc->media.data = (u_long) dev;
smc->media.expires = jiffies + HZ;
add_timer(&smc->media);
......@@ -1576,8 +1571,8 @@ static void smc_eph_irq(struct net_device *dev)
static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct smc_private *smc = dev_id;
struct net_device *dev = &smc->dev;
struct net_device *dev = dev_id;
struct smc_private *smc = dev->priv;
ioaddr_t ioaddr;
u_short saved_bank, saved_pointer, mask, status;
unsigned int handled = 1;
......@@ -1967,8 +1962,8 @@ static void smc_reset(struct net_device *dev)
static void media_check(u_long arg)
{
struct smc_private *smc = (struct smc_private *)(arg);
struct net_device *dev = &smc->dev;
struct net_device *dev = (struct net_device *) arg;
struct smc_private *smc = dev->priv;
ioaddr_t ioaddr = dev->base_addr;
u_short i, media, saved_bank;
u_short link;
......
/*
* Copyright (C) 2001 Broadcom Corporation
* Copyright (C) 2001,2002,2003 Broadcom Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -17,17 +17,21 @@
*/
/*
This driver is designed for the Broadcom BCM12500 SOC chip's built-in
This driver is designed for the Broadcom SiByte SOC built-in
Ethernet controllers.
The author may be reached as mpl@broadcom.com
Written by Mitch Lichtenberg at Broadcom Corp.
*/
#define CONFIG_SBMAC_COALESCE
/* A few user-configurable values.
These may be modified when a driver module is loaded. */
static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */
static int noisy_mii = 1; /* mii status msgs */
/* Used to pass the media type, etc.
Both 'options[]' and 'full_duplex[]' should exist for driver
......@@ -41,6 +45,10 @@ static int options[MAX_UNITS] = {-1, -1, -1};
static int full_duplex[MAX_UNITS] = {-1, -1, -1};
#endif
#ifdef CONFIG_SBMAC_COALESCE
static int int_pktcnt = 0;
static int int_timeout = 0;
#endif
/* Operational parameters that usually are not changed. */
......@@ -59,22 +67,21 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1};
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/config.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/bitops.h>
#include <asm/io.h>
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/64bit.h>
#include <asm/cache.h>
/* This is only here until the firmware is ready. In that case,
the firmware leaves the ethernet address in the register for us. */
#ifdef CONFIG_SWARM_STANDALONE
#ifdef CONFIG_SIBYTE_STANDALONE
#define SBMAC_ETH0_HWADDR "40:00:00:00:01:00"
#define SBMAC_ETH1_HWADDR "40:00:00:00:01:01"
#define SBMAC_ETH2_HWADDR "40:00:00:00:01:02"
......@@ -84,23 +91,29 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1};
/* These identify the driver base version and may not be removed. */
#if 0
static char version1[] __devinitdata =
"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg (mpl@broadcom.com)\n";
"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg\n";
#endif
MODULE_AUTHOR("Mitch Lichtenberg (mpl@broadcom.com)");
MODULE_DESCRIPTION("Broadcom BCM12500 SOC GB Ethernet driver");
MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");
MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");
MODULE_PARM(debug, "i");
MODULE_PARM(noisy_mii, "i");
MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(int_pktcnt, "i");
MODULE_PARM(int_timeout, "i");
#include <asm/sibyte/sb1250.h>
#include <asm/sibyte/sb1250_defs.h>
#include <asm/sibyte/sb1250_regs.h>
#include <asm/sibyte/sb1250_mac.h>
#include <asm/sibyte/sb1250_dma.h>
#include <asm/sibyte/sb1250_int.h>
#include <asm/sibyte/sb1250_scd.h>
#include <asm/sibyte/64bit.h>
/**********************************************************************
......@@ -109,8 +122,6 @@ MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
typedef unsigned long sbmac_port_t;
typedef uint64_t sbmac_physaddr_t;
typedef uint64_t sbmac_enetaddr_t;
typedef enum { sbmac_speed_auto, sbmac_speed_10,
sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t;
......@@ -134,17 +145,11 @@ typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
(d)->sbdma_dscrtable : (d)->f+1)
#define CACHELINESIZE 32
#define NUMCACHEBLKS(x) (((x)+CACHELINESIZE-1)/CACHELINESIZE)
#define KMALLOC(x) kmalloc((x),GFP_KERNEL)
#define KFREE(x) kfree(x)
#define KVTOPHYS(x) virt_to_bus((void *)(x))
#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
#define SBMAC_READCSR(t) in64((unsigned long)t)
#define SBMAC_WRITECSR(t,v) out64(v, (unsigned long)t)
#define SBMAC_READCSR(t) (in64((unsigned long)(t)))
#define SBMAC_WRITECSR(t,v) (out64(v, (unsigned long)(t)))
#define PKSEG1(x) ((sbmac_port_t) KSEG1ADDR(x))
#define SBMAC_MAX_TXDESCR 32
#define SBMAC_MAX_RXDESCR 32
......@@ -152,6 +157,7 @@ typedef enum { sbmac_state_uninit, sbmac_state_off, sbmac_state_on,
#define ETHER_ALIGN 2
#define ETHER_ADDR_LEN 6
#define ENET_PACKET_SIZE 1518
/*#define ENET_PACKET_SIZE 9216 */
/**********************************************************************
* DMA Descriptor structure
......@@ -163,7 +169,6 @@ typedef struct sbdmadscr_s {
} sbdmadscr_t;
typedef unsigned long paddr_t;
typedef unsigned long vaddr_t;
/**********************************************************************
* DMA Controller structure
......@@ -180,6 +185,11 @@ typedef struct sbmacdma_s {
int sbdma_channel; /* channel number */
int sbdma_txdir; /* direction (1=transmit) */
int sbdma_maxdescr; /* total # of descriptors in ring */
#ifdef CONFIG_SBMAC_COALESCE
int sbdma_int_pktcnt; /* # descriptors rx/tx before interrupt*/
int sbdma_int_timeout; /* # usec rx/tx interrupt */
#endif
sbmac_port_t sbdma_config0; /* DMA config register 0 */
sbmac_port_t sbdma_config1; /* DMA config register 1 */
sbmac_port_t sbdma_dscrbase; /* Descriptor base address */
......@@ -198,7 +208,6 @@ typedef struct sbmacdma_s {
paddr_t sbdma_dscrtable_phys; /* and also the phys addr */
sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */
sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */
} sbmacdma_t;
......@@ -230,7 +239,7 @@ struct sbmac_softc {
* Controller-specific things
*/
sbmac_port_t sbm_base; /* MAC's base address */
unsigned long sbm_base; /* MAC's base address */
sbmac_state_t sbm_state; /* current state */
sbmac_port_t sbm_macenable; /* MAC Enable Register */
......@@ -246,11 +255,12 @@ struct sbmac_softc {
sbmac_duplex_t sbm_duplex; /* current duplex */
sbmac_fc_t sbm_fc; /* current flow control setting */
u_char sbm_hwaddr[ETHER_ADDR_LEN];
unsigned char sbm_hwaddr[ETHER_ADDR_LEN];
sbmacdma_t sbm_txdma; /* for now, only use channel 0 */
sbmacdma_t sbm_rxdma;
int rx_hw_checksum;
int sbe_idx;
};
......@@ -267,7 +277,7 @@ static void sbdma_initctx(sbmacdma_t *d,
int chan,
int txrx,
int maxdescr);
static void sbdma_channel_start(sbmacdma_t *d);
static void sbdma_channel_start(sbmacdma_t *d, int rxtx);
static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *m);
static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m);
static void sbdma_emptyring(sbmacdma_t *d);
......@@ -279,12 +289,11 @@ static void sbmac_channel_start(struct sbmac_softc *s);
static void sbmac_channel_stop(struct sbmac_softc *s);
static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t);
static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff);
/*static void sbmac_init_and_start(struct sbmac_softc *sc);*/
static uint64_t sbmac_addr2reg(unsigned char *ptr);
static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
static void sbmac_setmulti(struct sbmac_softc *sc);
static int sbmac_init(struct net_device *dev);
static int sbmac_init(struct net_device *dev, int idx);
static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed);
static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc);
......@@ -308,6 +317,8 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
* Globals
********************************************************************* */
static uint64_t sbmac_orig_hwaddr[MAX_UNITS];
/**********************************************************************
* MDIO constants
......@@ -328,8 +339,8 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
#define BMCR_DUPLEX 0x0100
#define BMCR_COLTEST 0x0080
#define BMCR_SPEED1 0x0040
#define BMCR_SPEED1000 (BMCR_SPEED1|BMCR_SPEED0)
#define BMCR_SPEED100 (BMCR_SPEED0)
#define BMCR_SPEED1000 BMCR_SPEED1
#define BMCR_SPEED100 BMCR_SPEED0
#define BMCR_SPEED10 0
#define BMSR_100BT4 0x8000
......@@ -437,6 +448,8 @@ static void sbmac_mii_write(struct sbmac_softc *s,int phyaddr,int regidx,
#define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */
#define ENABLE 1
#define DISABLE 0
/**********************************************************************
* SBMAC_MII_SYNC(s)
......@@ -490,7 +503,8 @@ static void sbmac_mii_senddata(struct sbmac_softc *s,unsigned int data, int bitc
curmask = 1 << (bitcnt - 1);
for (i = 0; i < bitcnt; i++) {
if (data & curmask) bits |= M_MAC_MDIO_OUT;
if (data & curmask)
bits |= M_MAC_MDIO_OUT;
else bits &= ~M_MAC_MDIO_OUT;
SBMAC_WRITECSR(s->sbm_mdio,bits);
SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC);
......@@ -571,7 +585,8 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
regval <<= 1;
if (error == 0) {
if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN) regval |= 1;
if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN)
regval |= 1;
}
SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC);
......@@ -581,7 +596,8 @@ static unsigned int sbmac_mii_read(struct sbmac_softc *s,int phyaddr,int regidx)
/* Switch back to output */
SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT);
if (error == 0) return regval;
if (error == 0)
return regval;
return 0;
}
......@@ -651,20 +667,68 @@ static void sbdma_initctx(sbmacdma_t *d,
d->sbdma_channel = chan;
d->sbdma_txdir = txrx;
#if 0
/* RMON clearing */
s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
#endif
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0);
SBMAC_WRITECSR(KSEG1ADDR(
A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0);
/*
* initialize register pointers
*/
d->sbdma_config0 =
PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
d->sbdma_config1 =
PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
d->sbdma_dscrbase =
PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE));
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
d->sbdma_dscrcnt =
PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT));
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
d->sbdma_curdscr =
PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR));
s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
/*
* Allocate memory for the ring
......@@ -673,23 +737,41 @@ static void sbdma_initctx(sbmacdma_t *d,
d->sbdma_maxdescr = maxdescr;
d->sbdma_dscrtable = (sbdmadscr_t *)
KMALLOC(d->sbdma_maxdescr*sizeof(sbdmadscr_t));
kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL);
memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t));
d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
d->sbdma_dscrtable_phys = KVTOPHYS(d->sbdma_dscrtable);
d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
/*
* And context table
*/
d->sbdma_ctxtable = (struct sk_buff **)
KMALLOC(d->sbdma_maxdescr*sizeof(struct sk_buff *));
kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL);
memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *));
#ifdef CONFIG_SBMAC_COALESCE
/*
* Setup Rx/Tx DMA coalescing defaults
*/
if ( int_pktcnt ) {
d->sbdma_int_pktcnt = int_pktcnt;
} else {
d->sbdma_int_pktcnt = 1;
}
if ( int_timeout ) {
d->sbdma_int_timeout = int_timeout;
} else {
d->sbdma_int_timeout = 0;
}
#endif
}
/**********************************************************************
......@@ -699,24 +781,35 @@ static void sbdma_initctx(sbmacdma_t *d,
*
* Input parameters:
* d - DMA channel to init (context must be previously init'd
* rxtx - DMA_RX or DMA_TX depending on what type of channel
*
* Return value:
* nothing
********************************************************************* */
static void sbdma_channel_start(sbmacdma_t *d)
static void sbdma_channel_start(sbmacdma_t *d, int rxtx )
{
/*
* Turn on the DMA channel
*/
#ifdef CONFIG_SBMAC_COALESCE
SBMAC_WRITECSR(d->sbdma_config1,
V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
0);
SBMAC_WRITECSR(d->sbdma_config0,
M_DMA_EOP_INT_EN |
V_DMA_RINGSZ(d->sbdma_maxdescr) |
V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
0);
#else
SBMAC_WRITECSR(d->sbdma_config1,0);
SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
SBMAC_WRITECSR(d->sbdma_config0,
V_DMA_RINGSZ(d->sbdma_maxdescr) |
0);
#endif
SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
/*
* Initialize ring pointers
......@@ -726,6 +819,37 @@ static void sbdma_channel_start(sbmacdma_t *d)
d->sbdma_remptr = d->sbdma_dscrtable;
}
/**********************************************************************
* SBDMA_CHANNEL_STOP(d)
*
* Initialize the hardware registers for a DMA channel.
*
* Input parameters:
* d - DMA channel to init (context must be previously init'd
*
* Return value:
* nothing
********************************************************************* */
static void sbdma_channel_stop(sbmacdma_t *d)
{
/*
* Turn off the DMA channel
*/
SBMAC_WRITECSR(d->sbdma_config1,0);
SBMAC_WRITECSR(d->sbdma_dscrbase,0);
SBMAC_WRITECSR(d->sbdma_config0,0);
/*
* Zero ring pointers
*/
d->sbdma_addptr = 0;
d->sbdma_remptr = 0;
}
static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset)
{
......@@ -791,21 +915,21 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
* 3. The buffer can be aligned such that the IP addresses are
* naturally aligned.
*
* Remember, the SB1250's MAC writes whole cache lines at a time,
* Remember, the SOCs MAC writes whole cache lines at a time,
* without reading the old contents first. So, if the sk_buff's
* data portion starts in the middle of a cache line, the SB1250
* data portion starts in the middle of a cache line, the SOC
* DMA will trash the beginning (and ending) portions.
*/
if (sb == NULL) {
sb_new = dev_alloc_skb(ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN);
sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN);
if (sb_new == NULL) {
printk(KERN_INFO "%s: sk_buff allocation failed\n",
d->sbdma_eth->sbm_dev->name);
return -ENOBUFS;
}
sbdma_align_skb(sb_new,CACHELINESIZE,ETHER_ALIGN);
sbdma_align_skb(sb_new, SMP_CACHE_BYTES, ETHER_ALIGN);
/* mark skbuff owned by our device */
sb_new->dev = d->sbdma_eth->sbm_dev;
......@@ -814,7 +938,7 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
sb_new = sb;
/*
* nothing special to reinit buffer, it's already aligned
* and sb->tail already points to a good place.
* and sb->data already points to a good place.
*/
}
......@@ -822,9 +946,18 @@ static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *sb)
* fill in the descriptor
*/
dsc->dscr_a = KVTOPHYS(sb_new->tail) |
#ifdef CONFIG_SBMAC_COALESCE
/*
* Do not interrupt per DMA transfer.
*/
dsc->dscr_a = virt_to_phys(sb_new->tail) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
0;
#else
dsc->dscr_a = virt_to_phys(sb_new->tail) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
M_DMA_DSCRA_INTERRUPT;
#endif
/* receiving: no options */
dsc->dscr_b = 0;
......@@ -904,12 +1037,14 @@ static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *sb)
* while doing the calculation.
*/
phys = KVTOPHYS(sb->data);
ncb = NUMCACHEBLKS(length+(phys & (CACHELINESIZE-1)));
phys = virt_to_phys(sb->data);
ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
dsc->dscr_a = phys |
V_DMA_DSCRA_A_SIZE(ncb) |
#ifndef CONFIG_SBMAC_COALESCE
M_DMA_DSCRA_INTERRUPT |
#endif
M_DMA_ETHTX_SOP;
/* transmitting: set outbound options and length */
......@@ -986,7 +1121,8 @@ static void sbdma_fillring(sbmacdma_t *d)
int idx;
for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) {
if (sbdma_add_rcvbuffer(d,NULL) != 0) break;
if (sbdma_add_rcvbuffer(d,NULL) != 0)
break;
}
}
......@@ -1037,7 +1173,8 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* the hardware is working on right now.
*/
if (curidx == hwidx) break;
if (curidx == hwidx)
break;
/*
* Otherwise, get the packet's sk_buff ptr back
......@@ -1057,11 +1194,6 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
/*
* Set length into the packet
*/
skb_put(sb,len);
/*
* Add a new buffer to replace the old one. If we fail
* to allocate a buffer, we're going to drop this
......@@ -1069,24 +1201,45 @@ static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d)
*/
if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
sc->sbm_stats.rx_dropped++;
sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
}
else {
} else {
/*
* Buffer has been replaced on the receive ring.
* Pass the buffer to the kernel
* Set length into the packet
*/
skb_put(sb,len);
/*
* Buffer has been replaced on the
* receive ring. Pass the buffer to
* the kernel */
sc->sbm_stats.rx_bytes += len;
sc->sbm_stats.rx_packets++;
sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
if (sc->rx_hw_checksum == ENABLE) {
/* if the ip checksum is good
indicate in skb. else set
CHECKSUM_NONE as device
failed to checksum the
packet */
if (((dsc->dscr_b) |M_DMA_ETHRX_BADTCPCS) ||
((dsc->dscr_a)| M_DMA_ETHRX_BADIP4CS)) {
sb->ip_summed = CHECKSUM_NONE;
} else {
printk(KERN_DEBUG "hw checksum fail .\n");
sb->ip_summed = CHECKSUM_UNNECESSARY;
}
} /* rx_hw_checksum */
netif_rx(sb);
}
}
else {
} else {
/*
* Packet was mangled somehow. Just drop it and
* put it back on the receive ring.
*/
sc->sbm_stats.rx_errors++;
sbdma_add_rcvbuffer(d,sb);
}
......@@ -1143,19 +1296,25 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
{
/* XXX This is gross, ugly, and only here because justin hacked it
in to fix a problem without really understanding it.
It seems that, for whatever reason, this routine is invoked immediately upon the enabling of interrupts.
So then the Read below returns zero, making hwidx a negative number, and anti-hilarity
ensues.
I'm guessing there's a proper fix involving clearing out interrupt state from old packets
before enabling interrupts, but I'm not sure.
Anyways, this hack seems to work, and is Good Enough for 11 PM. :)
-Justin
/* XXX This is gross, ugly, and only here
* because justin hacked it in to fix a
* problem without really understanding it.
*
* It seems that, for whatever reason, this
* routine is invoked immediately upon the
* enabling of interrupts. So then the Read
* below returns zero, making hwidx a negative
* number, and anti-hilarity ensues.
*
* I'm guessing there's a proper fix involving
* clearing out interrupt state from old
* packets before enabling interrupts, but I'm
* not sure.
*
* Anyways, this hack seems to work, and is
* Good Enough for 11 PM. :)
*
* -Justin
*/
uint64_t tmp = SBMAC_READCSR(d->sbdma_curdscr);
......@@ -1171,7 +1330,8 @@ static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d)
* the hardware is working on right now.
*/
if (curidx == hwidx) break;
if (curidx == hwidx)
break;
/*
* Otherwise, get the packet's sk_buff ptr back
......@@ -1238,14 +1398,14 @@ static int sbmac_initctx(struct sbmac_softc *s)
* figure out the addresses of some ports
*/
s->sbm_macenable = PKSEG1(s->sbm_base + R_MAC_ENABLE);
s->sbm_maccfg = PKSEG1(s->sbm_base + R_MAC_CFG);
s->sbm_fifocfg = PKSEG1(s->sbm_base + R_MAC_THRSH_CFG);
s->sbm_framecfg = PKSEG1(s->sbm_base + R_MAC_FRAMECFG);
s->sbm_rxfilter = PKSEG1(s->sbm_base + R_MAC_ADFILTER_CFG);
s->sbm_isr = PKSEG1(s->sbm_base + R_MAC_STATUS);
s->sbm_imr = PKSEG1(s->sbm_base + R_MAC_INT_MASK);
s->sbm_mdio = PKSEG1(s->sbm_base + R_MAC_MDIO);
s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
s->sbm_maccfg = s->sbm_base + R_MAC_CFG;
s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG;
s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG;
s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG;
s->sbm_isr = s->sbm_base + R_MAC_STATUS;
s->sbm_imr = s->sbm_base + R_MAC_INT_MASK;
s->sbm_mdio = s->sbm_base + R_MAC_MDIO;
s->sbm_phys[0] = 1;
s->sbm_phys[1] = 0;
......@@ -1284,12 +1444,12 @@ static int sbmac_initctx(struct sbmac_softc *s)
static void sbdma_uninitctx(struct sbmacdma_s *d)
{
if (d->sbdma_dscrtable) {
KFREE(d->sbdma_dscrtable);
kfree(d->sbdma_dscrtable);
d->sbdma_dscrtable = NULL;
}
if (d->sbdma_ctxtable) {
KFREE(d->sbdma_ctxtable);
kfree(d->sbdma_ctxtable);
d->sbdma_ctxtable = NULL;
}
}
......@@ -1319,13 +1479,14 @@ static void sbmac_channel_start(struct sbmac_softc *s)
uint64_t reg;
sbmac_port_t port;
uint64_t cfg,fifo,framecfg;
int idx;
int idx, th_value;
/*
* Don't do this if running
*/
if (s->sbm_state == sbmac_state_on) return;
if (s->sbm_state == sbmac_state_on)
return;
/*
* Bring the controller out of reset, but leave it off.
......@@ -1351,8 +1512,19 @@ static void sbmac_channel_start(struct sbmac_softc *s)
M_MAC_SS_EN |
0;
/*
* Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
* and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
* Use a larger RD_THRSH for gigabit
*/
if (periph_rev >= 2)
th_value = 64;
else
th_value = 28;
fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
V_MAC_TX_RD_THRSH(4) |
((s->sbm_speed == sbmac_speed_1000)
? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) |
V_MAC_TX_RL_THRSH(4) |
V_MAC_RX_PL_THRSH(4) |
V_MAC_RX_RD_THRSH(4) | /* Must be '4' */
......@@ -1364,12 +1536,11 @@ static void sbmac_channel_start(struct sbmac_softc *s)
V_MAC_MAX_FRAMESZ_DEFAULT |
V_MAC_BACKOFF_SEL(1);
/*
* Clear out the hash address map
*/
port = PKSEG1(s->sbm_base + R_MAC_HASH_BASE);
port = s->sbm_base + R_MAC_HASH_BASE;
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
......@@ -1379,7 +1550,7 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* Clear out the exact-match table
*/
port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
port = s->sbm_base + R_MAC_ADDR_BASE;
for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
......@@ -1389,14 +1560,14 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* Clear out the DMA Channel mapping table registers
*/
port = PKSEG1(s->sbm_base + R_MAC_CHUP0_BASE);
port = s->sbm_base + R_MAC_CHUP0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
}
port = PKSEG1(s->sbm_base + R_MAC_CHLO0_BASE);
port = s->sbm_base + R_MAC_CHLO0_BASE;
for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
SBMAC_WRITECSR(port,0);
port += sizeof(uint64_t);
......@@ -1409,13 +1580,13 @@ static void sbmac_channel_start(struct sbmac_softc *s)
reg = sbmac_addr2reg(s->sbm_hwaddr);
port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE);
port = s->sbm_base + R_MAC_ADDR_BASE;
SBMAC_WRITECSR(port,reg);
port = PKSEG1(s->sbm_base + R_MAC_ETHERNET_ADDR);
port = s->sbm_base + R_MAC_ETHERNET_ADDR;
#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
/*
* Pass1 SB1250s do not receive packets addressed to the
* Pass1 SOCs do not receive packets addressed to the
* destination address in the R_MAC_ETHERNET_ADDR register.
* Set the value to zero.
*/
......@@ -1439,8 +1610,8 @@ static void sbmac_channel_start(struct sbmac_softc *s)
* Initialize DMA channels (rings should be ok now)
*/
sbdma_channel_start(&(s->sbm_rxdma));
sbdma_channel_start(&(s->sbm_txdma));
sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
/*
* Configure the speed, duplex, and flow control
......@@ -1467,12 +1638,22 @@ static void sbmac_channel_start(struct sbmac_softc *s)
#ifdef CONFIG_SBMAC_COALESCE
/*
* Accept any TX interrupt and EOP count/timer RX interrupts on ch 0
*/
SBMAC_WRITECSR(s->sbm_imr,
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
#else
/*
* Accept any kind of interrupt on TX and RX DMA channel 0
*/
SBMAC_WRITECSR(s->sbm_imr,
(M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
(M_MAC_INT_CHANNEL << S_MAC_RX_CH0));
#endif
/*
* Enable receiving unicasts and broadcasts
......@@ -1517,11 +1698,10 @@ static void sbmac_channel_start(struct sbmac_softc *s)
static void sbmac_channel_stop(struct sbmac_softc *s)
{
uint64_t ctl;
/* don't do this if already stopped */
if (s->sbm_state == sbmac_state_off) return;
if (s->sbm_state == sbmac_state_off)
return;
/* don't accept any packets, disable all interrupts */
......@@ -1534,14 +1714,18 @@ static void sbmac_channel_stop(struct sbmac_softc *s)
/* turn off receiver and transmitter */
ctl = SBMAC_READCSR(s->sbm_macenable);
ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0);
SBMAC_WRITECSR(s->sbm_macenable,ctl);
SBMAC_WRITECSR(s->sbm_macenable,0);
/* We're stopped now. */
s->sbm_state = sbmac_state_off;
/*
* Stop DMA channels (rings should be ok now)
*/
sbdma_channel_stop(&(s->sbm_rxdma));
sbdma_channel_stop(&(s->sbm_txdma));
/* Empty the receive and transmit rings */
......@@ -1610,7 +1794,8 @@ static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
{
uint64_t reg;
if (sc->sbm_state != sbmac_state_on) return;
if (sc->sbm_state != sbmac_state_on)
return;
if (onoff) {
reg = SBMAC_READCSR(sc->sbm_rxfilter);
......@@ -1624,31 +1809,36 @@ static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
}
}
#if 0
/**********************************************************************
* SBMAC_INIT_AND_START(sc)
* SBMAC_SETIPHDR_OFFSET(sc,onoff)
*
* Stop the channel and restart it. This is generally used
* when we have to do something to the channel that requires
* a swift kick.
* Set the iphdr offset as 15 assuming ethernet encapsulation
*
* Input parameters:
* sc - softc
*
* Return value:
* nothing
********************************************************************* */
static void sbmac_init_and_start(struct sbmac_softc *sc)
static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
{
unsigned long flags;
spin_lock_irqsave(&(sc->sbm_lock),flags);
uint64_t reg;
sbmac_set_channel_state(sc,sbmac_state_on);
/* Hard code the off set to 15 for now */
reg = SBMAC_READCSR(sc->sbm_rxfilter);
reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
SBMAC_WRITECSR(sc->sbm_rxfilter,reg);
spin_unlock_irqrestore(&(sc->sbm_lock),flags);
/* read system identification to determine revision */
if (periph_rev >= 2) {
printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
sc->sbm_dev->name);
sc->rx_hw_checksum = ENABLE;
} else {
sc->rx_hw_checksum = DISABLE;
}
}
#endif
/**********************************************************************
......@@ -1712,7 +1902,8 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
s->sbm_speed = speed;
if (s->sbm_state == sbmac_state_on) return 0; /* save for next restart */
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
/*
* Read current register values
......@@ -1772,7 +1963,6 @@ static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed)
SBMAC_WRITECSR(s->sbm_maccfg,cfg);
return 1;
}
/**********************************************************************
......@@ -1802,7 +1992,8 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
s->sbm_duplex = duplex;
s->sbm_fc = fc;
if (s->sbm_state == sbmac_state_on) return 0; /* save for next restart */
if (s->sbm_state == sbmac_state_on)
return 0; /* save for next restart */
/*
* Read current register values
......@@ -1886,7 +2077,7 @@ static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc
* Return value:
* nothing
********************************************************************* */
static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
{
struct net_device *dev = (struct net_device *) dev_instance;
struct sbmac_softc *sc = (struct sbmac_softc *) (dev->priv);
......@@ -1896,14 +2087,17 @@ static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
for (;;) {
/*
* Read the ISR (this clears the bits in the real register)
* Read the ISR (this clears the bits in the real
* register, except for counter addr)
*/
isr = SBMAC_READCSR(sc->sbm_isr);
isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
if (isr == 0)
break;
handled = 1;
/*
* Transmits on channel 0
*/
......@@ -1916,6 +2110,23 @@ static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs)
* Receives on channel 0
*/
/*
* It's important to test all the bits (or at least the
* EOP_SEEN bit) when deciding to do the RX process
* particularly when coalescing, to make sure we
* take care of the following:
*
* If you have some packets waiting (have been received
* but no interrupt) and get a TX interrupt before
* the RX timer or counter expires, reading the ISR
* above will clear the timer and counter, and you
* won't get another interrupt until a packet shows
* up to start the timer again. Testing
* EOP_SEEN here takes care of this case.
* (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0)
*/
if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
sbdma_rx_process(sc,&(sc->sbm_rxdma));
}
......@@ -1952,6 +2163,9 @@ static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
/* XXX save skb that we could not send */
netif_stop_queue(dev);
spin_unlock_irq(&sc->sbm_lock);
return 1;
}
dev->trans_start = jiffies;
......@@ -1990,12 +2204,12 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
*/
for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
port = PKSEG1(sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)));
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
SBMAC_WRITECSR(port,0);
}
for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
port = PKSEG1(sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)));
port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
SBMAC_WRITECSR(port,0);
}
......@@ -2032,8 +2246,7 @@ static void sbmac_setmulti(struct sbmac_softc *sc)
mclist = dev->mc_list;
while (mclist && (idx < MAC_ADDR_COUNT)) {
reg = sbmac_addr2reg(mclist->dmi_addr);
port = PKSEG1(sc->sbm_base +
R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)));
port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
SBMAC_WRITECSR(port,reg);
idx++;
mclist = mclist->next;
......@@ -2070,10 +2283,14 @@ static int sbmac_parse_xdigit(char str)
{
int digit;
if ((str >= '0') && (str <= '9')) digit = str - '0';
else if ((str >= 'a') && (str <= 'f')) digit = str - 'a' + 10;
else if ((str >= 'A') && (str <= 'F')) digit = str - 'A' + 10;
else return -1;
if ((str >= '0') && (str <= '9'))
digit = str - '0';
else if ((str >= 'a') && (str <= 'f'))
digit = str - 'a' + 10;
else if ((str >= 'A') && (str <= 'F'))
digit = str - 'A' + 10;
else
return -1;
return digit;
}
......@@ -2092,16 +2309,18 @@ static int sbmac_parse_xdigit(char str)
* 0 if ok, else -1
********************************************************************* */
static int sbmac_parse_hwaddr(char *str,u_char *hwaddr)
static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr)
{
int digit1,digit2;
int idx = 6;
while (*str && (idx > 0)) {
digit1 = sbmac_parse_xdigit(*str);
if (digit1 < 0) return -1;
if (digit1 < 0)
return -1;
str++;
if (!*str) return -1;
if (!*str)
return -1;
if ((*str == ':') || (*str == '-')) {
digit2 = digit1;
......@@ -2109,20 +2328,32 @@ static int sbmac_parse_hwaddr(char *str,u_char *hwaddr)
}
else {
digit2 = sbmac_parse_xdigit(*str);
if (digit2 < 0) return -1;
if (digit2 < 0)
return -1;
str++;
}
*hwaddr++ = (digit1 << 4) | digit2;
idx--;
if (*str == '-') str++;
if (*str == ':') str++;
if (*str == '-')
str++;
if (*str == ':')
str++;
}
return 0;
}
#endif
static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
{
if (new_mtu > ENET_PACKET_SIZE)
return -EINVAL;
_dev->mtu = new_mtu;
printk(KERN_INFO "changing the mtu to %d\n", new_mtu);
return 0;
}
/**********************************************************************
* SBMAC_INIT(dev)
*
......@@ -2135,19 +2366,20 @@ static int sbmac_parse_hwaddr(char *str,u_char *hwaddr)
* status
********************************************************************* */
static int sbmac_init(struct net_device *dev)
static int sbmac_init(struct net_device *dev, int idx)
{
struct sbmac_softc *sc;
u_char *eaddr;
unsigned char *eaddr;
uint64_t ea_reg;
int idx;
int i;
sc = (struct sbmac_softc *)dev->priv;
/* Determine controller base address */
sc->sbm_base = (sbmac_port_t) dev->base_addr;
sc->sbm_base = KSEG1ADDR(dev->base_addr);
sc->sbm_dev = dev;
sc->sbe_idx = idx;
eaddr = sc->sbm_hwaddr;
......@@ -2156,16 +2388,15 @@ static int sbmac_init(struct net_device *dev)
* for us in the ethernet address register for each mac.
*/
ea_reg = SBMAC_READCSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR));
SBMAC_WRITECSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR), 0);
for (idx = 0; idx < 6; idx++) {
eaddr[idx] = (uint8_t) (ea_reg & 0xFF);
ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR);
SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0);
for (i = 0; i < 6; i++) {
eaddr[i] = (uint8_t) (ea_reg & 0xFF);
ea_reg >>= 8;
}
for (idx = 0; idx < 6; idx++) {
dev->dev_addr[idx] = eaddr[idx];
for (i = 0; i < 6; i++) {
dev->dev_addr[i] = eaddr[i];
}
......@@ -2173,7 +2404,7 @@ static int sbmac_init(struct net_device *dev)
* Init packet size
*/
sc->sbm_buffersize = ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN;
sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN;
/*
* Initialize context (get pointers to registers and stuff), then
......@@ -2184,13 +2415,13 @@ static int sbmac_init(struct net_device *dev)
/*
* Display Ethernet address (this is called during the config process
* so we need to finish off the config message that was being displayed)
* Display Ethernet address (this is called during the config
* process so we need to finish off the config message that
* was being displayed)
*/
printk(KERN_INFO
"%s: SB1250 Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n",
dev->name,
(unsigned long) sc->sbm_base,
"%s: SiByte Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n",
dev->name, dev->base_addr,
eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]);
/*
......@@ -2209,8 +2440,12 @@ static int sbmac_init(struct net_device *dev)
dev->tx_timeout = sbmac_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
return 0;
dev->change_mtu = sb1250_change_mtu;
/* This is needed for PASS2 for Rx H/W checksum feature */
sbmac_set_iphdr_offset(sc);
return 0;
}
......@@ -2237,7 +2472,7 @@ static int sbmac_open(struct net_device *dev)
* Configure default speed
*/
sbmac_mii_poll(sc,1);
sbmac_mii_poll(sc,noisy_mii);
/*
* Turn on the channel
......@@ -2319,7 +2554,8 @@ static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
chg = 1;
}
if (chg == 0) return 0;
if (chg == 0)
return 0;
p += sprintf(p,"Link speed: ");
......@@ -2371,8 +2607,6 @@ static int sbmac_mii_poll(struct sbmac_softc *s,int noisy)
}
static void sbmac_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
......@@ -2399,7 +2633,7 @@ static void sbmac_timer(unsigned long data)
* Poll the PHY to see what speed we should be running at
*/
if (sbmac_mii_poll(sc,1)) {
if (sbmac_mii_poll(sc,noisy_mii)) {
if (sc->sbm_state != sbmac_state_off) {
/*
* something changed, restart the channel
......@@ -2479,7 +2713,8 @@ static void sbmac_set_rx_mode(struct net_device *dev)
spin_unlock_irqrestore(&sc->sbm_lock, flags);
if (msg_flag) {
printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n", dev->name,(msg_flag==1)?"en":"dis");
printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n",
dev->name,(msg_flag==1)?"en":"dis");
}
/*
......@@ -2530,6 +2765,7 @@ static int sbmac_close(struct net_device *dev)
{
struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
unsigned long flags;
int irq;
sbmac_set_channel_state(sc,sbmac_state_off);
......@@ -2545,10 +2781,9 @@ static int sbmac_close(struct net_device *dev)
spin_unlock_irqrestore(&sc->sbm_lock, flags);
/* Make sure there is no irq-handler running on a different CPU. */
synchronize_irq(dev->irq);
free_irq(dev->irq, dev);
irq = dev->irq;
synchronize_irq(irq);
free_irq(irq, dev);
sbdma_emptyring(&(sc->sbm_txdma));
sbdma_emptyring(&(sc->sbm_rxdma));
......@@ -2571,8 +2806,8 @@ sbmac_setup_hwaddr(int chan,char *addr)
port = A_MAC_CHANNEL_BASE(chan);
sbmac_parse_hwaddr(addr,eaddr);
val = sbmac_addr2reg(eaddr);
SBMAC_WRITECSR(PKSEG1(port+R_MAC_ETHERNET_ADDR),val);
val = SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR));
SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR),val);
val = SBMAC_READCSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR));
}
#endif
......@@ -2585,6 +2820,7 @@ sbmac_init_module(void)
int macidx = 0;
struct net_device *dev;
sbmac_port_t port;
int chip_max_units;
/*
* For bringup when not using the firmware, we can pre-fill
......@@ -2605,8 +2841,25 @@ sbmac_init_module(void)
* Walk through the Ethernet controllers and find
* those who have their MAC addresses set.
*/
switch (soc_type) {
case K_SYS_SOC_TYPE_BCM1250:
case K_SYS_SOC_TYPE_BCM1250_ALT:
chip_max_units = 3;
break;
case K_SYS_SOC_TYPE_BCM1120:
case K_SYS_SOC_TYPE_BCM1125:
case K_SYS_SOC_TYPE_BCM1125H:
case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */
chip_max_units = 2;
break;
default:
chip_max_units = 0;
break;
}
if (chip_max_units > MAX_UNITS)
chip_max_units = MAX_UNITS;
for (idx = 0; idx < MAX_UNITS; idx++) {
for (idx = 0; idx < chip_max_units; idx++) {
/*
* This is the base address of the MAC.
......@@ -2620,7 +2873,10 @@ sbmac_init_module(void)
* If we find a zero, skip this MAC.
*/
if (SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR)) == 0) {
sbmac_orig_hwaddr[idx] = SBMAC_READCSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR));
if (sbmac_orig_hwaddr[idx] == 0) {
printk(KERN_DEBUG "sbmac: not configuring MAC at "
"%lx\n", port);
continue;
}
......@@ -2629,16 +2885,19 @@ sbmac_init_module(void)
*/
dev = init_etherdev(NULL,sizeof(struct sbmac_softc));
if (!dev) break; /* problems, get out now. */
if (!dev)
return -ENOMEM; /* return ENOMEM */
printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port);
dev->irq = K_INT_MAC_0 + idx;
dev->base_addr = port;
dev->mem_end = 0;
/*dev->init = sbmac_init;*/
sbmac_init(dev);
sbmac_init(dev, macidx);
dev_sbmac[macidx] = dev;
macidx++;
}
/*
......@@ -2654,9 +2913,11 @@ sbmac_cleanup_module(void)
{
int idx;
struct net_device *dev;
sbmac_port_t port;
for (idx = 0; idx < MAX_UNITS; idx++) {
dev = dev_sbmac[idx];
if (dev == NULL) continue;
if (dev == NULL)
continue;
if (dev->priv != NULL) {
struct sbmac_softc *sc = (struct sbmac_softc *) dev->priv;
......@@ -2664,9 +2925,11 @@ sbmac_cleanup_module(void)
sbmac_uninitctx(sc);
KFREE(sc);
}
KFREE(dev);
port = A_MAC_CHANNEL_BASE(idx);
SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR), sbmac_orig_hwaddr[idx] );
kfree(dev);
dev_sbmac[idx] = NULL;
}
}
......
......@@ -5,6 +5,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
......@@ -25,8 +26,8 @@
#include <asm/bitops.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/sgi/sgihpc.h>
#include <asm/sgi/sgint23.h>
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>
#include <asm/sgialib.h>
#include "sgiseeq.h"
......@@ -90,8 +91,8 @@ struct sgiseeq_init_block { /* Note the name ;-) */
struct sgiseeq_private {
volatile struct sgiseeq_init_block srings;
char *name;
volatile struct hpc3_ethregs *hregs;
volatile struct sgiseeq_regs *sregs;
struct hpc3_ethregs *hregs;
struct sgiseeq_regs *sregs;
/* Ring entry counters. */
unsigned int rx_new, tx_new;
......@@ -102,17 +103,22 @@ struct sgiseeq_private {
unsigned char mode;
struct net_device_stats stats;
struct net_device *next_module;
};
static inline void hpc3_eth_reset(volatile struct hpc3_ethregs *hregs)
/* A list of all installed seeq devices, for removing the driver module. */
static struct net_device *root_sgiseeq_dev;
static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs)
{
hregs->rx_reset = (HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ);
udelay(20);
hregs->rx_reset = 0;
}
static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs,
volatile struct sgiseeq_regs *sregs)
static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs,
struct sgiseeq_regs *sregs)
{
hregs->rx_ctrl = hregs->tx_ctrl = 0;
hpc3_eth_reset(hregs);
......@@ -122,15 +128,15 @@ static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs,
SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC)
static inline void seeq_go(struct sgiseeq_private *sp,
volatile struct hpc3_ethregs *hregs,
volatile struct sgiseeq_regs *sregs)
struct hpc3_ethregs *hregs,
struct sgiseeq_regs *sregs)
{
sregs->rstat = sp->mode | RSTAT_GO_BITS;
hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
}
static inline void seeq_load_eaddr(struct net_device *dev,
volatile struct sgiseeq_regs *sregs)
struct sgiseeq_regs *sregs)
{
int i;
......@@ -171,7 +177,6 @@ static int seeq_init_ring(struct net_device *dev)
return -ENOMEM;
ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer);
// flush_cache_all();
}
ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT);
}
......@@ -186,7 +191,6 @@ static int seeq_init_ring(struct net_device *dev)
return -ENOMEM;
ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer);
// flush_cache_all();
}
ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT);
}
......@@ -203,7 +207,7 @@ void sgiseeq_dump_rings(void)
static int once;
struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc;
struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc;
volatile struct hpc3_ethregs *hregs = gpriv->hregs;
struct hpc3_ethregs *hregs = gpriv->hregs;
int i;
if(once)
......@@ -242,9 +246,9 @@ void sgiseeq_dump_rings(void)
#define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ)
static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp,
volatile struct sgiseeq_regs *sregs)
struct sgiseeq_regs *sregs)
{
volatile struct hpc3_ethregs *hregs = sp->hregs;
struct hpc3_ethregs *hregs = sp->hregs;
int err;
reset_hpc3_and_seeq(hregs, sregs);
......@@ -285,8 +289,8 @@ static inline void record_rx_errors(struct sgiseeq_private *sp,
}
static inline void rx_maybe_restart(struct sgiseeq_private *sp,
volatile struct hpc3_ethregs *hregs,
volatile struct sgiseeq_regs *sregs)
struct hpc3_ethregs *hregs,
struct sgiseeq_regs *sregs)
{
if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) {
hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]);
......@@ -299,8 +303,8 @@ static inline void rx_maybe_restart(struct sgiseeq_private *sp,
(rd) = &(sp)->srings.rx_desc[(sp)->rx_new])
static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp,
volatile struct hpc3_ethregs *hregs,
volatile struct sgiseeq_regs *sregs)
struct hpc3_ethregs *hregs,
struct sgiseeq_regs *sregs)
{
struct sgiseeq_rx_desc *rd;
struct sk_buff *skb = 0;
......@@ -332,7 +336,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
sp->stats.rx_packets++;
sp->stats.rx_bytes += len;
} else {
printk ("%s: Memory squeeze, deferring packet.\n",
printk (KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
dev->name);
sp->stats.rx_dropped++;
}
......@@ -350,7 +354,7 @@ static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp
}
static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
volatile struct sgiseeq_regs *sregs)
struct sgiseeq_regs *sregs)
{
if (sp->is_edlc) {
sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT);
......@@ -359,7 +363,7 @@ static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp,
}
static inline void kick_tx(struct sgiseeq_tx_desc *td,
volatile struct hpc3_ethregs *hregs)
struct hpc3_ethregs *hregs)
{
/* If the HPC aint doin nothin, and there are more packets
* with ETXD cleared and XIU set we must make very certain
......@@ -377,8 +381,8 @@ static inline void kick_tx(struct sgiseeq_tx_desc *td,
}
static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp,
volatile struct hpc3_ethregs *hregs,
volatile struct sgiseeq_regs *sregs)
struct hpc3_ethregs *hregs,
struct sgiseeq_regs *sregs)
{
struct sgiseeq_tx_desc *td;
unsigned long status = hregs->tx_ctrl;
......@@ -420,8 +424,8 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
{
struct net_device *dev = (struct net_device *) dev_id;
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
volatile struct hpc3_ethregs *hregs = sp->hregs;
volatile struct sgiseeq_regs *sregs = sp->sregs;
struct hpc3_ethregs *hregs = sp->hregs;
struct sgiseeq_regs *sregs = sp->sregs;
/* Ack the IRQ and set software state. */
hregs->rx_reset = HPC3_ERXRST_CLRIRQ;
......@@ -429,7 +433,7 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
/* Always check for received packets. */
sgiseeq_rx(dev, sp, hregs, sregs);
/* Only check for tx acks iff we have something queued. */
/* Only check for tx acks if we have something queued. */
if (sp->tx_old != sp->tx_new)
sgiseeq_tx(dev, sp, hregs, sregs);
......@@ -442,47 +446,34 @@ static irqreturn_t sgiseeq_interrupt(int irq, void *dev_id, struct pt_regs *regs
static int sgiseeq_open(struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv;
volatile struct sgiseeq_regs *sregs = sp->sregs;
unsigned long flags;
int err;
local_irq_save(flags);
struct sgiseeq_regs *sregs = sp->sregs;
err = -EAGAIN;
if (request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
printk("Seeq8003: Can't get irq %d\n", dev->irq);
goto out;
}
err = init_seeq(dev, sp, sregs);
int err = init_seeq(dev, sp, sregs);
if (err)
goto out;
return err;
netif_start_queue(dev);
out:
local_irq_restore(flags);
return err;
return 0;
}
static int sgiseeq_close(struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
volatile struct sgiseeq_regs *sregs = sp->sregs;
struct sgiseeq_regs *sregs = sp->sregs;
netif_stop_queue(dev);
/* Shutdown the Seeq. */
reset_hpc3_and_seeq(sp->hregs, sregs);
free_irq(dev->irq, dev);
return 0;
}
static inline int sgiseeq_reset(struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
volatile struct sgiseeq_regs *sregs = sp->sregs;
struct sgiseeq_regs *sregs = sp->sregs;
int err;
err = init_seeq(dev, sp, sregs);
......@@ -504,12 +495,12 @@ void sgiseeq_my_reset(void)
static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
volatile struct hpc3_ethregs *hregs = sp->hregs;
struct hpc3_ethregs *hregs = sp->hregs;
unsigned long flags;
struct sgiseeq_tx_desc *td;
int skblen, len, entry;
save_and_cli(flags);
local_irq_save(flags);
/* Setup... */
skblen = skb->len;
......@@ -553,14 +544,14 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (!TX_BUFFS_AVAIL(sp))
netif_stop_queue(dev);
restore_flags(flags);
local_irq_restore(flags);
return 0;
}
static void timeout(struct net_device *dev)
{
printk("%s: transmit timed out, resetting\n", dev->name);
printk(KERN_NOTICE "%s: transmit timed out, resetting\n", dev->name);
sgiseeq_reset(dev);
dev->trans_start = jiffies;
......@@ -603,41 +594,56 @@ static inline void setup_rx_ring(struct sgiseeq_rx_desc *buf, int nbufs)
buf[i].rdma.pnext = PHYSADDR(&buf[0]);
}
static char onboard_eth_addr[6];
#define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf))
int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
struct hpc3_ethregs *hregs, int irq)
int sgiseeq_init(struct hpc3_regs* regs, int irq)
{
static unsigned version_printed;
int i;
struct net_device *dev;
struct sgiseeq_private *sp;
int i;
dev->priv = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
if (dev->priv == NULL)
sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL);
if (!sp) {
printk (KERN_ERR
"Seeq8003: Could not allocate private data.\n");
return -ENOMEM;
}
if (!version_printed++)
printk(version);
dev = init_etherdev(NULL, 0);
if (!dev) {
printk (KERN_ERR
"Seeq8003: Could not allocate memory for device.\n");
free_page((unsigned long) sp);
return -ENOMEM;
}
printk("%s: SGI Seeq8003 ", dev->name);
if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) {
printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq);
free_page((unsigned long) sp);
unregister_netdev(dev);
return -EAGAIN;
}
for (i = 0; i < 6; i++)
printk("%2.2x%c",
dev->dev_addr[i] = onboard_eth_addr[i],
i == 5 ? ' ': ':');
printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name);
#define EADDR_NVOFS 250
for (i = 0; i < 3; i++) {
unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i);
printk("%2.2x:%2.2x%c",
dev->dev_addr[2 * i] = tmp >> 8,
dev->dev_addr[2 * i + 1] = tmp & 0xff,
i == 2 ? ' ' : ':');
}
printk("\n");
sp = (struct sgiseeq_private *) dev->priv;
dev->priv = sp;
#ifdef DEBUG
gpriv = sp;
gdev = dev;
#endif
memset((char *)dev->priv, 0, sizeof(struct sgiseeq_private));
sp->sregs = sregs;
sp->hregs = hregs;
sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
sp->hregs = &hpc3c0->ethregs;
sp->name = sgiseeqstr;
sp->srings.rx_desc = (struct sgiseeq_rx_desc *)
......@@ -654,14 +660,13 @@ int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS);
/* Reset the chip. */
hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs);
hpc3_eth_reset(sp->hregs);
sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff);
if (sp->is_edlc) {
sp->is_edlc = !(sp->sregs->rw.rregs.collision_tx[0] & 0xff);
if (sp->is_edlc)
sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT |
SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT |
SEEQ_CTRL_ENCARR);
}
dev->open = sgiseeq_open;
dev->stop = sgiseeq_close;
......@@ -674,51 +679,37 @@ int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs,
dev->dma = 0;
ether_setup(dev);
sp->next_module = root_sgiseeq_dev;
root_sgiseeq_dev = dev;
return 0;
}
static inline unsigned char str2hexnum(unsigned char c)
static int __init sgiseeq_probe(void)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
return 0; /* foo */
printk(version);
/* On board adapter on 1st HPC is always present */
return sgiseeq_init(hpc3c0, SGI_ENET_IRQ);
}
static inline void str2eaddr(unsigned char *ea, unsigned char *str)
static void __exit sgiseeq_exit(void)
{
int i;
for (i = 0; i < 6; i++) {
unsigned char num;
struct sgiseeq_private *sp;
struct net_device *next, *dev = root_sgiseeq_dev;
if(*str == ':')
str++;
num = str2hexnum(*str++) << 4;
num |= (str2hexnum(*str++));
ea[i] = num;
while (dev) {
sp = (struct sgiseeq_private *) dev->priv;
next = sp->next_module;
free_irq(dev->irq, dev);
free_page((unsigned long) sp);
unregister_netdev(dev);
kfree(dev);
dev = next;
}
}
int sgiseeq_probe(struct net_device *dev)
{
static int initialized;
char *ep;
if (initialized) /* Already initialized? */
return 1;
initialized++;
/* First get the ethernet address of the onboard interface from ARCS.
* This is fragile; PROM doesn't like running from cache.
* On MIPS64 it crashes for some other, yet unknown reason ...
*/
ep = ArcGetEnvironmentVariable("eaddr");
str2eaddr(onboard_eth_addr, ep);
return sgiseeq_init(dev,
(struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
&hpc3c0->ethregs, SGI_ENET_IRQ);
}
module_init(sgiseeq_probe);
module_exit(sgiseeq_exit);
MODULE_LICENSE("GPL");
/* $Id: sgiseeq.h,v 1.4 1999/10/09 00:01:24 ralf Exp $
/*
* sgiseeq.h: Defines for the Seeq8003 ethernet controller.
*
* Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
......
......@@ -2384,9 +2384,6 @@ static int gem_ethtool_ioctl(struct net_device *dev, void *ep_user)
return 0;
case ETHTOOL_SSET:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
/* Verify the settings we care about. */
if (ecmd.autoneg != AUTONEG_ENABLE &&
ecmd.autoneg != AUTONEG_DISABLE)
......
......@@ -2481,9 +2481,6 @@ static int happy_meal_ioctl(struct net_device *dev,
return -EFAULT;
return 0;
} else if (ecmd.cmd == ETHTOOL_SSET) {
if (!capable(CAP_NET_ADMIN))
return -EPERM;
/* Verify the settings we care about. */
if (ecmd.autoneg != AUTONEG_ENABLE &&
ecmd.autoneg != AUTONEG_DISABLE)
......
......@@ -94,6 +94,8 @@ static int csr0 = 0x01A00000 | 0x8000;
static int csr0 = 0x01A00000 | 0x9000;
#elif defined(__arm__) || defined(__sh__)
static int csr0 = 0x01A00000 | 0x4800;
#elif defined(__mips__)
static int csr0 = 0x00200000 | 0x4000;
#else
#warning Processor architecture undefined!
static int csr0 = 0x00A00000 | 0x4800;
......@@ -1491,6 +1493,16 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
tp->flags &= ~HAS_MEDIA_TABLE;
}
#endif
#ifdef CONFIG_MIPS_COBALT
if ((pdev->bus->number == 0) &&
((PCI_SLOT(pdev->devfn) == 7) ||
(PCI_SLOT(pdev->devfn) == 12))) {
/* Cobalt MAC address in first EEPROM locations. */
sa_offset = 0;
/* No media table either */
tp->flags &= ~HAS_MEDIA_TABLE;
}
#endif
#ifdef __hppa__
/* 3x5 HSC (J3514A) has a broken srom */
if(ee_data[0] == 0x61 && ee_data[1] == 0x10) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment