From 6e07ba3e6ad939c89befc2588e72bf37038f7f53 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 8 Jan 2013 22:00:39 -0500 Subject: drivers/net: delete 486 Apricot support The Apricot was a 486 PC with 4MB RAM, and an on-board ethernet via an intel i82596 hard-wired to i/o 0x300. Those who were using linux in the 1990's will recall that the i82596 driver was not one of the more stable or widely used drivers of its day. Combine that with the extremely limited resources of the platform, and it is truly time to expire the support for this thing. There are some old m68k targets who were also using this chip, so rather than poll the m68k user base, we simply cut out the x86/Apricot support here in this commit. Signed-off-by: Paul Gortmaker --- drivers/net/ethernet/i825xx/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/ethernet/i825xx/Makefile') diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile index 6adff85e8ec..e5ab9d04a18 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o obj-$(CONFIG_ZNET) += znet.o -obj-$(CONFIG_APRICOT) += 82596.o obj-$(CONFIG_LASI_82596) += lasi_82596.o obj-$(CONFIG_SNI_82596) += sni_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o -- cgit v1.2.3-70-g09d2 From 5205939d0f15803cc402e32ac5b886dbb7c50b99 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Tue, 8 Jan 2013 22:11:54 -0500 Subject: drivers/net: delete intel 486 panther onboard ethernet support This driver was specific to a "professional workstation" line of products from around 1993 that used the i82596 ethernet chip as an on-board ethernet solution. With a 486 processor, and the premium top of the line model maxing out at a clock speed of 50MHz, we can safely retire this support. Signed-off-by: Paul Gortmaker --- drivers/net/ethernet/i825xx/Kconfig | 8 - drivers/net/ethernet/i825xx/Makefile | 1 - drivers/net/ethernet/i825xx/lp486e.c | 1337 ---------------------------------- 3 files changed, 1346 deletions(-) delete mode 100644 drivers/net/ethernet/i825xx/lp486e.c (limited to 'drivers/net/ethernet/i825xx/Makefile') diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig index c39698ae980..46edb81bbed 100644 --- a/drivers/net/ethernet/i825xx/Kconfig +++ b/drivers/net/ethernet/i825xx/Kconfig @@ -93,14 +93,6 @@ config LASI_82596 Say Y here to support the builtin Intel 82596 ethernet controller found in Hewlett-Packard PA-RISC machines with 10Mbit ethernet. -config LP486E - tristate "LP486E on board Ethernet" - depends on ISA - ---help--- - Say Y here to support the 82596-based on-board Ethernet controller - for the Panther motherboard, which is one of the two shipped in the - Intel Professional Workstation. - config MVME16x_NET tristate "MVME16x Ethernet support" depends on MVME16x diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile index e5ab9d04a18..4f01584bd89 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_EEXPRESS) += eexpress.o obj-$(CONFIG_EEXPRESS_PRO) += eepro.o obj-$(CONFIG_ELPLUS) += 3c505.o obj-$(CONFIG_EL16) += 3c507.o -obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o obj-$(CONFIG_ZNET) += znet.o diff --git a/drivers/net/ethernet/i825xx/lp486e.c b/drivers/net/ethernet/i825xx/lp486e.c deleted file mode 100644 index 3735bfa5360..00000000000 --- a/drivers/net/ethernet/i825xx/lp486e.c +++ /dev/null @@ -1,1337 +0,0 @@ -/* Intel Professional Workstation/panther ethernet driver */ -/* lp486e.c: A panther 82596 ethernet driver for linux. */ -/* - History and copyrights: - - Driver skeleton - Written 1993 by Donald Becker. - Copyright 1993 United States Government as represented by the Director, - National Security Agency. This software may only be used and - distributed according to the terms of the GNU General Public License - as modified by SRC, incorporated herein by reference. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - Apricot - Written 1994 by Mark Evans. - This driver is for the Apricot 82596 bus-master interface - - Modularised 12/94 Mark Evans - - Professional Workstation - Derived from apricot.c by Ard van Breemen - || - - Credits: - Thanks to Murphy Software BV for letting me write this in their time. - Well, actually, I get paid doing this... - (Also: see http://www.murphy.nl for murphy, and my homepage ~ard for - more information on the Professional Workstation) - - Present version - aeb@cwi.nl -*/ -/* - There are currently two motherboards that I know of in the - professional workstation. The only one that I know is the - intel panther motherboard. -- ard -*/ -/* -The pws is equipped with an intel 82596. This is a very intelligent controller -which runs its own micro-code. Communication with the hostprocessor is done -through linked lists of commands and buffers in the hostprocessors memory. -A complete description of the 82596 is available from intel. Search for -a file called "29021806.pdf". It is a complete description of the chip itself. -To use it for the pws some additions are needed regarding generation of -the PORT and CA signal, and the interrupt glue needed for a pc. -I/O map: -PORT SIZE ACTION MEANING -0xCB0 2 WRITE Lower 16 bits for PORT command -0xCB2 2 WRITE Upper 16 bits for PORT command, and issue of PORT command -0xCB4 1 WRITE Generation of CA signal -0xCB8 1 WRITE Clear interrupt glue -All other communication is through memory! -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRV_NAME "lp486e" - -/* debug print flags */ -#define LOG_SRCDST 0x80000000 -#define LOG_STATINT 0x40000000 -#define LOG_STARTINT 0x20000000 - -#define i596_debug debug - -static int i596_debug = 0; - -static const char * const medianame[] = { - "10baseT", "AUI", - "10baseT-FD", "AUI-FD", -}; - -#define LP486E_TOTAL_SIZE 16 - -#define I596_NULL (0xffffffff) - -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -#define CMD_FLEX 0x0008 /* Enable flexible memory model */ - -enum commands { - CmdNOP = 0, - CmdIASetup = 1, - CmdConfigure = 2, - CmdMulticastList = 3, - CmdTx = 4, - CmdTDR = 5, - CmdDump = 6, - CmdDiagnose = 7 -}; - -#if 0 -static const char *CUcmdnames[8] = { "NOP", "IASetup", "Configure", "MulticastList", - "Tx", "TDR", "Dump", "Diagnose" }; -#endif - -/* Status word bits */ -#define STAT_CX 0x8000 /* The CU finished executing a command - with the Interrupt bit set */ -#define STAT_FR 0x4000 /* The RU finished receiving a frame */ -#define STAT_CNA 0x2000 /* The CU left the active state */ -#define STAT_RNR 0x1000 /* The RU left the active state */ -#define STAT_ACK (STAT_CX | STAT_FR | STAT_CNA | STAT_RNR) -#define STAT_CUS 0x0700 /* Status of CU: 0: idle, 1: suspended, - 2: active, 3-7: unused */ -#define STAT_RUS 0x00f0 /* Status of RU: 0: idle, 1: suspended, - 2: no resources, 4: ready, - 10: no resources due to no more RBDs, - 12: no more RBDs, other: unused */ -#define STAT_T 0x0008 /* Bus throttle timers loaded */ -#define STAT_ZERO 0x0807 /* Always zero */ - -#if 0 -static char *CUstates[8] = { - "idle", "suspended", "active", 0, 0, 0, 0, 0 -}; -static char *RUstates[16] = { - "idle", "suspended", "no resources", 0, "ready", 0, 0, 0, - 0, 0, "no RBDs", 0, "out of RBDs", 0, 0, 0 -}; - -static void -i596_out_status(int status) { - int bad = 0; - char *s; - - printk("status %4.4x:", status); - if (status == 0xffff) - printk(" strange..\n"); - else { - if (status & STAT_CX) - printk(" CU done"); - if (status & STAT_CNA) - printk(" CU stopped"); - if (status & STAT_FR) - printk(" got a frame"); - if (status & STAT_RNR) - printk(" RU stopped"); - if (status & STAT_T) - printk(" throttled"); - if (status & STAT_ZERO) - bad = 1; - s = CUstates[(status & STAT_CUS) >> 8]; - if (!s) - bad = 1; - else - printk(" CU(%s)", s); - s = RUstates[(status & STAT_RUS) >> 4]; - if (!s) - bad = 1; - else - printk(" RU(%s)", s); - if (bad) - printk(" bad status"); - printk("\n"); - } -} -#endif - -/* Command word bits */ -#define ACK_CX 0x8000 -#define ACK_FR 0x4000 -#define ACK_CNA 0x2000 -#define ACK_RNR 0x1000 - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define CUC_ABORT 0x0400 - -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 -#define RX_ABORT 0x0040 - -typedef u32 phys_addr; - -static inline phys_addr -va_to_pa(void *x) { - return x ? virt_to_bus(x) : I596_NULL; -} - -static inline void * -pa_to_va(phys_addr x) { - return (x == I596_NULL) ? NULL : bus_to_virt(x); -} - -/* status bits for cmd */ -#define CMD_STAT_C 0x8000 /* CU command complete */ -#define CMD_STAT_B 0x4000 /* CU command in progress */ -#define CMD_STAT_OK 0x2000 /* CU command completed without errors */ -#define CMD_STAT_A 0x1000 /* CU command abnormally terminated */ - -struct i596_cmd { /* 8 bytes */ - unsigned short status; - unsigned short command; - phys_addr pa_next; /* va_to_pa(struct i596_cmd *next) */ -}; - -#define EOF 0x8000 -#define SIZE_MASK 0x3fff - -struct i596_tbd { - unsigned short size; - unsigned short pad; - phys_addr pa_next; /* va_to_pa(struct i596_tbd *next) */ - phys_addr pa_data; /* va_to_pa(char *data) */ - struct sk_buff *skb; -}; - -struct tx_cmd { - struct i596_cmd cmd; - phys_addr pa_tbd; /* va_to_pa(struct i596_tbd *tbd) */ - unsigned short size; - unsigned short pad; -}; - -/* status bits for rfd */ -#define RFD_STAT_C 0x8000 /* Frame reception complete */ -#define RFD_STAT_B 0x4000 /* Frame reception in progress */ -#define RFD_STAT_OK 0x2000 /* Frame received without errors */ -#define RFD_STATUS 0x1fff -#define RFD_LENGTH_ERR 0x1000 -#define RFD_CRC_ERR 0x0800 -#define RFD_ALIGN_ERR 0x0400 -#define RFD_NOBUFS_ERR 0x0200 -#define RFD_DMA_ERR 0x0100 /* DMA overrun failure to acquire system bus */ -#define RFD_SHORT_FRAME_ERR 0x0080 -#define RFD_NOEOP_ERR 0x0040 -#define RFD_TRUNC_ERR 0x0020 -#define RFD_MULTICAST 0x0002 /* 0: destination had our address - 1: destination was broadcast/multicast */ -#define RFD_COLLISION 0x0001 - -/* receive frame descriptor */ -struct i596_rfd { - unsigned short stat; - unsigned short cmd; - phys_addr pa_next; /* va_to_pa(struct i596_rfd *next) */ - phys_addr pa_rbd; /* va_to_pa(struct i596_rbd *rbd) */ - unsigned short count; - unsigned short size; - char data[1532]; -}; - -#define RBD_EL 0x8000 -#define RBD_P 0x4000 -#define RBD_SIZEMASK 0x3fff -#define RBD_EOF 0x8000 -#define RBD_F 0x4000 - -/* receive buffer descriptor */ -struct i596_rbd { - unsigned short size; - unsigned short pad; - phys_addr pa_next; /* va_to_pa(struct i596_tbd *next) */ - phys_addr pa_data; /* va_to_pa(char *data) */ - phys_addr pa_prev; /* va_to_pa(struct i596_tbd *prev) */ - - /* Driver private part */ - struct sk_buff *skb; -}; - -#define RX_RING_SIZE 64 -#define RX_SKBSIZE (ETH_FRAME_LEN+10) -#define RX_RBD_SIZE 32 - -/* System Control Block - 40 bytes */ -struct i596_scb { - u16 status; /* 0 */ - u16 command; /* 2 */ - phys_addr pa_cmd; /* 4 - va_to_pa(struct i596_cmd *cmd) */ - phys_addr pa_rfd; /* 8 - va_to_pa(struct i596_rfd *rfd) */ - u32 crc_err; /* 12 */ - u32 align_err; /* 16 */ - u32 resource_err; /* 20 */ - u32 over_err; /* 24 */ - u32 rcvdt_err; /* 28 */ - u32 short_err; /* 32 */ - u16 t_on; /* 36 */ - u16 t_off; /* 38 */ -}; - -/* Intermediate System Configuration Pointer - 8 bytes */ -struct i596_iscp { - u32 busy; /* 0 */ - phys_addr pa_scb; /* 4 - va_to_pa(struct i596_scb *scb) */ -}; - -/* System Configuration Pointer - 12 bytes */ -struct i596_scp { - u32 sysbus; /* 0 */ - u32 pad; /* 4 */ - phys_addr pa_iscp; /* 8 - va_to_pa(struct i596_iscp *iscp) */ -}; - -/* Selftest and dump results - needs 16-byte alignment */ -/* - * The size of the dump area is 304 bytes. When the dump is executed - * by the Port command an extra word will be appended to the dump area. - * The extra word is a copy of the Dump status word (containing the - * C, B, OK bits). [I find 0xa006, with a0 for C+OK and 6 for dump] - */ -struct i596_dump { - u16 dump[153]; /* (304 = 130h) + 2 bytes */ -}; - -struct i596_private { /* aligned to a 16-byte boundary */ - struct i596_scp scp; /* 0 - needs 16-byte alignment */ - struct i596_iscp iscp; /* 12 */ - struct i596_scb scb; /* 20 */ - u32 dummy; /* 60 */ - struct i596_dump dump; /* 64 - needs 16-byte alignment */ - - struct i596_cmd set_add; - char eth_addr[8]; /* directly follows set_add */ - - struct i596_cmd set_conf; - char i596_config[16]; /* directly follows set_conf */ - - struct i596_cmd tdr; - unsigned long tdr_stat; /* directly follows tdr */ - - int last_restart; - struct i596_rbd *rbd_list; - struct i596_rbd *rbd_tail; - struct i596_rfd *rx_tail; - struct i596_cmd *cmd_tail; - struct i596_cmd *cmd_head; - int cmd_backlog; - unsigned long last_cmd; - spinlock_t cmd_lock; -}; - -static char init_setup[14] = { - 0x8E, /* length 14 bytes, prefetch on */ - 0xC8, /* default: fifo to 8, monitor off */ - 0x40, /* default: don't save bad frames (apricot.c had 0x80) */ - 0x2E, /* (default is 0x26) - No source address insertion, 8 byte preamble */ - 0x00, /* default priority and backoff */ - 0x60, /* default interframe spacing */ - 0x00, /* default slot time LSB */ - 0xf2, /* default slot time and nr of retries */ - 0x00, /* default various bits - (0: promiscuous mode, 1: broadcast disable, - 2: encoding mode, 3: transmit on no CRS, - 4: no CRC insertion, 5: CRC type, - 6: bit stuffing, 7: padding) */ - 0x00, /* default carrier sense and collision detect */ - 0x40, /* default minimum frame length */ - 0xff, /* (default is 0xff, and that is what apricot.c has; - elp486.c has 0xfb: Enable crc append in memory.) */ - 0x00, /* default: not full duplex */ - 0x7f /* (default is 0x3f) multi IA */ -}; - -static int i596_open(struct net_device *dev); -static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t i596_interrupt(int irq, void *dev_id); -static int i596_close(struct net_device *dev); -static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd); -static void print_eth(char *); -static void set_multicast_list(struct net_device *dev); -static void i596_tx_timeout(struct net_device *dev); - -static int -i596_timeout(struct net_device *dev, char *msg, int ct) { - struct i596_private *lp; - int boguscnt = ct; - - lp = netdev_priv(dev); - while (lp->scb.command) { - if (--boguscnt == 0) { - printk("%s: %s timed out - stat %4.4x, cmd %4.4x\n", - dev->name, msg, - lp->scb.status, lp->scb.command); - return 1; - } - udelay(5); - barrier(); - } - return 0; -} - -static inline int -init_rx_bufs(struct net_device *dev, int num) { - struct i596_private *lp; - struct i596_rfd *rfd; - int i; - // struct i596_rbd *rbd; - - lp = netdev_priv(dev); - lp->scb.pa_rfd = I596_NULL; - - for (i = 0; i < num; i++) { - rfd = kmalloc(sizeof(struct i596_rfd), GFP_KERNEL); - if (rfd == NULL) - break; - - rfd->stat = 0; - rfd->pa_rbd = I596_NULL; - rfd->count = 0; - rfd->size = 1532; - if (i == 0) { - rfd->cmd = CMD_EOL; - lp->rx_tail = rfd; - } else { - rfd->cmd = 0; - } - rfd->pa_next = lp->scb.pa_rfd; - lp->scb.pa_rfd = va_to_pa(rfd); - lp->rx_tail->pa_next = lp->scb.pa_rfd; - } - -#if 0 - for (i = 0; ipad = 0; - rbd->count = 0; - rbd->skb = dev_alloc_skb(RX_SKBSIZE); - if (!rbd->skb) { - printk("dev_alloc_skb failed"); - } - rbd->next = rfd->rbd; - if (i) { - rfd->rbd->prev = rbd; - rbd->size = RX_SKBSIZE; - } else { - rbd->size = (RX_SKBSIZE | RBD_EL); - lp->rbd_tail = rbd; - } - - rfd->rbd = rbd; - } - } - lp->rbd_tail->next = rfd->rbd; -#endif - return i; -} - -static inline void -remove_rx_bufs(struct net_device *dev) { - struct i596_private *lp; - struct i596_rfd *rfd; - - lp = netdev_priv(dev); - lp->rx_tail->pa_next = I596_NULL; - - do { - rfd = pa_to_va(lp->scb.pa_rfd); - lp->scb.pa_rfd = rfd->pa_next; - kfree(rfd); - } while (rfd != lp->rx_tail); - - lp->rx_tail = NULL; - -#if 0 - for (lp->rbd_list) { - } -#endif -} - -#define PORT_RESET 0x00 /* reset 82596 */ -#define PORT_SELFTEST 0x01 /* selftest */ -#define PORT_ALTSCP 0x02 /* alternate SCB address */ -#define PORT_DUMP 0x03 /* dump */ - -#define IOADDR 0xcb0 /* real constant */ -#define IRQ 10 /* default IRQ - can be changed by ECU */ - -/* The 82596 requires two 16-bit write cycles for a port command */ -static inline void -PORT(phys_addr a, unsigned int cmd) { - if (a & 0xf) - printk("lp486e.c: PORT: address not aligned\n"); - outw(((a & 0xffff) | cmd), IOADDR); - outw(((a>>16) & 0xffff), IOADDR+2); -} - -static inline void -CA(void) { - outb(0, IOADDR+4); - udelay(8); -} - -static inline void -CLEAR_INT(void) { - outb(0, IOADDR+8); -} - -#if 0 -/* selftest or dump */ -static void -i596_port_do(struct net_device *dev, int portcmd, char *cmdname) { - struct i596_private *lp = netdev_priv(dev); - u16 *outp; - int i, m; - - memset((void *)&(lp->dump), 0, sizeof(struct i596_dump)); - outp = &(lp->dump.dump[0]); - - PORT(va_to_pa(outp), portcmd); - mdelay(30); /* random, unmotivated */ - - printk("lp486e i82596 %s result:\n", cmdname); - for (m = ARRAY_SIZE(lp->dump.dump); m && lp->dump.dump[m-1] == 0; m--) - ; - for (i = 0; i < m; i++) { - printk(" %04x", lp->dump.dump[i]); - if (i%8 == 7) - printk("\n"); - } - printk("\n"); -} -#endif - -static int -i596_scp_setup(struct net_device *dev) { - struct i596_private *lp = netdev_priv(dev); - int boguscnt; - - /* Setup SCP, ISCP, SCB */ - /* - * sysbus bits: - * only a single byte is significant - here 0x44 - * 0x80: big endian mode (details depend on stepping) - * 0x40: 1 - * 0x20: interrupt pin is active low - * 0x10: lock function disabled - * 0x08: external triggering of bus throttle timers - * 0x06: 00: 82586 compat mode, 01: segmented mode, 10: linear mode - * 0x01: unused - */ - lp->scp.sysbus = 0x00440000; /* linear mode */ - lp->scp.pad = 0; /* must be zero */ - lp->scp.pa_iscp = va_to_pa(&(lp->iscp)); - - /* - * The CPU sets the ISCP to 1 before it gives the first CA() - */ - lp->iscp.busy = 0x0001; - lp->iscp.pa_scb = va_to_pa(&(lp->scb)); - - lp->scb.command = 0; - lp->scb.status = 0; - lp->scb.pa_cmd = I596_NULL; - /* lp->scb.pa_rfd has been initialised already */ - - lp->last_cmd = jiffies; - lp->cmd_backlog = 0; - lp->cmd_head = NULL; - - /* - * Reset the 82596. - * We need to wait 10 systemclock cycles, and - * 5 serial clock cycles. - */ - PORT(0, PORT_RESET); /* address part ignored */ - udelay(100); - - /* - * Before the CA signal is asserted, the default SCP address - * (0x00fffff4) can be changed to a 16-byte aligned value - */ - PORT(va_to_pa(&lp->scp), PORT_ALTSCP); /* change the scp address */ - - /* - * The initialization procedure begins when a - * Channel Attention signal is asserted after a reset. - */ - - CA(); - - /* - * The ISCP busy is cleared by the 82596 after the SCB address is read. - */ - boguscnt = 100; - while (lp->iscp.busy) { - if (--boguscnt == 0) { - /* No i82596 present? */ - printk("%s: i82596 initialization timed out\n", - dev->name); - return 1; - } - udelay(5); - barrier(); - } - /* I find here boguscnt==100, so no delay was required. */ - - return 0; -} - -static int -init_i596(struct net_device *dev) { - struct i596_private *lp; - - if (i596_scp_setup(dev)) - return 1; - - lp = netdev_priv(dev); - lp->scb.command = 0; - - memcpy ((void *)lp->i596_config, init_setup, 14); - lp->set_conf.command = CmdConfigure; - i596_add_cmd(dev, (void *)&lp->set_conf); - - memcpy ((void *)lp->eth_addr, dev->dev_addr, 6); - lp->set_add.command = CmdIASetup; - i596_add_cmd(dev, &lp->set_add); - - lp->tdr.command = CmdTDR; - i596_add_cmd(dev, &lp->tdr); - - if (lp->scb.command && i596_timeout(dev, "i82596 init", 200)) - return 1; - - lp->scb.command = RX_START; - CA(); - - barrier(); - - if (lp->scb.command && i596_timeout(dev, "Receive Unit start", 100)) - return 1; - - return 0; -} - -/* Receive a single frame */ -static inline int -i596_rx_one(struct net_device *dev, struct i596_private *lp, - struct i596_rfd *rfd, int *frames) { - - if (rfd->stat & RFD_STAT_OK) { - /* a good frame */ - int pkt_len = (rfd->count & 0x3fff); - struct sk_buff *skb = netdev_alloc_skb(dev, pkt_len); - - (*frames)++; - - if (rfd->cmd & CMD_EOL) - printk("Received on EOL\n"); - - if (skb == NULL) { - printk ("%s: i596_rx Memory squeeze, " - "dropping packet.\n", dev->name); - dev->stats.rx_dropped++; - return 1; - } - - memcpy(skb_put(skb,pkt_len), rfd->data, pkt_len); - - skb->protocol = eth_type_trans(skb,dev); - netif_rx(skb); - dev->stats.rx_packets++; - } else { -#if 0 - printk("Frame reception error status %04x\n", - rfd->stat); -#endif - dev->stats.rx_errors++; - if (rfd->stat & RFD_COLLISION) - dev->stats.collisions++; - if (rfd->stat & RFD_SHORT_FRAME_ERR) - dev->stats.rx_length_errors++; - if (rfd->stat & RFD_DMA_ERR) - dev->stats.rx_over_errors++; - if (rfd->stat & RFD_NOBUFS_ERR) - dev->stats.rx_fifo_errors++; - if (rfd->stat & RFD_ALIGN_ERR) - dev->stats.rx_frame_errors++; - if (rfd->stat & RFD_CRC_ERR) - dev->stats.rx_crc_errors++; - if (rfd->stat & RFD_LENGTH_ERR) - dev->stats.rx_length_errors++; - } - rfd->stat = rfd->count = 0; - return 0; -} - -static int -i596_rx(struct net_device *dev) { - struct i596_private *lp = netdev_priv(dev); - struct i596_rfd *rfd; - int frames = 0; - - while (1) { - rfd = pa_to_va(lp->scb.pa_rfd); - if (!rfd) { - printk(KERN_ERR "i596_rx: NULL rfd?\n"); - return 0; - } -#if 1 - if (rfd->stat && !(rfd->stat & (RFD_STAT_C | RFD_STAT_B))) - printk("SF:%p-%04x\n", rfd, rfd->stat); -#endif - if (!(rfd->stat & RFD_STAT_C)) - break; /* next one not ready */ - if (i596_rx_one(dev, lp, rfd, &frames)) - break; /* out of memory */ - rfd->cmd = CMD_EOL; - lp->rx_tail->cmd = 0; - lp->rx_tail = rfd; - lp->scb.pa_rfd = rfd->pa_next; - barrier(); - } - - return frames; -} - -static void -i596_cleanup_cmd(struct net_device *dev) { - struct i596_private *lp; - struct i596_cmd *cmd; - - lp = netdev_priv(dev); - while (lp->cmd_head) { - cmd = lp->cmd_head; - - lp->cmd_head = pa_to_va(lp->cmd_head->pa_next); - lp->cmd_backlog--; - - switch ((cmd->command) & 0x7) { - case CmdTx: { - struct tx_cmd *tx_cmd = (struct tx_cmd *) cmd; - struct i596_tbd * tx_cmd_tbd; - tx_cmd_tbd = pa_to_va(tx_cmd->pa_tbd); - - dev_kfree_skb_any(tx_cmd_tbd->skb); - - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; - - cmd->pa_next = I596_NULL; - kfree((unsigned char *)tx_cmd); - netif_wake_queue(dev); - break; - } - case CmdMulticastList: { - // unsigned short count = *((unsigned short *) (ptr + 1)); - - cmd->pa_next = I596_NULL; - kfree((unsigned char *)cmd); - break; - } - default: { - cmd->pa_next = I596_NULL; - break; - } - } - barrier(); - } - - if (lp->scb.command && i596_timeout(dev, "i596_cleanup_cmd", 100)) - ; - - lp->scb.pa_cmd = va_to_pa(lp->cmd_head); -} - -static void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr) { - - if (lp->scb.command && i596_timeout(dev, "i596_reset", 100)) - ; - - netif_stop_queue(dev); - - lp->scb.command = CUC_ABORT | RX_ABORT; - CA(); - barrier(); - - /* wait for shutdown */ - if (lp->scb.command && i596_timeout(dev, "i596_reset(2)", 400)) - ; - - i596_cleanup_cmd(dev); - i596_rx(dev); - - netif_start_queue(dev); - /*dev_kfree_skb(skb, FREE_WRITE);*/ - init_i596(dev); -} - -static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) { - struct i596_private *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - unsigned long flags; - - cmd->status = 0; - cmd->command |= (CMD_EOL | CMD_INTR); - cmd->pa_next = I596_NULL; - - spin_lock_irqsave(&lp->cmd_lock, flags); - - if (lp->cmd_head) { - lp->cmd_tail->pa_next = va_to_pa(cmd); - } else { - lp->cmd_head = cmd; - if (lp->scb.command && i596_timeout(dev, "i596_add_cmd", 100)) - ; - lp->scb.pa_cmd = va_to_pa(cmd); - lp->scb.command = CUC_START; - CA(); - } - lp->cmd_tail = cmd; - lp->cmd_backlog++; - - lp->cmd_head = pa_to_va(lp->scb.pa_cmd); - spin_unlock_irqrestore(&lp->cmd_lock, flags); - - if (lp->cmd_backlog > 16) { - int tickssofar = jiffies - lp->last_cmd; - if (tickssofar < HZ/4) - return; - - printk(KERN_WARNING "%s: command unit timed out, status resetting.\n", dev->name); - i596_reset(dev, lp, ioaddr); - } -} - -static int i596_open(struct net_device *dev) -{ - int i; - - i = request_irq(dev->irq, i596_interrupt, IRQF_SHARED, dev->name, dev); - if (i) { - printk(KERN_ERR "%s: IRQ %d not free\n", dev->name, dev->irq); - return i; - } - - if ((i = init_rx_bufs(dev, RX_RING_SIZE)) < RX_RING_SIZE) - printk(KERN_ERR "%s: only able to allocate %d receive buffers\n", dev->name, i); - - if (i < 4) { - free_irq(dev->irq, dev); - return -EAGAIN; - } - netif_start_queue(dev); - init_i596(dev); - return 0; /* Always succeed */ -} - -static netdev_tx_t i596_start_xmit (struct sk_buff *skb, struct net_device *dev) { - struct tx_cmd *tx_cmd; - short length; - - length = skb->len; - - if (length < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - length = ETH_ZLEN; - } - - tx_cmd = kmalloc((sizeof (struct tx_cmd) + sizeof (struct i596_tbd)), GFP_ATOMIC); - if (tx_cmd == NULL) { - printk(KERN_WARNING "%s: i596_xmit Memory squeeze, dropping packet.\n", dev->name); - dev->stats.tx_dropped++; - dev_kfree_skb (skb); - } else { - struct i596_tbd *tx_cmd_tbd; - tx_cmd_tbd = (struct i596_tbd *) (tx_cmd + 1); - tx_cmd->pa_tbd = va_to_pa (tx_cmd_tbd); - tx_cmd_tbd->pa_next = I596_NULL; - - tx_cmd->cmd.command = (CMD_FLEX | CmdTx); - - tx_cmd->pad = 0; - tx_cmd->size = 0; - tx_cmd_tbd->pad = 0; - tx_cmd_tbd->size = (EOF | length); - - tx_cmd_tbd->pa_data = va_to_pa (skb->data); - tx_cmd_tbd->skb = skb; - - if (i596_debug & LOG_SRCDST) - print_eth (skb->data); - - i596_add_cmd (dev, (struct i596_cmd *) tx_cmd); - - dev->stats.tx_packets++; - } - - return NETDEV_TX_OK; -} - -static void -i596_tx_timeout (struct net_device *dev) { - struct i596_private *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - - /* Transmitter timeout, serious problems. */ - printk(KERN_WARNING "%s: transmit timed out, status resetting.\n", dev->name); - dev->stats.tx_errors++; - - /* Try to restart the adaptor */ - if (lp->last_restart == dev->stats.tx_packets) { - printk ("Resetting board.\n"); - - /* Shutdown and restart */ - i596_reset (dev, lp, ioaddr); - } else { - /* Issue a channel attention signal */ - printk ("Kicking board.\n"); - lp->scb.command = (CUC_START | RX_START); - CA(); - lp->last_restart = dev->stats.tx_packets; - } - netif_wake_queue(dev); -} - -static void print_eth(char *add) -{ - int i; - - printk ("Dest "); - for (i = 0; i < 6; i++) - printk(" %2.2X", (unsigned char) add[i]); - printk ("\n"); - - printk ("Source"); - for (i = 0; i < 6; i++) - printk(" %2.2X", (unsigned char) add[i+6]); - printk ("\n"); - - printk ("type %2.2X%2.2X\n", - (unsigned char) add[12], (unsigned char) add[13]); -} - -static const struct net_device_ops i596_netdev_ops = { - .ndo_open = i596_open, - .ndo_stop = i596_close, - .ndo_start_xmit = i596_start_xmit, - .ndo_set_rx_mode = set_multicast_list, - .ndo_tx_timeout = i596_tx_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static int __init lp486e_probe(struct net_device *dev) { - struct i596_private *lp; - unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 }; - unsigned char *bios; - int i, j; - int ret = -ENOMEM; - static int probed; - - if (probed) - return -ENODEV; - probed++; - - if (!request_region(IOADDR, LP486E_TOTAL_SIZE, DRV_NAME)) { - printk(KERN_ERR "lp486e: IO address 0x%x in use\n", IOADDR); - return -EBUSY; - } - - lp = netdev_priv(dev); - spin_lock_init(&lp->cmd_lock); - - /* - * Do we really have this thing? - */ - if (i596_scp_setup(dev)) { - ret = -ENODEV; - goto err_out_kfree; - } - - dev->base_addr = IOADDR; - dev->irq = IRQ; - - - /* - * How do we find the ethernet address? I don't know. - * One possibility is to look at the EISA configuration area - * [0xe8000-0xe9fff]. This contains the ethernet address - * but not at a fixed address - things depend on setup options. - * - * If we find no address, or the wrong address, use - * ifconfig eth0 hw ether a1:a2:a3:a4:a5:a6 - * with the value found in the BIOS setup. - */ - bios = bus_to_virt(0xe8000); - for (j = 0; j < 0x2000; j++) { - if (bios[j] == 0 && bios[j+1] == 0xaa && bios[j+2] == 0) { - printk("%s: maybe address at BIOS 0x%x:", - dev->name, 0xe8000+j); - for (i = 0; i < 6; i++) { - eth_addr[i] = bios[i+j]; - printk(" %2.2X", eth_addr[i]); - } - printk("\n"); - } - } - - printk("%s: lp486e 82596 at %#3lx, IRQ %d,", - dev->name, dev->base_addr, dev->irq); - for (i = 0; i < 6; i++) - printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]); - printk("\n"); - - /* The LP486E-specific entries in the device structure. */ - dev->netdev_ops = &i596_netdev_ops; - dev->watchdog_timeo = 5*HZ; - -#if 0 - /* selftest reports 0x320925ae - don't know what that means */ - i596_port_do(dev, PORT_SELFTEST, "selftest"); - i596_port_do(dev, PORT_DUMP, "dump"); -#endif - return 0; - -err_out_kfree: - release_region(IOADDR, LP486E_TOTAL_SIZE); - return ret; -} - -static inline void -i596_handle_CU_completion(struct net_device *dev, - struct i596_private *lp, - unsigned short status, - unsigned short *ack_cmdp) { - struct i596_cmd *cmd; - int frames_out = 0; - int commands_done = 0; - int cmd_val; - unsigned long flags; - - spin_lock_irqsave(&lp->cmd_lock, flags); - cmd = lp->cmd_head; - - while (lp->cmd_head && (lp->cmd_head->status & CMD_STAT_C)) { - cmd = lp->cmd_head; - - lp->cmd_head = pa_to_va(lp->cmd_head->pa_next); - lp->cmd_backlog--; - - commands_done++; - cmd_val = cmd->command & 0x7; -#if 0 - printk("finished CU %s command (%d)\n", - CUcmdnames[cmd_val], cmd_val); -#endif - switch (cmd_val) { - case CmdTx: - { - struct tx_cmd *tx_cmd; - struct i596_tbd *tx_cmd_tbd; - - tx_cmd = (struct tx_cmd *) cmd; - tx_cmd_tbd = pa_to_va(tx_cmd->pa_tbd); - - frames_out++; - if (cmd->status & CMD_STAT_OK) { - if (i596_debug) - print_eth(pa_to_va(tx_cmd_tbd->pa_data)); - } else { - dev->stats.tx_errors++; - if (i596_debug) - printk("transmission failure:%04x\n", - cmd->status); - if (cmd->status & 0x0020) - dev->stats.collisions++; - if (!(cmd->status & 0x0040)) - dev->stats.tx_heartbeat_errors++; - if (cmd->status & 0x0400) - dev->stats.tx_carrier_errors++; - if (cmd->status & 0x0800) - dev->stats.collisions++; - if (cmd->status & 0x1000) - dev->stats.tx_aborted_errors++; - } - dev_kfree_skb_irq(tx_cmd_tbd->skb); - - cmd->pa_next = I596_NULL; - kfree((unsigned char *)tx_cmd); - netif_wake_queue(dev); - break; - } - - case CmdMulticastList: - cmd->pa_next = I596_NULL; - kfree((unsigned char *)cmd); - break; - - case CmdTDR: - { - unsigned long status = *((unsigned long *) (cmd + 1)); - if (status & 0x8000) { - if (i596_debug) - printk("%s: link ok.\n", dev->name); - } else { - if (status & 0x4000) - printk("%s: Transceiver problem.\n", - dev->name); - if (status & 0x2000) - printk("%s: Termination problem.\n", - dev->name); - if (status & 0x1000) - printk("%s: Short circuit.\n", - dev->name); - printk("%s: Time %ld.\n", - dev->name, status & 0x07ff); - } - } - default: - cmd->pa_next = I596_NULL; - lp->last_cmd = jiffies; - - } - barrier(); - } - - cmd = lp->cmd_head; - while (cmd && (cmd != lp->cmd_tail)) { - cmd->command &= 0x1fff; - cmd = pa_to_va(cmd->pa_next); - barrier(); - } - - if (lp->cmd_head) - *ack_cmdp |= CUC_START; - lp->scb.pa_cmd = va_to_pa(lp->cmd_head); - spin_unlock_irqrestore(&lp->cmd_lock, flags); -} - -static irqreturn_t -i596_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct i596_private *lp = netdev_priv(dev); - unsigned short status, ack_cmd = 0; - int frames_in = 0; - - /* - * The 82596 examines the command, performs the required action, - * and then clears the SCB command word. - */ - if (lp->scb.command && i596_timeout(dev, "interrupt", 40)) - ; - - /* - * The status word indicates the status of the 82596. - * It is modified only by the 82596. - * - * [So, we must not clear it. I find often status 0xffff, - * which is not one of the values allowed by the docs.] - */ - status = lp->scb.status; -#if 0 - if (i596_debug) { - printk("%s: i596 interrupt, ", dev->name); - i596_out_status(status); - } -#endif - /* Impossible, but it happens - perhaps when we get - a receive interrupt but scb.pa_rfd is I596_NULL. */ - if (status == 0xffff) { - printk("%s: i596_interrupt: got status 0xffff\n", dev->name); - goto out; - } - - ack_cmd = (status & STAT_ACK); - - if (status & (STAT_CX | STAT_CNA)) - i596_handle_CU_completion(dev, lp, status, &ack_cmd); - - if (status & (STAT_FR | STAT_RNR)) { - /* Restart the receive unit when it got inactive somehow */ - if ((status & STAT_RNR) && netif_running(dev)) - ack_cmd |= RX_START; - - if (status & STAT_FR) { - frames_in = i596_rx(dev); - if (!frames_in) - printk("receive frame reported, but no frames\n"); - } - } - - /* acknowledge the interrupt */ - /* - if ((lp->scb.pa_cmd != I596_NULL) && netif_running(dev)) - ack_cmd |= CUC_START; - */ - - if (lp->scb.command && i596_timeout(dev, "i596 interrupt", 100)) - ; - - lp->scb.command = ack_cmd; - - CLEAR_INT(); - CA(); - - out: - return IRQ_HANDLED; -} - -static int i596_close(struct net_device *dev) { - struct i596_private *lp = netdev_priv(dev); - - netif_stop_queue(dev); - - if (i596_debug) - printk("%s: Shutting down ethercard, status was %4.4x.\n", - dev->name, lp->scb.status); - - lp->scb.command = (CUC_ABORT | RX_ABORT); - CA(); - - i596_cleanup_cmd(dev); - - if (lp->scb.command && i596_timeout(dev, "i596_close", 200)) - ; - - free_irq(dev->irq, dev); - remove_rx_bufs(dev); - - return 0; -} - -/* -* Set or clear the multicast filter for this adaptor. -*/ - -static void set_multicast_list(struct net_device *dev) { - struct i596_private *lp = netdev_priv(dev); - struct i596_cmd *cmd; - - if (i596_debug > 1) - printk ("%s: set multicast list %d\n", - dev->name, netdev_mc_count(dev)); - - if (!netdev_mc_empty(dev)) { - struct netdev_hw_addr *ha; - char *cp; - cmd = kmalloc(sizeof(struct i596_cmd) + 2 + - netdev_mc_count(dev) * 6, GFP_ATOMIC); - if (cmd == NULL) { - printk (KERN_ERR "%s: set_multicast Memory squeeze.\n", dev->name); - return; - } - cmd->command = CmdMulticastList; - *((unsigned short *) (cmd + 1)) = netdev_mc_count(dev) * 6; - cp = ((char *)(cmd + 1))+2; - netdev_for_each_mc_addr(ha, dev) { - memcpy(cp, ha->addr, 6); - cp += 6; - } - if (i596_debug & LOG_SRCDST) - print_eth (((char *)(cmd + 1)) + 2); - i596_add_cmd(dev, cmd); - } else { - if (lp->set_conf.pa_next != I596_NULL) { - return; - } - if (netdev_mc_empty(dev) && - !(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { - lp->i596_config[8] &= ~0x01; - } else { - lp->i596_config[8] |= 0x01; - } - - i596_add_cmd(dev, &lp->set_conf); - } -} - -MODULE_AUTHOR("Ard van Breemen "); -MODULE_DESCRIPTION("Intel Panther onboard i82596 driver"); -MODULE_LICENSE("GPL"); - -static struct net_device *dev_lp486e; -static int full_duplex; -static int options; -static int io = IOADDR; -static int irq = IRQ; - -module_param(debug, int, 0); -//module_param(max_interrupt_work, int, 0); -//module_param(reverse_probe, int, 0); -//module_param(rx_copybreak, int, 0); -module_param(options, int, 0); -module_param(full_duplex, int, 0); - -static int __init lp486e_init_module(void) { - int err; - struct net_device *dev = alloc_etherdev(sizeof(struct i596_private)); - if (!dev) - return -ENOMEM; - - dev->irq = irq; - dev->base_addr = io; - err = lp486e_probe(dev); - if (err) { - free_netdev(dev); - return err; - } - err = register_netdev(dev); - if (err) { - release_region(dev->base_addr, LP486E_TOTAL_SIZE); - free_netdev(dev); - return err; - } - dev_lp486e = dev; - full_duplex = 0; - options = 0; - return 0; -} - -static void __exit lp486e_cleanup_module(void) { - unregister_netdev(dev_lp486e); - release_region(dev_lp486e->base_addr, LP486E_TOTAL_SIZE); - free_netdev(dev_lp486e); -} - -module_init(lp486e_init_module); -module_exit(lp486e_cleanup_module); -- cgit v1.2.3-70-g09d2 From 0e245dbaac9fa1c2fd0f4e2af7b9f6d874083a8b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 9 Jan 2013 20:51:58 -0500 Subject: drivers/net: delete the 3Com 3c505/3c507 intel i825xx support For those of us who were around in the early to mid 1990's, we will remember that the i825xx ethernet support was not something that was considered sufficiently vetted for 24/7 use. Folks might be inclined to use *functional* ISA hardware on some near expired P3 ISA machines for dedicated workhorse applications, but the odds of using (and relying on) one of these old/experimental drivers is essentially nil. So lets remove them. Signed-off-by: Paul Gortmaker --- drivers/net/Space.c | 8 - drivers/net/ethernet/i825xx/3c505.c | 1672 ---------------------------------- drivers/net/ethernet/i825xx/3c505.h | 292 ------ drivers/net/ethernet/i825xx/3c507.c | 939 ------------------- drivers/net/ethernet/i825xx/Kconfig | 23 - drivers/net/ethernet/i825xx/Makefile | 2 - 6 files changed, 2936 deletions(-) delete mode 100644 drivers/net/ethernet/i825xx/3c505.c delete mode 100644 drivers/net/ethernet/i825xx/3c505.h delete mode 100644 drivers/net/ethernet/i825xx/3c507.c (limited to 'drivers/net/ethernet/i825xx/Makefile') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index d4871275135..ac66a6af713 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -51,8 +51,6 @@ extern struct net_device *fmv18x_probe(int unit); extern struct net_device *eth16i_probe(int unit); extern struct net_device *i82596_probe(int unit); extern struct net_device *ewrk3_probe(int unit); -extern struct net_device *el16_probe(int unit); -extern struct net_device *elplus_probe(int unit); extern struct net_device *e2100_probe(int unit); extern struct net_device *ni5010_probe(int unit); extern struct net_device *ni52_probe(int unit); @@ -164,12 +162,6 @@ static struct devprobe2 isa_probes[] __initdata = { #if defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) /* Intel I82596 */ {i82596_probe, 0}, #endif -#ifdef CONFIG_EL16 /* 3c507 */ - {el16_probe, 0}, -#endif -#ifdef CONFIG_ELPLUS /* 3c505 */ - {elplus_probe, 0}, -#endif #ifdef CONFIG_NI5010 {ni5010_probe, 0}, #endif diff --git a/drivers/net/ethernet/i825xx/3c505.c b/drivers/net/ethernet/i825xx/3c505.c deleted file mode 100644 index 6d000d678a5..00000000000 --- a/drivers/net/ethernet/i825xx/3c505.c +++ /dev/null @@ -1,1672 +0,0 @@ -/* - * Linux Ethernet device driver for the 3Com Etherlink Plus (3C505) - * By Craig Southeren, Juha Laiho and Philip Blundell - * - * 3c505.c This module implements an interface to the 3Com - * Etherlink Plus (3c505) Ethernet card. Linux device - * driver interface reverse engineered from the Linux 3C509 - * device drivers. Some 3C505 information gleaned from - * the Crynwr packet driver. Still this driver would not - * be here without 3C505 technical reference provided by - * 3Com. - * - * $Id: 3c505.c,v 1.10 1996/04/16 13:06:27 phil Exp $ - * - * Authors: Linux 3c505 device driver by - * Craig Southeren, - * Final debugging by - * Andrew Tridgell, - * Auto irq/address, tuning, cleanup and v1.1.4+ kernel mods by - * Juha Laiho, - * Linux 3C509 driver by - * Donald Becker, - * (Now at ) - * Crynwr packet driver by - * Krishnan Gopalan and Gregg Stefancik, - * Clemson University Engineering Computer Operations. - * Portions of the code have been adapted from the 3c505 - * driver for NCSA Telnet by Bruce Orchard and later - * modified by Warren Van Houten and krus@diku.dk. - * 3C505 technical information provided by - * Terry Murphy, of 3Com Network Adapter Division - * Linux 1.3.0 changes by - * Alan Cox - * More debugging, DMA support, currently maintained by - * Philip Blundell - * Multicard/soft configurable dma channel/rev 2 hardware support - * by Christopher Collins - * Ethtool support (jgarzik), 11/17/2001 - */ - -#define DRV_NAME "3c505" -#define DRV_VERSION "1.10a" - - -/* Theory of operation: - * - * The 3c505 is quite an intelligent board. All communication with it is done - * by means of Primary Command Blocks (PCBs); these are transferred using PIO - * through the command register. The card has 256k of on-board RAM, which is - * used to buffer received packets. It might seem at first that more buffers - * are better, but in fact this isn't true. From my tests, it seems that - * more than about 10 buffers are unnecessary, and there is a noticeable - * performance hit in having more active on the card. So the majority of the - * card's memory isn't, in fact, used. Sadly, the card only has one transmit - * buffer and, short of loading our own firmware into it (which is what some - * drivers resort to) there's nothing we can do about this. - * - * We keep up to 4 "receive packet" commands active on the board at a time. - * When a packet comes in, so long as there is a receive command active, the - * board will send us a "packet received" PCB and then add the data for that - * packet to the DMA queue. If a DMA transfer is not already in progress, we - * set one up to start uploading the data. We have to maintain a list of - * backlogged receive packets, because the card may decide to tell us about - * a newly-arrived packet at any time, and we may not be able to start a DMA - * transfer immediately (ie one may already be going on). We can't NAK the - * PCB, because then it would throw the packet away. - * - * Trying to send a PCB to the card at the wrong moment seems to have bad - * effects. If we send it a transmit PCB while a receive DMA is happening, - * it will just NAK the PCB and so we will have wasted our time. Worse, it - * sometimes seems to interrupt the transfer. The majority of the low-level - * code is protected by one huge semaphore -- "busy" -- which is set whenever - * it probably isn't safe to do anything to the card. The receive routine - * must gain a lock on "busy" before it can start a DMA transfer, and the - * transmit routine must gain a lock before it sends the first PCB to the card. - * The send_pcb() routine also has an internal semaphore to protect it against - * being re-entered (which would be disastrous) -- this is needed because - * several things can happen asynchronously (re-priming the receiver and - * asking the card for statistics, for example). send_pcb() will also refuse - * to talk to the card at all if a DMA upload is happening. The higher-level - * networking code will reschedule a later retry if some part of the driver - * is blocked. In practice, this doesn't seem to happen very often. - */ - -/* This driver may now work with revision 2.x hardware, since all the read - * operations on the HCR have been removed (we now keep our own softcopy). - * But I don't have an old card to test it on. - * - * This has had the bad effect that the autoprobe routine is now a bit - * less friendly to other devices. However, it was never very good. - * before, so I doubt it will hurt anybody. - */ - -/* The driver is a mess. I took Craig's and Juha's code, and hacked it firstly - * to make it more reliable, and secondly to add DMA mode. Many things could - * probably be done better; the concurrency protection is particularly awful. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "3c505.h" - -/********************************************************* - * - * define debug messages here as common strings to reduce space - * - *********************************************************/ - -#define timeout_msg "*** timeout at %s:%s (line %d) ***\n" -#define TIMEOUT_MSG(lineno) \ - pr_notice(timeout_msg, __FILE__, __func__, (lineno)) - -#define invalid_pcb_msg "*** invalid pcb length %d at %s:%s (line %d) ***\n" -#define INVALID_PCB_MSG(len) \ - pr_notice(invalid_pcb_msg, (len), __FILE__, __func__, __LINE__) - -#define search_msg "%s: Looking for 3c505 adapter at address %#x..." - -#define stilllooking_msg "still looking..." - -#define found_msg "found.\n" - -#define notfound_msg "not found (reason = %d)\n" - -#define couldnot_msg "%s: 3c505 not found\n" - -/********************************************************* - * - * various other debug stuff - * - *********************************************************/ - -#ifdef ELP_DEBUG -static int elp_debug = ELP_DEBUG; -#else -static int elp_debug; -#endif -#define debug elp_debug - -/* - * 0 = no messages (well, some) - * 1 = messages when high level commands performed - * 2 = messages when low level commands performed - * 3 = messages when interrupts received - */ - -/***************************************************************** - * - * List of I/O-addresses we try to auto-sense - * Last element MUST BE 0! - *****************************************************************/ - -static int addr_list[] __initdata = {0x300, 0x280, 0x310, 0}; - -/* Dma Memory related stuff */ - -static unsigned long dma_mem_alloc(int size) -{ - int order = get_order(size); - return __get_dma_pages(GFP_KERNEL, order); -} - - -/***************************************************************** - * - * Functions for I/O (note the inline !) - * - *****************************************************************/ - -static inline unsigned char inb_status(unsigned int base_addr) -{ - return inb(base_addr + PORT_STATUS); -} - -static inline int inb_command(unsigned int base_addr) -{ - return inb(base_addr + PORT_COMMAND); -} - -static inline void outb_control(unsigned char val, struct net_device *dev) -{ - outb(val, dev->base_addr + PORT_CONTROL); - ((elp_device *)(netdev_priv(dev)))->hcr_val = val; -} - -#define HCR_VAL(x) (((elp_device *)(netdev_priv(x)))->hcr_val) - -static inline void outb_command(unsigned char val, unsigned int base_addr) -{ - outb(val, base_addr + PORT_COMMAND); -} - -static inline unsigned int backlog_next(unsigned int n) -{ - return (n + 1) % BACKLOG_SIZE; -} - -/***************************************************************** - * - * useful functions for accessing the adapter - * - *****************************************************************/ - -/* - * use this routine when accessing the ASF bits as they are - * changed asynchronously by the adapter - */ - -/* get adapter PCB status */ -#define GET_ASF(addr) \ - (get_status(addr)&ASF_PCB_MASK) - -static inline int get_status(unsigned int base_addr) -{ - unsigned long timeout = jiffies + 10*HZ/100; - register int stat1; - do { - stat1 = inb_status(base_addr); - } while (stat1 != inb_status(base_addr) && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) - TIMEOUT_MSG(__LINE__); - return stat1; -} - -static inline void set_hsf(struct net_device *dev, int hsf) -{ - elp_device *adapter = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&adapter->lock, flags); - outb_control((HCR_VAL(dev) & ~HSF_PCB_MASK) | hsf, dev); - spin_unlock_irqrestore(&adapter->lock, flags); -} - -static bool start_receive(struct net_device *, pcb_struct *); - -static inline void adapter_reset(struct net_device *dev) -{ - unsigned long timeout; - elp_device *adapter = netdev_priv(dev); - unsigned char orig_hcr = adapter->hcr_val; - - outb_control(0, dev); - - if (inb_status(dev->base_addr) & ACRF) { - do { - inb_command(dev->base_addr); - timeout = jiffies + 2*HZ/100; - while (time_before_eq(jiffies, timeout) && !(inb_status(dev->base_addr) & ACRF)); - } while (inb_status(dev->base_addr) & ACRF); - set_hsf(dev, HSF_PCB_NAK); - } - outb_control(adapter->hcr_val | ATTN | DIR, dev); - mdelay(10); - outb_control(adapter->hcr_val & ~ATTN, dev); - mdelay(10); - outb_control(adapter->hcr_val | FLSH, dev); - mdelay(10); - outb_control(adapter->hcr_val & ~FLSH, dev); - mdelay(10); - - outb_control(orig_hcr, dev); - if (!start_receive(dev, &adapter->tx_pcb)) - pr_err("%s: start receive command failed\n", dev->name); -} - -/* Check to make sure that a DMA transfer hasn't timed out. This should - * never happen in theory, but seems to occur occasionally if the card gets - * prodded at the wrong time. - */ -static inline void check_3c505_dma(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) { - unsigned long flags, f; - pr_err("%s: DMA %s timed out, %d bytes left\n", dev->name, - adapter->current_dma.direction ? "download" : "upload", - get_dma_residue(dev->dma)); - spin_lock_irqsave(&adapter->lock, flags); - adapter->dmaing = 0; - adapter->busy = 0; - - f=claim_dma_lock(); - disable_dma(dev->dma); - release_dma_lock(f); - - if (adapter->rx_active) - adapter->rx_active--; - outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev); - spin_unlock_irqrestore(&adapter->lock, flags); - } -} - -/* Primitive functions used by send_pcb() */ -static inline bool send_pcb_slow(unsigned int base_addr, unsigned char byte) -{ - unsigned long timeout; - outb_command(byte, base_addr); - for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) { - if (inb_status(base_addr) & HCRE) - return false; - } - pr_warning("3c505: send_pcb_slow timed out\n"); - return true; -} - -static inline bool send_pcb_fast(unsigned int base_addr, unsigned char byte) -{ - unsigned int timeout; - outb_command(byte, base_addr); - for (timeout = 0; timeout < 40000; timeout++) { - if (inb_status(base_addr) & HCRE) - return false; - } - pr_warning("3c505: send_pcb_fast timed out\n"); - return true; -} - -/* Check to see if the receiver needs restarting, and kick it if so */ -static inline void prime_rx(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - while (adapter->rx_active < ELP_RX_PCBS && netif_running(dev)) { - if (!start_receive(dev, &adapter->itx_pcb)) - break; - } -} - -/***************************************************************** - * - * send_pcb - * Send a PCB to the adapter. - * - * output byte to command reg --<--+ - * wait until HCRE is non zero | - * loop until all bytes sent -->--+ - * set HSF1 and HSF2 to 1 - * output pcb length - * wait until ASF give ACK or NAK - * set HSF1 and HSF2 to 0 - * - *****************************************************************/ - -/* This can be quite slow -- the adapter is allowed to take up to 40ms - * to respond to the initial interrupt. - * - * We run initially with interrupts turned on, but with a semaphore set - * so that nobody tries to re-enter this code. Once the first byte has - * gone through, we turn interrupts off and then send the others (the - * timeout is reduced to 500us). - */ - -static bool send_pcb(struct net_device *dev, pcb_struct * pcb) -{ - int i; - unsigned long timeout; - elp_device *adapter = netdev_priv(dev); - unsigned long flags; - - check_3c505_dma(dev); - - if (adapter->dmaing && adapter->current_dma.direction == 0) - return false; - - /* Avoid contention */ - if (test_and_set_bit(1, &adapter->send_pcb_semaphore)) { - if (elp_debug >= 3) { - pr_debug("%s: send_pcb entered while threaded\n", dev->name); - } - return false; - } - /* - * load each byte into the command register and - * wait for the HCRE bit to indicate the adapter - * had read the byte - */ - set_hsf(dev, 0); - - if (send_pcb_slow(dev->base_addr, pcb->command)) - goto abort; - - spin_lock_irqsave(&adapter->lock, flags); - - if (send_pcb_fast(dev->base_addr, pcb->length)) - goto sti_abort; - - for (i = 0; i < pcb->length; i++) { - if (send_pcb_fast(dev->base_addr, pcb->data.raw[i])) - goto sti_abort; - } - - outb_control(adapter->hcr_val | 3, dev); /* signal end of PCB */ - outb_command(2 + pcb->length, dev->base_addr); - - /* now wait for the acknowledgement */ - spin_unlock_irqrestore(&adapter->lock, flags); - - for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) { - switch (GET_ASF(dev->base_addr)) { - case ASF_PCB_ACK: - adapter->send_pcb_semaphore = 0; - return true; - - case ASF_PCB_NAK: -#ifdef ELP_DEBUG - pr_debug("%s: send_pcb got NAK\n", dev->name); -#endif - goto abort; - } - } - - if (elp_debug >= 1) - pr_debug("%s: timeout waiting for PCB acknowledge (status %02x)\n", - dev->name, inb_status(dev->base_addr)); - goto abort; - - sti_abort: - spin_unlock_irqrestore(&adapter->lock, flags); - abort: - adapter->send_pcb_semaphore = 0; - return false; -} - - -/***************************************************************** - * - * receive_pcb - * Read a PCB from the adapter - * - * wait for ACRF to be non-zero ---<---+ - * input a byte | - * if ASF1 and ASF2 were not both one | - * before byte was read, loop --->---+ - * set HSF1 and HSF2 for ack - * - *****************************************************************/ - -static bool receive_pcb(struct net_device *dev, pcb_struct * pcb) -{ - int i, j; - int total_length; - int stat; - unsigned long timeout; - unsigned long flags; - - elp_device *adapter = netdev_priv(dev); - - set_hsf(dev, 0); - - /* get the command code */ - timeout = jiffies + 2*HZ/100; - while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) { - TIMEOUT_MSG(__LINE__); - return false; - } - pcb->command = inb_command(dev->base_addr); - - /* read the data length */ - timeout = jiffies + 3*HZ/100; - while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) { - TIMEOUT_MSG(__LINE__); - pr_info("%s: status %02x\n", dev->name, stat); - return false; - } - pcb->length = inb_command(dev->base_addr); - - if (pcb->length > MAX_PCB_DATA) { - INVALID_PCB_MSG(pcb->length); - adapter_reset(dev); - return false; - } - /* read the data */ - spin_lock_irqsave(&adapter->lock, flags); - for (i = 0; i < MAX_PCB_DATA; i++) { - for (j = 0; j < 20000; j++) { - stat = get_status(dev->base_addr); - if (stat & ACRF) - break; - } - pcb->data.raw[i] = inb_command(dev->base_addr); - if ((stat & ASF_PCB_MASK) == ASF_PCB_END || j >= 20000) - break; - } - spin_unlock_irqrestore(&adapter->lock, flags); - if (i >= MAX_PCB_DATA) { - INVALID_PCB_MSG(i); - return false; - } - if (j >= 20000) { - TIMEOUT_MSG(__LINE__); - return false; - } - /* the last "data" byte was really the length! */ - total_length = pcb->data.raw[i]; - - /* safety check total length vs data length */ - if (total_length != (pcb->length + 2)) { - if (elp_debug >= 2) - pr_warning("%s: mangled PCB received\n", dev->name); - set_hsf(dev, HSF_PCB_NAK); - return false; - } - - if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) { - if (test_and_set_bit(0, (void *) &adapter->busy)) { - if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) { - set_hsf(dev, HSF_PCB_NAK); - pr_warning("%s: PCB rejected, transfer in progress and backlog full\n", dev->name); - pcb->command = 0; - return true; - } else { - pcb->command = 0xff; - } - } - } - set_hsf(dev, HSF_PCB_ACK); - return true; -} - -/****************************************************** - * - * queue a receive command on the adapter so we will get an - * interrupt when a packet is received. - * - ******************************************************/ - -static bool start_receive(struct net_device *dev, pcb_struct * tx_pcb) -{ - bool status; - elp_device *adapter = netdev_priv(dev); - - if (elp_debug >= 3) - pr_debug("%s: restarting receiver\n", dev->name); - tx_pcb->command = CMD_RECEIVE_PACKET; - tx_pcb->length = sizeof(struct Rcv_pkt); - tx_pcb->data.rcv_pkt.buf_seg - = tx_pcb->data.rcv_pkt.buf_ofs = 0; /* Unused */ - tx_pcb->data.rcv_pkt.buf_len = 1600; - tx_pcb->data.rcv_pkt.timeout = 0; /* set timeout to zero */ - status = send_pcb(dev, tx_pcb); - if (status) - adapter->rx_active++; - return status; -} - -/****************************************************** - * - * extract a packet from the adapter - * this routine is only called from within the interrupt - * service routine, so no cli/sti calls are needed - * note that the length is always assumed to be even - * - ******************************************************/ - -static void receive_packet(struct net_device *dev, int len) -{ - int rlen; - elp_device *adapter = netdev_priv(dev); - void *target; - struct sk_buff *skb; - unsigned long flags; - - rlen = (len + 1) & ~1; - skb = netdev_alloc_skb(dev, rlen + 2); - - if (!skb) { - pr_warning("%s: memory squeeze, dropping packet\n", dev->name); - target = adapter->dma_buffer; - adapter->current_dma.target = NULL; - /* FIXME: stats */ - return; - } - - skb_reserve(skb, 2); - target = skb_put(skb, rlen); - if ((unsigned long)(target + rlen) >= MAX_DMA_ADDRESS) { - adapter->current_dma.target = target; - target = adapter->dma_buffer; - } else { - adapter->current_dma.target = NULL; - } - - /* if this happens, we die */ - if (test_and_set_bit(0, (void *) &adapter->dmaing)) - pr_err("%s: rx blocked, DMA in progress, dir %d\n", - dev->name, adapter->current_dma.direction); - - adapter->current_dma.direction = 0; - adapter->current_dma.length = rlen; - adapter->current_dma.skb = skb; - adapter->current_dma.start_time = jiffies; - - outb_control(adapter->hcr_val | DIR | TCEN | DMAE, dev); - - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, 0x04); /* dma read */ - set_dma_addr(dev->dma, isa_virt_to_bus(target)); - set_dma_count(dev->dma, rlen); - enable_dma(dev->dma); - release_dma_lock(flags); - - if (elp_debug >= 3) { - pr_debug("%s: rx DMA transfer started\n", dev->name); - } - - if (adapter->rx_active) - adapter->rx_active--; - - if (!adapter->busy) - pr_warning("%s: receive_packet called, busy not set.\n", dev->name); -} - -/****************************************************** - * - * interrupt handler - * - ******************************************************/ - -static irqreturn_t elp_interrupt(int irq, void *dev_id) -{ - int len; - int dlen; - int icount = 0; - struct net_device *dev = dev_id; - elp_device *adapter = netdev_priv(dev); - unsigned long timeout; - - spin_lock(&adapter->lock); - - do { - /* - * has a DMA transfer finished? - */ - if (inb_status(dev->base_addr) & DONE) { - if (!adapter->dmaing) - pr_warning("%s: phantom DMA completed\n", dev->name); - - if (elp_debug >= 3) - pr_debug("%s: %s DMA complete, status %02x\n", dev->name, - adapter->current_dma.direction ? "tx" : "rx", - inb_status(dev->base_addr)); - - outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev); - if (adapter->current_dma.direction) { - dev_kfree_skb_irq(adapter->current_dma.skb); - } else { - struct sk_buff *skb = adapter->current_dma.skb; - if (skb) { - if (adapter->current_dma.target) { - /* have already done the skb_put() */ - memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length); - } - skb->protocol = eth_type_trans(skb,dev); - dev->stats.rx_bytes += skb->len; - netif_rx(skb); - } - } - adapter->dmaing = 0; - if (adapter->rx_backlog.in != adapter->rx_backlog.out) { - int t = adapter->rx_backlog.length[adapter->rx_backlog.out]; - adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out); - if (elp_debug >= 2) - pr_debug("%s: receiving backlogged packet (%d)\n", dev->name, t); - receive_packet(dev, t); - } else { - adapter->busy = 0; - } - } else { - /* has one timed out? */ - check_3c505_dma(dev); - } - - /* - * receive a PCB from the adapter - */ - timeout = jiffies + 3*HZ/100; - while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) { - if (receive_pcb(dev, &adapter->irx_pcb)) { - switch (adapter->irx_pcb.command) - { - case 0: - break; - /* - * received a packet - this must be handled fast - */ - case 0xff: - case CMD_RECEIVE_PACKET_COMPLETE: - /* if the device isn't open, don't pass packets up the stack */ - if (!netif_running(dev)) - break; - len = adapter->irx_pcb.data.rcv_resp.pkt_len; - dlen = adapter->irx_pcb.data.rcv_resp.buf_len; - if (adapter->irx_pcb.data.rcv_resp.timeout != 0) { - pr_err("%s: interrupt - packet not received correctly\n", dev->name); - } else { - if (elp_debug >= 3) { - pr_debug("%s: interrupt - packet received of length %i (%i)\n", - dev->name, len, dlen); - } - if (adapter->irx_pcb.command == 0xff) { - if (elp_debug >= 2) - pr_debug("%s: adding packet to backlog (len = %d)\n", - dev->name, dlen); - adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen; - adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in); - } else { - receive_packet(dev, dlen); - } - if (elp_debug >= 3) - pr_debug("%s: packet received\n", dev->name); - } - break; - - /* - * 82586 configured correctly - */ - case CMD_CONFIGURE_82586_RESPONSE: - adapter->got[CMD_CONFIGURE_82586] = 1; - if (elp_debug >= 3) - pr_debug("%s: interrupt - configure response received\n", dev->name); - break; - - /* - * Adapter memory configuration - */ - case CMD_CONFIGURE_ADAPTER_RESPONSE: - adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1; - if (elp_debug >= 3) - pr_debug("%s: Adapter memory configuration %s.\n", dev->name, - adapter->irx_pcb.data.failed ? "failed" : "succeeded"); - break; - - /* - * Multicast list loading - */ - case CMD_LOAD_MULTICAST_RESPONSE: - adapter->got[CMD_LOAD_MULTICAST_LIST] = 1; - if (elp_debug >= 3) - pr_debug("%s: Multicast address list loading %s.\n", dev->name, - adapter->irx_pcb.data.failed ? "failed" : "succeeded"); - break; - - /* - * Station address setting - */ - case CMD_SET_ADDRESS_RESPONSE: - adapter->got[CMD_SET_STATION_ADDRESS] = 1; - if (elp_debug >= 3) - pr_debug("%s: Ethernet address setting %s.\n", dev->name, - adapter->irx_pcb.data.failed ? "failed" : "succeeded"); - break; - - - /* - * received board statistics - */ - case CMD_NETWORK_STATISTICS_RESPONSE: - dev->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv; - dev->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit; - dev->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC; - dev->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align; - dev->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun; - dev->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res; - adapter->got[CMD_NETWORK_STATISTICS] = 1; - if (elp_debug >= 3) - pr_debug("%s: interrupt - statistics response received\n", dev->name); - break; - - /* - * sent a packet - */ - case CMD_TRANSMIT_PACKET_COMPLETE: - if (elp_debug >= 3) - pr_debug("%s: interrupt - packet sent\n", dev->name); - if (!netif_running(dev)) - break; - switch (adapter->irx_pcb.data.xmit_resp.c_stat) { - case 0xffff: - dev->stats.tx_aborted_errors++; - pr_info("%s: transmit timed out, network cable problem?\n", dev->name); - break; - case 0xfffe: - dev->stats.tx_fifo_errors++; - pr_info("%s: transmit timed out, FIFO underrun\n", dev->name); - break; - } - netif_wake_queue(dev); - break; - - /* - * some unknown PCB - */ - default: - pr_debug("%s: unknown PCB received - %2.2x\n", - dev->name, adapter->irx_pcb.command); - break; - } - } else { - pr_warning("%s: failed to read PCB on interrupt\n", dev->name); - adapter_reset(dev); - } - } - - } while (icount++ < 5 && (inb_status(dev->base_addr) & (ACRF | DONE))); - - prime_rx(dev); - - /* - * indicate no longer in interrupt routine - */ - spin_unlock(&adapter->lock); - return IRQ_HANDLED; -} - - -/****************************************************** - * - * open the board - * - ******************************************************/ - -static int elp_open(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - int retval; - - if (elp_debug >= 3) - pr_debug("%s: request to open device\n", dev->name); - - /* - * make sure we actually found the device - */ - if (adapter == NULL) { - pr_err("%s: Opening a non-existent physical device\n", dev->name); - return -EAGAIN; - } - /* - * disable interrupts on the board - */ - outb_control(0, dev); - - /* - * clear any pending interrupts - */ - inb_command(dev->base_addr); - adapter_reset(dev); - - /* - * no receive PCBs active - */ - adapter->rx_active = 0; - - adapter->busy = 0; - adapter->send_pcb_semaphore = 0; - adapter->rx_backlog.in = 0; - adapter->rx_backlog.out = 0; - - spin_lock_init(&adapter->lock); - - /* - * install our interrupt service routine - */ - if ((retval = request_irq(dev->irq, elp_interrupt, 0, dev->name, dev))) { - pr_err("%s: could not allocate IRQ%d\n", dev->name, dev->irq); - return retval; - } - if ((retval = request_dma(dev->dma, dev->name))) { - free_irq(dev->irq, dev); - pr_err("%s: could not allocate DMA%d channel\n", dev->name, dev->dma); - return retval; - } - adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE); - if (!adapter->dma_buffer) { - pr_err("%s: could not allocate DMA buffer\n", dev->name); - free_dma(dev->dma); - free_irq(dev->irq, dev); - return -ENOMEM; - } - adapter->dmaing = 0; - - /* - * enable interrupts on the board - */ - outb_control(CMDE, dev); - - /* - * configure adapter memory: we need 10 multicast addresses, default==0 - */ - if (elp_debug >= 3) - pr_debug("%s: sending 3c505 memory configuration command\n", dev->name); - adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY; - adapter->tx_pcb.data.memconf.cmd_q = 10; - adapter->tx_pcb.data.memconf.rcv_q = 20; - adapter->tx_pcb.data.memconf.mcast = 10; - adapter->tx_pcb.data.memconf.frame = 20; - adapter->tx_pcb.data.memconf.rcv_b = 20; - adapter->tx_pcb.data.memconf.progs = 0; - adapter->tx_pcb.length = sizeof(struct Memconf); - adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - pr_err("%s: couldn't send memory configuration command\n", dev->name); - else { - unsigned long timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) - TIMEOUT_MSG(__LINE__); - } - - - /* - * configure adapter to receive broadcast messages and wait for response - */ - if (elp_debug >= 3) - pr_debug("%s: sending 82586 configure command\n", dev->name); - adapter->tx_pcb.command = CMD_CONFIGURE_82586; - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; - adapter->tx_pcb.length = 2; - adapter->got[CMD_CONFIGURE_82586] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - pr_err("%s: couldn't send 82586 configure command\n", dev->name); - else { - unsigned long timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) - TIMEOUT_MSG(__LINE__); - } - - /* enable burst-mode DMA */ - /* outb(0x1, dev->base_addr + PORT_AUXDMA); */ - - /* - * queue receive commands to provide buffering - */ - prime_rx(dev); - if (elp_debug >= 3) - pr_debug("%s: %d receive PCBs active\n", dev->name, adapter->rx_active); - - /* - * device is now officially open! - */ - - netif_start_queue(dev); - return 0; -} - - -/****************************************************** - * - * send a packet to the adapter - * - ******************************************************/ - -static netdev_tx_t send_packet(struct net_device *dev, struct sk_buff *skb) -{ - elp_device *adapter = netdev_priv(dev); - unsigned long target; - unsigned long flags; - - /* - * make sure the length is even and no shorter than 60 bytes - */ - unsigned int nlen = (((skb->len < 60) ? 60 : skb->len) + 1) & (~1); - - if (test_and_set_bit(0, (void *) &adapter->busy)) { - if (elp_debug >= 2) - pr_debug("%s: transmit blocked\n", dev->name); - return false; - } - - dev->stats.tx_bytes += nlen; - - /* - * send the adapter a transmit packet command. Ignore segment and offset - * and make sure the length is even - */ - adapter->tx_pcb.command = CMD_TRANSMIT_PACKET; - adapter->tx_pcb.length = sizeof(struct Xmit_pkt); - adapter->tx_pcb.data.xmit_pkt.buf_ofs - = adapter->tx_pcb.data.xmit_pkt.buf_seg = 0; /* Unused */ - adapter->tx_pcb.data.xmit_pkt.pkt_len = nlen; - - if (!send_pcb(dev, &adapter->tx_pcb)) { - adapter->busy = 0; - return false; - } - /* if this happens, we die */ - if (test_and_set_bit(0, (void *) &adapter->dmaing)) - pr_debug("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction); - - adapter->current_dma.direction = 1; - adapter->current_dma.start_time = jiffies; - - if ((unsigned long)(skb->data + nlen) >= MAX_DMA_ADDRESS || nlen != skb->len) { - skb_copy_from_linear_data(skb, adapter->dma_buffer, nlen); - memset(adapter->dma_buffer+skb->len, 0, nlen-skb->len); - target = isa_virt_to_bus(adapter->dma_buffer); - } - else { - target = isa_virt_to_bus(skb->data); - } - adapter->current_dma.skb = skb; - - flags=claim_dma_lock(); - disable_dma(dev->dma); - clear_dma_ff(dev->dma); - set_dma_mode(dev->dma, 0x48); /* dma memory -> io */ - set_dma_addr(dev->dma, target); - set_dma_count(dev->dma, nlen); - outb_control(adapter->hcr_val | DMAE | TCEN, dev); - enable_dma(dev->dma); - release_dma_lock(flags); - - if (elp_debug >= 3) - pr_debug("%s: DMA transfer started\n", dev->name); - - return true; -} - -/* - * The upper layer thinks we timed out - */ - -static void elp_timeout(struct net_device *dev) -{ - int stat; - - stat = inb_status(dev->base_addr); - pr_warning("%s: transmit timed out, lost %s?\n", dev->name, - (stat & ACRF) ? "interrupt" : "command"); - if (elp_debug >= 1) - pr_debug("%s: status %#02x\n", dev->name, stat); - dev->trans_start = jiffies; /* prevent tx timeout */ - dev->stats.tx_dropped++; - netif_wake_queue(dev); -} - -/****************************************************** - * - * start the transmitter - * return 0 if sent OK, else return 1 - * - ******************************************************/ - -static netdev_tx_t elp_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned long flags; - elp_device *adapter = netdev_priv(dev); - - spin_lock_irqsave(&adapter->lock, flags); - check_3c505_dma(dev); - - if (elp_debug >= 3) - pr_debug("%s: request to send packet of length %d\n", dev->name, (int) skb->len); - - netif_stop_queue(dev); - - /* - * send the packet at skb->data for skb->len - */ - if (!send_packet(dev, skb)) { - if (elp_debug >= 2) { - pr_debug("%s: failed to transmit packet\n", dev->name); - } - spin_unlock_irqrestore(&adapter->lock, flags); - return NETDEV_TX_BUSY; - } - if (elp_debug >= 3) - pr_debug("%s: packet of length %d sent\n", dev->name, (int) skb->len); - - prime_rx(dev); - spin_unlock_irqrestore(&adapter->lock, flags); - netif_start_queue(dev); - return NETDEV_TX_OK; -} - -/****************************************************** - * - * return statistics on the board - * - ******************************************************/ - -static struct net_device_stats *elp_get_stats(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - - if (elp_debug >= 3) - pr_debug("%s: request for stats\n", dev->name); - - /* If the device is closed, just return the latest stats we have, - - we cannot ask from the adapter without interrupts */ - if (!netif_running(dev)) - return &dev->stats; - - /* send a get statistics command to the board */ - adapter->tx_pcb.command = CMD_NETWORK_STATISTICS; - adapter->tx_pcb.length = 0; - adapter->got[CMD_NETWORK_STATISTICS] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - pr_err("%s: couldn't send get statistics command\n", dev->name); - else { - unsigned long timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) { - TIMEOUT_MSG(__LINE__); - return &dev->stats; - } - } - - /* statistics are now up to date */ - return &dev->stats; -} - - -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - snprintf(info->bus_info, sizeof(info->bus_info), "ISA 0x%lx", - dev->base_addr); -} - -static u32 netdev_get_msglevel(struct net_device *dev) -{ - return debug; -} - -static void netdev_set_msglevel(struct net_device *dev, u32 level) -{ - debug = level; -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, - .get_msglevel = netdev_get_msglevel, - .set_msglevel = netdev_set_msglevel, -}; - -/****************************************************** - * - * close the board - * - ******************************************************/ - -static int elp_close(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - - if (elp_debug >= 3) - pr_debug("%s: request to close device\n", dev->name); - - netif_stop_queue(dev); - - /* Someone may request the device statistic information even when - * the interface is closed. The following will update the statistics - * structure in the driver, so we'll be able to give current statistics. - */ - (void) elp_get_stats(dev); - - /* - * disable interrupts on the board - */ - outb_control(0, dev); - - /* - * release the IRQ - */ - free_irq(dev->irq, dev); - - free_dma(dev->dma); - free_pages((unsigned long) adapter->dma_buffer, get_order(DMA_BUFFER_SIZE)); - - return 0; -} - - -/************************************************************ - * - * Set multicast list - * num_addrs==0: clear mc_list - * num_addrs==-1: set promiscuous mode - * num_addrs>0: set mc_list - * - ************************************************************/ - -static void elp_set_mc_list(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - struct netdev_hw_addr *ha; - int i; - unsigned long flags; - - if (elp_debug >= 3) - pr_debug("%s: request to set multicast list\n", dev->name); - - spin_lock_irqsave(&adapter->lock, flags); - - if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) { - /* send a "load multicast list" command to the board, max 10 addrs/cmd */ - /* if num_addrs==0 the list will be cleared */ - adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST; - adapter->tx_pcb.length = 6 * netdev_mc_count(dev); - i = 0; - netdev_for_each_mc_addr(ha, dev) - memcpy(adapter->tx_pcb.data.multicast[i++], - ha->addr, 6); - adapter->got[CMD_LOAD_MULTICAST_LIST] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - pr_err("%s: couldn't send set_multicast command\n", dev->name); - else { - unsigned long timeout = jiffies + TIMEOUT; - while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) { - TIMEOUT_MSG(__LINE__); - } - } - if (!netdev_mc_empty(dev)) - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI; - else /* num_addrs == 0 */ - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD; - } else - adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC; - /* - * configure adapter to receive messages (as specified above) - * and wait for response - */ - if (elp_debug >= 3) - pr_debug("%s: sending 82586 configure command\n", dev->name); - adapter->tx_pcb.command = CMD_CONFIGURE_82586; - adapter->tx_pcb.length = 2; - adapter->got[CMD_CONFIGURE_82586] = 0; - if (!send_pcb(dev, &adapter->tx_pcb)) - { - spin_unlock_irqrestore(&adapter->lock, flags); - pr_err("%s: couldn't send 82586 configure command\n", dev->name); - } - else { - unsigned long timeout = jiffies + TIMEOUT; - spin_unlock_irqrestore(&adapter->lock, flags); - while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout)); - if (time_after_eq(jiffies, timeout)) - TIMEOUT_MSG(__LINE__); - } -} - -/************************************************************ - * - * A couple of tests to see if there's 3C505 or not - * Called only by elp_autodetect - ************************************************************/ - -static int __init elp_sense(struct net_device *dev) -{ - int addr = dev->base_addr; - const char *name = dev->name; - byte orig_HSR; - - if (!request_region(addr, ELP_IO_EXTENT, "3c505")) - return -ENODEV; - - orig_HSR = inb_status(addr); - - if (elp_debug > 0) - pr_debug(search_msg, name, addr); - - if (orig_HSR == 0xff) { - if (elp_debug > 0) - pr_cont(notfound_msg, 1); - goto out; - } - - /* Wait for a while; the adapter may still be booting up */ - if (elp_debug > 0) - pr_cont(stilllooking_msg); - - if (orig_HSR & DIR) { - /* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */ - outb(0, dev->base_addr + PORT_CONTROL); - msleep(300); - if (inb_status(addr) & DIR) { - if (elp_debug > 0) - pr_cont(notfound_msg, 2); - goto out; - } - } else { - /* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */ - outb(DIR, dev->base_addr + PORT_CONTROL); - msleep(300); - if (!(inb_status(addr) & DIR)) { - if (elp_debug > 0) - pr_cont(notfound_msg, 3); - goto out; - } - } - /* - * It certainly looks like a 3c505. - */ - if (elp_debug > 0) - pr_cont(found_msg); - - return 0; -out: - release_region(addr, ELP_IO_EXTENT); - return -ENODEV; -} - -/************************************************************* - * - * Search through addr_list[] and try to find a 3C505 - * Called only by eplus_probe - *************************************************************/ - -static int __init elp_autodetect(struct net_device *dev) -{ - int idx = 0; - - /* if base address set, then only check that address - otherwise, run through the table */ - if (dev->base_addr != 0) { /* dev->base_addr == 0 ==> plain autodetect */ - if (elp_sense(dev) == 0) - return dev->base_addr; - } else - while ((dev->base_addr = addr_list[idx++])) { - if (elp_sense(dev) == 0) - return dev->base_addr; - } - - /* could not find an adapter */ - if (elp_debug > 0) - pr_debug(couldnot_msg, dev->name); - - return 0; /* Because of this, the layer above will return -ENODEV */ -} - -static const struct net_device_ops elp_netdev_ops = { - .ndo_open = elp_open, - .ndo_stop = elp_close, - .ndo_get_stats = elp_get_stats, - .ndo_start_xmit = elp_start_xmit, - .ndo_tx_timeout = elp_timeout, - .ndo_set_rx_mode = elp_set_mc_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/****************************************************** - * - * probe for an Etherlink Plus board at the specified address - * - ******************************************************/ - -/* There are three situations we need to be able to detect here: - - * a) the card is idle - * b) the card is still booting up - * c) the card is stuck in a strange state (some DOS drivers do this) - * - * In case (a), all is well. In case (b), we wait 10 seconds to see if the - * card finishes booting, and carry on if so. In case (c), we do a hard reset, - * loop round, and hope for the best. - * - * This is all very unpleasant, but hopefully avoids the problems with the old - * probe code (which had a 15-second delay if the card was idle, and didn't - * work at all if it was in a weird state). - */ - -static int __init elplus_setup(struct net_device *dev) -{ - elp_device *adapter = netdev_priv(dev); - int i, tries, tries1, okay; - unsigned long timeout; - unsigned long cookie = 0; - int err = -ENODEV; - - /* - * setup adapter structure - */ - - dev->base_addr = elp_autodetect(dev); - if (!dev->base_addr) - return -ENODEV; - - adapter->send_pcb_semaphore = 0; - - for (tries1 = 0; tries1 < 3; tries1++) { - outb_control((adapter->hcr_val | CMDE) & ~DIR, dev); - /* First try to write just one byte, to see if the card is - * responding at all normally. - */ - timeout = jiffies + 5*HZ/100; - okay = 0; - while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE)); - if ((inb_status(dev->base_addr) & HCRE)) { - outb_command(0, dev->base_addr); /* send a spurious byte */ - timeout = jiffies + 5*HZ/100; - while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE)); - if (inb_status(dev->base_addr) & HCRE) - okay = 1; - } - if (!okay) { - /* Nope, it's ignoring the command register. This means that - * either it's still booting up, or it's died. - */ - pr_err("%s: command register wouldn't drain, ", dev->name); - if ((inb_status(dev->base_addr) & 7) == 3) { - /* If the adapter status is 3, it *could* still be booting. - * Give it the benefit of the doubt for 10 seconds. - */ - pr_cont("assuming 3c505 still starting\n"); - timeout = jiffies + 10*HZ; - while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7)); - if (inb_status(dev->base_addr) & 7) { - pr_err("%s: 3c505 failed to start\n", dev->name); - } else { - okay = 1; /* It started */ - } - } else { - /* Otherwise, it must just be in a strange - * state. We probably need to kick it. - */ - pr_cont("3c505 is sulking\n"); - } - } - for (tries = 0; tries < 5 && okay; tries++) { - - /* - * Try to set the Ethernet address, to make sure that the board - * is working. - */ - adapter->tx_pcb.command = CMD_STATION_ADDRESS; - adapter->tx_pcb.length = 0; - cookie = probe_irq_on(); - if (!send_pcb(dev, &adapter->tx_pcb)) { - pr_err("%s: could not send first PCB\n", dev->name); - probe_irq_off(cookie); - continue; - } - if (!receive_pcb(dev, &adapter->rx_pcb)) { - pr_err("%s: could not read first PCB\n", dev->name); - probe_irq_off(cookie); - continue; - } - if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) || - (adapter->rx_pcb.length != 6)) { - pr_err("%s: first PCB wrong (%d, %d)\n", dev->name, - adapter->rx_pcb.command, adapter->rx_pcb.length); - probe_irq_off(cookie); - continue; - } - goto okay; - } - /* It's broken. Do a hard reset to re-initialise the board, - * and try again. - */ - pr_info("%s: resetting adapter\n", dev->name); - outb_control(adapter->hcr_val | FLSH | ATTN, dev); - outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev); - } - pr_err("%s: failed to initialise 3c505\n", dev->name); - goto out; - - okay: - if (dev->irq) { /* Is there a preset IRQ? */ - int rpt = probe_irq_off(cookie); - if (dev->irq != rpt) { - pr_warning("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt); - } - /* if dev->irq == probe_irq_off(cookie), all is well */ - } else /* No preset IRQ; just use what we can detect */ - dev->irq = probe_irq_off(cookie); - switch (dev->irq) { /* Legal, sane? */ - case 0: - pr_err("%s: IRQ probe failed: check 3c505 jumpers.\n", - dev->name); - goto out; - case 1: - case 6: - case 8: - case 13: - pr_err("%s: Impossible IRQ %d reported by probe_irq_off().\n", - dev->name, dev->irq); - goto out; - } - /* - * Now we have the IRQ number so we can disable the interrupts from - * the board until the board is opened. - */ - outb_control(adapter->hcr_val & ~CMDE, dev); - - /* - * copy Ethernet address into structure - */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = adapter->rx_pcb.data.eth_addr[i]; - - /* find a DMA channel */ - if (!dev->dma) { - if (dev->mem_start) { - dev->dma = dev->mem_start & 7; - } - else { - pr_warning("%s: warning, DMA channel not specified, using default\n", dev->name); - dev->dma = ELP_DMA; - } - } - - /* - * print remainder of startup message - */ - pr_info("%s: 3c505 at %#lx, irq %d, dma %d, addr %pM, ", - dev->name, dev->base_addr, dev->irq, dev->dma, dev->dev_addr); - /* - * read more information from the adapter - */ - - adapter->tx_pcb.command = CMD_ADAPTER_INFO; - adapter->tx_pcb.length = 0; - if (!send_pcb(dev, &adapter->tx_pcb) || - !receive_pcb(dev, &adapter->rx_pcb) || - (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) || - (adapter->rx_pcb.length != 10)) { - pr_cont("not responding to second PCB\n"); - } - pr_cont("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, - adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz); - - /* - * reconfigure the adapter memory to better suit our purposes - */ - adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY; - adapter->tx_pcb.length = 12; - adapter->tx_pcb.data.memconf.cmd_q = 8; - adapter->tx_pcb.data.memconf.rcv_q = 8; - adapter->tx_pcb.data.memconf.mcast = 10; - adapter->tx_pcb.data.memconf.frame = 10; - adapter->tx_pcb.data.memconf.rcv_b = 10; - adapter->tx_pcb.data.memconf.progs = 0; - if (!send_pcb(dev, &adapter->tx_pcb) || - !receive_pcb(dev, &adapter->rx_pcb) || - (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) || - (adapter->rx_pcb.length != 2)) { - pr_err("%s: could not configure adapter memory\n", dev->name); - } - if (adapter->rx_pcb.data.configure) { - pr_err("%s: adapter configuration failed\n", dev->name); - } - - dev->netdev_ops = &elp_netdev_ops; - dev->watchdog_timeo = 10*HZ; - dev->ethtool_ops = &netdev_ethtool_ops; /* local */ - - dev->mem_start = dev->mem_end = 0; - - err = register_netdev(dev); - if (err) - goto out; - - return 0; -out: - release_region(dev->base_addr, ELP_IO_EXTENT); - return err; -} - -#ifndef MODULE -struct net_device * __init elplus_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(elp_device)); - int err; - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = elplus_setup(dev); - if (err) { - free_netdev(dev); - return ERR_PTR(err); - } - return dev; -} - -#else -static struct net_device *dev_3c505[ELP_MAX_CARDS]; -static int io[ELP_MAX_CARDS]; -static int irq[ELP_MAX_CARDS]; -static int dma[ELP_MAX_CARDS]; -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param_array(dma, int, NULL, 0); -MODULE_PARM_DESC(io, "EtherLink Plus I/O base address(es)"); -MODULE_PARM_DESC(irq, "EtherLink Plus IRQ number(s) (assigned)"); -MODULE_PARM_DESC(dma, "EtherLink Plus DMA channel(s)"); - -int __init init_module(void) -{ - int this_dev, found = 0; - - for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) { - struct net_device *dev = alloc_etherdev(sizeof(elp_device)); - if (!dev) - break; - - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - if (dma[this_dev]) { - dev->dma = dma[this_dev]; - } else { - dev->dma = ELP_DMA; - pr_warning("3c505.c: warning, using default DMA channel,\n"); - } - if (io[this_dev] == 0) { - if (this_dev) { - free_netdev(dev); - break; - } - pr_notice("3c505.c: module autoprobe not recommended, give io=xx.\n"); - } - if (elplus_setup(dev) != 0) { - pr_warning("3c505.c: Failed to register card at 0x%x.\n", io[this_dev]); - free_netdev(dev); - break; - } - dev_3c505[this_dev] = dev; - found++; - } - if (!found) - return -ENODEV; - return 0; -} - -void __exit cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < ELP_MAX_CARDS; this_dev++) { - struct net_device *dev = dev_3c505[this_dev]; - if (dev) { - unregister_netdev(dev); - release_region(dev->base_addr, ELP_IO_EXTENT); - free_netdev(dev); - } - } -} - -#endif /* MODULE */ -MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/i825xx/3c505.h b/drivers/net/ethernet/i825xx/3c505.h deleted file mode 100644 index 04df2a9002b..00000000000 --- a/drivers/net/ethernet/i825xx/3c505.h +++ /dev/null @@ -1,292 +0,0 @@ -/***************************************************************** - * - * defines for 3Com Etherlink Plus adapter - * - *****************************************************************/ - -#define ELP_DMA 6 -#define ELP_RX_PCBS 4 -#define ELP_MAX_CARDS 4 - -/* - * I/O register offsets - */ -#define PORT_COMMAND 0x00 /* read/write, 8-bit */ -#define PORT_STATUS 0x02 /* read only, 8-bit */ -#define PORT_AUXDMA 0x02 /* write only, 8-bit */ -#define PORT_DATA 0x04 /* read/write, 16-bit */ -#define PORT_CONTROL 0x06 /* read/write, 8-bit */ - -#define ELP_IO_EXTENT 0x10 /* size of used IO registers */ - -/* - * host control registers bits - */ -#define ATTN 0x80 /* attention */ -#define FLSH 0x40 /* flush data register */ -#define DMAE 0x20 /* DMA enable */ -#define DIR 0x10 /* direction */ -#define TCEN 0x08 /* terminal count interrupt enable */ -#define CMDE 0x04 /* command register interrupt enable */ -#define HSF2 0x02 /* host status flag 2 */ -#define HSF1 0x01 /* host status flag 1 */ - -/* - * combinations of HSF flags used for PCB transmission - */ -#define HSF_PCB_ACK HSF1 -#define HSF_PCB_NAK HSF2 -#define HSF_PCB_END (HSF2|HSF1) -#define HSF_PCB_MASK (HSF2|HSF1) - -/* - * host status register bits - */ -#define HRDY 0x80 /* data register ready */ -#define HCRE 0x40 /* command register empty */ -#define ACRF 0x20 /* adapter command register full */ -/* #define DIR 0x10 direction - same as in control register */ -#define DONE 0x08 /* DMA done */ -#define ASF3 0x04 /* adapter status flag 3 */ -#define ASF2 0x02 /* adapter status flag 2 */ -#define ASF1 0x01 /* adapter status flag 1 */ - -/* - * combinations of ASF flags used for PCB reception - */ -#define ASF_PCB_ACK ASF1 -#define ASF_PCB_NAK ASF2 -#define ASF_PCB_END (ASF2|ASF1) -#define ASF_PCB_MASK (ASF2|ASF1) - -/* - * host aux DMA register bits - */ -#define DMA_BRST 0x01 /* DMA burst */ - -/* - * maximum amount of data allowed in a PCB - */ -#define MAX_PCB_DATA 62 - -/***************************************************************** - * - * timeout value - * this is a rough value used for loops to stop them from - * locking up the whole machine in the case of failure or - * error conditions - * - *****************************************************************/ - -#define TIMEOUT 300 - -/***************************************************************** - * - * PCB commands - * - *****************************************************************/ - -enum { - /* - * host PCB commands - */ - CMD_CONFIGURE_ADAPTER_MEMORY = 0x01, - CMD_CONFIGURE_82586 = 0x02, - CMD_STATION_ADDRESS = 0x03, - CMD_DMA_DOWNLOAD = 0x04, - CMD_DMA_UPLOAD = 0x05, - CMD_PIO_DOWNLOAD = 0x06, - CMD_PIO_UPLOAD = 0x07, - CMD_RECEIVE_PACKET = 0x08, - CMD_TRANSMIT_PACKET = 0x09, - CMD_NETWORK_STATISTICS = 0x0a, - CMD_LOAD_MULTICAST_LIST = 0x0b, - CMD_CLEAR_PROGRAM = 0x0c, - CMD_DOWNLOAD_PROGRAM = 0x0d, - CMD_EXECUTE_PROGRAM = 0x0e, - CMD_SELF_TEST = 0x0f, - CMD_SET_STATION_ADDRESS = 0x10, - CMD_ADAPTER_INFO = 0x11, - NUM_TRANSMIT_CMDS, - - /* - * adapter PCB commands - */ - CMD_CONFIGURE_ADAPTER_RESPONSE = 0x31, - CMD_CONFIGURE_82586_RESPONSE = 0x32, - CMD_ADDRESS_RESPONSE = 0x33, - CMD_DOWNLOAD_DATA_REQUEST = 0x34, - CMD_UPLOAD_DATA_REQUEST = 0x35, - CMD_RECEIVE_PACKET_COMPLETE = 0x38, - CMD_TRANSMIT_PACKET_COMPLETE = 0x39, - CMD_NETWORK_STATISTICS_RESPONSE = 0x3a, - CMD_LOAD_MULTICAST_RESPONSE = 0x3b, - CMD_CLEAR_PROGRAM_RESPONSE = 0x3c, - CMD_DOWNLOAD_PROGRAM_RESPONSE = 0x3d, - CMD_EXECUTE_RESPONSE = 0x3e, - CMD_SELF_TEST_RESPONSE = 0x3f, - CMD_SET_ADDRESS_RESPONSE = 0x40, - CMD_ADAPTER_INFO_RESPONSE = 0x41 -}; - -/* Definitions for the PCB data structure */ - -/* Data units */ -typedef unsigned char byte; -typedef unsigned short int word; -typedef unsigned long int dword; - -/* Data structures */ -struct Memconf { - word cmd_q, - rcv_q, - mcast, - frame, - rcv_b, - progs; -}; - -struct Rcv_pkt { - word buf_ofs, - buf_seg, - buf_len, - timeout; -}; - -struct Xmit_pkt { - word buf_ofs, - buf_seg, - pkt_len; -}; - -struct Rcv_resp { - word buf_ofs, - buf_seg, - buf_len, - pkt_len, - timeout, - status; - dword timetag; -}; - -struct Xmit_resp { - word buf_ofs, - buf_seg, - c_stat, - status; -}; - - -struct Netstat { - dword tot_recv, - tot_xmit; - word err_CRC, - err_align, - err_res, - err_ovrrun; -}; - - -struct Selftest { - word error; - union { - word ROM_cksum; - struct { - word ofs, seg; - } RAM; - word i82586; - } failure; -}; - -struct Info { - byte minor_vers, - major_vers; - word ROM_cksum, - RAM_sz, - free_ofs, - free_seg; -}; - -struct Memdump { - word size, - off, - seg; -}; - -/* -Primary Command Block. The most important data structure. All communication -between the host and the adapter is done with these. (Except for the actual -Ethernet data, which has different packaging.) -*/ -typedef struct { - byte command; - byte length; - union { - struct Memconf memconf; - word configure; - struct Rcv_pkt rcv_pkt; - struct Xmit_pkt xmit_pkt; - byte multicast[10][6]; - byte eth_addr[6]; - byte failed; - struct Rcv_resp rcv_resp; - struct Xmit_resp xmit_resp; - struct Netstat netstat; - struct Selftest selftest; - struct Info info; - struct Memdump memdump; - byte raw[62]; - } data; -} pcb_struct; - -/* These defines for 'configure' */ -#define RECV_STATION 0x00 -#define RECV_BROAD 0x01 -#define RECV_MULTI 0x02 -#define RECV_PROMISC 0x04 -#define NO_LOOPBACK 0x00 -#define INT_LOOPBACK 0x08 -#define EXT_LOOPBACK 0x10 - -/***************************************************************** - * - * structure to hold context information for adapter - * - *****************************************************************/ - -#define DMA_BUFFER_SIZE 1600 -#define BACKLOG_SIZE 4 - -typedef struct { - volatile short got[NUM_TRANSMIT_CMDS]; /* flags for - command completion */ - pcb_struct tx_pcb; /* PCB for foreground sending */ - pcb_struct rx_pcb; /* PCB for foreground receiving */ - pcb_struct itx_pcb; /* PCB for background sending */ - pcb_struct irx_pcb; /* PCB for background receiving */ - - void *dma_buffer; - - struct { - unsigned int length[BACKLOG_SIZE]; - unsigned int in; - unsigned int out; - } rx_backlog; - - struct { - unsigned int direction; - unsigned int length; - struct sk_buff *skb; - void *target; - unsigned long start_time; - } current_dma; - - /* flags */ - unsigned long send_pcb_semaphore; - unsigned long dmaing; - unsigned long busy; - - unsigned int rx_active; /* number of receive PCBs */ - volatile unsigned char hcr_val; /* what we think the HCR contains */ - spinlock_t lock; /* Interrupt v tx lock */ -} elp_device; diff --git a/drivers/net/ethernet/i825xx/3c507.c b/drivers/net/ethernet/i825xx/3c507.c deleted file mode 100644 index 13983ee6bcf..00000000000 --- a/drivers/net/ethernet/i825xx/3c507.c +++ /dev/null @@ -1,939 +0,0 @@ -/* 3c507.c: An EtherLink16 device driver for Linux. */ -/* - Written 1993,1994 by Donald Becker. - - Copyright 1993 United States Government as represented by the - Director, National Security Agency. - - This software may be used and distributed according to the terms - of the GNU General Public License, incorporated herein by reference. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - - Thanks go to jennings@Montrouge.SMR.slb.com ( Patrick Jennings) - and jrs@world.std.com (Rick Sladkey) for testing and bugfixes. - Mark Salazar made the changes for cards with - only 16K packet buffers. - - Things remaining to do: - Verify that the tx and rx buffers don't have fencepost errors. - Move the theory of operation and memory map documentation. - The statistics need to be updated correctly. -*/ - -#define DRV_NAME "3c507" -#define DRV_VERSION "1.10a" -#define DRV_RELDATE "11/17/2001" - -static const char version[] = - DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Donald Becker (becker@scyld.com)\n"; - -/* - Sources: - This driver wouldn't have been written with the availability of the - Crynwr driver source code. It provided a known-working implementation - that filled in the gaping holes of the Intel documentation. Three cheers - for Russ Nelson. - - Intel Microcommunications Databook, Vol. 1, 1990. It provides just enough - info that the casual reader might think that it documents the i82586 :-<. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* use 0 for production, 1 for verification, 2..7 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 1 -#endif -static unsigned int net_debug = NET_DEBUG; -#define debug net_debug - - -/* - Details of the i82586. - - You'll really need the databook to understand the details of this part, - but the outline is that the i82586 has two separate processing units. - Both are started from a list of three configuration tables, of which only - the last, the System Control Block (SCB), is used after reset-time. The SCB - has the following fields: - Status word - Command word - Tx/Command block addr. - Rx block addr. - The command word accepts the following controls for the Tx and Rx units: - */ - -#define CUC_START 0x0100 -#define CUC_RESUME 0x0200 -#define CUC_SUSPEND 0x0300 -#define RX_START 0x0010 -#define RX_RESUME 0x0020 -#define RX_SUSPEND 0x0030 - -/* The Rx unit uses a list of frame descriptors and a list of data buffer - descriptors. We use full-sized (1518 byte) data buffers, so there is - a one-to-one pairing of frame descriptors to buffer descriptors. - - The Tx ("command") unit executes a list of commands that look like: - Status word Written by the 82586 when the command is done. - Command word Command in lower 3 bits, post-command action in upper 3 - Link word The address of the next command. - Parameters (as needed). - - Some definitions related to the Command Word are: - */ -#define CMD_EOL 0x8000 /* The last command of the list, stop. */ -#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ -#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ - -enum commands { - CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, - CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7}; - -/* Information that need to be kept for each board. */ -struct net_local { - int last_restart; - ushort rx_head; - ushort rx_tail; - ushort tx_head; - ushort tx_cmd_link; - ushort tx_reap; - ushort tx_pkts_in_ring; - spinlock_t lock; - void __iomem *base; -}; - -/* - Details of the EtherLink16 Implementation - The 3c507 is a generic shared-memory i82586 implementation. - The host can map 16K, 32K, 48K, or 64K of the 64K memory into - 0x0[CD][08]0000, or all 64K into 0xF[02468]0000. - */ - -/* Offsets from the base I/O address. */ -#define SA_DATA 0 /* Station address data, or 3Com signature. */ -#define MISC_CTRL 6 /* Switch the SA_DATA banks, and bus config bits. */ -#define RESET_IRQ 10 /* Reset the latched IRQ line. */ -#define SIGNAL_CA 11 /* Frob the 82586 Channel Attention line. */ -#define ROM_CONFIG 13 -#define MEM_CONFIG 14 -#define IRQ_CONFIG 15 -#define EL16_IO_EXTENT 16 - -/* The ID port is used at boot-time to locate the ethercard. */ -#define ID_PORT 0x100 - -/* Offsets to registers in the mailbox (SCB). */ -#define iSCB_STATUS 0x8 -#define iSCB_CMD 0xA -#define iSCB_CBL 0xC /* Command BLock offset. */ -#define iSCB_RFA 0xE /* Rx Frame Area offset. */ - -/* Since the 3c507 maps the shared memory window so that the last byte is - at 82586 address FFFF, the first byte is at 82586 address 0, 16K, 32K, or - 48K corresponding to window sizes of 64K, 48K, 32K and 16K respectively. - We can account for this be setting the 'SBC Base' entry in the ISCP table - below for all the 16 bit offset addresses, and also adding the 'SCB Base' - value to all 24 bit physical addresses (in the SCP table and the TX and RX - Buffer Descriptors). - -Mark - */ -#define SCB_BASE ((unsigned)64*1024 - (dev->mem_end - dev->mem_start)) - -/* - What follows in 'init_words[]' is the "program" that is downloaded to the - 82586 memory. It's mostly tables and command blocks, and starts at the - reset address 0xfffff6. This is designed to be similar to the EtherExpress, - thus the unusual location of the SCB at 0x0008. - - Even with the additional "don't care" values, doing it this way takes less - program space than initializing the individual tables, and I feel it's much - cleaner. - - The databook is particularly useless for the first two structures, I had - to use the Crynwr driver as an example. - - The memory setup is as follows: - */ - -#define CONFIG_CMD 0x0018 -#define SET_SA_CMD 0x0024 -#define SA_OFFSET 0x002A -#define IDLELOOP 0x30 -#define TDR_CMD 0x38 -#define TDR_TIME 0x3C -#define DUMP_CMD 0x40 -#define DIAG_CMD 0x48 -#define SET_MC_CMD 0x4E -#define DUMP_DATA 0x56 /* A 170 byte buffer for dump and Set-MC into. */ - -#define TX_BUF_START 0x0100 -#define NUM_TX_BUFS 5 -#define TX_BUF_SIZE (1518+14+20+16) /* packet+header+TBD */ - -#define RX_BUF_START 0x2000 -#define RX_BUF_SIZE (1518+14+18) /* packet+header+RBD */ -#define RX_BUF_END (dev->mem_end - dev->mem_start) - -#define TX_TIMEOUT (HZ/20) - -/* - That's it: only 86 bytes to set up the beast, including every extra - command available. The 170 byte buffer at DUMP_DATA is shared between the - Dump command (called only by the diagnostic program) and the SetMulticastList - command. - - To complete the memory setup you only have to write the station address at - SA_OFFSET and create the Tx & Rx buffer lists. - - The Tx command chain and buffer list is setup as follows: - A Tx command table, with the data buffer pointing to... - A Tx data buffer descriptor. The packet is in a single buffer, rather than - chaining together several smaller buffers. - A NoOp command, which initially points to itself, - And the packet data. - - A transmit is done by filling in the Tx command table and data buffer, - re-writing the NoOp command, and finally changing the offset of the last - command to point to the current Tx command. When the Tx command is finished, - it jumps to the NoOp, when it loops until the next Tx command changes the - "link offset" in the NoOp. This way the 82586 never has to go through the - slow restart sequence. - - The Rx buffer list is set up in the obvious ring structure. We have enough - memory (and low enough interrupt latency) that we can avoid the complicated - Rx buffer linked lists by alway associating a full-size Rx data buffer with - each Rx data frame. - - I current use four transmit buffers starting at TX_BUF_START (0x0100), and - use the rest of memory, from RX_BUF_START to RX_BUF_END, for Rx buffers. - - */ - -static unsigned short init_words[] = { - /* System Configuration Pointer (SCP). */ - 0x0000, /* Set bus size to 16 bits. */ - 0,0, /* pad words. */ - 0x0000,0x0000, /* ISCP phys addr, set in init_82586_mem(). */ - - /* Intermediate System Configuration Pointer (ISCP). */ - 0x0001, /* Status word that's cleared when init is done. */ - 0x0008,0,0, /* SCB offset, (skip, skip) */ - - /* System Control Block (SCB). */ - 0,0xf000|RX_START|CUC_START, /* SCB status and cmd. */ - CONFIG_CMD, /* Command list pointer, points to Configure. */ - RX_BUF_START, /* Rx block list. */ - 0,0,0,0, /* Error count: CRC, align, buffer, overrun. */ - - /* 0x0018: Configure command. Change to put MAC data with packet. */ - 0, CmdConfigure, /* Status, command. */ - SET_SA_CMD, /* Next command is Set Station Addr. */ - 0x0804, /* "4" bytes of config data, 8 byte FIFO. */ - 0x2e40, /* Magic values, including MAC data location. */ - 0, /* Unused pad word. */ - - /* 0x0024: Setup station address command. */ - 0, CmdSASetup, - SET_MC_CMD, /* Next command. */ - 0xaa00,0xb000,0x0bad, /* Station address (to be filled in) */ - - /* 0x0030: NOP, looping back to itself. Point to first Tx buffer to Tx. */ - 0, CmdNOp, IDLELOOP, 0 /* pad */, - - /* 0x0038: A unused Time-Domain Reflectometer command. */ - 0, CmdTDR, IDLELOOP, 0, - - /* 0x0040: An unused Dump State command. */ - 0, CmdDump, IDLELOOP, DUMP_DATA, - - /* 0x0048: An unused Diagnose command. */ - 0, CmdDiagnose, IDLELOOP, - - /* 0x004E: An empty set-multicast-list command. */ - 0, CmdMulticastList, IDLELOOP, 0, -}; - -/* Index to functions, as function prototypes. */ - -static int el16_probe1(struct net_device *dev, int ioaddr); -static int el16_open(struct net_device *dev); -static netdev_tx_t el16_send_packet(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t el16_interrupt(int irq, void *dev_id); -static void el16_rx(struct net_device *dev); -static int el16_close(struct net_device *dev); -static void el16_tx_timeout (struct net_device *dev); - -static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad); -static void init_82586_mem(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; -static void init_rx_bufs(struct net_device *); - -static int io = 0x300; -static int irq; -static int mem_start; - - -/* Check for a network adaptor of this type, and return '0' iff one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, (detachable devices only) allocate space for the - device and return success. - */ - -struct net_device * __init el16_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); - static const unsigned ports[] = { 0x300, 0x320, 0x340, 0x280, 0}; - const unsigned *port; - int err = -ENODEV; - - if (!dev) - return ERR_PTR(-ENODEV); - - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - io = dev->base_addr; - irq = dev->irq; - mem_start = dev->mem_start & 15; - } - - if (io > 0x1ff) /* Check a single specified location. */ - err = el16_probe1(dev, io); - else if (io != 0) - err = -ENXIO; /* Don't probe at all. */ - else { - for (port = ports; *port; port++) { - err = el16_probe1(dev, *port); - if (!err) - break; - } - } - - if (err) - goto out; - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - free_irq(dev->irq, dev); - iounmap(((struct net_local *)netdev_priv(dev))->base); - release_region(dev->base_addr, EL16_IO_EXTENT); -out: - free_netdev(dev); - return ERR_PTR(err); -} - -static const struct net_device_ops netdev_ops = { - .ndo_open = el16_open, - .ndo_stop = el16_close, - .ndo_start_xmit = el16_send_packet, - .ndo_tx_timeout = el16_tx_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static int __init el16_probe1(struct net_device *dev, int ioaddr) -{ - static unsigned char init_ID_done; - int i, irq, irqval, retval; - struct net_local *lp; - - if (init_ID_done == 0) { - ushort lrs_state = 0xff; - /* Send the ID sequence to the ID_PORT to enable the board(s). */ - outb(0x00, ID_PORT); - for(i = 0; i < 255; i++) { - outb(lrs_state, ID_PORT); - lrs_state <<= 1; - if (lrs_state & 0x100) - lrs_state ^= 0xe7; - } - outb(0x00, ID_PORT); - init_ID_done = 1; - } - - if (!request_region(ioaddr, EL16_IO_EXTENT, DRV_NAME)) - return -ENODEV; - - if ((inb(ioaddr) != '*') || (inb(ioaddr + 1) != '3') || - (inb(ioaddr + 2) != 'C') || (inb(ioaddr + 3) != 'O')) { - retval = -ENODEV; - goto out; - } - - pr_info("%s: 3c507 at %#x,", dev->name, ioaddr); - - /* We should make a few more checks here, like the first three octets of - the S.A. for the manufacturer's code. */ - - irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - - irqval = request_irq(irq, el16_interrupt, 0, DRV_NAME, dev); - if (irqval) { - pr_cont("\n"); - pr_err("3c507: unable to get IRQ %d (irqval=%d).\n", irq, irqval); - retval = -EAGAIN; - goto out; - } - - /* We've committed to using the board, and can start filling in *dev. */ - dev->base_addr = ioaddr; - - outb(0x01, ioaddr + MISC_CTRL); - for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb(ioaddr + i); - pr_cont(" %pM", dev->dev_addr); - - if (mem_start) - net_debug = mem_start & 7; - -#ifdef MEM_BASE - dev->mem_start = MEM_BASE; - dev->mem_end = dev->mem_start + 0x10000; -#else - { - int base; - int size; - char mem_config = inb(ioaddr + MEM_CONFIG); - if (mem_config & 0x20) { - size = 64*1024; - base = 0xf00000 + (mem_config & 0x08 ? 0x080000 - : ((mem_config & 3) << 17)); - } else { - size = ((mem_config & 3) + 1) << 14; - base = 0x0c0000 + ( (mem_config & 0x18) << 12); - } - dev->mem_start = base; - dev->mem_end = base + size; - } -#endif - - dev->if_port = (inb(ioaddr + ROM_CONFIG) & 0x80) ? 1 : 0; - dev->irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - - pr_cont(", IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->irq, - dev->if_port ? "ex" : "in", dev->mem_start, dev->mem_end-1); - - if (net_debug) - pr_debug("%s", version); - - lp = netdev_priv(dev); - spin_lock_init(&lp->lock); - lp->base = ioremap(dev->mem_start, RX_BUF_END); - if (!lp->base) { - pr_err("3c507: unable to remap memory\n"); - retval = -EAGAIN; - goto out1; - } - - dev->netdev_ops = &netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; - dev->ethtool_ops = &netdev_ethtool_ops; - dev->flags &= ~IFF_MULTICAST; /* Multicast doesn't work */ - return 0; -out1: - free_irq(dev->irq, dev); -out: - release_region(ioaddr, EL16_IO_EXTENT); - return retval; -} - -static int el16_open(struct net_device *dev) -{ - /* Initialize the 82586 memory and start it. */ - init_82586_mem(dev); - - netif_start_queue(dev); - return 0; -} - - -static void el16_tx_timeout (struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - void __iomem *shmem = lp->base; - - if (net_debug > 1) - pr_debug("%s: transmit timed out, %s? ", dev->name, - readw(shmem + iSCB_STATUS) & 0x8000 ? "IRQ conflict" : - "network cable problem"); - /* Try to restart the adaptor. */ - if (lp->last_restart == dev->stats.tx_packets) { - if (net_debug > 1) - pr_cont("Resetting board.\n"); - /* Completely reset the adaptor. */ - init_82586_mem (dev); - lp->tx_pkts_in_ring = 0; - } else { - /* Issue the channel attention signal and hope it "gets better". */ - if (net_debug > 1) - pr_cont("Kicking board.\n"); - writew(0xf000 | CUC_START | RX_START, shmem + iSCB_CMD); - outb (0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ - lp->last_restart = dev->stats.tx_packets; - } - dev->trans_start = jiffies; /* prevent tx timeout */ - netif_wake_queue (dev); -} - - -static netdev_tx_t el16_send_packet (struct sk_buff *skb, - struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - unsigned long flags; - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char *buf = skb->data; - - netif_stop_queue (dev); - - spin_lock_irqsave (&lp->lock, flags); - - dev->stats.tx_bytes += length; - /* Disable the 82586's input to the interrupt line. */ - outb (0x80, ioaddr + MISC_CTRL); - - hardware_send_packet (dev, buf, skb->len, length - skb->len); - - /* Enable the 82586 interrupt input. */ - outb (0x84, ioaddr + MISC_CTRL); - - spin_unlock_irqrestore (&lp->lock, flags); - - dev_kfree_skb (skb); - - /* You might need to clean up and record Tx statistics here. */ - - return NETDEV_TX_OK; -} - -/* The typical workload of the driver: - Handle the network interface interrupts. */ -static irqreturn_t el16_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct net_local *lp; - int ioaddr, status, boguscount = 0; - ushort ack_cmd = 0; - void __iomem *shmem; - - if (dev == NULL) { - pr_err("net_interrupt(): irq %d for unknown device.\n", irq); - return IRQ_NONE; - } - - ioaddr = dev->base_addr; - lp = netdev_priv(dev); - shmem = lp->base; - - spin_lock(&lp->lock); - - status = readw(shmem+iSCB_STATUS); - - if (net_debug > 4) { - pr_debug("%s: 3c507 interrupt, status %4.4x.\n", dev->name, status); - } - - /* Disable the 82586's input to the interrupt line. */ - outb(0x80, ioaddr + MISC_CTRL); - - /* Reap the Tx packet buffers. */ - while (lp->tx_pkts_in_ring) { - unsigned short tx_status = readw(shmem+lp->tx_reap); - if (!(tx_status & 0x8000)) { - if (net_debug > 5) - pr_debug("Tx command incomplete (%#x).\n", lp->tx_reap); - break; - } - /* Tx unsuccessful or some interesting status bit set. */ - if (!(tx_status & 0x2000) || (tx_status & 0x0f3f)) { - dev->stats.tx_errors++; - if (tx_status & 0x0600) dev->stats.tx_carrier_errors++; - if (tx_status & 0x0100) dev->stats.tx_fifo_errors++; - if (!(tx_status & 0x0040)) dev->stats.tx_heartbeat_errors++; - if (tx_status & 0x0020) dev->stats.tx_aborted_errors++; - dev->stats.collisions += tx_status & 0xf; - } - dev->stats.tx_packets++; - if (net_debug > 5) - pr_debug("Reaped %x, Tx status %04x.\n" , lp->tx_reap, tx_status); - lp->tx_reap += TX_BUF_SIZE; - if (lp->tx_reap > RX_BUF_START - TX_BUF_SIZE) - lp->tx_reap = TX_BUF_START; - - lp->tx_pkts_in_ring--; - /* There is always more space in the Tx ring buffer now. */ - netif_wake_queue(dev); - - if (++boguscount > 10) - break; - } - - if (status & 0x4000) { /* Packet received. */ - if (net_debug > 5) - pr_debug("Received packet, rx_head %04x.\n", lp->rx_head); - el16_rx(dev); - } - - /* Acknowledge the interrupt sources. */ - ack_cmd = status & 0xf000; - - if ((status & 0x0700) != 0x0200 && netif_running(dev)) { - if (net_debug) - pr_debug("%s: Command unit stopped, status %04x, restarting.\n", - dev->name, status); - /* If this ever occurs we should really re-write the idle loop, reset - the Tx list, and do a complete restart of the command unit. - For now we rely on the Tx timeout if the resume doesn't work. */ - ack_cmd |= CUC_RESUME; - } - - if ((status & 0x0070) != 0x0040 && netif_running(dev)) { - /* The Rx unit is not ready, it must be hung. Restart the receiver by - initializing the rx buffers, and issuing an Rx start command. */ - if (net_debug) - pr_debug("%s: Rx unit stopped, status %04x, restarting.\n", - dev->name, status); - init_rx_bufs(dev); - writew(RX_BUF_START,shmem+iSCB_RFA); - ack_cmd |= RX_START; - } - - writew(ack_cmd,shmem+iSCB_CMD); - outb(0, ioaddr + SIGNAL_CA); /* Issue channel-attn. */ - - /* Clear the latched interrupt. */ - outb(0, ioaddr + RESET_IRQ); - - /* Enable the 82586's interrupt input. */ - outb(0x84, ioaddr + MISC_CTRL); - spin_unlock(&lp->lock); - return IRQ_HANDLED; -} - -static int el16_close(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - void __iomem *shmem = lp->base; - - netif_stop_queue(dev); - - /* Flush the Tx and disable Rx. */ - writew(RX_SUSPEND | CUC_SUSPEND,shmem+iSCB_CMD); - outb(0, ioaddr + SIGNAL_CA); - - /* Disable the 82586's input to the interrupt line. */ - outb(0x80, ioaddr + MISC_CTRL); - - /* We always physically use the IRQ line, so we don't do free_irq(). */ - - /* Update the statistics here. */ - - return 0; -} - -/* Initialize the Rx-block list. */ -static void init_rx_bufs(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - void __iomem *write_ptr; - unsigned short SCB_base = SCB_BASE; - - int cur_rxbuf = lp->rx_head = RX_BUF_START; - - /* Initialize each Rx frame + data buffer. */ - do { /* While there is room for one more. */ - - write_ptr = lp->base + cur_rxbuf; - - writew(0x0000,write_ptr); /* Status */ - writew(0x0000,write_ptr+=2); /* Command */ - writew(cur_rxbuf + RX_BUF_SIZE,write_ptr+=2); /* Link */ - writew(cur_rxbuf + 22,write_ptr+=2); /* Buffer offset */ - writew(0x0000,write_ptr+=2); /* Pad for dest addr. */ - writew(0x0000,write_ptr+=2); - writew(0x0000,write_ptr+=2); - writew(0x0000,write_ptr+=2); /* Pad for source addr. */ - writew(0x0000,write_ptr+=2); - writew(0x0000,write_ptr+=2); - writew(0x0000,write_ptr+=2); /* Pad for protocol. */ - - writew(0x0000,write_ptr+=2); /* Buffer: Actual count */ - writew(-1,write_ptr+=2); /* Buffer: Next (none). */ - writew(cur_rxbuf + 0x20 + SCB_base,write_ptr+=2);/* Buffer: Address low */ - writew(0x0000,write_ptr+=2); - /* Finally, the number of bytes in the buffer. */ - writew(0x8000 + RX_BUF_SIZE-0x20,write_ptr+=2); - - lp->rx_tail = cur_rxbuf; - cur_rxbuf += RX_BUF_SIZE; - } while (cur_rxbuf <= RX_BUF_END - RX_BUF_SIZE); - - /* Terminate the list by setting the EOL bit, and wrap the pointer to make - the list a ring. */ - write_ptr = lp->base + lp->rx_tail + 2; - writew(0xC000,write_ptr); /* Command, mark as last. */ - writew(lp->rx_head,write_ptr+2); /* Link */ -} - -static void init_82586_mem(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - void __iomem *shmem = lp->base; - - /* Enable loopback to protect the wire while starting up, - and hold the 586 in reset during the memory initialization. */ - outb(0x20, ioaddr + MISC_CTRL); - - /* Fix the ISCP address and base. */ - init_words[3] = SCB_BASE; - init_words[7] = SCB_BASE; - - /* Write the words at 0xfff6 (address-aliased to 0xfffff6). */ - memcpy_toio(lp->base + RX_BUF_END - 10, init_words, 10); - - /* Write the words at 0x0000. */ - memcpy_toio(lp->base, init_words + 5, sizeof(init_words) - 10); - - /* Fill in the station address. */ - memcpy_toio(lp->base+SA_OFFSET, dev->dev_addr, ETH_ALEN); - - /* The Tx-block list is written as needed. We just set up the values. */ - lp->tx_cmd_link = IDLELOOP + 4; - lp->tx_head = lp->tx_reap = TX_BUF_START; - - init_rx_bufs(dev); - - /* Start the 586 by releasing the reset line, but leave loopback. */ - outb(0xA0, ioaddr + MISC_CTRL); - - /* This was time consuming to track down: you need to give two channel - attention signals to reliably start up the i82586. */ - outb(0, ioaddr + SIGNAL_CA); - - { - int boguscnt = 50; - while (readw(shmem+iSCB_STATUS) == 0) - if (--boguscnt == 0) { - pr_warning("%s: i82586 initialization timed out with status %04x, cmd %04x.\n", - dev->name, readw(shmem+iSCB_STATUS), readw(shmem+iSCB_CMD)); - break; - } - /* Issue channel-attn -- the 82586 won't start. */ - outb(0, ioaddr + SIGNAL_CA); - } - - /* Disable loopback and enable interrupts. */ - outb(0x84, ioaddr + MISC_CTRL); - if (net_debug > 4) - pr_debug("%s: Initialized 82586, status %04x.\n", dev->name, - readw(shmem+iSCB_STATUS)); -} - -static void hardware_send_packet(struct net_device *dev, void *buf, short length, short pad) -{ - struct net_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - ushort tx_block = lp->tx_head; - void __iomem *write_ptr = lp->base + tx_block; - static char padding[ETH_ZLEN]; - - /* Set the write pointer to the Tx block, and put out the header. */ - writew(0x0000,write_ptr); /* Tx status */ - writew(CMD_INTR|CmdTx,write_ptr+=2); /* Tx command */ - writew(tx_block+16,write_ptr+=2); /* Next command is a NoOp. */ - writew(tx_block+8,write_ptr+=2); /* Data Buffer offset. */ - - /* Output the data buffer descriptor. */ - writew((pad + length) | 0x8000,write_ptr+=2); /* Byte count parameter. */ - writew(-1,write_ptr+=2); /* No next data buffer. */ - writew(tx_block+22+SCB_BASE,write_ptr+=2); /* Buffer follows the NoOp command. */ - writew(0x0000,write_ptr+=2); /* Buffer address high bits (always zero). */ - - /* Output the Loop-back NoOp command. */ - writew(0x0000,write_ptr+=2); /* Tx status */ - writew(CmdNOp,write_ptr+=2); /* Tx command */ - writew(tx_block+16,write_ptr+=2); /* Next is myself. */ - - /* Output the packet at the write pointer. */ - memcpy_toio(write_ptr+2, buf, length); - if (pad) - memcpy_toio(write_ptr+length+2, padding, pad); - - /* Set the old command link pointing to this send packet. */ - writew(tx_block,lp->base + lp->tx_cmd_link); - lp->tx_cmd_link = tx_block + 20; - - /* Set the next free tx region. */ - lp->tx_head = tx_block + TX_BUF_SIZE; - if (lp->tx_head > RX_BUF_START - TX_BUF_SIZE) - lp->tx_head = TX_BUF_START; - - if (net_debug > 4) { - pr_debug("%s: 3c507 @%x send length = %d, tx_block %3x, next %3x.\n", - dev->name, ioaddr, length, tx_block, lp->tx_head); - } - - /* Grimly block further packets if there has been insufficient reaping. */ - if (++lp->tx_pkts_in_ring < NUM_TX_BUFS) - netif_wake_queue(dev); -} - -static void el16_rx(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - void __iomem *shmem = lp->base; - ushort rx_head = lp->rx_head; - ushort rx_tail = lp->rx_tail; - ushort boguscount = 10; - short frame_status; - - while ((frame_status = readw(shmem+rx_head)) < 0) { /* Command complete */ - void __iomem *read_frame = lp->base + rx_head; - ushort rfd_cmd = readw(read_frame+2); - ushort next_rx_frame = readw(read_frame+4); - ushort data_buffer_addr = readw(read_frame+6); - void __iomem *data_frame = lp->base + data_buffer_addr; - ushort pkt_len = readw(data_frame); - - if (rfd_cmd != 0 || data_buffer_addr != rx_head + 22 || - (pkt_len & 0xC000) != 0xC000) { - pr_err("%s: Rx frame at %#x corrupted, " - "status %04x cmd %04x next %04x " - "data-buf @%04x %04x.\n", - dev->name, rx_head, frame_status, rfd_cmd, - next_rx_frame, data_buffer_addr, pkt_len); - } else if ((frame_status & 0x2000) == 0) { - /* Frame Rxed, but with error. */ - dev->stats.rx_errors++; - if (frame_status & 0x0800) dev->stats.rx_crc_errors++; - if (frame_status & 0x0400) dev->stats.rx_frame_errors++; - if (frame_status & 0x0200) dev->stats.rx_fifo_errors++; - if (frame_status & 0x0100) dev->stats.rx_over_errors++; - if (frame_status & 0x0080) dev->stats.rx_length_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - pkt_len &= 0x3fff; - skb = netdev_alloc_skb(dev, pkt_len + 2); - if (skb == NULL) { - pr_err("%s: Memory squeeze, dropping packet.\n", - dev->name); - dev->stats.rx_dropped++; - break; - } - - skb_reserve(skb,2); - - /* 'skb->data' points to the start of sk_buff data area. */ - memcpy_fromio(skb_put(skb,pkt_len), data_frame + 10, pkt_len); - - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - } - - /* Clear the status word and set End-of-List on the rx frame. */ - writew(0,read_frame); - writew(0xC000,read_frame+2); - /* Clear the end-of-list on the prev. RFD. */ - writew(0x0000,lp->base + rx_tail + 2); - - rx_tail = rx_head; - rx_head = next_rx_frame; - if (--boguscount == 0) - break; - } - - lp->rx_head = rx_head; - lp->rx_tail = rx_tail; -} - -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - snprintf(info->bus_info, sizeof(info->bus_info), "ISA 0x%lx", - dev->base_addr); -} - -static u32 netdev_get_msglevel(struct net_device *dev) -{ - return debug; -} - -static void netdev_set_msglevel(struct net_device *dev, u32 level) -{ - debug = level; -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, - .get_msglevel = netdev_get_msglevel, - .set_msglevel = netdev_set_msglevel, -}; - -#ifdef MODULE -static struct net_device *dev_3c507; -module_param(io, int, 0); -module_param(irq, int, 0); -MODULE_PARM_DESC(io, "EtherLink16 I/O base address"); -MODULE_PARM_DESC(irq, "(ignored)"); - -int __init init_module(void) -{ - if (io == 0) - pr_notice("3c507: You should not use auto-probing with insmod!\n"); - dev_3c507 = el16_probe(-1); - return IS_ERR(dev_3c507) ? PTR_ERR(dev_3c507) : 0; -} - -void __exit -cleanup_module(void) -{ - struct net_device *dev = dev_3c507; - unregister_netdev(dev); - free_irq(dev->irq, dev); - iounmap(((struct net_local *)netdev_priv(dev))->base); - release_region(dev->base_addr, EL16_IO_EXTENT); - free_netdev(dev); -} -#endif /* MODULE */ -MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig index 46edb81bbed..b800a94fc87 100644 --- a/drivers/net/ethernet/i825xx/Kconfig +++ b/drivers/net/ethernet/i825xx/Kconfig @@ -20,29 +20,6 @@ config NET_VENDOR_I825XX if NET_VENDOR_I825XX -config ELPLUS - tristate "3c505 \"EtherLink Plus\" support" - depends on ISA && ISA_DMA_API - ---help--- - Information about this network (Ethernet) card can be found in - . If you have a card of - this type, say Y and read the Ethernet-HOWTO, available from - . - - To compile this driver as a module, choose M here. The module - will be called 3c505. - -config EL16 - tristate "3c507 \"EtherLink 16\" support (EXPERIMENTAL)" - depends on ISA && EXPERIMENTAL - ---help--- - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - To compile this driver as a module, choose M here. The module - will be called 3c507. - config ARM_ETHER1 tristate "Acorn Ether1 support" depends on ARM && ARCH_ACORN diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile index 4f01584bd89..bc81e14ed5b 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -5,8 +5,6 @@ obj-$(CONFIG_ARM_ETHER1) += ether1.o obj-$(CONFIG_EEXPRESS) += eexpress.o obj-$(CONFIG_EEXPRESS_PRO) += eepro.o -obj-$(CONFIG_ELPLUS) += 3c505.o -obj-$(CONFIG_EL16) += 3c507.o obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o obj-$(CONFIG_ZNET) += znet.o -- cgit v1.2.3-70-g09d2 From f84932d8313af16a37cf25412b7d9054d01d3bea Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 9 Jan 2013 21:01:40 -0500 Subject: drivers/net: delete ISA intel eexpress and eepro i825xx drivers These old drivers should not be confused with the very common PCI cards that are supported by e100.c -- these older 10Mbit ISA only drivers were not as commonly used as some of the other ISA drivers, simply due to hardware availability and pricing. Given the rarity of the hardware, and the subsequent less extensive use of the drivers, it makes sense to obsolete them at this point in time, along with other rare/experimental ISA drivers. Signed-off-by: Paul Gortmaker --- drivers/net/Space.c | 8 - drivers/net/ethernet/i825xx/Kconfig | 27 - drivers/net/ethernet/i825xx/Makefile | 2 - drivers/net/ethernet/i825xx/eepro.c | 1822 -------------------------------- drivers/net/ethernet/i825xx/eexpress.c | 1661 ----------------------------- drivers/net/ethernet/i825xx/eexpress.h | 179 ---- 6 files changed, 3699 deletions(-) delete mode 100644 drivers/net/ethernet/i825xx/eepro.c delete mode 100644 drivers/net/ethernet/i825xx/eexpress.c delete mode 100644 drivers/net/ethernet/i825xx/eexpress.h (limited to 'drivers/net/ethernet/i825xx/Makefile') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index ac66a6af713..726b17b7961 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -44,8 +44,6 @@ extern struct net_device *el2_probe(int unit); extern struct net_device *ne_probe(int unit); extern struct net_device *hp_probe(int unit); extern struct net_device *hp_plus_probe(int unit); -extern struct net_device *express_probe(int unit); -extern struct net_device *eepro_probe(int unit); extern struct net_device *at1700_probe(int unit); extern struct net_device *fmv18x_probe(int unit); extern struct net_device *eth16i_probe(int unit); @@ -150,12 +148,6 @@ static struct devprobe2 isa_probes[] __initdata = { #ifdef CONFIG_ETH16I {eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */ #endif -#ifdef CONFIG_EEXPRESS /* Intel EtherExpress */ - {express_probe, 0}, -#endif -#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */ - {eepro_probe, 0}, -#endif #ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */ {ewrk3_probe, 0}, #endif diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig index b800a94fc87..16b14a93c20 100644 --- a/drivers/net/ethernet/i825xx/Kconfig +++ b/drivers/net/ethernet/i825xx/Kconfig @@ -36,33 +36,6 @@ config BVME6000_NET in your kernel. To compile this driver as a module, choose M here. -config EEXPRESS - tristate "EtherExpress 16 support" - depends on ISA - ---help--- - If you have an EtherExpress16 network (Ethernet) card, say Y and - read the Ethernet-HOWTO, available from - . Note that the Intel - EtherExpress16 card used to be regarded as a very poor choice - because the driver was very unreliable. We now have a new driver - that should do better. - - To compile this driver as a module, choose M here. The module - will be called eexpress. - -config EEXPRESS_PRO - tristate "EtherExpressPro support/EtherExpress 10 (i82595) support" - depends on ISA - ---help--- - If you have a network (Ethernet) card of this type, say Y. This - driver supports Intel i82595{FX,TX} based boards. Note however - that the EtherExpress PRO/100 Ethernet card has its own separate - driver. Please read the Ethernet-HOWTO, available from - . - - To compile this driver as a module, choose M here. The module - will be called eepro. - config LASI_82596 tristate "Lasi ethernet" depends on GSC diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile index bc81e14ed5b..4267ae72c5d 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -3,8 +3,6 @@ # obj-$(CONFIG_ARM_ETHER1) += ether1.o -obj-$(CONFIG_EEXPRESS) += eexpress.o -obj-$(CONFIG_EEXPRESS_PRO) += eepro.o obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o obj-$(CONFIG_ZNET) += znet.o diff --git a/drivers/net/ethernet/i825xx/eepro.c b/drivers/net/ethernet/i825xx/eepro.c deleted file mode 100644 index 7f49fd54c52..00000000000 --- a/drivers/net/ethernet/i825xx/eepro.c +++ /dev/null @@ -1,1822 +0,0 @@ -/* eepro.c: Intel EtherExpress Pro/10 device driver for Linux. */ -/* - Written 1994, 1995,1996 by Bao C. Ha. - - Copyright (C) 1994, 1995,1996 by Bao C. Ha. - - This software may be used and distributed - according to the terms of the GNU General Public License, - incorporated herein by reference. - - The author may be reached at bao.ha@srs.gov - or 418 Hastings Place, Martinez, GA 30907. - - Things remaining to do: - Better record keeping of errors. - Eliminate transmit interrupt to reduce overhead. - Implement "concurrent processing". I won't be doing it! - - Bugs: - - If you have a problem of not detecting the 82595 during a - reboot (warm reset), disable the FLASH memory should fix it. - This is a compatibility hardware problem. - - Versions: - 0.13b basic ethtool support (aris, 09/13/2004) - 0.13a in memory shortage, drop packets also in board - (Michael Westermann , 07/30/2002) - 0.13 irq sharing, rewrote probe function, fixed a nasty bug in - hardware_send_packet and a major cleanup (aris, 11/08/2001) - 0.12d fixing a problem with single card detected as eight eth devices - fixing a problem with sudden drop in card performance - (chris (asdn@go2.pl), 10/29/2001) - 0.12c fixing some problems with old cards (aris, 01/08/2001) - 0.12b misc fixes (aris, 06/26/2000) - 0.12a port of version 0.12a of 2.2.x kernels to 2.3.x - (aris (aris@conectiva.com.br), 05/19/2000) - 0.11e some tweaks about multiple cards support (PdP, jul/aug 1999) - 0.11d added __initdata, __init stuff; call spin_lock_init - in eepro_probe1. Replaced "eepro" by dev->name. Augmented - the code protected by spin_lock in interrupt routine - (PdP, 12/12/1998) - 0.11c minor cleanup (PdP, RMC, 09/12/1998) - 0.11b Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module - under 2.1.xx. Debug messages are flagged as KERN_DEBUG to - avoid console flooding. Added locking at critical parts. Now - the dawn thing is SMP safe. - 0.11a Attempt to get 2.1.xx support up (RMC) - 0.11 Brian Candler added support for multiple cards. Tested as - a module, no idea if it works when compiled into kernel. - - 0.10e Rick Bressler notified me that ifconfig up;ifconfig down fails - because the irq is lost somewhere. Fixed that by moving - request_irq and free_irq to eepro_open and eepro_close respectively. - 0.10d Ugh! Now Wakeup works. Was seriously broken in my first attempt. - I'll need to find a way to specify an ioport other than - the default one in the PnP case. PnP definitively sucks. - And, yes, this is not the only reason. - 0.10c PnP Wakeup Test for 595FX. uncomment #define PnPWakeup; - to use. - 0.10b Should work now with (some) Pro/10+. At least for - me (and my two cards) it does. _No_ guarantee for - function with non-Pro/10+ cards! (don't have any) - (RMC, 9/11/96) - - 0.10 Added support for the Etherexpress Pro/10+. The - IRQ map was changed significantly from the old - pro/10. The new interrupt map was provided by - Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu). - (BCH, 9/3/96) - - 0.09 Fixed a race condition in the transmit algorithm, - which causes crashes under heavy load with fast - pentium computers. The performance should also - improve a bit. The size of RX buffer, and hence - TX buffer, can also be changed via lilo or insmod. - (BCH, 7/31/96) - - 0.08 Implement 32-bit I/O for the 82595TX and 82595FX - based lan cards. Disable full-duplex mode if TPE - is not used. (BCH, 4/8/96) - - 0.07a Fix a stat report which counts every packet as a - heart-beat failure. (BCH, 6/3/95) - - 0.07 Modified to support all other 82595-based lan cards. - The IRQ vector of the EtherExpress Pro will be set - according to the value saved in the EEPROM. For other - cards, I will do autoirq_request() to grab the next - available interrupt vector. (BCH, 3/17/95) - - 0.06a,b Interim released. Minor changes in the comments and - print out format. (BCH, 3/9/95 and 3/14/95) - - 0.06 First stable release that I am comfortable with. (BCH, - 3/2/95) - - 0.05 Complete testing of multicast. (BCH, 2/23/95) - - 0.04 Adding multicast support. (BCH, 2/14/95) - - 0.03 First widely alpha release for public testing. - (BCH, 2/14/95) - -*/ - -static const char version[] = - "eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n"; - -#include - -/* - Sources: - - This driver wouldn't have been written without the availability - of the Crynwr's Lan595 driver source code. It helps me to - familiarize with the 82595 chipset while waiting for the Intel - documentation. I also learned how to detect the 82595 using - the packet driver's technique. - - This driver is written by cutting and pasting the skeleton.c driver - provided by Donald Becker. I also borrowed the EEPROM routine from - Donald Becker's 82586 driver. - - Datasheet for the Intel 82595 (including the TX and FX version). It - provides just enough info that the casual reader might think that it - documents the i82595. - - The User Manual for the 82595. It provides a lot of the missing - information. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DRV_NAME "eepro" -#define DRV_VERSION "0.13c" - -#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) ) -/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */ -#define SLOW_DOWN inb(0x80) -/* udelay(2) */ -#define compat_init_data __initdata -enum iftype { AUI=0, BNC=1, TPE=2 }; - -/* First, a few definitions that the brave might change. */ -/* A zero-terminated list of I/O addresses to be probed. */ -static unsigned int eepro_portlist[] compat_init_data = - { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0}; -/* note: 0x300 is default, the 595FX supports ALL IO Ports - from 0x000 to 0x3F0, some of which are reserved in PCs */ - -/* To try the (not-really PnP Wakeup: */ -/* -#define PnPWakeup -*/ - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 0 -#endif -static unsigned int net_debug = NET_DEBUG; - -/* The number of low I/O ports used by the ethercard. */ -#define EEPRO_IO_EXTENT 16 - -/* Different 82595 chips */ -#define LAN595 0 -#define LAN595TX 1 -#define LAN595FX 2 -#define LAN595FX_10ISA 3 - -/* Information that need to be kept for each board. */ -struct eepro_local { - unsigned rx_start; - unsigned tx_start; /* start of the transmit chain */ - int tx_last; /* pointer to last packet in the transmit chain */ - unsigned tx_end; /* end of the transmit chain (plus 1) */ - int eepro; /* 1 for the EtherExpress Pro/10, - 2 for the EtherExpress Pro/10+, - 3 for the EtherExpress 10 (blue cards), - 0 for other 82595-based lan cards. */ - int version; /* a flag to indicate if this is a TX or FX - version of the 82595 chip. */ - int stepping; - - spinlock_t lock; /* Serializing lock */ - - unsigned rcv_ram; /* pre-calculated space for rx */ - unsigned xmt_ram; /* pre-calculated space for tx */ - unsigned char xmt_bar; - unsigned char xmt_lower_limit_reg; - unsigned char xmt_upper_limit_reg; - short xmt_lower_limit; - short xmt_upper_limit; - short rcv_lower_limit; - short rcv_upper_limit; - unsigned char eeprom_reg; - unsigned short word[8]; -}; - -/* The station (ethernet) address prefix, used for IDing the board. */ -#define SA_ADDR0 0x00 /* Etherexpress Pro/10 */ -#define SA_ADDR1 0xaa -#define SA_ADDR2 0x00 - -#define GetBit(x,y) ((x & (1<>y) - -/* EEPROM Word 0: */ -#define ee_PnP 0 /* Plug 'n Play enable bit */ -#define ee_Word1 1 /* Word 1? */ -#define ee_BusWidth 2 /* 8/16 bit */ -#define ee_FlashAddr 3 /* Flash Address */ -#define ee_FlashMask 0x7 /* Mask */ -#define ee_AutoIO 6 /* */ -#define ee_reserved0 7 /* =0! */ -#define ee_Flash 8 /* Flash there? */ -#define ee_AutoNeg 9 /* Auto Negotiation enabled? */ -#define ee_IO0 10 /* IO Address LSB */ -#define ee_IO0Mask 0x /*...*/ -#define ee_IO1 15 /* IO MSB */ - -/* EEPROM Word 1: */ -#define ee_IntSel 0 /* Interrupt */ -#define ee_IntMask 0x7 -#define ee_LI 3 /* Link Integrity 0= enabled */ -#define ee_PC 4 /* Polarity Correction 0= enabled */ -#define ee_TPE_AUI 5 /* PortSelection 1=TPE */ -#define ee_Jabber 6 /* Jabber prevention 0= enabled */ -#define ee_AutoPort 7 /* Auto Port Selection 1= Disabled */ -#define ee_SMOUT 8 /* SMout Pin Control 0= Input */ -#define ee_PROM 9 /* Flash EPROM / PROM 0=Flash */ -#define ee_reserved1 10 /* .. 12 =0! */ -#define ee_AltReady 13 /* Alternate Ready, 0=normal */ -#define ee_reserved2 14 /* =0! */ -#define ee_Duplex 15 - -/* Word2,3,4: */ -#define ee_IA5 0 /*bit start for individual Addr Byte 5 */ -#define ee_IA4 8 /*bit start for individual Addr Byte 5 */ -#define ee_IA3 0 /*bit start for individual Addr Byte 5 */ -#define ee_IA2 8 /*bit start for individual Addr Byte 5 */ -#define ee_IA1 0 /*bit start for individual Addr Byte 5 */ -#define ee_IA0 8 /*bit start for individual Addr Byte 5 */ - -/* Word 5: */ -#define ee_BNC_TPE 0 /* 0=TPE */ -#define ee_BootType 1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */ -#define ee_BootTypeMask 0x3 -#define ee_NumConn 3 /* Number of Connections 0= One or Two */ -#define ee_FlashSock 4 /* Presence of Flash Socket 0= Present */ -#define ee_PortTPE 5 -#define ee_PortBNC 6 -#define ee_PortAUI 7 -#define ee_PowerMgt 10 /* 0= disabled */ -#define ee_CP 13 /* Concurrent Processing */ -#define ee_CPMask 0x7 - -/* Word 6: */ -#define ee_Stepping 0 /* Stepping info */ -#define ee_StepMask 0x0F -#define ee_BoardID 4 /* Manucaturer Board ID, reserved */ -#define ee_BoardMask 0x0FFF - -/* Word 7: */ -#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping = 0x1EB8 for Pro/10+ */ -#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */ - -/*..*/ -#define ee_SIZE 0x40 /* total EEprom Size */ -#define ee_Checksum 0xBABA /* initial and final value for adding checksum */ - - -/* Card identification via EEprom: */ -#define ee_addr_vendor 0x10 /* Word offset for EISA Vendor ID */ -#define ee_addr_id 0x11 /* Word offset for Card ID */ -#define ee_addr_SN 0x12 /* Serial Number */ -#define ee_addr_CRC_8 0x14 /* CRC over last thee Bytes */ - - -#define ee_vendor_intel0 0x25 /* Vendor ID Intel */ -#define ee_vendor_intel1 0xD4 -#define ee_id_eepro10p0 0x10 /* ID for eepro/10+ */ -#define ee_id_eepro10p1 0x31 - -#define TX_TIMEOUT ((4*HZ)/10) - -/* Index to functions, as function prototypes. */ - -static int eepro_probe1(struct net_device *dev, int autoprobe); -static int eepro_open(struct net_device *dev); -static netdev_tx_t eepro_send_packet(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t eepro_interrupt(int irq, void *dev_id); -static void eepro_rx(struct net_device *dev); -static void eepro_transmit_interrupt(struct net_device *dev); -static int eepro_close(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static void eepro_tx_timeout (struct net_device *dev); - -static int read_eeprom(int ioaddr, int location, struct net_device *dev); -static int hardware_send_packet(struct net_device *dev, void *buf, short length); -static int eepro_grab_irq(struct net_device *dev); - -/* - Details of the i82595. - -You will need either the datasheet or the user manual to understand what -is going on here. The 82595 is very different from the 82586, 82593. - -The receive algorithm in eepro_rx() is just an implementation of the -RCV ring structure that the Intel 82595 imposes at the hardware level. -The receive buffer is set at 24K, and the transmit buffer is 8K. I -am assuming that the total buffer memory is 32K, which is true for the -Intel EtherExpress Pro/10. If it is less than that on a generic card, -the driver will be broken. - -The transmit algorithm in the hardware_send_packet() is similar to the -one in the eepro_rx(). The transmit buffer is a ring linked list. -I just queue the next available packet to the end of the list. In my -system, the 82595 is so fast that the list seems to always contain a -single packet. In other systems with faster computers and more congested -network traffics, the ring linked list should improve performance by -allowing up to 8K worth of packets to be queued. - -The sizes of the receive and transmit buffers can now be changed via lilo -or insmod. Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0" -where rx-buffer is in KB unit. Modules uses the parameter mem which is -also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer." -The receive buffer has to be more than 3K or less than 29K. Otherwise, -it is reset to the default of 24K, and, hence, 8K for the trasnmit -buffer (transmit-buffer = 32K - receive-buffer). - -*/ -#define RAM_SIZE 0x8000 - -#define RCV_HEADER 8 -#define RCV_DEFAULT_RAM 0x6000 - -#define XMT_HEADER 8 -#define XMT_DEFAULT_RAM (RAM_SIZE - RCV_DEFAULT_RAM) - -#define XMT_START_PRO RCV_DEFAULT_RAM -#define XMT_START_10 0x0000 -#define RCV_START_PRO 0x0000 -#define RCV_START_10 XMT_DEFAULT_RAM - -#define RCV_DONE 0x0008 -#define RX_OK 0x2000 -#define RX_ERROR 0x0d81 - -#define TX_DONE_BIT 0x0080 -#define TX_OK 0x2000 -#define CHAIN_BIT 0x8000 -#define XMT_STATUS 0x02 -#define XMT_CHAIN 0x04 -#define XMT_COUNT 0x06 - -#define BANK0_SELECT 0x00 -#define BANK1_SELECT 0x40 -#define BANK2_SELECT 0x80 - -/* Bank 0 registers */ -#define COMMAND_REG 0x00 /* Register 0 */ -#define MC_SETUP 0x03 -#define XMT_CMD 0x04 -#define DIAGNOSE_CMD 0x07 -#define RCV_ENABLE_CMD 0x08 -#define RCV_DISABLE_CMD 0x0a -#define STOP_RCV_CMD 0x0b -#define RESET_CMD 0x0e -#define POWER_DOWN_CMD 0x18 -#define RESUME_XMT_CMD 0x1c -#define SEL_RESET_CMD 0x1e -#define STATUS_REG 0x01 /* Register 1 */ -#define RX_INT 0x02 -#define TX_INT 0x04 -#define EXEC_STATUS 0x30 -#define ID_REG 0x02 /* Register 2 */ -#define R_ROBIN_BITS 0xc0 /* round robin counter */ -#define ID_REG_MASK 0x2c -#define ID_REG_SIG 0x24 -#define AUTO_ENABLE 0x10 -#define INT_MASK_REG 0x03 /* Register 3 */ -#define RX_STOP_MASK 0x01 -#define RX_MASK 0x02 -#define TX_MASK 0x04 -#define EXEC_MASK 0x08 -#define ALL_MASK 0x0f -#define IO_32_BIT 0x10 -#define RCV_BAR 0x04 /* The following are word (16-bit) registers */ -#define RCV_STOP 0x06 - -#define XMT_BAR_PRO 0x0a -#define XMT_BAR_10 0x0b - -#define HOST_ADDRESS_REG 0x0c -#define IO_PORT 0x0e -#define IO_PORT_32_BIT 0x0c - -/* Bank 1 registers */ -#define REG1 0x01 -#define WORD_WIDTH 0x02 -#define INT_ENABLE 0x80 -#define INT_NO_REG 0x02 -#define RCV_LOWER_LIMIT_REG 0x08 -#define RCV_UPPER_LIMIT_REG 0x09 - -#define XMT_LOWER_LIMIT_REG_PRO 0x0a -#define XMT_UPPER_LIMIT_REG_PRO 0x0b -#define XMT_LOWER_LIMIT_REG_10 0x0b -#define XMT_UPPER_LIMIT_REG_10 0x0a - -/* Bank 2 registers */ -#define XMT_Chain_Int 0x20 /* Interrupt at the end of the transmit chain */ -#define XMT_Chain_ErrStop 0x40 /* Interrupt at the end of the chain even if there are errors */ -#define RCV_Discard_BadFrame 0x80 /* Throw bad frames away, and continue to receive others */ -#define REG2 0x02 -#define PRMSC_Mode 0x01 -#define Multi_IA 0x20 -#define REG3 0x03 -#define TPE_BIT 0x04 -#define BNC_BIT 0x20 -#define REG13 0x0d -#define FDX 0x00 -#define A_N_ENABLE 0x02 - -#define I_ADD_REG0 0x04 -#define I_ADD_REG1 0x05 -#define I_ADD_REG2 0x06 -#define I_ADD_REG3 0x07 -#define I_ADD_REG4 0x08 -#define I_ADD_REG5 0x09 - -#define EEPROM_REG_PRO 0x0a -#define EEPROM_REG_10 0x0b - -#define EESK 0x01 -#define EECS 0x02 -#define EEDI 0x04 -#define EEDO 0x08 - -/* do a full reset */ -#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr) - -/* do a nice reset */ -#define eepro_sel_reset(ioaddr) { \ - outb(SEL_RESET_CMD, ioaddr); \ - SLOW_DOWN; \ - SLOW_DOWN; \ - } - -/* disable all interrupts */ -#define eepro_dis_int(ioaddr) outb(ALL_MASK, ioaddr + INT_MASK_REG) - -/* clear all interrupts */ -#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG) - -/* enable tx/rx */ -#define eepro_en_int(ioaddr) outb(ALL_MASK & ~(RX_MASK | TX_MASK), \ - ioaddr + INT_MASK_REG) - -/* enable exec event interrupt */ -#define eepro_en_intexec(ioaddr) outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG) - -/* enable rx */ -#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr) - -/* disable rx */ -#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr) - -/* switch bank */ -#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr) -#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr) -#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr) - -/* enable interrupt line */ -#define eepro_en_intline(ioaddr) outb(inb(ioaddr + REG1) | INT_ENABLE,\ - ioaddr + REG1) - -/* disable interrupt line */ -#define eepro_dis_intline(ioaddr) outb(inb(ioaddr + REG1) & 0x7f, \ - ioaddr + REG1); - -/* set diagnose flag */ -#define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr) - -/* ack for rx int */ -#define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG) - -/* ack for tx int */ -#define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG) - -/* a complete sel reset */ -#define eepro_complete_selreset(ioaddr) { \ - dev->stats.tx_errors++;\ - eepro_sel_reset(ioaddr);\ - lp->tx_end = \ - lp->xmt_lower_limit;\ - lp->tx_start = lp->tx_end;\ - lp->tx_last = 0;\ - dev->trans_start = jiffies;\ - netif_wake_queue(dev);\ - eepro_en_rx(ioaddr);\ - } - -/* Check for a network adaptor of this type, and return '0' if one exists. - If dev->base_addr == 0, probe all likely locations. - If dev->base_addr == 1, always return failure. - If dev->base_addr == 2, allocate space for the device and return success - (detachable devices only). - */ -static int __init do_eepro_probe(struct net_device *dev) -{ - int i; - int base_addr = dev->base_addr; - int irq = dev->irq; - -#ifdef PnPWakeup - /* XXXX for multiple cards should this only be run once? */ - - /* Wakeup: */ - #define WakeupPort 0x279 - #define WakeupSeq {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\ - 0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\ - 0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\ - 0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43} - - { - unsigned short int WS[32]=WakeupSeq; - - if (request_region(WakeupPort, 2, "eepro wakeup")) { - if (net_debug>5) - printk(KERN_DEBUG "Waking UP\n"); - - outb_p(0,WakeupPort); - outb_p(0,WakeupPort); - for (i=0; i<32; i++) { - outb_p(WS[i],WakeupPort); - if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]); - } - - release_region(WakeupPort, 2); - } else - printk(KERN_WARNING "PnP wakeup region busy!\n"); - } -#endif - - if (base_addr > 0x1ff) /* Check a single specified location. */ - return eepro_probe1(dev, 0); - - else if (base_addr != 0) /* Don't probe at all. */ - return -ENXIO; - - for (i = 0; eepro_portlist[i]; i++) { - dev->base_addr = eepro_portlist[i]; - dev->irq = irq; - if (eepro_probe1(dev, 1) == 0) - return 0; - } - - return -ENODEV; -} - -#ifndef MODULE -struct net_device * __init eepro_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local)); - int err; - - if (!dev) - return ERR_PTR(-ENODEV); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_eepro_probe(dev); - if (err) - goto out; - return dev; -out: - free_netdev(dev); - return ERR_PTR(err); -} -#endif - -static void __init printEEPROMInfo(struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - unsigned short Word; - int i,j; - - j = ee_Checksum; - for (i = 0; i < 8; i++) - j += lp->word[i]; - for ( ; i < ee_SIZE; i++) - j += read_eeprom(ioaddr, i, dev); - - printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff); - - Word = lp->word[0]; - printk(KERN_DEBUG "Word0:\n"); - printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP)); - printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 ); - printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg)); - printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4); - - if (net_debug>4) { - Word = lp->word[1]; - printk(KERN_DEBUG "Word1:\n"); - printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask); - printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI)); - printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC)); - printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI)); - printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber)); - printk(KERN_DEBUG " AutoPort: %d\n", !GetBit(Word,ee_AutoPort)); - printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex)); - } - - Word = lp->word[5]; - printk(KERN_DEBUG "Word5:\n"); - printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE)); - printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn)); - printk(KERN_DEBUG " Has "); - if (GetBit(Word,ee_PortTPE)) printk(KERN_DEBUG "TPE "); - if (GetBit(Word,ee_PortBNC)) printk(KERN_DEBUG "BNC "); - if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI "); - printk(KERN_DEBUG "port(s)\n"); - - Word = lp->word[6]; - printk(KERN_DEBUG "Word6:\n"); - printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask); - printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID); - - Word = lp->word[7]; - printk(KERN_DEBUG "Word7:\n"); - printk(KERN_DEBUG " INT to IRQ:\n"); - - for (i=0, j=0; i<15; i++) - if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i); - - printk(KERN_DEBUG "\n"); -} - -/* function to recalculate the limits of buffer based on rcv_ram */ -static void eepro_recalc (struct net_device *dev) -{ - struct eepro_local * lp; - - lp = netdev_priv(dev); - lp->xmt_ram = RAM_SIZE - lp->rcv_ram; - - if (lp->eepro == LAN595FX_10ISA) { - lp->xmt_lower_limit = XMT_START_10; - lp->xmt_upper_limit = (lp->xmt_ram - 2); - lp->rcv_lower_limit = lp->xmt_ram; - lp->rcv_upper_limit = (RAM_SIZE - 2); - } - else { - lp->rcv_lower_limit = RCV_START_PRO; - lp->rcv_upper_limit = (lp->rcv_ram - 2); - lp->xmt_lower_limit = lp->rcv_ram; - lp->xmt_upper_limit = (RAM_SIZE - 2); - } -} - -/* prints boot-time info */ -static void __init eepro_print_info (struct net_device *dev) -{ - struct eepro_local * lp = netdev_priv(dev); - int i; - const char * ifmap[] = {"AUI", "10Base2", "10BaseT"}; - - i = inb(dev->base_addr + ID_REG); - printk(KERN_DEBUG " id: %#x ",i); - printk(" io: %#x ", (unsigned)dev->base_addr); - - switch (lp->eepro) { - case LAN595FX_10ISA: - printk("%s: Intel EtherExpress 10 ISA\n at %#x,", - dev->name, (unsigned)dev->base_addr); - break; - case LAN595FX: - printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,", - dev->name, (unsigned)dev->base_addr); - break; - case LAN595TX: - printk("%s: Intel EtherExpress Pro/10 ISA at %#x,", - dev->name, (unsigned)dev->base_addr); - break; - case LAN595: - printk("%s: Intel 82595-based lan card at %#x,", - dev->name, (unsigned)dev->base_addr); - break; - } - - printk(" %pM", dev->dev_addr); - - if (net_debug > 3) - printk(KERN_DEBUG ", %dK RCV buffer", - (int)(lp->rcv_ram)/1024); - - if (dev->irq > 2) - printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); - else - printk(", %s.\n", ifmap[dev->if_port]); - - if (net_debug > 3) { - i = lp->word[5]; - if (i & 0x2000) /* bit 13 of EEPROM word 5 */ - printk(KERN_DEBUG "%s: Concurrent Processing is " - "enabled but not used!\n", dev->name); - } - - /* Check the station address for the manufacturer's code */ - if (net_debug>3) - printEEPROMInfo(dev); -} - -static const struct ethtool_ops eepro_ethtool_ops; - -static const struct net_device_ops eepro_netdev_ops = { - .ndo_open = eepro_open, - .ndo_stop = eepro_close, - .ndo_start_xmit = eepro_send_packet, - .ndo_set_rx_mode = set_multicast_list, - .ndo_tx_timeout = eepro_tx_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/* This is the real probe routine. Linux has a history of friendly device - probes on the ISA bus. A good device probe avoids doing writes, and - verifies that the correct device exists and functions. */ - -static int __init eepro_probe1(struct net_device *dev, int autoprobe) -{ - unsigned short station_addr[3], id, counter; - int i; - struct eepro_local *lp; - int ioaddr = dev->base_addr; - int err; - - /* Grab the region so we can find another board if autoIRQ fails. */ - if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) { - if (!autoprobe) - printk(KERN_WARNING "EEPRO: io-port 0x%04x in use\n", - ioaddr); - return -EBUSY; - } - - /* Now, we are going to check for the signature of the - ID_REG (register 2 of bank 0) */ - - id = inb(ioaddr + ID_REG); - - if ((id & ID_REG_MASK) != ID_REG_SIG) - goto exit; - - /* We seem to have the 82595 signature, let's - play with its counter (last 2 bits of - register 2 of bank 0) to be sure. */ - - counter = id & R_ROBIN_BITS; - - if ((inb(ioaddr + ID_REG) & R_ROBIN_BITS) != (counter + 0x40)) - goto exit; - - lp = netdev_priv(dev); - memset(lp, 0, sizeof(struct eepro_local)); - lp->xmt_bar = XMT_BAR_PRO; - lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO; - lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO; - lp->eeprom_reg = EEPROM_REG_PRO; - spin_lock_init(&lp->lock); - - /* Now, get the ethernet hardware address from - the EEPROM */ - station_addr[0] = read_eeprom(ioaddr, 2, dev); - - /* FIXME - find another way to know that we've found - * an Etherexpress 10 - */ - if (station_addr[0] == 0x0000 || station_addr[0] == 0xffff) { - lp->eepro = LAN595FX_10ISA; - lp->eeprom_reg = EEPROM_REG_10; - lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; - lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10; - lp->xmt_bar = XMT_BAR_10; - station_addr[0] = read_eeprom(ioaddr, 2, dev); - } - - /* get all words at once. will be used here and for ethtool */ - for (i = 0; i < 8; i++) { - lp->word[i] = read_eeprom(ioaddr, i, dev); - } - station_addr[1] = lp->word[3]; - station_addr[2] = lp->word[4]; - - if (!lp->eepro) { - if (lp->word[7] == ee_FX_INT2IRQ) - lp->eepro = 2; - else if (station_addr[2] == SA_ADDR1) - lp->eepro = 1; - } - - /* Fill in the 'dev' fields. */ - for (i=0; i < 6; i++) - dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i]; - - /* RX buffer must be more than 3K and less than 29K */ - if (dev->mem_end < 3072 || dev->mem_end > 29696) - lp->rcv_ram = RCV_DEFAULT_RAM; - - /* calculate {xmt,rcv}_{lower,upper}_limit */ - eepro_recalc(dev); - - if (GetBit(lp->word[5], ee_BNC_TPE)) - dev->if_port = BNC; - else - dev->if_port = TPE; - - if (dev->irq < 2 && lp->eepro != 0) { - /* Mask off INT number */ - int count = lp->word[1] & 7; - unsigned irqMask = lp->word[7]; - - while (count--) - irqMask &= irqMask - 1; - - count = ffs(irqMask); - - if (count) - dev->irq = count - 1; - - if (dev->irq < 2) { - printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n"); - goto exit; - } else if (dev->irq == 2) { - dev->irq = 9; - } - } - - dev->netdev_ops = &eepro_netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; - dev->ethtool_ops = &eepro_ethtool_ops; - - /* print boot time info */ - eepro_print_info(dev); - - /* reset 82595 */ - eepro_reset(ioaddr); - - err = register_netdev(dev); - if (err) - goto err; - return 0; -exit: - err = -ENODEV; -err: - release_region(dev->base_addr, EEPRO_IO_EXTENT); - return err; -} - -/* Open/initialize the board. This is called (in the current kernel) - sometime after booting when the 'ifconfig' program is run. - - This routine should set everything up anew at each open, even - registers that "should" only need to be set once at boot, so that - there is non-reboot way to recover if something goes wrong. - */ - -static const char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1}; -static const char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1}; -static int eepro_grab_irq(struct net_device *dev) -{ - static const int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 }; - const int *irqp = irqlist; - int temp_reg, ioaddr = dev->base_addr; - - eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */ - - /* Enable the interrupt line. */ - eepro_en_intline(ioaddr); - - /* be CAREFUL, BANK 0 now */ - eepro_sw2bank0(ioaddr); - - /* clear all interrupts */ - eepro_clear_int(ioaddr); - - /* Let EXEC event to interrupt */ - eepro_en_intexec(ioaddr); - - do { - eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */ - - temp_reg = inb(ioaddr + INT_NO_REG); - outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); - - eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ - - if (request_irq (*irqp, NULL, IRQF_SHARED, "bogus", dev) != EBUSY) { - unsigned long irq_mask; - /* Twinkle the interrupt, and check if it's seen */ - irq_mask = probe_irq_on(); - - eepro_diag(ioaddr); /* RESET the 82595 */ - mdelay(20); - - if (*irqp == probe_irq_off(irq_mask)) /* It's a good IRQ line */ - break; - - /* clear all interrupts */ - eepro_clear_int(ioaddr); - } - } while (*++irqp); - - eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */ - - /* Disable the physical interrupt line. */ - eepro_dis_intline(ioaddr); - - eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ - - /* Mask all the interrupts. */ - eepro_dis_int(ioaddr); - - /* clear all interrupts */ - eepro_clear_int(ioaddr); - - return dev->irq; -} - -static int eepro_open(struct net_device *dev) -{ - unsigned short temp_reg, old8, old9; - int irqMask; - int i, ioaddr = dev->base_addr; - struct eepro_local *lp = netdev_priv(dev); - - if (net_debug > 3) - printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name); - - irqMask = lp->word[7]; - - if (lp->eepro == LAN595FX_10ISA) { - if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n"); - } - else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */ - { - lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */ - if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n"); - } - - else if ((dev->dev_addr[0] == SA_ADDR0 && - dev->dev_addr[1] == SA_ADDR1 && - dev->dev_addr[2] == SA_ADDR2)) - { - lp->eepro = 1; - if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n"); - } /* Yes, an Intel EtherExpress Pro/10 */ - - else lp->eepro = 0; /* No, it is a generic 82585 lan card */ - - /* Get the interrupt vector for the 82595 */ - if (dev->irq < 2 && eepro_grab_irq(dev) == 0) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return -EAGAIN; - } - - if (request_irq(dev->irq , eepro_interrupt, 0, dev->name, dev)) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq); - return -EAGAIN; - } - - /* Initialize the 82595. */ - - eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ - temp_reg = inb(ioaddr + lp->eeprom_reg); - - lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */ - - if (net_debug > 3) - printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping); - - if (temp_reg & 0x10) /* Check the TurnOff Enable bit */ - outb(temp_reg & 0xef, ioaddr + lp->eeprom_reg); - for (i=0; i < 6; i++) - outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); - - temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */ - outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */ - | RCV_Discard_BadFrame, ioaddr + REG1); - - temp_reg = inb(ioaddr + REG2); /* Match broadcast */ - outb(temp_reg | 0x14, ioaddr + REG2); - - temp_reg = inb(ioaddr + REG3); - outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */ - - /* Set the receiving mode */ - eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */ - - /* Set the interrupt vector */ - temp_reg = inb(ioaddr + INT_NO_REG); - if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA) - outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG); - else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); - - - temp_reg = inb(ioaddr + INT_NO_REG); - if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA) - outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG); - else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); - - if (net_debug > 3) - printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg); - - - /* Initialize the RCV and XMT upper and lower limits */ - outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG); - outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG); - outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg); - outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg); - - /* Enable the interrupt line. */ - eepro_en_intline(ioaddr); - - /* Switch back to Bank 0 */ - eepro_sw2bank0(ioaddr); - - /* Let RX and TX events to interrupt */ - eepro_en_int(ioaddr); - - /* clear all interrupts */ - eepro_clear_int(ioaddr); - - /* Initialize RCV */ - outw(lp->rcv_lower_limit, ioaddr + RCV_BAR); - lp->rx_start = lp->rcv_lower_limit; - outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP); - - /* Initialize XMT */ - outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar); - lp->tx_start = lp->tx_end = lp->xmt_lower_limit; - lp->tx_last = 0; - - /* Check for the i82595TX and i82595FX */ - old8 = inb(ioaddr + 8); - outb(~old8, ioaddr + 8); - - if ((temp_reg = inb(ioaddr + 8)) == old8) { - if (net_debug > 3) - printk(KERN_DEBUG "i82595 detected!\n"); - lp->version = LAN595; - } - else { - lp->version = LAN595TX; - outb(old8, ioaddr + 8); - old9 = inb(ioaddr + 9); - - if (irqMask==ee_FX_INT2IRQ) { - if (net_debug > 3) { - printk(KERN_DEBUG "IrqMask: %#x\n",irqMask); - printk(KERN_DEBUG "i82595FX detected!\n"); - } - lp->version = LAN595FX; - outb(old9, ioaddr + 9); - if (dev->if_port != TPE) { /* Hopefully, this will fix the - problem of using Pentiums and - pro/10 w/ BNC. */ - eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ - temp_reg = inb(ioaddr + REG13); - /* disable the full duplex mode since it is not - applicable with the 10Base2 cable. */ - outb(temp_reg & ~(FDX | A_N_ENABLE), REG13); - eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */ - } - } - else if (net_debug > 3) { - printk(KERN_DEBUG "temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff)); - printk(KERN_DEBUG "i82595TX detected!\n"); - } - } - - eepro_sel_reset(ioaddr); - - netif_start_queue(dev); - - if (net_debug > 3) - printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name); - - /* enabling rx */ - eepro_en_rx(ioaddr); - - return 0; -} - -static void eepro_tx_timeout (struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - - /* if (net_debug > 1) */ - printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name, - "network cable problem"); - /* This is not a duplicate. One message for the console, - one for the log file */ - printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name, - "network cable problem"); - eepro_complete_selreset(ioaddr); -} - - -static netdev_tx_t eepro_send_packet(struct sk_buff *skb, - struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - unsigned long flags; - int ioaddr = dev->base_addr; - short length = skb->len; - - if (net_debug > 5) - printk(KERN_DEBUG "%s: entering eepro_send_packet routine.\n", dev->name); - - if (length < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - length = ETH_ZLEN; - } - netif_stop_queue (dev); - - eepro_dis_int(ioaddr); - spin_lock_irqsave(&lp->lock, flags); - - { - unsigned char *buf = skb->data; - - if (hardware_send_packet(dev, buf, length)) - /* we won't wake queue here because we're out of space */ - dev->stats.tx_dropped++; - else { - dev->stats.tx_bytes+=skb->len; - netif_wake_queue(dev); - } - - } - - dev_kfree_skb (skb); - - /* You might need to clean up and record Tx statistics here. */ - /* dev->stats.tx_aborted_errors++; */ - - if (net_debug > 5) - printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name); - - eepro_en_int(ioaddr); - spin_unlock_irqrestore(&lp->lock, flags); - - return NETDEV_TX_OK; -} - - -/* The typical workload of the driver: - Handle the network interface interrupts. */ - -static irqreturn_t -eepro_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct eepro_local *lp; - int ioaddr, status, boguscount = 20; - int handled = 0; - - lp = netdev_priv(dev); - - spin_lock(&lp->lock); - - if (net_debug > 5) - printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name); - - ioaddr = dev->base_addr; - - while (((status = inb(ioaddr + STATUS_REG)) & (RX_INT|TX_INT)) && (boguscount--)) - { - handled = 1; - if (status & RX_INT) { - if (net_debug > 4) - printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name); - - eepro_dis_int(ioaddr); - - /* Get the received packets */ - eepro_ack_rx(ioaddr); - eepro_rx(dev); - - eepro_en_int(ioaddr); - } - if (status & TX_INT) { - if (net_debug > 4) - printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name); - - - eepro_dis_int(ioaddr); - - /* Process the status of transmitted packets */ - eepro_ack_tx(ioaddr); - eepro_transmit_interrupt(dev); - - eepro_en_int(ioaddr); - } - } - - if (net_debug > 5) - printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name); - - spin_unlock(&lp->lock); - return IRQ_RETVAL(handled); -} - -static int eepro_close(struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - short temp_reg; - - netif_stop_queue(dev); - - eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */ - - /* Disable the physical interrupt line. */ - temp_reg = inb(ioaddr + REG1); - outb(temp_reg & 0x7f, ioaddr + REG1); - - eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */ - - /* Flush the Tx and disable Rx. */ - outb(STOP_RCV_CMD, ioaddr); - lp->tx_start = lp->tx_end = lp->xmt_lower_limit; - lp->tx_last = 0; - - /* Mask all the interrupts. */ - eepro_dis_int(ioaddr); - - /* clear all interrupts */ - eepro_clear_int(ioaddr); - - /* Reset the 82595 */ - eepro_reset(ioaddr); - - /* release the interrupt */ - free_irq(dev->irq, dev); - - /* Update the statistics here. What statistics? */ - - return 0; -} - -/* Set or clear the multicast filter for this adaptor. - */ -static void -set_multicast_list(struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - unsigned short mode; - struct netdev_hw_addr *ha; - int mc_count = netdev_mc_count(dev); - - if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63) - { - eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ - mode = inb(ioaddr + REG2); - outb(mode | PRMSC_Mode, ioaddr + REG2); - mode = inb(ioaddr + REG3); - outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ - } - - else if (mc_count == 0) - { - eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ - mode = inb(ioaddr + REG2); - outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */ - mode = inb(ioaddr + REG3); - outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ - } - - else - { - unsigned short status, *eaddrs; - int i, boguscount = 0; - - /* Disable RX and TX interrupts. Necessary to avoid - corruption of the HOST_ADDRESS_REG by interrupt - service routines. */ - eepro_dis_int(ioaddr); - - eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */ - mode = inb(ioaddr + REG2); - outb(mode | Multi_IA, ioaddr + REG2); - mode = inb(ioaddr + REG3); - outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */ - eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */ - outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG); - outw(MC_SETUP, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(6 * (mc_count + 1), ioaddr + IO_PORT); - - netdev_for_each_mc_addr(ha, dev) { - eaddrs = (unsigned short *) ha->addr; - outw(*eaddrs++, ioaddr + IO_PORT); - outw(*eaddrs++, ioaddr + IO_PORT); - outw(*eaddrs++, ioaddr + IO_PORT); - } - - eaddrs = (unsigned short *) dev->dev_addr; - outw(eaddrs[0], ioaddr + IO_PORT); - outw(eaddrs[1], ioaddr + IO_PORT); - outw(eaddrs[2], ioaddr + IO_PORT); - outw(lp->tx_end, ioaddr + lp->xmt_bar); - outb(MC_SETUP, ioaddr); - - /* Update the transmit queue */ - i = lp->tx_end + XMT_HEADER + 6 * (mc_count + 1); - - if (lp->tx_start != lp->tx_end) - { - /* update the next address and the chain bit in the - last packet */ - outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); - outw(i, ioaddr + IO_PORT); - outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); - status = inw(ioaddr + IO_PORT); - outw(status | CHAIN_BIT, ioaddr + IO_PORT); - lp->tx_end = i ; - } - else { - lp->tx_start = lp->tx_end = i ; - } - - /* Acknowledge that the MC setup is done */ - do { /* We should be doing this in the eepro_interrupt()! */ - SLOW_DOWN; - SLOW_DOWN; - if (inb(ioaddr + STATUS_REG) & 0x08) - { - i = inb(ioaddr); - outb(0x08, ioaddr + STATUS_REG); - - if (i & 0x20) { /* command ABORTed */ - printk(KERN_NOTICE "%s: multicast setup failed.\n", - dev->name); - break; - } else if ((i & 0x0f) == 0x03) { /* MC-Done */ - printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n", - dev->name, mc_count, - mc_count > 1 ? "es":""); - break; - } - } - } while (++boguscount < 100); - - /* Re-enable RX and TX interrupts */ - eepro_en_int(ioaddr); - } - if (lp->eepro == LAN595FX_10ISA) { - eepro_complete_selreset(ioaddr); - } - else - eepro_en_rx(ioaddr); -} - -/* The horrible routine to read a word from the serial EEPROM. */ -/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */ - -/* The delay between EEPROM clock transitions. */ -#define eeprom_delay() { udelay(40); } -#define EE_READ_CMD (6 << 6) - -static int -read_eeprom(int ioaddr, int location, struct net_device *dev) -{ - int i; - unsigned short retval = 0; - struct eepro_local *lp = netdev_priv(dev); - short ee_addr = ioaddr + lp->eeprom_reg; - int read_cmd = location | EE_READ_CMD; - short ctrl_val = EECS ; - - /* XXXX - black magic */ - eepro_sw2bank1(ioaddr); - outb(0x00, ioaddr + STATUS_REG); - /* XXXX - black magic */ - - eepro_sw2bank2(ioaddr); - outb(ctrl_val, ee_addr); - - /* Shift the read command bits out. */ - for (i = 8; i >= 0; i--) { - short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI - : ctrl_val; - outb(outval, ee_addr); - outb(outval | EESK, ee_addr); /* EEPROM clock tick. */ - eeprom_delay(); - outb(outval, ee_addr); /* Finish EEPROM a clock tick. */ - eeprom_delay(); - } - outb(ctrl_val, ee_addr); - - for (i = 16; i > 0; i--) { - outb(ctrl_val | EESK, ee_addr); eeprom_delay(); - retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0); - outb(ctrl_val, ee_addr); eeprom_delay(); - } - - /* Terminate the EEPROM access. */ - ctrl_val &= ~EECS; - outb(ctrl_val | EESK, ee_addr); - eeprom_delay(); - outb(ctrl_val, ee_addr); - eeprom_delay(); - eepro_sw2bank0(ioaddr); - return retval; -} - -static int -hardware_send_packet(struct net_device *dev, void *buf, short length) -{ - struct eepro_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - unsigned status, tx_available, last, end; - - if (net_debug > 5) - printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name); - - /* determine how much of the transmit buffer space is available */ - if (lp->tx_end > lp->tx_start) - tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start); - else if (lp->tx_end < lp->tx_start) - tx_available = lp->tx_start - lp->tx_end; - else tx_available = lp->xmt_ram; - - if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) { - /* No space available ??? */ - return 1; - } - - last = lp->tx_end; - end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - - if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */ - if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) { - /* Arrrr!!!, must keep the xmt header together, - several days were lost to chase this one down. */ - last = lp->xmt_lower_limit; - end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; - } - else end = lp->xmt_lower_limit + (end - - lp->xmt_upper_limit + 2); - } - - outw(last, ioaddr + HOST_ADDRESS_REG); - outw(XMT_CMD, ioaddr + IO_PORT); - outw(0, ioaddr + IO_PORT); - outw(end, ioaddr + IO_PORT); - outw(length, ioaddr + IO_PORT); - - if (lp->version == LAN595) - outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1); - else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ - unsigned short temp = inb(ioaddr + INT_MASK_REG); - outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); - outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2); - outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); - } - - /* A dummy read to flush the DRAM write pipeline */ - status = inw(ioaddr + IO_PORT); - - if (lp->tx_start == lp->tx_end) { - outw(last, ioaddr + lp->xmt_bar); - outb(XMT_CMD, ioaddr); - lp->tx_start = last; /* I don't like to change tx_start here */ - } - else { - /* update the next address and the chain bit in the - last packet */ - - if (lp->tx_end != last) { - outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG); - outw(last, ioaddr + IO_PORT); - } - - outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG); - status = inw(ioaddr + IO_PORT); - outw(status | CHAIN_BIT, ioaddr + IO_PORT); - - /* Continue the transmit command */ - outb(RESUME_XMT_CMD, ioaddr); - } - - lp->tx_last = last; - lp->tx_end = end; - - if (net_debug > 5) - printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name); - - return 0; -} - -static void -eepro_rx(struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - short boguscount = 20; - short rcv_car = lp->rx_start; - unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size; - - if (net_debug > 5) - printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name); - - /* Set the read pointer to the start of the RCV */ - outw(rcv_car, ioaddr + HOST_ADDRESS_REG); - - rcv_event = inw(ioaddr + IO_PORT); - - while (rcv_event == RCV_DONE) { - - rcv_status = inw(ioaddr + IO_PORT); - rcv_next_frame = inw(ioaddr + IO_PORT); - rcv_size = inw(ioaddr + IO_PORT); - - if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) { - - /* Malloc up new buffer. */ - struct sk_buff *skb; - - dev->stats.rx_bytes+=rcv_size; - rcv_size &= 0x3fff; - skb = netdev_alloc_skb(dev, rcv_size + 5); - if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name); - dev->stats.rx_dropped++; - rcv_car = lp->rx_start + RCV_HEADER + rcv_size; - lp->rx_start = rcv_next_frame; - outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); - - break; - } - skb_reserve(skb,2); - - if (lp->version == LAN595) - insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1); - else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */ - unsigned short temp = inb(ioaddr + INT_MASK_REG); - outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG); - insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size), - (rcv_size + 3) >> 2); - outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG); - } - - skb->protocol = eth_type_trans(skb,dev); - netif_rx(skb); - dev->stats.rx_packets++; - } - - else { /* Not sure will ever reach here, - I set the 595 to discard bad received frames */ - dev->stats.rx_errors++; - - if (rcv_status & 0x0100) - dev->stats.rx_over_errors++; - - else if (rcv_status & 0x0400) - dev->stats.rx_frame_errors++; - - else if (rcv_status & 0x0800) - dev->stats.rx_crc_errors++; - - printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n", - dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size); - } - - if (rcv_status & 0x1000) - dev->stats.rx_length_errors++; - - rcv_car = lp->rx_start + RCV_HEADER + rcv_size; - lp->rx_start = rcv_next_frame; - - if (--boguscount == 0) - break; - - outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG); - rcv_event = inw(ioaddr + IO_PORT); - - } - if (rcv_car == 0) - rcv_car = lp->rcv_upper_limit | 0xff; - - outw(rcv_car - 1, ioaddr + RCV_STOP); - - if (net_debug > 5) - printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name); -} - -static void -eepro_transmit_interrupt(struct net_device *dev) -{ - struct eepro_local *lp = netdev_priv(dev); - short ioaddr = dev->base_addr; - short boguscount = 25; - short xmt_status; - - while ((lp->tx_start != lp->tx_end) && boguscount--) { - - outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG); - xmt_status = inw(ioaddr+IO_PORT); - - if (!(xmt_status & TX_DONE_BIT)) - break; - - xmt_status = inw(ioaddr+IO_PORT); - lp->tx_start = inw(ioaddr+IO_PORT); - - netif_wake_queue (dev); - - if (xmt_status & TX_OK) - dev->stats.tx_packets++; - else { - dev->stats.tx_errors++; - if (xmt_status & 0x0400) { - dev->stats.tx_carrier_errors++; - printk(KERN_DEBUG "%s: carrier error\n", - dev->name); - printk(KERN_DEBUG "%s: XMT status = %#x\n", - dev->name, xmt_status); - } - else { - printk(KERN_DEBUG "%s: XMT status = %#x\n", - dev->name, xmt_status); - printk(KERN_DEBUG "%s: XMT status = %#x\n", - dev->name, xmt_status); - } - } - if (xmt_status & 0x000f) { - dev->stats.collisions += (xmt_status & 0x000f); - } - - if ((xmt_status & 0x0040) == 0x0) { - dev->stats.tx_heartbeat_errors++; - } - } -} - -static int eepro_ethtool_get_settings(struct net_device *dev, - struct ethtool_cmd *cmd) -{ - struct eepro_local *lp = netdev_priv(dev); - - cmd->supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_Autoneg; - cmd->advertising = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_Autoneg; - - if (GetBit(lp->word[5], ee_PortTPE)) { - cmd->supported |= SUPPORTED_TP; - cmd->advertising |= ADVERTISED_TP; - } - if (GetBit(lp->word[5], ee_PortBNC)) { - cmd->supported |= SUPPORTED_BNC; - cmd->advertising |= ADVERTISED_BNC; - } - if (GetBit(lp->word[5], ee_PortAUI)) { - cmd->supported |= SUPPORTED_AUI; - cmd->advertising |= ADVERTISED_AUI; - } - - ethtool_cmd_speed_set(cmd, SPEED_10); - - if (dev->if_port == TPE && lp->word[1] & ee_Duplex) { - cmd->duplex = DUPLEX_FULL; - } - else { - cmd->duplex = DUPLEX_HALF; - } - - cmd->port = dev->if_port; - cmd->phy_address = dev->base_addr; - cmd->transceiver = XCVR_INTERNAL; - - if (lp->word[0] & ee_AutoNeg) { - cmd->autoneg = 1; - } - - return 0; -} - -static void eepro_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *drvinfo) -{ - strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version)); - snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info), - "ISA 0x%lx", dev->base_addr); -} - -static const struct ethtool_ops eepro_ethtool_ops = { - .get_settings = eepro_ethtool_get_settings, - .get_drvinfo = eepro_ethtool_get_drvinfo, -}; - -#ifdef MODULE - -#define MAX_EEPRO 8 -static struct net_device *dev_eepro[MAX_EEPRO]; - -static int io[MAX_EEPRO] = { - [0 ... MAX_EEPRO-1] = -1 -}; -static int irq[MAX_EEPRO]; -static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */ - [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024 -}; -static int autodetect; - -static int n_eepro; -/* For linux 2.1.xx */ - -MODULE_AUTHOR("Pascal Dupuis and others"); -MODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver"); -MODULE_LICENSE("GPL"); - -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param_array(mem, int, NULL, 0); -module_param(autodetect, int, 0); -MODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base address(es)"); -MODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)"); -MODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)"); -MODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)"); - -int __init init_module(void) -{ - struct net_device *dev; - int i; - if (io[0] == -1 && autodetect == 0) { - printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n"); - printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n"); - return -ENODEV; - } - else if (autodetect) { - /* if autodetect is set then we must force detection */ - for (i = 0; i < MAX_EEPRO; i++) { - io[i] = 0; - } - - printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n"); - } - - for (i = 0; i < MAX_EEPRO && io[i] != -1; i++) { - dev = alloc_etherdev(sizeof(struct eepro_local)); - if (!dev) - break; - - dev->mem_end = mem[i]; - dev->base_addr = io[i]; - dev->irq = irq[i]; - - if (do_eepro_probe(dev) == 0) { - dev_eepro[n_eepro++] = dev; - continue; - } - free_netdev(dev); - break; - } - - if (n_eepro) - printk(KERN_INFO "%s", version); - - return n_eepro ? 0 : -ENODEV; -} - -void __exit -cleanup_module(void) -{ - int i; - - for (i=0; ibase_addr, EEPRO_IO_EXTENT); - free_netdev(dev); - } -} -#endif /* MODULE */ diff --git a/drivers/net/ethernet/i825xx/eexpress.c b/drivers/net/ethernet/i825xx/eexpress.c deleted file mode 100644 index 7a6a2f04c5b..00000000000 --- a/drivers/net/ethernet/i825xx/eexpress.c +++ /dev/null @@ -1,1661 +0,0 @@ -/* Intel EtherExpress 16 device driver for Linux - * - * Written by John Sullivan, 1995 - * based on original code by Donald Becker, with changes by - * Alan Cox and Pauline Middelink. - * - * Support for 8-bit mode by Zoltan Szilagyi - * - * Many modifications, and currently maintained, by - * Philip Blundell - * Added the Compaq LTE Alan Cox - * Added MCA support Adam Fritzler (now deleted) - * - * Note - this driver is experimental still - it has problems on faster - * machines. Someone needs to sit down and go through it line by line with - * a databook... - */ - -/* The EtherExpress 16 is a fairly simple card, based on a shared-memory - * design using the i82586 Ethernet coprocessor. It bears no relationship, - * as far as I know, to the similarly-named "EtherExpress Pro" range. - * - * Historically, Linux support for these cards has been very bad. However, - * things seem to be getting better slowly. - */ - -/* If your card is confused about what sort of interface it has (eg it - * persistently reports "10baseT" when none is fitted), running 'SOFTSET /BART' - * or 'SOFTSET /LISA' from DOS seems to help. - */ - -/* Here's the scoop on memory mapping. - * - * There are three ways to access EtherExpress card memory: either using the - * shared-memory mapping, or using PIO through the dataport, or using PIO - * through the "shadow memory" ports. - * - * The shadow memory system works by having the card map some of its memory - * as follows: - * - * (the low five bits of the SMPTR are ignored) - * - * base+0x4000..400f memory at SMPTR+0..15 - * base+0x8000..800f memory at SMPTR+16..31 - * base+0xc000..c007 dubious stuff (memory at SMPTR+16..23 apparently) - * base+0xc008..c00f memory at 0x0008..0x000f - * - * This last set (the one at c008) is particularly handy because the SCB - * lives at 0x0008. So that set of ports gives us easy random access to data - * in the SCB without having to mess around setting up pointers and the like. - * We always use this method to access the SCB (via the scb_xx() functions). - * - * Dataport access works by aiming the appropriate (read or write) pointer - * at the first address you're interested in, and then reading or writing from - * the dataport. The pointers auto-increment after each transfer. We use - * this for data transfer. - * - * We don't use the shared-memory system because it allegedly doesn't work on - * all cards, and because it's a bit more prone to go wrong (it's one more - * thing to configure...). - */ - -/* Known bugs: - * - * - The card seems to want to give us two interrupts every time something - * happens, where just one would be better. - */ - -/* - * - * Note by Zoltan Szilagyi 10-12-96: - * - * I've succeeded in eliminating the "CU wedged" messages, and hence the - * lockups, which were only occurring with cards running in 8-bit mode ("force - * 8-bit operation" in Intel's SoftSet utility). This version of the driver - * sets the 82586 and the ASIC to 8-bit mode at startup; it also stops the - * CU before submitting a packet for transmission, and then restarts it as soon - * as the process of handing the packet is complete. This is definitely an - * unnecessary slowdown if the card is running in 16-bit mode; therefore one - * should detect 16-bit vs 8-bit mode from the EEPROM settings and act - * accordingly. In 8-bit mode with this bugfix I'm getting about 150 K/s for - * ftp's, which is significantly better than I get in DOS, so the overhead of - * stopping and restarting the CU with each transmit is not prohibitive in - * practice. - * - * Update by David Woodhouse 11/5/99: - * - * I've seen "CU wedged" messages in 16-bit mode, on the Alpha architecture. - * I assume that this is because 16-bit accesses are actually handled as two - * 8-bit accesses. - */ - -#ifdef __alpha__ -#define LOCKUP16 1 -#endif -#ifndef LOCKUP16 -#define LOCKUP16 0 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#ifndef NET_DEBUG -#define NET_DEBUG 4 -#endif - -#include "eexpress.h" - -#define EEXP_IO_EXTENT 16 - -/* - * Private data declarations - */ - -struct net_local -{ - unsigned long last_tx; /* jiffies when last transmit started */ - unsigned long init_time; /* jiffies when eexp_hw_init586 called */ - unsigned short rx_first; /* first rx buf, same as RX_BUF_START */ - unsigned short rx_last; /* last rx buf */ - unsigned short rx_ptr; /* first rx buf to look at */ - unsigned short tx_head; /* next free tx buf */ - unsigned short tx_reap; /* first in-use tx buf */ - unsigned short tx_tail; /* previous tx buf to tx_head */ - unsigned short tx_link; /* last known-executing tx buf */ - unsigned short last_tx_restart; /* set to tx_link when we - restart the CU */ - unsigned char started; - unsigned short rx_buf_start; - unsigned short rx_buf_end; - unsigned short num_tx_bufs; - unsigned short num_rx_bufs; - unsigned char width; /* 0 for 16bit, 1 for 8bit */ - unsigned char was_promisc; - unsigned char old_mc_count; - spinlock_t lock; -}; - -/* This is the code and data that is downloaded to the EtherExpress card's - * memory at boot time. - */ - -static unsigned short start_code[] = { -/* 0x0000 */ - 0x0001, /* ISCP: busy - cleared after reset */ - 0x0008,0x0000,0x0000, /* offset,address (lo,hi) of SCB */ - - 0x0000,0x0000, /* SCB: status, commands */ - 0x0000,0x0000, /* links to first command block, - first receive descriptor */ - 0x0000,0x0000, /* CRC error, alignment error counts */ - 0x0000,0x0000, /* out of resources, overrun error counts */ - - 0x0000,0x0000, /* pad */ - 0x0000,0x0000, - -/* 0x20 -- start of 82586 CU program */ -#define CONF_LINK 0x20 - 0x0000,Cmd_Config, - 0x0032, /* link to next command */ - 0x080c, /* 12 bytes follow : fifo threshold=8 */ - 0x2e40, /* don't rx bad frames - * SRDY/ARDY => ext. sync. : preamble len=8 - * take addresses from data buffers - * 6 bytes/address - */ - 0x6000, /* default backoff method & priority - * interframe spacing = 0x60 */ - 0xf200, /* slot time=0x200 - * max collision retry = 0xf */ -#define CONF_PROMISC 0x2e - 0x0000, /* no HDLC : normal CRC : enable broadcast - * disable promiscuous/multicast modes */ - 0x003c, /* minimum frame length = 60 octets) */ - - 0x0000,Cmd_SetAddr, - 0x003e, /* link to next command */ -#define CONF_HWADDR 0x38 - 0x0000,0x0000,0x0000, /* hardware address placed here */ - - 0x0000,Cmd_MCast, - 0x0076, /* link to next command */ -#define CONF_NR_MULTICAST 0x44 - 0x0000, /* number of bytes in multicast address(es) */ -#define CONF_MULTICAST 0x46 - 0x0000, 0x0000, 0x0000, /* some addresses */ - 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, - -#define CONF_DIAG_RESULT 0x76 - 0x0000, Cmd_Diag, - 0x007c, /* link to next command */ - - 0x0000,Cmd_TDR|Cmd_INT, - 0x0084, -#define CONF_TDR_RESULT 0x82 - 0x0000, - - 0x0000,Cmd_END|Cmd_Nop, /* end of configure sequence */ - 0x0084 /* dummy link */ -}; - -/* maps irq number to EtherExpress magic value */ -static char irqrmap[] = { 0,0,1,2,3,4,0,0,0,1,5,6,0,0,0,0 }; - -/* - * Prototypes for Linux interface - */ - -static int eexp_open(struct net_device *dev); -static int eexp_close(struct net_device *dev); -static void eexp_timeout(struct net_device *dev); -static netdev_tx_t eexp_xmit(struct sk_buff *buf, - struct net_device *dev); - -static irqreturn_t eexp_irq(int irq, void *dev_addr); -static void eexp_set_multicast(struct net_device *dev); - -/* - * Prototypes for hardware access functions - */ - -static void eexp_hw_rx_pio(struct net_device *dev); -static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf, - unsigned short len); -static int eexp_hw_probe(struct net_device *dev,unsigned short ioaddr); -static unsigned short eexp_hw_readeeprom(unsigned short ioaddr, - unsigned char location); - -static unsigned short eexp_hw_lasttxstat(struct net_device *dev); -static void eexp_hw_txrestart(struct net_device *dev); - -static void eexp_hw_txinit (struct net_device *dev); -static void eexp_hw_rxinit (struct net_device *dev); - -static void eexp_hw_init586 (struct net_device *dev); -static void eexp_setup_filter (struct net_device *dev); - -static char *eexp_ifmap[]={"AUI", "BNC", "RJ45"}; -enum eexp_iftype {AUI=0, BNC=1, TPE=2}; - -#define STARTED_RU 2 -#define STARTED_CU 1 - -/* - * Primitive hardware access functions. - */ - -static inline unsigned short scb_status(struct net_device *dev) -{ - return inw(dev->base_addr + 0xc008); -} - -static inline unsigned short scb_rdcmd(struct net_device *dev) -{ - return inw(dev->base_addr + 0xc00a); -} - -static inline void scb_command(struct net_device *dev, unsigned short cmd) -{ - outw(cmd, dev->base_addr + 0xc00a); -} - -static inline void scb_wrcbl(struct net_device *dev, unsigned short val) -{ - outw(val, dev->base_addr + 0xc00c); -} - -static inline void scb_wrrfa(struct net_device *dev, unsigned short val) -{ - outw(val, dev->base_addr + 0xc00e); -} - -static inline void set_loopback(struct net_device *dev) -{ - outb(inb(dev->base_addr + Config) | 2, dev->base_addr + Config); -} - -static inline void clear_loopback(struct net_device *dev) -{ - outb(inb(dev->base_addr + Config) & ~2, dev->base_addr + Config); -} - -static inline unsigned short int SHADOW(short int addr) -{ - addr &= 0x1f; - if (addr > 0xf) addr += 0x3ff0; - return addr + 0x4000; -} - -/* - * Linux interface - */ - -/* - * checks for presence of EtherExpress card - */ - -static int __init do_express_probe(struct net_device *dev) -{ - unsigned short *port; - static unsigned short ports[] = { 0x240,0x300,0x310,0x270,0x320,0x340,0 }; - unsigned short ioaddr = dev->base_addr; - int dev_irq = dev->irq; - int err; - - dev->if_port = 0xff; /* not set */ - - if (ioaddr&0xfe00) { - if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) - return -EBUSY; - err = eexp_hw_probe(dev,ioaddr); - release_region(ioaddr, EEXP_IO_EXTENT); - return err; - } else if (ioaddr) - return -ENXIO; - - for (port=&ports[0] ; *port ; port++ ) - { - unsigned short sum = 0; - int i; - if (!request_region(*port, EEXP_IO_EXTENT, "EtherExpress")) - continue; - for ( i=0 ; i<4 ; i++ ) - { - unsigned short t; - t = inb(*port + ID_PORT); - sum |= (t>>4) << ((t & 0x03)<<2); - } - if (sum==0xbaba && !eexp_hw_probe(dev,*port)) { - release_region(*port, EEXP_IO_EXTENT); - return 0; - } - release_region(*port, EEXP_IO_EXTENT); - dev->irq = dev_irq; - } - return -ENODEV; -} - -#ifndef MODULE -struct net_device * __init express_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct net_local)); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_express_probe(dev); - if (!err) - return dev; - free_netdev(dev); - return ERR_PTR(err); -} -#endif - -/* - * open and initialize the adapter, ready for use - */ - -static int eexp_open(struct net_device *dev) -{ - int ret; - unsigned short ioaddr = dev->base_addr; - struct net_local *lp = netdev_priv(dev); - -#if NET_DEBUG > 6 - printk(KERN_DEBUG "%s: eexp_open()\n", dev->name); -#endif - - if (!dev->irq || !irqrmap[dev->irq]) - return -ENXIO; - - ret = request_irq(dev->irq, eexp_irq, 0, dev->name, dev); - if (ret) - return ret; - - if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) { - printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" - , ioaddr); - goto err_out1; - } - if (!request_region(ioaddr+0x4000, EEXP_IO_EXTENT, "EtherExpress shadow")) { - printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" - , ioaddr+0x4000); - goto err_out2; - } - if (!request_region(ioaddr+0x8000, EEXP_IO_EXTENT, "EtherExpress shadow")) { - printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" - , ioaddr+0x8000); - goto err_out3; - } - if (!request_region(ioaddr+0xc000, EEXP_IO_EXTENT, "EtherExpress shadow")) { - printk(KERN_WARNING "EtherExpress io port %x, is busy.\n" - , ioaddr+0xc000); - goto err_out4; - } - - if (lp->width) { - printk("%s: forcing ASIC to 8-bit mode\n", dev->name); - outb(inb(dev->base_addr+Config)&~4, dev->base_addr+Config); - } - - eexp_hw_init586(dev); - netif_start_queue(dev); -#if NET_DEBUG > 6 - printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name); -#endif - return 0; - - err_out4: - release_region(ioaddr+0x8000, EEXP_IO_EXTENT); - err_out3: - release_region(ioaddr+0x4000, EEXP_IO_EXTENT); - err_out2: - release_region(ioaddr, EEXP_IO_EXTENT); - err_out1: - free_irq(dev->irq, dev); - return -EBUSY; -} - -/* - * close and disable the interface, leaving the 586 in reset. - */ - -static int eexp_close(struct net_device *dev) -{ - unsigned short ioaddr = dev->base_addr; - struct net_local *lp = netdev_priv(dev); - - int irq = dev->irq; - - netif_stop_queue(dev); - - outb(SIRQ_dis|irqrmap[irq],ioaddr+SET_IRQ); - lp->started = 0; - scb_command(dev, SCB_CUsuspend|SCB_RUsuspend); - outb(0,ioaddr+SIGNAL_CA); - free_irq(irq,dev); - outb(i586_RST,ioaddr+EEPROM_Ctrl); - release_region(ioaddr, EEXP_IO_EXTENT); - release_region(ioaddr+0x4000, 16); - release_region(ioaddr+0x8000, 16); - release_region(ioaddr+0xc000, 16); - - return 0; -} - -/* - * This gets called when a higher level thinks we are broken. Check that - * nothing has become jammed in the CU. - */ - -static void unstick_cu(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; - - if (lp->started) - { - if (time_after(jiffies, dev_trans_start(dev) + HZ/2)) - { - if (lp->tx_link==lp->last_tx_restart) - { - unsigned short boguscount=200,rsst; - printk(KERN_WARNING "%s: Retransmit timed out, status %04x, resetting...\n", - dev->name, scb_status(dev)); - eexp_hw_txinit(dev); - lp->last_tx_restart = 0; - scb_wrcbl(dev, lp->tx_link); - scb_command(dev, SCB_CUstart); - outb(0,ioaddr+SIGNAL_CA); - while (!SCB_complete(rsst=scb_status(dev))) - { - if (!--boguscount) - { - boguscount=200; - printk(KERN_WARNING "%s: Reset timed out status %04x, retrying...\n", - dev->name,rsst); - scb_wrcbl(dev, lp->tx_link); - scb_command(dev, SCB_CUstart); - outb(0,ioaddr+SIGNAL_CA); - } - } - netif_wake_queue(dev); - } - else - { - unsigned short status = scb_status(dev); - if (SCB_CUdead(status)) - { - unsigned short txstatus = eexp_hw_lasttxstat(dev); - printk(KERN_WARNING "%s: Transmit timed out, CU not active status %04x %04x, restarting...\n", - dev->name, status, txstatus); - eexp_hw_txrestart(dev); - } - else - { - unsigned short txstatus = eexp_hw_lasttxstat(dev); - if (netif_queue_stopped(dev) && !txstatus) - { - printk(KERN_WARNING "%s: CU wedged, status %04x %04x, resetting...\n", - dev->name,status,txstatus); - eexp_hw_init586(dev); - netif_wake_queue(dev); - } - else - { - printk(KERN_WARNING "%s: transmit timed out\n", dev->name); - } - } - } - } - } - else - { - if (time_after(jiffies, lp->init_time + 10)) - { - unsigned short status = scb_status(dev); - printk(KERN_WARNING "%s: i82586 startup timed out, status %04x, resetting...\n", - dev->name, status); - eexp_hw_init586(dev); - netif_wake_queue(dev); - } - } -} - -static void eexp_timeout(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); -#ifdef CONFIG_SMP - unsigned long flags; -#endif - int status; - - disable_irq(dev->irq); - - /* - * Best would be to use synchronize_irq(); spin_lock() here - * lets make it work first.. - */ - -#ifdef CONFIG_SMP - spin_lock_irqsave(&lp->lock, flags); -#endif - - status = scb_status(dev); - unstick_cu(dev); - printk(KERN_INFO "%s: transmit timed out, %s?\n", dev->name, - (SCB_complete(status)?"lost interrupt": - "board on fire")); - dev->stats.tx_errors++; - lp->last_tx = jiffies; - if (!SCB_complete(status)) { - scb_command(dev, SCB_CUabort); - outb(0,dev->base_addr+SIGNAL_CA); - } - netif_wake_queue(dev); -#ifdef CONFIG_SMP - spin_unlock_irqrestore(&lp->lock, flags); -#endif -} - -/* - * Called to transmit a packet, or to allow us to right ourselves - * if the kernel thinks we've died. - */ -static netdev_tx_t eexp_xmit(struct sk_buff *buf, struct net_device *dev) -{ - short length = buf->len; -#ifdef CONFIG_SMP - struct net_local *lp = netdev_priv(dev); - unsigned long flags; -#endif - -#if NET_DEBUG > 6 - printk(KERN_DEBUG "%s: eexp_xmit()\n", dev->name); -#endif - - if (buf->len < ETH_ZLEN) { - if (skb_padto(buf, ETH_ZLEN)) - return NETDEV_TX_OK; - length = ETH_ZLEN; - } - - disable_irq(dev->irq); - - /* - * Best would be to use synchronize_irq(); spin_lock() here - * lets make it work first.. - */ - -#ifdef CONFIG_SMP - spin_lock_irqsave(&lp->lock, flags); -#endif - - { - unsigned short *data = (unsigned short *)buf->data; - - dev->stats.tx_bytes += length; - - eexp_hw_tx_pio(dev,data,length); - } - dev_kfree_skb(buf); -#ifdef CONFIG_SMP - spin_unlock_irqrestore(&lp->lock, flags); -#endif - enable_irq(dev->irq); - return NETDEV_TX_OK; -} - -/* - * Handle an EtherExpress interrupt - * If we've finished initializing, start the RU and CU up. - * If we've already started, reap tx buffers, handle any received packets, - * check to make sure we've not become wedged. - */ - -static unsigned short eexp_start_irq(struct net_device *dev, - unsigned short status) -{ - unsigned short ack_cmd = SCB_ack(status); - struct net_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; - if ((dev->flags & IFF_UP) && !(lp->started & STARTED_CU)) { - short diag_status, tdr_status; - while (SCB_CUstat(status)==2) - status = scb_status(dev); -#if NET_DEBUG > 4 - printk("%s: CU went non-active (status %04x)\n", - dev->name, status); -#endif - - outw(CONF_DIAG_RESULT & ~31, ioaddr + SM_PTR); - diag_status = inw(ioaddr + SHADOW(CONF_DIAG_RESULT)); - if (diag_status & 1<<11) { - printk(KERN_WARNING "%s: 82586 failed self-test\n", - dev->name); - } else if (!(diag_status & 1<<13)) { - printk(KERN_WARNING "%s: 82586 self-test failed to complete\n", dev->name); - } - - outw(CONF_TDR_RESULT & ~31, ioaddr + SM_PTR); - tdr_status = inw(ioaddr + SHADOW(CONF_TDR_RESULT)); - if (tdr_status & (TDR_SHORT|TDR_OPEN)) { - printk(KERN_WARNING "%s: TDR reports cable %s at %d tick%s\n", dev->name, (tdr_status & TDR_SHORT)?"short":"broken", tdr_status & TDR_TIME, ((tdr_status & TDR_TIME) != 1) ? "s" : ""); - } - else if (tdr_status & TDR_XCVRPROBLEM) { - printk(KERN_WARNING "%s: TDR reports transceiver problem\n", dev->name); - } - else if (tdr_status & TDR_LINKOK) { -#if NET_DEBUG > 4 - printk(KERN_DEBUG "%s: TDR reports link OK\n", dev->name); -#endif - } else { - printk("%s: TDR is ga-ga (status %04x)\n", dev->name, - tdr_status); - } - - lp->started |= STARTED_CU; - scb_wrcbl(dev, lp->tx_link); - /* if the RU isn't running, start it now */ - if (!(lp->started & STARTED_RU)) { - ack_cmd |= SCB_RUstart; - scb_wrrfa(dev, lp->rx_buf_start); - lp->rx_ptr = lp->rx_buf_start; - lp->started |= STARTED_RU; - } - ack_cmd |= SCB_CUstart | 0x2000; - } - - if ((dev->flags & IFF_UP) && !(lp->started & STARTED_RU) && SCB_RUstat(status)==4) - lp->started|=STARTED_RU; - - return ack_cmd; -} - -static void eexp_cmd_clear(struct net_device *dev) -{ - unsigned long int oldtime = jiffies; - while (scb_rdcmd(dev) && (time_before(jiffies, oldtime + 10))); - if (scb_rdcmd(dev)) { - printk("%s: command didn't clear\n", dev->name); - } -} - -static irqreturn_t eexp_irq(int dummy, void *dev_info) -{ - struct net_device *dev = dev_info; - struct net_local *lp; - unsigned short ioaddr,status,ack_cmd; - unsigned short old_read_ptr, old_write_ptr; - - lp = netdev_priv(dev); - ioaddr = dev->base_addr; - - spin_lock(&lp->lock); - - old_read_ptr = inw(ioaddr+READ_PTR); - old_write_ptr = inw(ioaddr+WRITE_PTR); - - outb(SIRQ_dis|irqrmap[dev->irq], ioaddr+SET_IRQ); - - status = scb_status(dev); - -#if NET_DEBUG > 4 - printk(KERN_DEBUG "%s: interrupt (status %x)\n", dev->name, status); -#endif - - if (lp->started == (STARTED_CU | STARTED_RU)) { - - do { - eexp_cmd_clear(dev); - - ack_cmd = SCB_ack(status); - scb_command(dev, ack_cmd); - outb(0,ioaddr+SIGNAL_CA); - - eexp_cmd_clear(dev); - - if (SCB_complete(status)) { - if (!eexp_hw_lasttxstat(dev)) { - printk("%s: tx interrupt but no status\n", dev->name); - } - } - - if (SCB_rxdframe(status)) - eexp_hw_rx_pio(dev); - - status = scb_status(dev); - } while (status & 0xc000); - - if (SCB_RUdead(status)) - { - printk(KERN_WARNING "%s: RU stopped: status %04x\n", - dev->name,status); -#if 0 - printk(KERN_WARNING "%s: cur_rfd=%04x, cur_rbd=%04x\n", dev->name, lp->cur_rfd, lp->cur_rbd); - outw(lp->cur_rfd, ioaddr+READ_PTR); - printk(KERN_WARNING "%s: [%04x]\n", dev->name, inw(ioaddr+DATAPORT)); - outw(lp->cur_rfd+6, ioaddr+READ_PTR); - printk(KERN_WARNING "%s: rbd is %04x\n", dev->name, rbd= inw(ioaddr+DATAPORT)); - outw(rbd, ioaddr+READ_PTR); - printk(KERN_WARNING "%s: [%04x %04x] ", dev->name, inw(ioaddr+DATAPORT), inw(ioaddr+DATAPORT)); - outw(rbd+8, ioaddr+READ_PTR); - printk("[%04x]\n", inw(ioaddr+DATAPORT)); -#endif - dev->stats.rx_errors++; -#if 1 - eexp_hw_rxinit(dev); -#else - lp->cur_rfd = lp->first_rfd; -#endif - scb_wrrfa(dev, lp->rx_buf_start); - scb_command(dev, SCB_RUstart); - outb(0,ioaddr+SIGNAL_CA); - } - } else { - if (status & 0x8000) - ack_cmd = eexp_start_irq(dev, status); - else - ack_cmd = SCB_ack(status); - scb_command(dev, ack_cmd); - outb(0,ioaddr+SIGNAL_CA); - } - - eexp_cmd_clear(dev); - - outb(SIRQ_en|irqrmap[dev->irq], ioaddr+SET_IRQ); - -#if NET_DEBUG > 6 - printk("%s: leaving eexp_irq()\n", dev->name); -#endif - outw(old_read_ptr, ioaddr+READ_PTR); - outw(old_write_ptr, ioaddr+WRITE_PTR); - - spin_unlock(&lp->lock); - return IRQ_HANDLED; -} - -/* - * Hardware access functions - */ - -/* - * Set the cable type to use. - */ - -static void eexp_hw_set_interface(struct net_device *dev) -{ - unsigned char oldval = inb(dev->base_addr + 0x300e); - oldval &= ~0x82; - switch (dev->if_port) { - case TPE: - oldval |= 0x2; - case BNC: - oldval |= 0x80; - break; - } - outb(oldval, dev->base_addr+0x300e); - mdelay(20); -} - -/* - * Check all the receive buffers, and hand any received packets - * to the upper levels. Basic sanity check on each frame - * descriptor, though we don't bother trying to fix broken ones. - */ - -static void eexp_hw_rx_pio(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short rx_block = lp->rx_ptr; - unsigned short boguscount = lp->num_rx_bufs; - unsigned short ioaddr = dev->base_addr; - unsigned short status; - -#if NET_DEBUG > 6 - printk(KERN_DEBUG "%s: eexp_hw_rx()\n", dev->name); -#endif - - do { - unsigned short rfd_cmd, rx_next, pbuf, pkt_len; - - outw(rx_block, ioaddr + READ_PTR); - status = inw(ioaddr + DATAPORT); - - if (FD_Done(status)) - { - rfd_cmd = inw(ioaddr + DATAPORT); - rx_next = inw(ioaddr + DATAPORT); - pbuf = inw(ioaddr + DATAPORT); - - outw(pbuf, ioaddr + READ_PTR); - pkt_len = inw(ioaddr + DATAPORT); - - if (rfd_cmd!=0x0000) - { - printk(KERN_WARNING "%s: rfd_cmd not zero:0x%04x\n", - dev->name, rfd_cmd); - continue; - } - else if (pbuf!=rx_block+0x16) - { - printk(KERN_WARNING "%s: rfd and rbd out of sync 0x%04x 0x%04x\n", - dev->name, rx_block+0x16, pbuf); - continue; - } - else if ((pkt_len & 0xc000)!=0xc000) - { - printk(KERN_WARNING "%s: EOF or F not set on received buffer (%04x)\n", - dev->name, pkt_len & 0xc000); - continue; - } - else if (!FD_OK(status)) - { - dev->stats.rx_errors++; - if (FD_CRC(status)) - dev->stats.rx_crc_errors++; - if (FD_Align(status)) - dev->stats.rx_frame_errors++; - if (FD_Resrc(status)) - dev->stats.rx_fifo_errors++; - if (FD_DMA(status)) - dev->stats.rx_over_errors++; - if (FD_Short(status)) - dev->stats.rx_length_errors++; - } - else - { - struct sk_buff *skb; - pkt_len &= 0x3fff; - skb = netdev_alloc_skb(dev, pkt_len + 16); - if (skb == NULL) - { - printk(KERN_WARNING "%s: Memory squeeze, dropping packet\n",dev->name); - dev->stats.rx_dropped++; - break; - } - skb_reserve(skb, 2); - outw(pbuf+10, ioaddr+READ_PTR); - insw(ioaddr+DATAPORT, skb_put(skb,pkt_len),(pkt_len+1)>>1); - skb->protocol = eth_type_trans(skb,dev); - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - } - outw(rx_block, ioaddr+WRITE_PTR); - outw(0, ioaddr+DATAPORT); - outw(0, ioaddr+DATAPORT); - rx_block = rx_next; - } - } while (FD_Done(status) && boguscount--); - lp->rx_ptr = rx_block; -} - -/* - * Hand a packet to the card for transmission - * If we get here, we MUST have already checked - * to make sure there is room in the transmit - * buffer region. - */ - -static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf, - unsigned short len) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; - - if (LOCKUP16 || lp->width) { - /* Stop the CU so that there is no chance that it - jumps off to a bogus address while we are writing the - pointer to the next transmit packet in 8-bit mode -- - this eliminates the "CU wedged" errors in 8-bit mode. - (Zoltan Szilagyi 10-12-96) */ - scb_command(dev, SCB_CUsuspend); - outw(0xFFFF, ioaddr+SIGNAL_CA); - } - - outw(lp->tx_head, ioaddr + WRITE_PTR); - - outw(0x0000, ioaddr + DATAPORT); - outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT); - outw(lp->tx_head+0x08, ioaddr + DATAPORT); - outw(lp->tx_head+0x0e, ioaddr + DATAPORT); - - outw(0x0000, ioaddr + DATAPORT); - outw(0x0000, ioaddr + DATAPORT); - outw(lp->tx_head+0x08, ioaddr + DATAPORT); - - outw(0x8000|len, ioaddr + DATAPORT); - outw(-1, ioaddr + DATAPORT); - outw(lp->tx_head+0x16, ioaddr + DATAPORT); - outw(0, ioaddr + DATAPORT); - - outsw(ioaddr + DATAPORT, buf, (len+1)>>1); - - outw(lp->tx_tail+0xc, ioaddr + WRITE_PTR); - outw(lp->tx_head, ioaddr + DATAPORT); - - dev->trans_start = jiffies; - lp->tx_tail = lp->tx_head; - if (lp->tx_head==TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) - lp->tx_head = TX_BUF_START; - else - lp->tx_head += TX_BUF_SIZE; - if (lp->tx_head != lp->tx_reap) - netif_wake_queue(dev); - - if (LOCKUP16 || lp->width) { - /* Restart the CU so that the packet can actually - be transmitted. (Zoltan Szilagyi 10-12-96) */ - scb_command(dev, SCB_CUresume); - outw(0xFFFF, ioaddr+SIGNAL_CA); - } - - dev->stats.tx_packets++; - lp->last_tx = jiffies; -} - -static const struct net_device_ops eexp_netdev_ops = { - .ndo_open = eexp_open, - .ndo_stop = eexp_close, - .ndo_start_xmit = eexp_xmit, - .ndo_set_rx_mode = eexp_set_multicast, - .ndo_tx_timeout = eexp_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/* - * Sanity check the suspected EtherExpress card - * Read hardware address, reset card, size memory and initialize buffer - * memory pointers. These are held in netdev_priv(), in case someone has more - * than one card in a machine. - */ - -static int __init eexp_hw_probe(struct net_device *dev, unsigned short ioaddr) -{ - unsigned short hw_addr[3]; - unsigned char buswidth; - unsigned int memory_size; - int i; - unsigned short xsum = 0; - struct net_local *lp = netdev_priv(dev); - - printk("%s: EtherExpress 16 at %#x ",dev->name,ioaddr); - - outb(ASIC_RST, ioaddr+EEPROM_Ctrl); - outb(0, ioaddr+EEPROM_Ctrl); - udelay(500); - outb(i586_RST, ioaddr+EEPROM_Ctrl); - - hw_addr[0] = eexp_hw_readeeprom(ioaddr,2); - hw_addr[1] = eexp_hw_readeeprom(ioaddr,3); - hw_addr[2] = eexp_hw_readeeprom(ioaddr,4); - - /* Standard Address or Compaq LTE Address */ - if (!((hw_addr[2]==0x00aa && ((hw_addr[1] & 0xff00)==0x0000)) || - (hw_addr[2]==0x0080 && ((hw_addr[1] & 0xff00)==0x5F00)))) - { - printk(" rejected: invalid address %04x%04x%04x\n", - hw_addr[2],hw_addr[1],hw_addr[0]); - return -ENODEV; - } - - /* Calculate the EEPROM checksum. Carry on anyway if it's bad, - * though. - */ - for (i = 0; i < 64; i++) - xsum += eexp_hw_readeeprom(ioaddr, i); - if (xsum != 0xbaba) - printk(" (bad EEPROM xsum 0x%02x)", xsum); - - dev->base_addr = ioaddr; - for ( i=0 ; i<6 ; i++ ) - dev->dev_addr[i] = ((unsigned char *)hw_addr)[5-i]; - - { - static const char irqmap[] = { 0, 9, 3, 4, 5, 10, 11, 0 }; - unsigned short setupval = eexp_hw_readeeprom(ioaddr,0); - - /* Use the IRQ from EEPROM if none was given */ - if (!dev->irq) - dev->irq = irqmap[setupval>>13]; - - if (dev->if_port == 0xff) { - dev->if_port = !(setupval & 0x1000) ? AUI : - eexp_hw_readeeprom(ioaddr,5) & 0x1 ? TPE : BNC; - } - - buswidth = !((setupval & 0x400) >> 10); - } - - memset(lp, 0, sizeof(struct net_local)); - spin_lock_init(&lp->lock); - - printk("(IRQ %d, %s connector, %d-bit bus", dev->irq, - eexp_ifmap[dev->if_port], buswidth?8:16); - - if (!request_region(dev->base_addr + 0x300e, 1, "EtherExpress")) - return -EBUSY; - - eexp_hw_set_interface(dev); - - release_region(dev->base_addr + 0x300e, 1); - - /* Find out how much RAM we have on the card */ - outw(0, dev->base_addr + WRITE_PTR); - for (i = 0; i < 32768; i++) - outw(0, dev->base_addr + DATAPORT); - - for (memory_size = 0; memory_size < 64; memory_size++) - { - outw(memory_size<<10, dev->base_addr + READ_PTR); - if (inw(dev->base_addr+DATAPORT)) - break; - outw(memory_size<<10, dev->base_addr + WRITE_PTR); - outw(memory_size | 0x5000, dev->base_addr+DATAPORT); - outw(memory_size<<10, dev->base_addr + READ_PTR); - if (inw(dev->base_addr+DATAPORT) != (memory_size | 0x5000)) - break; - } - - /* Sort out the number of buffers. We may have 16, 32, 48 or 64k - * of RAM to play with. - */ - lp->num_tx_bufs = 4; - lp->rx_buf_end = 0x3ff6; - switch (memory_size) - { - case 64: - lp->rx_buf_end += 0x4000; - case 48: - lp->num_tx_bufs += 4; - lp->rx_buf_end += 0x4000; - case 32: - lp->rx_buf_end += 0x4000; - case 16: - printk(", %dk RAM)\n", memory_size); - break; - default: - printk(") bad memory size (%dk).\n", memory_size); - return -ENODEV; - break; - } - - lp->rx_buf_start = TX_BUF_START + (lp->num_tx_bufs*TX_BUF_SIZE); - lp->width = buswidth; - - dev->netdev_ops = &eexp_netdev_ops; - dev->watchdog_timeo = 2*HZ; - - return register_netdev(dev); -} - -/* - * Read a word from the EtherExpress on-board serial EEPROM. - * The EEPROM contains 64 words of 16 bits. - */ -static unsigned short __init eexp_hw_readeeprom(unsigned short ioaddr, - unsigned char location) -{ - unsigned short cmd = 0x180|(location&0x7f); - unsigned short rval = 0,wval = EC_CS|i586_RST; - int i; - - outb(EC_CS|i586_RST,ioaddr+EEPROM_Ctrl); - for (i=0x100 ; i ; i>>=1 ) - { - if (cmd&i) - wval |= EC_Wr; - else - wval &= ~EC_Wr; - - outb(wval,ioaddr+EEPROM_Ctrl); - outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl); - eeprom_delay(); - outb(wval,ioaddr+EEPROM_Ctrl); - eeprom_delay(); - } - wval &= ~EC_Wr; - outb(wval,ioaddr+EEPROM_Ctrl); - for (i=0x8000 ; i ; i>>=1 ) - { - outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl); - eeprom_delay(); - if (inb(ioaddr+EEPROM_Ctrl)&EC_Rd) - rval |= i; - outb(wval,ioaddr+EEPROM_Ctrl); - eeprom_delay(); - } - wval &= ~EC_CS; - outb(wval|EC_Clk,ioaddr+EEPROM_Ctrl); - eeprom_delay(); - outb(wval,ioaddr+EEPROM_Ctrl); - eeprom_delay(); - return rval; -} - -/* - * Reap tx buffers and return last transmit status. - * if ==0 then either: - * a) we're not transmitting anything, so why are we here? - * b) we've died. - * otherwise, Stat_Busy(return) means we've still got some packets - * to transmit, Stat_Done(return) means our buffers should be empty - * again - */ - -static unsigned short eexp_hw_lasttxstat(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short tx_block = lp->tx_reap; - unsigned short status; - - if (!netif_queue_stopped(dev) && lp->tx_head==lp->tx_reap) - return 0x0000; - - do - { - outw(tx_block & ~31, dev->base_addr + SM_PTR); - status = inw(dev->base_addr + SHADOW(tx_block)); - if (!Stat_Done(status)) - { - lp->tx_link = tx_block; - return status; - } - else - { - lp->last_tx_restart = 0; - dev->stats.collisions += Stat_NoColl(status); - if (!Stat_OK(status)) - { - char *whatsup = NULL; - dev->stats.tx_errors++; - if (Stat_Abort(status)) - dev->stats.tx_aborted_errors++; - if (Stat_TNoCar(status)) { - whatsup = "aborted, no carrier"; - dev->stats.tx_carrier_errors++; - } - if (Stat_TNoCTS(status)) { - whatsup = "aborted, lost CTS"; - dev->stats.tx_carrier_errors++; - } - if (Stat_TNoDMA(status)) { - whatsup = "FIFO underran"; - dev->stats.tx_fifo_errors++; - } - if (Stat_TXColl(status)) { - whatsup = "aborted, too many collisions"; - dev->stats.tx_aborted_errors++; - } - if (whatsup) - printk(KERN_INFO "%s: transmit %s\n", - dev->name, whatsup); - } - else - dev->stats.tx_packets++; - } - if (tx_block == TX_BUF_START+((lp->num_tx_bufs-1)*TX_BUF_SIZE)) - lp->tx_reap = tx_block = TX_BUF_START; - else - lp->tx_reap = tx_block += TX_BUF_SIZE; - netif_wake_queue(dev); - } - while (lp->tx_reap != lp->tx_head); - - lp->tx_link = lp->tx_tail + 0x08; - - return status; -} - -/* - * This should never happen. It is called when some higher routine detects - * that the CU has stopped, to try to restart it from the last packet we knew - * we were working on, or the idle loop if we had finished for the time. - */ - -static void eexp_hw_txrestart(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; - - lp->last_tx_restart = lp->tx_link; - scb_wrcbl(dev, lp->tx_link); - scb_command(dev, SCB_CUstart); - outb(0,ioaddr+SIGNAL_CA); - - { - unsigned short boguscount=50,failcount=5; - while (!scb_status(dev)) - { - if (!--boguscount) - { - if (--failcount) - { - printk(KERN_WARNING "%s: CU start timed out, status %04x, cmd %04x\n", dev->name, scb_status(dev), scb_rdcmd(dev)); - scb_wrcbl(dev, lp->tx_link); - scb_command(dev, SCB_CUstart); - outb(0,ioaddr+SIGNAL_CA); - boguscount = 100; - } - else - { - printk(KERN_WARNING "%s: Failed to restart CU, resetting board...\n",dev->name); - eexp_hw_init586(dev); - netif_wake_queue(dev); - return; - } - } - } - } -} - -/* - * Writes down the list of transmit buffers into card memory. Each - * entry consists of an 82586 transmit command, followed by a jump - * pointing to itself. When we want to transmit a packet, we write - * the data into the appropriate transmit buffer and then modify the - * preceding jump to point at the new transmit command. This means that - * the 586 command unit is continuously active. - */ - -static void eexp_hw_txinit(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short tx_block = TX_BUF_START; - unsigned short curtbuf; - unsigned short ioaddr = dev->base_addr; - - for ( curtbuf=0 ; curtbufnum_tx_bufs ; curtbuf++ ) - { - outw(tx_block, ioaddr + WRITE_PTR); - - outw(0x0000, ioaddr + DATAPORT); - outw(Cmd_INT|Cmd_Xmit, ioaddr + DATAPORT); - outw(tx_block+0x08, ioaddr + DATAPORT); - outw(tx_block+0x0e, ioaddr + DATAPORT); - - outw(0x0000, ioaddr + DATAPORT); - outw(0x0000, ioaddr + DATAPORT); - outw(tx_block+0x08, ioaddr + DATAPORT); - - outw(0x8000, ioaddr + DATAPORT); - outw(-1, ioaddr + DATAPORT); - outw(tx_block+0x16, ioaddr + DATAPORT); - outw(0x0000, ioaddr + DATAPORT); - - tx_block += TX_BUF_SIZE; - } - lp->tx_head = TX_BUF_START; - lp->tx_reap = TX_BUF_START; - lp->tx_tail = tx_block - TX_BUF_SIZE; - lp->tx_link = lp->tx_tail + 0x08; - lp->rx_buf_start = tx_block; - -} - -/* - * Write the circular list of receive buffer descriptors to card memory. - * The end of the list isn't marked, which means that the 82586 receive - * unit will loop until buffers become available (this avoids it giving us - * "out of resources" messages). - */ - -static void eexp_hw_rxinit(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short rx_block = lp->rx_buf_start; - unsigned short ioaddr = dev->base_addr; - - lp->num_rx_bufs = 0; - lp->rx_first = lp->rx_ptr = rx_block; - do - { - lp->num_rx_bufs++; - - outw(rx_block, ioaddr + WRITE_PTR); - - outw(0, ioaddr + DATAPORT); outw(0, ioaddr+DATAPORT); - outw(rx_block + RX_BUF_SIZE, ioaddr+DATAPORT); - outw(0xffff, ioaddr+DATAPORT); - - outw(0x0000, ioaddr+DATAPORT); - outw(0xdead, ioaddr+DATAPORT); - outw(0xdead, ioaddr+DATAPORT); - outw(0xdead, ioaddr+DATAPORT); - outw(0xdead, ioaddr+DATAPORT); - outw(0xdead, ioaddr+DATAPORT); - outw(0xdead, ioaddr+DATAPORT); - - outw(0x0000, ioaddr+DATAPORT); - outw(rx_block + RX_BUF_SIZE + 0x16, ioaddr+DATAPORT); - outw(rx_block + 0x20, ioaddr+DATAPORT); - outw(0, ioaddr+DATAPORT); - outw(RX_BUF_SIZE-0x20, ioaddr+DATAPORT); - - lp->rx_last = rx_block; - rx_block += RX_BUF_SIZE; - } while (rx_block <= lp->rx_buf_end-RX_BUF_SIZE); - - - /* Make first Rx frame descriptor point to first Rx buffer - descriptor */ - outw(lp->rx_first + 6, ioaddr+WRITE_PTR); - outw(lp->rx_first + 0x16, ioaddr+DATAPORT); - - /* Close Rx frame descriptor ring */ - outw(lp->rx_last + 4, ioaddr+WRITE_PTR); - outw(lp->rx_first, ioaddr+DATAPORT); - - /* Close Rx buffer descriptor ring */ - outw(lp->rx_last + 0x16 + 2, ioaddr+WRITE_PTR); - outw(lp->rx_first + 0x16, ioaddr+DATAPORT); - -} - -/* - * Un-reset the 586, and start the configuration sequence. We don't wait for - * this to finish, but allow the interrupt handler to start the CU and RU for - * us. We can't start the receive/transmission system up before we know that - * the hardware is configured correctly. - */ - -static void eexp_hw_init586(struct net_device *dev) -{ - struct net_local *lp = netdev_priv(dev); - unsigned short ioaddr = dev->base_addr; - int i; - -#if NET_DEBUG > 6 - printk("%s: eexp_hw_init586()\n", dev->name); -#endif - - lp->started = 0; - - set_loopback(dev); - - outb(SIRQ_dis|irqrmap[dev->irq],ioaddr+SET_IRQ); - - /* Download the startup code */ - outw(lp->rx_buf_end & ~31, ioaddr + SM_PTR); - outw(lp->width?0x0001:0x0000, ioaddr + 0x8006); - outw(0x0000, ioaddr + 0x8008); - outw(0x0000, ioaddr + 0x800a); - outw(0x0000, ioaddr + 0x800c); - outw(0x0000, ioaddr + 0x800e); - - for (i = 0; i < ARRAY_SIZE(start_code) * 2; i+=32) { - int j; - outw(i, ioaddr + SM_PTR); - for (j = 0; j < 16 && (i+j)/2 < ARRAY_SIZE(start_code); j+=2) - outw(start_code[(i+j)/2], - ioaddr+0x4000+j); - for (j = 0; j < 16 && (i+j+16)/2 < ARRAY_SIZE(start_code); j+=2) - outw(start_code[(i+j+16)/2], - ioaddr+0x8000+j); - } - - /* Do we want promiscuous mode or multicast? */ - outw(CONF_PROMISC & ~31, ioaddr+SM_PTR); - i = inw(ioaddr+SHADOW(CONF_PROMISC)); - outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1), - ioaddr+SHADOW(CONF_PROMISC)); - lp->was_promisc = dev->flags & IFF_PROMISC; -#if 0 - eexp_setup_filter(dev); -#endif - - /* Write our hardware address */ - outw(CONF_HWADDR & ~31, ioaddr+SM_PTR); - outw(((unsigned short *)dev->dev_addr)[0], ioaddr+SHADOW(CONF_HWADDR)); - outw(((unsigned short *)dev->dev_addr)[1], - ioaddr+SHADOW(CONF_HWADDR+2)); - outw(((unsigned short *)dev->dev_addr)[2], - ioaddr+SHADOW(CONF_HWADDR+4)); - - eexp_hw_txinit(dev); - eexp_hw_rxinit(dev); - - outb(0,ioaddr+EEPROM_Ctrl); - mdelay(5); - - scb_command(dev, 0xf000); - outb(0,ioaddr+SIGNAL_CA); - - outw(0, ioaddr+SM_PTR); - - { - unsigned short rboguscount=50,rfailcount=5; - while (inw(ioaddr+0x4000)) - { - if (!--rboguscount) - { - printk(KERN_WARNING "%s: i82586 reset timed out, kicking...\n", - dev->name); - scb_command(dev, 0); - outb(0,ioaddr+SIGNAL_CA); - rboguscount = 100; - if (!--rfailcount) - { - printk(KERN_WARNING "%s: i82586 not responding, giving up.\n", - dev->name); - return; - } - } - } - } - - scb_wrcbl(dev, CONF_LINK); - scb_command(dev, 0xf000|SCB_CUstart); - outb(0,ioaddr+SIGNAL_CA); - - { - unsigned short iboguscount=50,ifailcount=5; - while (!scb_status(dev)) - { - if (!--iboguscount) - { - if (--ifailcount) - { - printk(KERN_WARNING "%s: i82586 initialization timed out, status %04x, cmd %04x\n", - dev->name, scb_status(dev), scb_rdcmd(dev)); - scb_wrcbl(dev, CONF_LINK); - scb_command(dev, 0xf000|SCB_CUstart); - outb(0,ioaddr+SIGNAL_CA); - iboguscount = 100; - } - else - { - printk(KERN_WARNING "%s: Failed to initialize i82586, giving up.\n",dev->name); - return; - } - } - } - } - - clear_loopback(dev); - outb(SIRQ_en|irqrmap[dev->irq],ioaddr+SET_IRQ); - - lp->init_time = jiffies; -#if NET_DEBUG > 6 - printk("%s: leaving eexp_hw_init586()\n", dev->name); -#endif -} - -static void eexp_setup_filter(struct net_device *dev) -{ - struct netdev_hw_addr *ha; - unsigned short ioaddr = dev->base_addr; - int count = netdev_mc_count(dev); - int i; - if (count > 8) { - printk(KERN_INFO "%s: too many multicast addresses (%d)\n", - dev->name, count); - count = 8; - } - - outw(CONF_NR_MULTICAST & ~31, ioaddr+SM_PTR); - outw(6*count, ioaddr+SHADOW(CONF_NR_MULTICAST)); - i = 0; - netdev_for_each_mc_addr(ha, dev) { - unsigned short *data = (unsigned short *) ha->addr; - - if (i == count) - break; - outw((CONF_MULTICAST+(6*i)) & ~31, ioaddr+SM_PTR); - outw(data[0], ioaddr+SHADOW(CONF_MULTICAST+(6*i))); - outw((CONF_MULTICAST+(6*i)+2) & ~31, ioaddr+SM_PTR); - outw(data[1], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+2)); - outw((CONF_MULTICAST+(6*i)+4) & ~31, ioaddr+SM_PTR); - outw(data[2], ioaddr+SHADOW(CONF_MULTICAST+(6*i)+4)); - i++; - } -} - -/* - * Set or clear the multicast filter for this adaptor. - */ -static void -eexp_set_multicast(struct net_device *dev) -{ - unsigned short ioaddr = dev->base_addr; - struct net_local *lp = netdev_priv(dev); - int kick = 0, i; - if ((dev->flags & IFF_PROMISC) != lp->was_promisc) { - outw(CONF_PROMISC & ~31, ioaddr+SM_PTR); - i = inw(ioaddr+SHADOW(CONF_PROMISC)); - outw((dev->flags & IFF_PROMISC)?(i|1):(i & ~1), - ioaddr+SHADOW(CONF_PROMISC)); - lp->was_promisc = dev->flags & IFF_PROMISC; - kick = 1; - } - if (!(dev->flags & IFF_PROMISC)) { - eexp_setup_filter(dev); - if (lp->old_mc_count != netdev_mc_count(dev)) { - kick = 1; - lp->old_mc_count = netdev_mc_count(dev); - } - } - if (kick) { - unsigned long oj; - scb_command(dev, SCB_CUsuspend); - outb(0, ioaddr+SIGNAL_CA); - outb(0, ioaddr+SIGNAL_CA); -#if 0 - printk("%s: waiting for CU to go suspended\n", dev->name); -#endif - oj = jiffies; - while ((SCB_CUstat(scb_status(dev)) == 2) && - (time_before(jiffies, oj + 2000))); - if (SCB_CUstat(scb_status(dev)) == 2) - printk("%s: warning, CU didn't stop\n", dev->name); - lp->started &= ~(STARTED_CU); - scb_wrcbl(dev, CONF_LINK); - scb_command(dev, SCB_CUstart); - outb(0, ioaddr+SIGNAL_CA); - } -} - - -/* - * MODULE stuff - */ - -#ifdef MODULE - -#define EEXP_MAX_CARDS 4 /* max number of cards to support */ - -static struct net_device *dev_eexp[EEXP_MAX_CARDS]; -static int irq[EEXP_MAX_CARDS]; -static int io[EEXP_MAX_CARDS]; - -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -MODULE_PARM_DESC(io, "EtherExpress 16 I/O base address(es)"); -MODULE_PARM_DESC(irq, "EtherExpress 16 IRQ number(s)"); -MODULE_LICENSE("GPL"); - - -/* Ideally the user would give us io=, irq= for every card. If any parameters - * are specified, we verify and then use them. If no parameters are given, we - * autoprobe for one card only. - */ -int __init init_module(void) -{ - struct net_device *dev; - int this_dev, found = 0; - - for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { - dev = alloc_etherdev(sizeof(struct net_local)); - dev->irq = irq[this_dev]; - dev->base_addr = io[this_dev]; - if (io[this_dev] == 0) { - if (this_dev) - break; - printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n"); - } - if (do_express_probe(dev) == 0) { - dev_eexp[this_dev] = dev; - found++; - continue; - } - printk(KERN_WARNING "eexpress.c: Failed to register card at 0x%x.\n", io[this_dev]); - free_netdev(dev); - break; - } - if (found) - return 0; - return -ENXIO; -} - -void __exit cleanup_module(void) -{ - int this_dev; - - for (this_dev = 0; this_dev < EEXP_MAX_CARDS; this_dev++) { - struct net_device *dev = dev_eexp[this_dev]; - if (dev) { - unregister_netdev(dev); - free_netdev(dev); - } - } -} -#endif - -/* - * Local Variables: - * c-file-style: "linux" - * tab-width: 8 - * End: - */ diff --git a/drivers/net/ethernet/i825xx/eexpress.h b/drivers/net/ethernet/i825xx/eexpress.h deleted file mode 100644 index dc9c6ea289e..00000000000 --- a/drivers/net/ethernet/i825xx/eexpress.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * eexpress.h: Intel EtherExpress16 defines - */ - -/* - * EtherExpress card register addresses - * as offsets from the base IO region (dev->base_addr) - */ - -#define DATAPORT 0x0000 -#define WRITE_PTR 0x0002 -#define READ_PTR 0x0004 -#define SIGNAL_CA 0x0006 -#define SET_IRQ 0x0007 -#define SM_PTR 0x0008 -#define MEM_Dec 0x000a -#define MEM_Ctrl 0x000b -#define MEM_Page_Ctrl 0x000c -#define Config 0x000d -#define EEPROM_Ctrl 0x000e -#define ID_PORT 0x000f -#define MEM_ECtrl 0x000f - -/* - * card register defines - */ - -/* SET_IRQ */ -#define SIRQ_en 0x08 -#define SIRQ_dis 0x00 - -/* EEPROM_Ctrl */ -#define EC_Clk 0x01 -#define EC_CS 0x02 -#define EC_Wr 0x04 -#define EC_Rd 0x08 -#define ASIC_RST 0x40 -#define i586_RST 0x80 - -#define eeprom_delay() { udelay(40); } - -/* - * i82586 Memory Configuration - */ - -/* (System Configuration Pointer) System start up block, read after 586_RST */ -#define SCP_START 0xfff6 - -/* Intermediate System Configuration Pointer */ -#define ISCP_START 0x0000 - -/* System Command Block */ -#define SCB_START 0x0008 - -/* Start of buffer region. Everything before this is used for control - * structures and the CU configuration program. The memory layout is - * determined in eexp_hw_probe(), once we know how much memory is - * available on the card. - */ - -#define TX_BUF_START 0x0100 - -#define TX_BUF_SIZE ((24+ETH_FRAME_LEN+31)&~0x1f) -#define RX_BUF_SIZE ((32+ETH_FRAME_LEN+31)&~0x1f) - -/* - * SCB defines - */ - -/* these functions take the SCB status word and test the relevant status bit */ -#define SCB_complete(s) (((s) & 0x8000) != 0) -#define SCB_rxdframe(s) (((s) & 0x4000) != 0) -#define SCB_CUdead(s) (((s) & 0x2000) != 0) -#define SCB_RUdead(s) (((s) & 0x1000) != 0) -#define SCB_ack(s) ((s) & 0xf000) - -/* Command unit status: 0=idle, 1=suspended, 2=active */ -#define SCB_CUstat(s) (((s)&0x0300)>>8) - -/* Receive unit status: 0=idle, 1=suspended, 2=out of resources, 4=ready */ -#define SCB_RUstat(s) (((s)&0x0070)>>4) - -/* SCB commands */ -#define SCB_CUnop 0x0000 -#define SCB_CUstart 0x0100 -#define SCB_CUresume 0x0200 -#define SCB_CUsuspend 0x0300 -#define SCB_CUabort 0x0400 -#define SCB_resetchip 0x0080 - -#define SCB_RUnop 0x0000 -#define SCB_RUstart 0x0010 -#define SCB_RUresume 0x0020 -#define SCB_RUsuspend 0x0030 -#define SCB_RUabort 0x0040 - -/* - * Command block defines - */ - -#define Stat_Done(s) (((s) & 0x8000) != 0) -#define Stat_Busy(s) (((s) & 0x4000) != 0) -#define Stat_OK(s) (((s) & 0x2000) != 0) -#define Stat_Abort(s) (((s) & 0x1000) != 0) -#define Stat_STFail (((s) & 0x0800) != 0) -#define Stat_TNoCar(s) (((s) & 0x0400) != 0) -#define Stat_TNoCTS(s) (((s) & 0x0200) != 0) -#define Stat_TNoDMA(s) (((s) & 0x0100) != 0) -#define Stat_TDefer(s) (((s) & 0x0080) != 0) -#define Stat_TColl(s) (((s) & 0x0040) != 0) -#define Stat_TXColl(s) (((s) & 0x0020) != 0) -#define Stat_NoColl(s) ((s) & 0x000f) - -/* Cmd_END will end AFTER the command if this is the first - * command block after an SCB_CUstart, but BEFORE the command - * for all subsequent commands. Best strategy is to place - * Cmd_INT on the last command in the sequence, followed by a - * dummy Cmd_Nop with Cmd_END after this. - */ - -#define Cmd_END 0x8000 -#define Cmd_SUS 0x4000 -#define Cmd_INT 0x2000 - -#define Cmd_Nop 0x0000 -#define Cmd_SetAddr 0x0001 -#define Cmd_Config 0x0002 -#define Cmd_MCast 0x0003 -#define Cmd_Xmit 0x0004 -#define Cmd_TDR 0x0005 -#define Cmd_Dump 0x0006 -#define Cmd_Diag 0x0007 - - -/* - * Frame Descriptor (Receive block) defines - */ - -#define FD_Done(s) (((s) & 0x8000) != 0) -#define FD_Busy(s) (((s) & 0x4000) != 0) -#define FD_OK(s) (((s) & 0x2000) != 0) - -#define FD_CRC(s) (((s) & 0x0800) != 0) -#define FD_Align(s) (((s) & 0x0400) != 0) -#define FD_Resrc(s) (((s) & 0x0200) != 0) -#define FD_DMA(s) (((s) & 0x0100) != 0) -#define FD_Short(s) (((s) & 0x0080) != 0) -#define FD_NoEOF(s) (((s) & 0x0040) != 0) - -struct rfd_header { - volatile unsigned long flags; - volatile unsigned short link; - volatile unsigned short rbd_offset; - volatile unsigned short dstaddr1; - volatile unsigned short dstaddr2; - volatile unsigned short dstaddr3; - volatile unsigned short srcaddr1; - volatile unsigned short srcaddr2; - volatile unsigned short srcaddr3; - volatile unsigned short length; - - /* This is actually a Receive Buffer Descriptor. The way we - * arrange memory means that an RBD always follows the RFD that - * points to it, so they might as well be in the same structure. - */ - volatile unsigned short actual_count; - volatile unsigned short next_rbd; - volatile unsigned short buf_addr1; - volatile unsigned short buf_addr2; - volatile unsigned short size; -}; - -/* Returned data from the Time Domain Reflectometer */ - -#define TDR_LINKOK (1<<15) -#define TDR_XCVRPROBLEM (1<<14) -#define TDR_OPEN (1<<13) -#define TDR_SHORT (1<<12) -#define TDR_TIME 0x7ff -- cgit v1.2.3-70-g09d2 From 8a594170de2232194134d5965df92f4316a97abc Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 10 Jan 2013 18:09:44 -0500 Subject: drivers/net: delete intel i825xx based znet notebook driver This driver supported early to mid 1990's Zenith laptops, of the 2" thick variety. The driver was already dead 10+ years ago, but we see this in the source: ---------------- /* 10/2002 [...] Tested on a vintage Zenith Z-Note 433Lnp+. Probably broken on anything else. Testers (and detailed bug reports) are welcome :-). ---------------- To clarify, a 433 translates into a 486 at 33MHz, and a system with a default of 4MB RAM. I can't fault the noble effort to keep things working a decade ago, but at this point in time, there is no valid justification to continue carrying this driver along. Note that there is no associated Space.c cleanup here since this driver was using module_init to hook itself in. Signed-off-by: Paul Gortmaker --- drivers/net/ethernet/i825xx/Kconfig | 10 - drivers/net/ethernet/i825xx/Makefile | 1 - drivers/net/ethernet/i825xx/znet.c | 928 ----------------------------------- 3 files changed, 939 deletions(-) delete mode 100644 drivers/net/ethernet/i825xx/znet.c (limited to 'drivers/net/ethernet/i825xx/Makefile') diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig index 16b14a93c20..c3cfa576cde 100644 --- a/drivers/net/ethernet/i825xx/Kconfig +++ b/drivers/net/ethernet/i825xx/Kconfig @@ -79,14 +79,4 @@ config SUN3_82586 that this driver does not support 82586-based adapters on additional VME boards. -config ZNET - tristate "Zenith Z-Note support (EXPERIMENTAL)" - depends on EXPERIMENTAL && ISA_DMA_API && X86 - ---help--- - The Zenith Z-Note notebook computer has a built-in network - (Ethernet) card, and this is the Linux driver for it. Note that the - IBM Thinkpad 300 is compatible with the Z-Note and is also supported - by this driver. Read the Ethernet-HOWTO, available from - . - endif # NET_VENDOR_I825XX diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile index 4267ae72c5d..df9e2ecdc63 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_ARM_ETHER1) += ether1.o obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o -obj-$(CONFIG_ZNET) += znet.o obj-$(CONFIG_LASI_82596) += lasi_82596.o obj-$(CONFIG_SNI_82596) += sni_82596.o obj-$(CONFIG_MVME16x_NET) += 82596.o diff --git a/drivers/net/ethernet/i825xx/znet.c b/drivers/net/ethernet/i825xx/znet.c deleted file mode 100644 index c9479e081b8..00000000000 --- a/drivers/net/ethernet/i825xx/znet.c +++ /dev/null @@ -1,928 +0,0 @@ -/* znet.c: An Zenith Z-Note ethernet driver for linux. */ - -/* - Written by Donald Becker. - - The author may be reached as becker@scyld.com. - This driver is based on the Linux skeleton driver. The copyright of the - skeleton driver is held by the United States Government, as represented - by DIRNSA, and it is released under the GPL. - - Thanks to Mike Hollick for alpha testing and suggestions. - - References: - The Crynwr packet driver. - - "82593 CSMA/CD Core LAN Controller" Intel datasheet, 1992 - Intel Microcommunications Databook, Vol. 1, 1990. - As usual with Intel, the documentation is incomplete and inaccurate. - I had to read the Crynwr packet driver to figure out how to actually - use the i82593, and guess at what register bits matched the loosely - related i82586. - - Theory of Operation - - The i82593 used in the Zenith Z-Note series operates using two(!) slave - DMA channels, one interrupt, and one 8-bit I/O port. - - While there several ways to configure '593 DMA system, I chose the one - that seemed commensurate with the highest system performance in the face - of moderate interrupt latency: Both DMA channels are configured as - recirculating ring buffers, with one channel (#0) dedicated to Rx and - the other channel (#1) to Tx and configuration. (Note that this is - different than the Crynwr driver, where the Tx DMA channel is initialized - before each operation. That approach simplifies operation and Tx error - recovery, but requires additional I/O in normal operation and precludes - transmit buffer chaining.) - - Both rings are set to 8192 bytes using {TX,RX}_RING_SIZE. This provides - a reasonable ring size for Rx, while simplifying DMA buffer allocation -- - DMA buffers must not cross a 128K boundary. (In truth the size selection - was influenced by my lack of '593 documentation. I thus was constrained - to use the Crynwr '593 initialization table, which sets the Rx ring size - to 8K.) - - Despite my usual low opinion about Intel-designed parts, I must admit - that the bulk data handling of the i82593 is a good design for - an integrated system, like a laptop, where using two slave DMA channels - doesn't pose a problem. I still take issue with using only a single I/O - port. In the same controlled environment there are essentially no - limitations on I/O space, and using multiple locations would eliminate - the need for multiple operations when looking at status registers, - setting the Rx ring boundary, or switching to promiscuous mode. - - I also question Zenith's selection of the '593: one of the advertised - advantages of earlier Intel parts was that if you figured out the magic - initialization incantation you could use the same part on many different - network types. Zenith's use of the "FriendlyNet" (sic) connector rather - than an on-board transceiver leads me to believe that they were planning - to take advantage of this. But, uhmmm, the '593 omits all but ethernet - functionality from the serial subsystem. - */ - -/* 10/2002 - - o Resurected for Linux 2.5+ by Marc Zyngier : - - - Removed strange DMA snooping in znet_sent_packet, which lead to - TX buffer corruption on my laptop. - - Use init_etherdev stuff. - - Use kmalloc-ed DMA buffers. - - Use as few global variables as possible. - - Use proper resources management. - - Use wireless/i82593.h as much as possible (structure, constants) - - Compiles as module or build-in. - - Now survives unplugging/replugging cable. - - Some code was taken from wavelan_cs. - - Tested on a vintage Zenith Z-Note 433Lnp+. Probably broken on - anything else. Testers (and detailed bug reports) are welcome :-). - - o TODO : - - - Properly handle multicast - - Understand why some traffic patterns add a 1s latency... - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -static char version[] __initdata = "znet.c:v1.02 9/23/94 becker@scyld.com\n"; - -#ifndef ZNET_DEBUG -#define ZNET_DEBUG 1 -#endif -static unsigned int znet_debug = ZNET_DEBUG; -module_param (znet_debug, int, 0); -MODULE_PARM_DESC (znet_debug, "ZNet debug level"); -MODULE_LICENSE("GPL"); - -/* The DMA modes we need aren't in . */ -#define DMA_RX_MODE 0x14 /* Auto init, I/O to mem, ++, demand. */ -#define DMA_TX_MODE 0x18 /* Auto init, Mem to I/O, ++, demand. */ -#define dma_page_eq(ptr1, ptr2) ((long)(ptr1)>>17 == (long)(ptr2)>>17) -#define RX_BUF_SIZE 8192 -#define TX_BUF_SIZE 8192 -#define DMA_BUF_SIZE (RX_BUF_SIZE + 16) /* 8k + 16 bytes for trailers */ - -#define TX_TIMEOUT (HZ/10) - -struct znet_private { - int rx_dma, tx_dma; - spinlock_t lock; - short sia_base, sia_size, io_size; - struct i82593_conf_block i593_init; - /* The starting, current, and end pointers for the packet buffers. */ - ushort *rx_start, *rx_cur, *rx_end; - ushort *tx_start, *tx_cur, *tx_end; - ushort tx_buf_len; /* Tx buffer length, in words. */ -}; - -/* Only one can be built-in;-> */ -static struct net_device *znet_dev; - -#define NETIDBLK_MAGIC "NETIDBLK" -#define NETIDBLK_MAGIC_SIZE 8 - -struct netidblk { - char magic[NETIDBLK_MAGIC_SIZE]; /* The magic number (string) "NETIDBLK" */ - unsigned char netid[8]; /* The physical station address */ - char nettype, globalopt; - char vendor[8]; /* The machine vendor and product name. */ - char product[8]; - char irq1, irq2; /* Interrupts, only one is currently used. */ - char dma1, dma2; - short dma_mem_misc[8]; /* DMA buffer locations (unused in Linux). */ - short iobase1, iosize1; - short iobase2, iosize2; /* Second iobase unused. */ - char driver_options; /* Misc. bits */ - char pad; -}; - -static int znet_open(struct net_device *dev); -static netdev_tx_t znet_send_packet(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t znet_interrupt(int irq, void *dev_id); -static void znet_rx(struct net_device *dev); -static int znet_close(struct net_device *dev); -static void hardware_init(struct net_device *dev); -static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset); -static void znet_tx_timeout (struct net_device *dev); - -/* Request needed resources */ -static int znet_request_resources (struct net_device *dev) -{ - struct znet_private *znet = netdev_priv(dev); - - if (request_irq (dev->irq, znet_interrupt, 0, "ZNet", dev)) - goto failed; - if (request_dma (znet->rx_dma, "ZNet rx")) - goto free_irq; - if (request_dma (znet->tx_dma, "ZNet tx")) - goto free_rx_dma; - if (!request_region (znet->sia_base, znet->sia_size, "ZNet SIA")) - goto free_tx_dma; - if (!request_region (dev->base_addr, znet->io_size, "ZNet I/O")) - goto free_sia; - - return 0; /* Happy ! */ - - free_sia: - release_region (znet->sia_base, znet->sia_size); - free_tx_dma: - free_dma (znet->tx_dma); - free_rx_dma: - free_dma (znet->rx_dma); - free_irq: - free_irq (dev->irq, dev); - failed: - return -1; -} - -static void znet_release_resources (struct net_device *dev) -{ - struct znet_private *znet = netdev_priv(dev); - - release_region (znet->sia_base, znet->sia_size); - release_region (dev->base_addr, znet->io_size); - free_dma (znet->tx_dma); - free_dma (znet->rx_dma); - free_irq (dev->irq, dev); -} - -/* Keep the magical SIA stuff in a single function... */ -static void znet_transceiver_power (struct net_device *dev, int on) -{ - struct znet_private *znet = netdev_priv(dev); - unsigned char v; - - /* Turn on/off the 82501 SIA, using zenith-specific magic. */ - /* Select LAN control register */ - outb(0x10, znet->sia_base); - - if (on) - v = inb(znet->sia_base + 1) | 0x84; - else - v = inb(znet->sia_base + 1) & ~0x84; - - outb(v, znet->sia_base+1); /* Turn on/off LAN power (bit 2). */ -} - -/* Init the i82593, with current promisc/mcast configuration. - Also used from hardware_init. */ -static void znet_set_multicast_list (struct net_device *dev) -{ - struct znet_private *znet = netdev_priv(dev); - short ioaddr = dev->base_addr; - struct i82593_conf_block *cfblk = &znet->i593_init; - - memset(cfblk, 0x00, sizeof(struct i82593_conf_block)); - - /* The configuration block. What an undocumented nightmare. - The first set of values are those suggested (without explanation) - for ethernet in the Intel 82586 databook. The rest appear to be - completely undocumented, except for cryptic notes in the Crynwr - packet driver. This driver uses the Crynwr values verbatim. */ - - /* maz : Rewritten to take advantage of the wanvelan includes. - At least we have names, not just blind values */ - - /* Byte 0 */ - cfblk->fifo_limit = 10; /* = 16 B rx and 80 B tx fifo thresholds */ - cfblk->forgnesi = 0; /* 0=82C501, 1=AMD7992B compatibility */ - cfblk->fifo_32 = 1; - cfblk->d6mod = 0; /* Run in i82593 advanced mode */ - cfblk->throttle_enb = 1; - - /* Byte 1 */ - cfblk->throttle = 8; /* Continuous w/interrupts, 128-clock DMA. */ - cfblk->cntrxint = 0; /* enable continuous mode receive interrupts */ - cfblk->contin = 1; /* enable continuous mode */ - - /* Byte 2 */ - cfblk->addr_len = ETH_ALEN; - cfblk->acloc = 1; /* Disable source addr insertion by i82593 */ - cfblk->preamb_len = 2; /* 8 bytes preamble */ - cfblk->loopback = 0; /* Loopback off */ - - /* Byte 3 */ - cfblk->lin_prio = 0; /* Default priorities & backoff methods. */ - cfblk->tbofstop = 0; - cfblk->exp_prio = 0; - cfblk->bof_met = 0; - - /* Byte 4 */ - cfblk->ifrm_spc = 6; /* 96 bit times interframe spacing */ - - /* Byte 5 */ - cfblk->slottim_low = 0; /* 512 bit times slot time (low) */ - - /* Byte 6 */ - cfblk->slottim_hi = 2; /* 512 bit times slot time (high) */ - cfblk->max_retr = 15; /* 15 collisions retries */ - - /* Byte 7 */ - cfblk->prmisc = ((dev->flags & IFF_PROMISC) ? 1 : 0); /* Promiscuous mode */ - cfblk->bc_dis = 0; /* Enable broadcast reception */ - cfblk->crs_1 = 0; /* Don't transmit without carrier sense */ - cfblk->nocrc_ins = 0; /* i82593 generates CRC */ - cfblk->crc_1632 = 0; /* 32-bit Autodin-II CRC */ - cfblk->crs_cdt = 0; /* CD not to be interpreted as CS */ - - /* Byte 8 */ - cfblk->cs_filter = 0; /* CS is recognized immediately */ - cfblk->crs_src = 0; /* External carrier sense */ - cfblk->cd_filter = 0; /* CD is recognized immediately */ - - /* Byte 9 */ - cfblk->min_fr_len = ETH_ZLEN >> 2; /* Minimum frame length */ - - /* Byte A */ - cfblk->lng_typ = 1; /* Type/length checks OFF */ - cfblk->lng_fld = 1; /* Disable 802.3 length field check */ - cfblk->rxcrc_xf = 1; /* Don't transfer CRC to memory */ - cfblk->artx = 1; /* Disable automatic retransmission */ - cfblk->sarec = 1; /* Disable source addr trig of CD */ - cfblk->tx_jabber = 0; /* Disable jabber jam sequence */ - cfblk->hash_1 = 1; /* Use bits 0-5 in mc address hash */ - cfblk->lbpkpol = 0; /* Loopback pin active high */ - - /* Byte B */ - cfblk->fdx = 0; /* Disable full duplex operation */ - - /* Byte C */ - cfblk->dummy_6 = 0x3f; /* all ones, Default multicast addresses & backoff. */ - cfblk->mult_ia = 0; /* No multiple individual addresses */ - cfblk->dis_bof = 0; /* Disable the backoff algorithm ?! */ - - /* Byte D */ - cfblk->dummy_1 = 1; /* set to 1 */ - cfblk->tx_ifs_retrig = 3; /* Hmm... Disabled */ - cfblk->mc_all = (!netdev_mc_empty(dev) || - (dev->flags & IFF_ALLMULTI)); /* multicast all mode */ - cfblk->rcv_mon = 0; /* Monitor mode disabled */ - cfblk->frag_acpt = 0; /* Do not accept fragments */ - cfblk->tstrttrs = 0; /* No start transmission threshold */ - - /* Byte E */ - cfblk->fretx = 1; /* FIFO automatic retransmission */ - cfblk->runt_eop = 0; /* drop "runt" packets */ - cfblk->hw_sw_pin = 0; /* ?? */ - cfblk->big_endn = 0; /* Big Endian ? no... */ - cfblk->syncrqs = 1; /* Synchronous DRQ deassertion... */ - cfblk->sttlen = 1; /* 6 byte status registers */ - cfblk->rx_eop = 0; /* Signal EOP on packet reception */ - cfblk->tx_eop = 0; /* Signal EOP on packet transmission */ - - /* Byte F */ - cfblk->rbuf_size = RX_BUF_SIZE >> 12; /* Set receive buffer size */ - cfblk->rcvstop = 1; /* Enable Receive Stop Register */ - - if (znet_debug > 2) { - int i; - unsigned char *c; - - for (i = 0, c = (char *) cfblk; i < sizeof (*cfblk); i++) - printk ("%02X ", c[i]); - printk ("\n"); - } - - *znet->tx_cur++ = sizeof(struct i82593_conf_block); - memcpy(znet->tx_cur, cfblk, sizeof(struct i82593_conf_block)); - znet->tx_cur += sizeof(struct i82593_conf_block)/2; - outb(OP0_CONFIGURE | CR0_CHNL, ioaddr); - - /* XXX FIXME maz : Add multicast addresses here, so having a - * multicast address configured isn't equal to IFF_ALLMULTI */ -} - -static const struct net_device_ops znet_netdev_ops = { - .ndo_open = znet_open, - .ndo_stop = znet_close, - .ndo_start_xmit = znet_send_packet, - .ndo_set_rx_mode = znet_set_multicast_list, - .ndo_tx_timeout = znet_tx_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/* The Z-Note probe is pretty easy. The NETIDBLK exists in the safe-to-probe - BIOS area. We just scan for the signature, and pull the vital parameters - out of the structure. */ - -static int __init znet_probe (void) -{ - int i; - struct netidblk *netinfo; - struct znet_private *znet; - struct net_device *dev; - char *p; - char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE); - int err = -ENOMEM; - - /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */ - for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++) - if (*p == 'N' && - strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0) - break; - - if (p > plast) { - if (znet_debug > 1) - printk(KERN_INFO "No Z-Note ethernet adaptor found.\n"); - return -ENODEV; - } - - dev = alloc_etherdev(sizeof(struct znet_private)); - if (!dev) - return -ENOMEM; - - znet = netdev_priv(dev); - - netinfo = (struct netidblk *)p; - dev->base_addr = netinfo->iobase1; - dev->irq = netinfo->irq1; - - /* The station address is in the "netidblk" at 0x0f0000. */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = netinfo->netid[i]; - - printk(KERN_INFO "%s: ZNET at %#3lx, %pM" - ", using IRQ %d DMA %d and %d.\n", - dev->name, dev->base_addr, dev->dev_addr, - dev->irq, netinfo->dma1, netinfo->dma2); - - if (znet_debug > 1) { - printk(KERN_INFO "%s: vendor '%16.16s' IRQ1 %d IRQ2 %d DMA1 %d DMA2 %d.\n", - dev->name, netinfo->vendor, - netinfo->irq1, netinfo->irq2, - netinfo->dma1, netinfo->dma2); - printk(KERN_INFO "%s: iobase1 %#x size %d iobase2 %#x size %d net type %2.2x.\n", - dev->name, netinfo->iobase1, netinfo->iosize1, - netinfo->iobase2, netinfo->iosize2, netinfo->nettype); - } - - if (znet_debug > 0) - printk(KERN_INFO "%s", version); - - znet->rx_dma = netinfo->dma1; - znet->tx_dma = netinfo->dma2; - spin_lock_init(&znet->lock); - znet->sia_base = 0xe6; /* Magic address for the 82501 SIA */ - znet->sia_size = 2; - /* maz: Despite the '593 being advertised above as using a - * single 8bits I/O port, this driver does many 16bits - * access. So set io_size accordingly */ - znet->io_size = 2; - - if (!(znet->rx_start = kmalloc (DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA))) - goto free_dev; - if (!(znet->tx_start = kmalloc (DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA))) - goto free_rx; - - if (!dma_page_eq (znet->rx_start, znet->rx_start + (RX_BUF_SIZE/2-1)) || - !dma_page_eq (znet->tx_start, znet->tx_start + (TX_BUF_SIZE/2-1))) { - printk (KERN_WARNING "tx/rx crossing DMA frontiers, giving up\n"); - goto free_tx; - } - - znet->rx_end = znet->rx_start + RX_BUF_SIZE/2; - znet->tx_buf_len = TX_BUF_SIZE/2; - znet->tx_end = znet->tx_start + znet->tx_buf_len; - - /* The ZNET-specific entries in the device structure. */ - dev->netdev_ops = &znet_netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; - err = register_netdev(dev); - if (err) - goto free_tx; - znet_dev = dev; - return 0; - - free_tx: - kfree(znet->tx_start); - free_rx: - kfree(znet->rx_start); - free_dev: - free_netdev(dev); - return err; -} - - -static int znet_open(struct net_device *dev) -{ - int ioaddr = dev->base_addr; - - if (znet_debug > 2) - printk(KERN_DEBUG "%s: znet_open() called.\n", dev->name); - - /* These should never fail. You can't add devices to a sealed box! */ - if (znet_request_resources (dev)) { - printk(KERN_WARNING "%s: Not opened -- resource busy?!?\n", dev->name); - return -EBUSY; - } - - znet_transceiver_power (dev, 1); - - /* According to the Crynwr driver we should wait 50 msec. for the - LAN clock to stabilize. My experiments indicates that the '593 can - be initialized immediately. The delay is probably needed for the - DC-to-DC converter to come up to full voltage, and for the oscillator - to be spot-on at 20Mhz before transmitting. - Until this proves to be a problem we rely on the higher layers for the - delay and save allocating a timer entry. */ - - /* maz : Well, I'm getting every time the following message - * without the delay on a 486@33. This machine is much too - * fast... :-) So maybe the Crynwr driver wasn't wrong after - * all, even if the message is completly harmless on my - * setup. */ - mdelay (50); - - /* This follows the packet driver's lead, and checks for success. */ - if (inb(ioaddr) != 0x10 && inb(ioaddr) != 0x00) - printk(KERN_WARNING "%s: Problem turning on the transceiver power.\n", - dev->name); - - hardware_init(dev); - netif_start_queue (dev); - - return 0; -} - - -static void znet_tx_timeout (struct net_device *dev) -{ - int ioaddr = dev->base_addr; - ushort event, tx_status, rx_offset, state; - - outb (CR0_STATUS_0, ioaddr); - event = inb (ioaddr); - outb (CR0_STATUS_1, ioaddr); - tx_status = inw (ioaddr); - outb (CR0_STATUS_2, ioaddr); - rx_offset = inw (ioaddr); - outb (CR0_STATUS_3, ioaddr); - state = inb (ioaddr); - printk (KERN_WARNING "%s: transmit timed out, status %02x %04x %04x %02x," - " resetting.\n", dev->name, event, tx_status, rx_offset, state); - if (tx_status == TX_LOST_CRS) - printk (KERN_WARNING "%s: Tx carrier error, check transceiver cable.\n", - dev->name); - outb (OP0_RESET, ioaddr); - hardware_init (dev); - netif_wake_queue (dev); -} - -static netdev_tx_t znet_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - int ioaddr = dev->base_addr; - struct znet_private *znet = netdev_priv(dev); - unsigned long flags; - short length = skb->len; - - if (znet_debug > 4) - printk(KERN_DEBUG "%s: ZNet_send_packet.\n", dev->name); - - if (length < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - length = ETH_ZLEN; - } - - netif_stop_queue (dev); - - /* Check that the part hasn't reset itself, probably from suspend. */ - outb(CR0_STATUS_0, ioaddr); - if (inw(ioaddr) == 0x0010 && - inw(ioaddr) == 0x0000 && - inw(ioaddr) == 0x0010) { - if (znet_debug > 1) - printk (KERN_WARNING "%s : waking up\n", dev->name); - hardware_init(dev); - znet_transceiver_power (dev, 1); - } - - if (1) { - unsigned char *buf = (void *)skb->data; - ushort *tx_link = znet->tx_cur - 1; - ushort rnd_len = (length + 1)>>1; - - dev->stats.tx_bytes+=length; - - if (znet->tx_cur >= znet->tx_end) - znet->tx_cur = znet->tx_start; - *znet->tx_cur++ = length; - if (znet->tx_cur + rnd_len + 1 > znet->tx_end) { - int semi_cnt = (znet->tx_end - znet->tx_cur)<<1; /* Cvrt to byte cnt. */ - memcpy(znet->tx_cur, buf, semi_cnt); - rnd_len -= semi_cnt>>1; - memcpy(znet->tx_start, buf + semi_cnt, length - semi_cnt); - znet->tx_cur = znet->tx_start + rnd_len; - } else { - memcpy(znet->tx_cur, buf, skb->len); - znet->tx_cur += rnd_len; - } - *znet->tx_cur++ = 0; - - spin_lock_irqsave(&znet->lock, flags); - { - *tx_link = OP0_TRANSMIT | CR0_CHNL; - /* Is this always safe to do? */ - outb(OP0_TRANSMIT | CR0_CHNL, ioaddr); - } - spin_unlock_irqrestore (&znet->lock, flags); - - netif_start_queue (dev); - - if (znet_debug > 4) - printk(KERN_DEBUG "%s: Transmitter queued, length %d.\n", dev->name, length); - } - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -/* The ZNET interrupt handler. */ -static irqreturn_t znet_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct znet_private *znet = netdev_priv(dev); - int ioaddr; - int boguscnt = 20; - int handled = 0; - - spin_lock (&znet->lock); - - ioaddr = dev->base_addr; - - outb(CR0_STATUS_0, ioaddr); - do { - ushort status = inb(ioaddr); - if (znet_debug > 5) { - ushort result, rx_ptr, running; - outb(CR0_STATUS_1, ioaddr); - result = inw(ioaddr); - outb(CR0_STATUS_2, ioaddr); - rx_ptr = inw(ioaddr); - outb(CR0_STATUS_3, ioaddr); - running = inb(ioaddr); - printk(KERN_DEBUG "%s: interrupt, status %02x, %04x %04x %02x serial %d.\n", - dev->name, status, result, rx_ptr, running, boguscnt); - } - if ((status & SR0_INTERRUPT) == 0) - break; - - handled = 1; - - if ((status & SR0_EVENT_MASK) == SR0_TRANSMIT_DONE || - (status & SR0_EVENT_MASK) == SR0_RETRANSMIT_DONE || - (status & SR0_EVENT_MASK) == SR0_TRANSMIT_NO_CRC_DONE) { - int tx_status; - outb(CR0_STATUS_1, ioaddr); - tx_status = inw(ioaddr); - /* It's undocumented, but tx_status seems to match the i82586. */ - if (tx_status & TX_OK) { - dev->stats.tx_packets++; - dev->stats.collisions += tx_status & TX_NCOL_MASK; - } else { - if (tx_status & (TX_LOST_CTS | TX_LOST_CRS)) - dev->stats.tx_carrier_errors++; - if (tx_status & TX_UND_RUN) - dev->stats.tx_fifo_errors++; - if (!(tx_status & TX_HRT_BEAT)) - dev->stats.tx_heartbeat_errors++; - if (tx_status & TX_MAX_COL) - dev->stats.tx_aborted_errors++; - /* ...and the catch-all. */ - if ((tx_status | (TX_LOST_CRS | TX_LOST_CTS | TX_UND_RUN | TX_HRT_BEAT | TX_MAX_COL)) != (TX_LOST_CRS | TX_LOST_CTS | TX_UND_RUN | TX_HRT_BEAT | TX_MAX_COL)) - dev->stats.tx_errors++; - - /* Transceiver may be stuck if cable - * was removed while emitting a - * packet. Flip it off, then on to - * reset it. This is very empirical, - * but it seems to work. */ - - znet_transceiver_power (dev, 0); - znet_transceiver_power (dev, 1); - } - netif_wake_queue (dev); - } - - if ((status & SR0_RECEPTION) || - (status & SR0_EVENT_MASK) == SR0_STOP_REG_HIT) { - znet_rx(dev); - } - /* Clear the interrupts we've handled. */ - outb(CR0_INT_ACK, ioaddr); - } while (boguscnt--); - - spin_unlock (&znet->lock); - - return IRQ_RETVAL(handled); -} - -static void znet_rx(struct net_device *dev) -{ - struct znet_private *znet = netdev_priv(dev); - int ioaddr = dev->base_addr; - int boguscount = 1; - short next_frame_end_offset = 0; /* Offset of next frame start. */ - short *cur_frame_end; - short cur_frame_end_offset; - - outb(CR0_STATUS_2, ioaddr); - cur_frame_end_offset = inw(ioaddr); - - if (cur_frame_end_offset == znet->rx_cur - znet->rx_start) { - printk(KERN_WARNING "%s: Interrupted, but nothing to receive, offset %03x.\n", - dev->name, cur_frame_end_offset); - return; - } - - /* Use same method as the Crynwr driver: construct a forward list in - the same area of the backwards links we now have. This allows us to - pass packets to the upper layers in the order they were received -- - important for fast-path sequential operations. */ - while (znet->rx_start + cur_frame_end_offset != znet->rx_cur && - ++boguscount < 5) { - unsigned short hi_cnt, lo_cnt, hi_status, lo_status; - int count, status; - - if (cur_frame_end_offset < 4) { - /* Oh no, we have a special case: the frame trailer wraps around - the end of the ring buffer. We've saved space at the end of - the ring buffer for just this problem. */ - memcpy(znet->rx_end, znet->rx_start, 8); - cur_frame_end_offset += (RX_BUF_SIZE/2); - } - cur_frame_end = znet->rx_start + cur_frame_end_offset - 4; - - lo_status = *cur_frame_end++; - hi_status = *cur_frame_end++; - status = ((hi_status & 0xff) << 8) + (lo_status & 0xff); - lo_cnt = *cur_frame_end++; - hi_cnt = *cur_frame_end++; - count = ((hi_cnt & 0xff) << 8) + (lo_cnt & 0xff); - - if (znet_debug > 5) - printk(KERN_DEBUG "Constructing trailer at location %03x, %04x %04x %04x %04x" - " count %#x status %04x.\n", - cur_frame_end_offset<<1, lo_status, hi_status, lo_cnt, hi_cnt, - count, status); - cur_frame_end[-4] = status; - cur_frame_end[-3] = next_frame_end_offset; - cur_frame_end[-2] = count; - next_frame_end_offset = cur_frame_end_offset; - cur_frame_end_offset -= ((count + 1)>>1) + 3; - if (cur_frame_end_offset < 0) - cur_frame_end_offset += RX_BUF_SIZE/2; - } - - /* Now step forward through the list. */ - do { - ushort *this_rfp_ptr = znet->rx_start + next_frame_end_offset; - int status = this_rfp_ptr[-4]; - int pkt_len = this_rfp_ptr[-2]; - - if (znet_debug > 5) - printk(KERN_DEBUG "Looking at trailer ending at %04x status %04x length %03x" - " next %04x.\n", next_frame_end_offset<<1, status, pkt_len, - this_rfp_ptr[-3]<<1); - /* Once again we must assume that the i82586 docs apply. */ - if ( ! (status & RX_RCV_OK)) { /* There was an error. */ - dev->stats.rx_errors++; - if (status & RX_CRC_ERR) dev->stats.rx_crc_errors++; - if (status & RX_ALG_ERR) dev->stats.rx_frame_errors++; -#if 0 - if (status & 0x0200) dev->stats.rx_over_errors++; /* Wrong. */ - if (status & 0x0100) dev->stats.rx_fifo_errors++; -#else - /* maz : Wild guess... */ - if (status & RX_OVRRUN) dev->stats.rx_over_errors++; -#endif - if (status & RX_SRT_FRM) dev->stats.rx_length_errors++; - } else if (pkt_len > 1536) { - dev->stats.rx_length_errors++; - } else { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - skb = netdev_alloc_skb(dev, pkt_len); - if (skb == NULL) { - if (znet_debug) - printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); - dev->stats.rx_dropped++; - break; - } - - if (&znet->rx_cur[(pkt_len+1)>>1] > znet->rx_end) { - int semi_cnt = (znet->rx_end - znet->rx_cur)<<1; - memcpy(skb_put(skb,semi_cnt), znet->rx_cur, semi_cnt); - memcpy(skb_put(skb,pkt_len-semi_cnt), znet->rx_start, - pkt_len - semi_cnt); - } else { - memcpy(skb_put(skb,pkt_len), znet->rx_cur, pkt_len); - if (znet_debug > 6) { - unsigned int *packet = (unsigned int *) skb->data; - printk(KERN_DEBUG "Packet data is %08x %08x %08x %08x.\n", packet[0], - packet[1], packet[2], packet[3]); - } - } - skb->protocol=eth_type_trans(skb,dev); - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - } - znet->rx_cur = this_rfp_ptr; - if (znet->rx_cur >= znet->rx_end) - znet->rx_cur -= RX_BUF_SIZE/2; - update_stop_hit(ioaddr, (znet->rx_cur - znet->rx_start)<<1); - next_frame_end_offset = this_rfp_ptr[-3]; - if (next_frame_end_offset == 0) /* Read all the frames? */ - break; /* Done for now */ - this_rfp_ptr = znet->rx_start + next_frame_end_offset; - } while (--boguscount); - - /* If any worth-while packets have been received, dev_rint() - has done a mark_bh(INET_BH) for us and will work on them - when we get to the bottom-half routine. */ -} - -/* The inverse routine to znet_open(). */ -static int znet_close(struct net_device *dev) -{ - int ioaddr = dev->base_addr; - - netif_stop_queue (dev); - - outb(OP0_RESET, ioaddr); /* CMD0_RESET */ - - if (znet_debug > 1) - printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); - /* Turn off transceiver power. */ - znet_transceiver_power (dev, 0); - - znet_release_resources (dev); - - return 0; -} - -static void show_dma(struct net_device *dev) -{ - short ioaddr = dev->base_addr; - unsigned char stat = inb (ioaddr); - struct znet_private *znet = netdev_priv(dev); - unsigned long flags; - short dma_port = ((znet->tx_dma&3)<<2) + IO_DMA2_BASE; - unsigned addr = inb(dma_port); - short residue; - - addr |= inb(dma_port) << 8; - residue = get_dma_residue(znet->tx_dma); - - if (znet_debug > 1) { - flags=claim_dma_lock(); - printk(KERN_DEBUG "Stat:%02x Addr: %04x cnt:%3x\n", - stat, addr<<1, residue); - release_dma_lock(flags); - } -} - -/* Initialize the hardware. We have to do this when the board is open()ed - or when we come out of suspend mode. */ -static void hardware_init(struct net_device *dev) -{ - unsigned long flags; - short ioaddr = dev->base_addr; - struct znet_private *znet = netdev_priv(dev); - - znet->rx_cur = znet->rx_start; - znet->tx_cur = znet->tx_start; - - /* Reset the chip, and start it up. */ - outb(OP0_RESET, ioaddr); - - flags=claim_dma_lock(); - disable_dma(znet->rx_dma); /* reset by an interrupting task. */ - clear_dma_ff(znet->rx_dma); - set_dma_mode(znet->rx_dma, DMA_RX_MODE); - set_dma_addr(znet->rx_dma, isa_virt_to_bus(znet->rx_start)); - set_dma_count(znet->rx_dma, RX_BUF_SIZE); - enable_dma(znet->rx_dma); - /* Now set up the Tx channel. */ - disable_dma(znet->tx_dma); - clear_dma_ff(znet->tx_dma); - set_dma_mode(znet->tx_dma, DMA_TX_MODE); - set_dma_addr(znet->tx_dma, isa_virt_to_bus(znet->tx_start)); - set_dma_count(znet->tx_dma, znet->tx_buf_len<<1); - enable_dma(znet->tx_dma); - release_dma_lock(flags); - - if (znet_debug > 1) - printk(KERN_DEBUG "%s: Initializing the i82593, rx buf %p tx buf %p\n", - dev->name, znet->rx_start,znet->tx_start); - /* Do an empty configure command, just like the Crynwr driver. This - resets to chip to its default values. */ - *znet->tx_cur++ = 0; - *znet->tx_cur++ = 0; - show_dma(dev); - outb(OP0_CONFIGURE | CR0_CHNL, ioaddr); - - znet_set_multicast_list (dev); - - *znet->tx_cur++ = 6; - memcpy(znet->tx_cur, dev->dev_addr, 6); - znet->tx_cur += 3; - show_dma(dev); - outb(OP0_IA_SETUP | CR0_CHNL, ioaddr); - show_dma(dev); - - update_stop_hit(ioaddr, 8192); - if (znet_debug > 1) printk(KERN_DEBUG "enabling Rx.\n"); - outb(OP0_RCV_ENABLE, ioaddr); - netif_start_queue (dev); -} - -static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset) -{ - outb(OP0_SWIT_TO_PORT_1 | CR0_CHNL, ioaddr); - if (znet_debug > 5) - printk(KERN_DEBUG "Updating stop hit with value %02x.\n", - (rx_stop_offset >> 6) | CR1_STOP_REG_UPDATE); - outb((rx_stop_offset >> 6) | CR1_STOP_REG_UPDATE, ioaddr); - outb(OP1_SWIT_TO_PORT_0, ioaddr); -} - -static __exit void znet_cleanup (void) -{ - if (znet_dev) { - struct znet_private *znet = netdev_priv(znet_dev); - - unregister_netdev (znet_dev); - kfree (znet->rx_start); - kfree (znet->tx_start); - free_netdev (znet_dev); - } -} - -module_init (znet_probe); -module_exit (znet_cleanup); -- cgit v1.2.3-70-g09d2 From 04861c535d1f5bad0fd537820116c0429a2dfe4b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Thu, 10 Jan 2013 18:12:04 -0500 Subject: drivers/net: delete Racal Interlan ISA ni52 (i825xx) driver Like the other drivers that were in the ISA i825xx family, the ni52 was rather rare, not widely used, and hence perhaps not as reliable as the more mainstream ISA drivers that were heavily used. Given that, it is chosen for retirement at this time as well. Signed-off-by: Paul Gortmaker --- drivers/net/Space.c | 4 - drivers/net/ethernet/i825xx/Kconfig | 11 - drivers/net/ethernet/i825xx/Makefile | 1 - drivers/net/ethernet/i825xx/ni52.c | 1346 ---------------------------------- drivers/net/ethernet/i825xx/ni52.h | 310 -------- 5 files changed, 1672 deletions(-) delete mode 100644 drivers/net/ethernet/i825xx/ni52.c delete mode 100644 drivers/net/ethernet/i825xx/ni52.h (limited to 'drivers/net/ethernet/i825xx/Makefile') diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 726b17b7961..b69dac1df34 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -51,7 +51,6 @@ extern struct net_device *i82596_probe(int unit); extern struct net_device *ewrk3_probe(int unit); extern struct net_device *e2100_probe(int unit); extern struct net_device *ni5010_probe(int unit); -extern struct net_device *ni52_probe(int unit); extern struct net_device *ni65_probe(int unit); extern struct net_device *sonic_probe(int unit); extern struct net_device *seeq8005_probe(int unit); @@ -157,9 +156,6 @@ static struct devprobe2 isa_probes[] __initdata = { #ifdef CONFIG_NI5010 {ni5010_probe, 0}, #endif -#ifdef CONFIG_NI52 - {ni52_probe, 0}, -#endif #ifdef CONFIG_NI65 {ni65_probe, 0}, #endif diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig index c3cfa576cde..955d929cd00 100644 --- a/drivers/net/ethernet/i825xx/Kconfig +++ b/drivers/net/ethernet/i825xx/Kconfig @@ -52,17 +52,6 @@ config MVME16x_NET driver for this chip in your kernel. To compile this driver as a module, choose M here. -config NI52 - tristate "NI5210 support" - depends on ISA - ---help--- - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - . - - To compile this driver as a module, choose M here. The module - will be called ni52. - config SNI_82596 tristate "SNI RM ethernet" depends on SNI_RM diff --git a/drivers/net/ethernet/i825xx/Makefile b/drivers/net/ethernet/i825xx/Makefile index df9e2ecdc63..8c8dcd29c40 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -3,7 +3,6 @@ # obj-$(CONFIG_ARM_ETHER1) += ether1.o -obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o obj-$(CONFIG_LASI_82596) += lasi_82596.o obj-$(CONFIG_SNI_82596) += sni_82596.o diff --git a/drivers/net/ethernet/i825xx/ni52.c b/drivers/net/ethernet/i825xx/ni52.c deleted file mode 100644 index 272976e1bb0..00000000000 --- a/drivers/net/ethernet/i825xx/ni52.c +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * net-3-driver for the NI5210 card (i82586 Ethernet chip) - * - * This is an extension to the Linux operating system, and is covered by the - * same GNU General Public License that covers that work. - * - * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later) - * Copyrights (c) 1994,1995,1996 by M.Hipp (hippm@informatik.uni-tuebingen.de) - * [feel free to mail ....] - * - * when using as module: (no autoprobing!) - * run with e.g: - * insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000 - * - * CAN YOU PLEASE REPORT ME YOUR PERFORMANCE EXPERIENCES !!. - * - * If you find a bug, please report me: - * The kernel panic output and any kmsg from the ni52 driver - * the ni5210-driver-version and the linux-kernel version - * how many shared memory (memsize) on the netcard, - * bootprom: yes/no, base_addr, mem_start - * maybe the ni5210-card revision and the i82586 version - * - * autoprobe for: base_addr: 0x300,0x280,0x360,0x320,0x340 - * mem_start: 0xd0000,0xd2000,0xc8000,0xca000,0xd4000,0xd6000, - * 0xd8000,0xcc000,0xce000,0xda000,0xdc000 - * - * sources: - * skeleton.c from Donald Becker - * - * I have also done a look in the following sources: (mail me if you need them) - * crynwr-packet-driver by Russ Nelson - * Garret A. Wollman's (fourth) i82586-driver for BSD - * (before getting an i82596 (yes 596 not 586) manual, the existing drivers - * helped me a lot to understand this tricky chip.) - * - * Known Problems: - * The internal sysbus seems to be slow. So we often lose packets because of - * overruns while receiving from a fast remote host. - * This can slow down TCP connections. Maybe the newer ni5210 cards are - * better. My experience is, that if a machine sends with more than about - * 500-600K/s the fifo/sysbus overflows. - * - * IMPORTANT NOTE: - * On fast networks, it's a (very) good idea to have 16K shared memory. With - * 8K, we can store only 4 receive frames, so it can (easily) happen that a - * remote machine 'overruns' our system. - * - * Known i82586/card problems (I'm sure, there are many more!): - * Running the NOP-mode, the i82586 sometimes seems to forget to report - * every xmit-interrupt until we restart the CU. - * Another MAJOR bug is, that the RU sometimes seems to ignore the EL-Bit - * in the RBD-Struct which indicates an end of the RBD queue. - * Instead, the RU fetches another (randomly selected and - * usually used) RBD and begins to fill it. (Maybe, this happens only if - * the last buffer from the previous RFD fits exact into the queue and - * the next RFD can't fetch an initial RBD. Anyone knows more? ) - * - * results from ftp performance tests with Linux 1.2.5 - * send and receive about 350-400 KByte/s (peak up to 460 kbytes/s) - * sending in NOP-mode: peak performance up to 530K/s (but better don't - * run this mode) - */ - -/* - * 29.Sept.96: virt_to_bus changes for new memory scheme - * 19.Feb.96: more Mcast changes, module support (MH) - * - * 18.Nov.95: Mcast changes (AC). - * - * 23.April.95: fixed(?) receiving problems by configuring a RFD more - * than the number of RBD's. Can maybe cause other problems. - * 18.April.95: Added MODULE support (MH) - * 17.April.95: MC related changes in init586() and set_multicast_list(). - * removed use of 'jiffies' in init586() (MH) - * - * 19.Sep.94: Added Multicast support (not tested yet) (MH) - * - * 18.Sep.94: Workaround for 'EL-Bug'. Removed flexible RBD-handling. - * Now, every RFD has exact one RBD. (MH) - * - * 14.Sep.94: added promiscuous mode, a few cleanups (MH) - * - * 19.Aug.94: changed request_irq() parameter (MH) - * - * 20.July.94: removed cleanup bugs, removed a 16K-mem-probe-bug (MH) - * - * 19.July.94: lotsa cleanups .. (MH) - * - * 17.July.94: some patches ... verified to run with 1.1.29 (MH) - * - * 4.July.94: patches for Linux 1.1.24 (MH) - * - * 26.March.94: patches for Linux 1.0 and iomem-auto-probe (MH) - * - * 30.Sep.93: Added nop-chain .. driver now runs with only one Xmit-Buff, - * too (MH) - * - * < 30.Sep.93: first versions - */ - -static int debuglevel; /* debug-printk 0: off 1: a few 2: more */ -static int automatic_resume; /* experimental .. better should be zero */ -static int rfdadd; /* rfdadd=1 may be better for 8K MEM cards */ -static int fifo = 0x8; /* don't change */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ni52.h" - -#define DRV_NAME "ni52" - -#define DEBUG /* debug on */ -#define SYSBUSVAL 1 /* 8 Bit */ - -#define ni_attn586() { outb(0, dev->base_addr + NI52_ATTENTION); } -#define ni_reset586() { outb(0, dev->base_addr + NI52_RESET); } -#define ni_disint() { outb(0, dev->base_addr + NI52_INTDIS); } -#define ni_enaint() { outb(0, dev->base_addr + NI52_INTENA); } - -#define make32(ptr16) ((void __iomem *)(p->memtop + (short) (ptr16))) -#define make24(ptr32) ((char __iomem *)(ptr32)) - p->base -#define make16(ptr32) ((unsigned short) ((char __iomem *)(ptr32)\ - - p->memtop)) - -/******************* how to calculate the buffers ***************************** - - * IMPORTANT NOTE: if you configure only one NUM_XMIT_BUFFS, the driver works - * --------------- in a different (more stable?) mode. Only in this mode it's - * possible to configure the driver with 'NO_NOPCOMMANDS' - -sizeof(scp)=12; sizeof(scb)=16; sizeof(iscp)=8; -sizeof(scp)+sizeof(iscp)+sizeof(scb) = 36 = INIT -sizeof(rfd) = 24; sizeof(rbd) = 12; -sizeof(tbd) = 8; sizeof(transmit_cmd) = 16; -sizeof(nop_cmd) = 8; - - * if you don't know the driver, better do not change these values: */ - -#define RECV_BUFF_SIZE 1524 /* slightly oversized */ -#define XMIT_BUFF_SIZE 1524 /* slightly oversized */ -#define NUM_XMIT_BUFFS 1 /* config for both, 8K and 16K shmem */ -#define NUM_RECV_BUFFS_8 4 /* config for 8K shared mem */ -#define NUM_RECV_BUFFS_16 9 /* config for 16K shared mem */ -#define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */ - -/**************************************************************************/ - - -#define NI52_TOTAL_SIZE 16 -#define NI52_ADDR0 0x02 -#define NI52_ADDR1 0x07 -#define NI52_ADDR2 0x01 - -static int ni52_probe1(struct net_device *dev, int ioaddr); -static irqreturn_t ni52_interrupt(int irq, void *dev_id); -static int ni52_open(struct net_device *dev); -static int ni52_close(struct net_device *dev); -static netdev_tx_t ni52_send_packet(struct sk_buff *, struct net_device *); -static struct net_device_stats *ni52_get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static void ni52_timeout(struct net_device *dev); - -/* helper-functions */ -static int init586(struct net_device *dev); -static int check586(struct net_device *dev, unsigned size); -static void alloc586(struct net_device *dev); -static void startrecv586(struct net_device *dev); -static void __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr); -static void ni52_rcv_int(struct net_device *dev); -static void ni52_xmt_int(struct net_device *dev); -static void ni52_rnr_int(struct net_device *dev); - -struct priv { - char __iomem *base; - char __iomem *mapped; - char __iomem *memtop; - spinlock_t spinlock; - int reset; - struct rfd_struct __iomem *rfd_last, *rfd_top, *rfd_first; - struct scp_struct __iomem *scp; - struct iscp_struct __iomem *iscp; - struct scb_struct __iomem *scb; - struct tbd_struct __iomem *xmit_buffs[NUM_XMIT_BUFFS]; -#if (NUM_XMIT_BUFFS == 1) - struct transmit_cmd_struct __iomem *xmit_cmds[2]; - struct nop_cmd_struct __iomem *nop_cmds[2]; -#else - struct transmit_cmd_struct __iomem *xmit_cmds[NUM_XMIT_BUFFS]; - struct nop_cmd_struct __iomem *nop_cmds[NUM_XMIT_BUFFS]; -#endif - int nop_point, num_recv_buffs; - char __iomem *xmit_cbuffs[NUM_XMIT_BUFFS]; - int xmit_count, xmit_last; -}; - -/* wait for command with timeout: */ -static void wait_for_scb_cmd(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - int i; - for (i = 0; i < 16384; i++) { - if (readb(&p->scb->cmd_cuc) == 0) - break; - udelay(4); - if (i == 16383) { - printk(KERN_ERR "%s: scb_cmd timed out: %04x,%04x .. disabling i82586!!\n", - dev->name, readb(&p->scb->cmd_cuc), readb(&p->scb->cus)); - if (!p->reset) { - p->reset = 1; - ni_reset586(); - } - } - } -} - -static void wait_for_scb_cmd_ruc(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - int i; - for (i = 0; i < 16384; i++) { - if (readb(&p->scb->cmd_ruc) == 0) - break; - udelay(4); - if (i == 16383) { - printk(KERN_ERR "%s: scb_cmd (ruc) timed out: %04x,%04x .. disabling i82586!!\n", - dev->name, readb(&p->scb->cmd_ruc), - readb(&p->scb->rus)); - if (!p->reset) { - p->reset = 1; - ni_reset586(); - } - } - } -} - -static void wait_for_stat_compl(void __iomem *p) -{ - struct nop_cmd_struct __iomem *addr = p; - int i; - for (i = 0; i < 32767; i++) { - if (readw(&((addr)->cmd_status)) & STAT_COMPL) - break; - udelay(32); - } -} - -/********************************************** - * close device - */ -static int ni52_close(struct net_device *dev) -{ - free_irq(dev->irq, dev); - ni_reset586(); /* the hard way to stop the receiver */ - netif_stop_queue(dev); - return 0; -} - -/********************************************** - * open device - */ -static int ni52_open(struct net_device *dev) -{ - int ret; - - ni_disint(); - alloc586(dev); - init586(dev); - startrecv586(dev); - ni_enaint(); - - ret = request_irq(dev->irq, ni52_interrupt, 0, dev->name, dev); - if (ret) { - ni_reset586(); - return ret; - } - netif_start_queue(dev); - return 0; /* most done by init */ -} - -static int check_iscp(struct net_device *dev, void __iomem *addr) -{ - struct iscp_struct __iomem *iscp = addr; - struct priv *p = netdev_priv(dev); - memset_io(iscp, 0, sizeof(struct iscp_struct)); - - writel(make24(iscp), &p->scp->iscp); - writeb(1, &iscp->busy); - - ni_reset586(); - ni_attn586(); - mdelay(32); /* wait a while... */ - /* i82586 clears 'busy' after successful init */ - if (readb(&iscp->busy)) - return 0; - return 1; -} - -/********************************************** - * Check to see if there's an 82586 out there. - */ -static int check586(struct net_device *dev, unsigned size) -{ - struct priv *p = netdev_priv(dev); - int i; - - p->mapped = ioremap(dev->mem_start, size); - if (!p->mapped) - return 0; - - p->base = p->mapped + size - 0x01000000; - p->memtop = p->mapped + size; - p->scp = (struct scp_struct __iomem *)(p->base + SCP_DEFAULT_ADDRESS); - p->scb = (struct scb_struct __iomem *) p->mapped; - p->iscp = (struct iscp_struct __iomem *)p->scp - 1; - memset_io(p->scp, 0, sizeof(struct scp_struct)); - for (i = 0; i < sizeof(struct scp_struct); i++) - /* memory was writeable? */ - if (readb((char __iomem *)p->scp + i)) - goto Enodev; - writeb(SYSBUSVAL, &p->scp->sysbus); /* 1 = 8Bit-Bus, 0 = 16 Bit */ - if (readb(&p->scp->sysbus) != SYSBUSVAL) - goto Enodev; - - if (!check_iscp(dev, p->mapped)) - goto Enodev; - if (!check_iscp(dev, p->iscp)) - goto Enodev; - return 1; -Enodev: - iounmap(p->mapped); - return 0; -} - -/****************************************************************** - * set iscp at the right place, called by ni52_probe1 and open586. - */ -static void alloc586(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - - ni_reset586(); - mdelay(32); - - memset_io(p->iscp, 0, sizeof(struct iscp_struct)); - memset_io(p->scp , 0, sizeof(struct scp_struct)); - - writel(make24(p->iscp), &p->scp->iscp); - writeb(SYSBUSVAL, &p->scp->sysbus); - writew(make16(p->scb), &p->iscp->scb_offset); - - writeb(1, &p->iscp->busy); - ni_reset586(); - ni_attn586(); - - mdelay(32); - - if (readb(&p->iscp->busy)) - printk(KERN_ERR "%s: Init-Problems (alloc).\n", dev->name); - - p->reset = 0; - - memset_io(p->scb, 0, sizeof(struct scb_struct)); -} - -/* set: io,irq,memstart,memend or set it when calling insmod */ -static int irq = 9; -static int io = 0x300; -static long memstart; /* e.g 0xd0000 */ -static long memend; /* e.g 0xd4000 */ - -/********************************************** - * probe the ni5210-card - */ -struct net_device * __init ni52_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct priv)); - static const int ports[] = {0x300, 0x280, 0x360, 0x320, 0x340, 0}; - const int *port; - struct priv *p; - int err = 0; - - if (!dev) - return ERR_PTR(-ENOMEM); - - p = netdev_priv(dev); - - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - io = dev->base_addr; - irq = dev->irq; - memstart = dev->mem_start; - memend = dev->mem_end; - } - - if (io > 0x1ff) { /* Check a single specified location. */ - err = ni52_probe1(dev, io); - } else if (io > 0) { /* Don't probe at all. */ - err = -ENXIO; - } else { - for (port = ports; *port && ni52_probe1(dev, *port) ; port++) - ; - if (*port) - goto got_it; -#ifdef FULL_IO_PROBE - for (io = 0x200; io < 0x400 && ni52_probe1(dev, io); io += 8) - ; - if (io < 0x400) - goto got_it; -#endif - err = -ENODEV; - } - if (err) - goto out; -got_it: - err = register_netdev(dev); - if (err) - goto out1; - return dev; -out1: - iounmap(p->mapped); - release_region(dev->base_addr, NI52_TOTAL_SIZE); -out: - free_netdev(dev); - return ERR_PTR(err); -} - -static const struct net_device_ops ni52_netdev_ops = { - .ndo_open = ni52_open, - .ndo_stop = ni52_close, - .ndo_get_stats = ni52_get_stats, - .ndo_tx_timeout = ni52_timeout, - .ndo_start_xmit = ni52_send_packet, - .ndo_set_rx_mode = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static int __init ni52_probe1(struct net_device *dev, int ioaddr) -{ - int i, size, retval; - struct priv *priv = netdev_priv(dev); - - dev->base_addr = ioaddr; - dev->irq = irq; - dev->mem_start = memstart; - dev->mem_end = memend; - - spin_lock_init(&priv->spinlock); - - if (!request_region(ioaddr, NI52_TOTAL_SIZE, DRV_NAME)) - return -EBUSY; - - if (!(inb(ioaddr+NI52_MAGIC1) == NI52_MAGICVAL1) || - !(inb(ioaddr+NI52_MAGIC2) == NI52_MAGICVAL2)) { - retval = -ENODEV; - goto out; - } - - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = inb(dev->base_addr+i); - - if (dev->dev_addr[0] != NI52_ADDR0 || dev->dev_addr[1] != NI52_ADDR1 || - dev->dev_addr[2] != NI52_ADDR2) { - retval = -ENODEV; - goto out; - } - - printk(KERN_INFO "%s: NI5210 found at %#3lx, ", - dev->name, dev->base_addr); - - /* - * check (or search) IO-Memory, 8K and 16K - */ -#ifdef MODULE - size = dev->mem_end - dev->mem_start; - if (size != 0x2000 && size != 0x4000) { - printk("\n"); - printk(KERN_ERR "%s: Invalid memory size %d. Allowed is 0x2000 or 0x4000 bytes.\n", dev->name, size); - retval = -ENODEV; - goto out; - } - if (!check586(dev, size)) { - printk(KERN_ERR "?memcheck, Can't find memory at 0x%lx with size %d!\n", dev->mem_start, size); - retval = -ENODEV; - goto out; - } -#else - if (dev->mem_start != 0) { - /* no auto-mem-probe */ - size = 0x4000; /* check for 16K mem */ - if (!check586(dev, size)) { - size = 0x2000; /* check for 8K mem */ - if (!check586(dev, size)) { - printk(KERN_ERR "?memprobe, Can't find memory at 0x%lx!\n", dev->mem_start); - retval = -ENODEV; - goto out; - } - } - } else { - static const unsigned long memaddrs[] = { - 0xc8000, 0xca000, 0xcc000, 0xce000, 0xd0000, 0xd2000, - 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0 - }; - for (i = 0;; i++) { - if (!memaddrs[i]) { - printk(KERN_ERR "?memprobe, Can't find io-memory!\n"); - retval = -ENODEV; - goto out; - } - dev->mem_start = memaddrs[i]; - size = 0x2000; /* check for 8K mem */ - if (check586(dev, size)) - /* 8K-check */ - break; - size = 0x4000; /* check for 16K mem */ - if (check586(dev, size)) - /* 16K-check */ - break; - } - } - /* set mem_end showed by 'ifconfig' */ - dev->mem_end = dev->mem_start + size; -#endif - - alloc586(dev); - - /* set number of receive-buffs according to memsize */ - if (size == 0x2000) - priv->num_recv_buffs = NUM_RECV_BUFFS_8; - else - priv->num_recv_buffs = NUM_RECV_BUFFS_16; - - printk(KERN_DEBUG "Memaddr: 0x%lx, Memsize: %d, ", - dev->mem_start, size); - - if (dev->irq < 2) { - unsigned long irq_mask; - - irq_mask = probe_irq_on(); - ni_reset586(); - ni_attn586(); - - mdelay(20); - dev->irq = probe_irq_off(irq_mask); - if (!dev->irq) { - printk("?autoirq, Failed to detect IRQ line!\n"); - retval = -EAGAIN; - iounmap(priv->mapped); - goto out; - } - printk("IRQ %d (autodetected).\n", dev->irq); - } else { - if (dev->irq == 2) - dev->irq = 9; - printk("IRQ %d (assigned and not checked!).\n", dev->irq); - } - - dev->netdev_ops = &ni52_netdev_ops; - dev->watchdog_timeo = HZ/20; - - return 0; -out: - release_region(ioaddr, NI52_TOTAL_SIZE); - return retval; -} - -/********************************************** - * init the chip (ni52-interrupt should be disabled?!) - * needs a correct 'allocated' memory - */ - -static int init586(struct net_device *dev) -{ - void __iomem *ptr; - int i, result = 0; - struct priv *p = netdev_priv(dev); - struct configure_cmd_struct __iomem *cfg_cmd; - struct iasetup_cmd_struct __iomem *ias_cmd; - struct tdr_cmd_struct __iomem *tdr_cmd; - struct mcsetup_cmd_struct __iomem *mc_cmd; - struct netdev_hw_addr *ha; - int num_addrs = netdev_mc_count(dev); - - ptr = p->scb + 1; - - cfg_cmd = ptr; /* configure-command */ - writew(0, &cfg_cmd->cmd_status); - writew(CMD_CONFIGURE | CMD_LAST, &cfg_cmd->cmd_cmd); - writew(0xFFFF, &cfg_cmd->cmd_link); - - /* number of cfg bytes */ - writeb(0x0a, &cfg_cmd->byte_cnt); - /* fifo-limit (8=tx:32/rx:64) */ - writeb(fifo, &cfg_cmd->fifo); - /* hold or discard bad recv frames (bit 7) */ - writeb(0x40, &cfg_cmd->sav_bf); - /* addr_len |!src_insert |pre-len |loopback */ - writeb(0x2e, &cfg_cmd->adr_len); - writeb(0x00, &cfg_cmd->priority); - writeb(0x60, &cfg_cmd->ifs); - writeb(0x00, &cfg_cmd->time_low); - writeb(0xf2, &cfg_cmd->time_high); - writeb(0x00, &cfg_cmd->promisc); - if (dev->flags & IFF_ALLMULTI) { - int len = ((char __iomem *)p->iscp - (char __iomem *)ptr - 8) / 6; - if (num_addrs > len) { - printk(KERN_ERR "%s: switching to promisc. mode\n", - dev->name); - writeb(0x01, &cfg_cmd->promisc); - } - } - if (dev->flags & IFF_PROMISC) - writeb(0x01, &cfg_cmd->promisc); - writeb(0x00, &cfg_cmd->carr_coll); - writew(make16(cfg_cmd), &p->scb->cbl_offset); - writeb(0, &p->scb->cmd_ruc); - - writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ - ni_attn586(); - - wait_for_stat_compl(cfg_cmd); - - if ((readw(&cfg_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != - (STAT_COMPL|STAT_OK)) { - printk(KERN_ERR "%s: configure command failed: %x\n", - dev->name, readw(&cfg_cmd->cmd_status)); - return 1; - } - - /* - * individual address setup - */ - - ias_cmd = ptr; - - writew(0, &ias_cmd->cmd_status); - writew(CMD_IASETUP | CMD_LAST, &ias_cmd->cmd_cmd); - writew(0xffff, &ias_cmd->cmd_link); - - memcpy_toio(&ias_cmd->iaddr, (char *)dev->dev_addr, ETH_ALEN); - - writew(make16(ias_cmd), &p->scb->cbl_offset); - - writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ - ni_attn586(); - - wait_for_stat_compl(ias_cmd); - - if ((readw(&ias_cmd->cmd_status) & (STAT_OK|STAT_COMPL)) != - (STAT_OK|STAT_COMPL)) { - printk(KERN_ERR "%s (ni52): individual address setup command failed: %04x\n", dev->name, readw(&ias_cmd->cmd_status)); - return 1; - } - - /* - * TDR, wire check .. e.g. no resistor e.t.c - */ - - tdr_cmd = ptr; - - writew(0, &tdr_cmd->cmd_status); - writew(CMD_TDR | CMD_LAST, &tdr_cmd->cmd_cmd); - writew(0xffff, &tdr_cmd->cmd_link); - writew(0, &tdr_cmd->status); - - writew(make16(tdr_cmd), &p->scb->cbl_offset); - writeb(CUC_START, &p->scb->cmd_cuc); /* cmd.-unit start */ - ni_attn586(); - - wait_for_stat_compl(tdr_cmd); - - if (!(readw(&tdr_cmd->cmd_status) & STAT_COMPL)) - printk(KERN_ERR "%s: Problems while running the TDR.\n", - dev->name); - else { - udelay(16); - result = readw(&tdr_cmd->status); - writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); - ni_attn586(); /* ack the interrupts */ - - if (result & TDR_LNK_OK) - ; - else if (result & TDR_XCVR_PRB) - printk(KERN_ERR "%s: TDR: Transceiver problem. Check the cable(s)!\n", - dev->name); - else if (result & TDR_ET_OPN) - printk(KERN_ERR "%s: TDR: No correct termination %d clocks away.\n", - dev->name, result & TDR_TIMEMASK); - else if (result & TDR_ET_SRT) { - /* time == 0 -> strange :-) */ - if (result & TDR_TIMEMASK) - printk(KERN_ERR "%s: TDR: Detected a short circuit %d clocks away.\n", - dev->name, result & TDR_TIMEMASK); - } else - printk(KERN_ERR "%s: TDR: Unknown status %04x\n", - dev->name, result); - } - - /* - * Multicast setup - */ - if (num_addrs && !(dev->flags & IFF_PROMISC)) { - mc_cmd = ptr; - writew(0, &mc_cmd->cmd_status); - writew(CMD_MCSETUP | CMD_LAST, &mc_cmd->cmd_cmd); - writew(0xffff, &mc_cmd->cmd_link); - writew(num_addrs * 6, &mc_cmd->mc_cnt); - - i = 0; - netdev_for_each_mc_addr(ha, dev) - memcpy_toio(mc_cmd->mc_list[i++], ha->addr, 6); - - writew(make16(mc_cmd), &p->scb->cbl_offset); - writeb(CUC_START, &p->scb->cmd_cuc); - ni_attn586(); - - wait_for_stat_compl(mc_cmd); - - if ((readw(&mc_cmd->cmd_status) & (STAT_COMPL|STAT_OK)) - != (STAT_COMPL|STAT_OK)) - printk(KERN_ERR "%s: Can't apply multicast-address-list.\n", dev->name); - } - - /* - * alloc nop/xmit-cmds - */ -#if (NUM_XMIT_BUFFS == 1) - for (i = 0; i < 2; i++) { - p->nop_cmds[i] = ptr; - writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); - writew(0, &p->nop_cmds[i]->cmd_status); - writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); - ptr = ptr + sizeof(struct nop_cmd_struct); - } -#else - for (i = 0; i < NUM_XMIT_BUFFS; i++) { - p->nop_cmds[i] = ptr; - writew(CMD_NOP, &p->nop_cmds[i]->cmd_cmd); - writew(0, &p->nop_cmds[i]->cmd_status); - writew(make16(p->nop_cmds[i]), &p->nop_cmds[i]->cmd_link); - ptr = ptr + sizeof(struct nop_cmd_struct); - } -#endif - - ptr = alloc_rfa(dev, ptr); /* init receive-frame-area */ - - /* - * alloc xmit-buffs / init xmit_cmds - */ - for (i = 0; i < NUM_XMIT_BUFFS; i++) { - /* Transmit cmd/buff 0 */ - p->xmit_cmds[i] = ptr; - ptr = ptr + sizeof(struct transmit_cmd_struct); - p->xmit_cbuffs[i] = ptr; /* char-buffs */ - ptr = ptr + XMIT_BUFF_SIZE; - p->xmit_buffs[i] = ptr; /* TBD */ - ptr = ptr + sizeof(struct tbd_struct); - if ((void __iomem *)ptr > (void __iomem *)p->iscp) { - printk(KERN_ERR "%s: not enough shared-mem for your configuration!\n", - dev->name); - return 1; - } - memset_io(p->xmit_cmds[i], 0, - sizeof(struct transmit_cmd_struct)); - memset_io(p->xmit_buffs[i], 0, - sizeof(struct tbd_struct)); - writew(make16(p->nop_cmds[(i+1)%NUM_XMIT_BUFFS]), - &p->xmit_cmds[i]->cmd_link); - writew(STAT_COMPL, &p->xmit_cmds[i]->cmd_status); - writew(CMD_XMIT|CMD_INT, &p->xmit_cmds[i]->cmd_cmd); - writew(make16(p->xmit_buffs[i]), &p->xmit_cmds[i]->tbd_offset); - writew(0xffff, &p->xmit_buffs[i]->next); - writel(make24(p->xmit_cbuffs[i]), &p->xmit_buffs[i]->buffer); - } - - p->xmit_count = 0; - p->xmit_last = 0; -#ifndef NO_NOPCOMMANDS - p->nop_point = 0; -#endif - - /* - * 'start transmitter' - */ -#ifndef NO_NOPCOMMANDS - writew(make16(p->nop_cmds[0]), &p->scb->cbl_offset); - writeb(CUC_START, &p->scb->cmd_cuc); - ni_attn586(); - wait_for_scb_cmd(dev); -#else - writew(make16(p->xmit_cmds[0]), &p->xmit_cmds[0]->cmd_link); - writew(CMD_XMIT | CMD_SUSPEND | CMD_INT, &p->xmit_cmds[0]->cmd_cmd); -#endif - - /* - * ack. interrupts - */ - writeb(readb(&p->scb->cus) & STAT_MASK, &p->scb->cmd_cuc); - ni_attn586(); - udelay(16); - - ni_enaint(); - - return 0; -} - -/****************************************************** - * This is a helper routine for ni52_rnr_int() and init586(). - * It sets up the Receive Frame Area (RFA). - */ - -static void __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr) -{ - struct rfd_struct __iomem *rfd = ptr; - struct rbd_struct __iomem *rbd; - int i; - struct priv *p = netdev_priv(dev); - - memset_io(rfd, 0, - sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd)); - p->rfd_first = rfd; - - for (i = 0; i < (p->num_recv_buffs + rfdadd); i++) { - writew(make16(rfd + (i+1) % (p->num_recv_buffs+rfdadd)), - &rfd[i].next); - writew(0xffff, &rfd[i].rbd_offset); - } - /* RU suspend */ - writeb(RFD_SUSP, &rfd[p->num_recv_buffs-1+rfdadd].last); - - ptr = rfd + (p->num_recv_buffs + rfdadd); - - rbd = ptr; - ptr = rbd + p->num_recv_buffs; - - /* clr descriptors */ - memset_io(rbd, 0, sizeof(struct rbd_struct) * (p->num_recv_buffs)); - - for (i = 0; i < p->num_recv_buffs; i++) { - writew(make16(rbd + (i+1) % p->num_recv_buffs), &rbd[i].next); - writew(RECV_BUFF_SIZE, &rbd[i].size); - writel(make24(ptr), &rbd[i].buffer); - ptr = ptr + RECV_BUFF_SIZE; - } - p->rfd_top = p->rfd_first; - p->rfd_last = p->rfd_first + (p->num_recv_buffs - 1 + rfdadd); - - writew(make16(p->rfd_first), &p->scb->rfa_offset); - writew(make16(rbd), &p->rfd_first->rbd_offset); - - return ptr; -} - - -/************************************************** - * Interrupt Handler ... - */ - -static irqreturn_t ni52_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - unsigned int stat; - int cnt = 0; - struct priv *p; - - p = netdev_priv(dev); - - if (debuglevel > 1) - printk("I"); - - spin_lock(&p->spinlock); - - wait_for_scb_cmd(dev); /* wait for last command */ - - while ((stat = readb(&p->scb->cus) & STAT_MASK)) { - writeb(stat, &p->scb->cmd_cuc); - ni_attn586(); - - if (stat & STAT_FR) /* received a frame */ - ni52_rcv_int(dev); - - if (stat & STAT_RNR) { /* RU went 'not ready' */ - printk("(R)"); - if (readb(&p->scb->rus) & RU_SUSPEND) { - /* special case: RU_SUSPEND */ - wait_for_scb_cmd(dev); - writeb(RUC_RESUME, &p->scb->cmd_ruc); - ni_attn586(); - wait_for_scb_cmd_ruc(dev); - } else { - printk(KERN_ERR "%s: Receiver-Unit went 'NOT READY': %04x/%02x.\n", - dev->name, stat, readb(&p->scb->rus)); - ni52_rnr_int(dev); - } - } - - /* Command with I-bit set complete */ - if (stat & STAT_CX) - ni52_xmt_int(dev); - -#ifndef NO_NOPCOMMANDS - if (stat & STAT_CNA) { /* CU went 'not ready' */ - if (netif_running(dev)) - printk(KERN_ERR "%s: oops! CU has left active state. stat: %04x/%02x.\n", - dev->name, stat, readb(&p->scb->cus)); - } -#endif - - if (debuglevel > 1) - printk("%d", cnt++); - - /* Wait for ack. (ni52_xmt_int can be faster than ack!!) */ - wait_for_scb_cmd(dev); - if (readb(&p->scb->cmd_cuc)) { /* timed out? */ - printk(KERN_ERR "%s: Acknowledge timed out.\n", - dev->name); - ni_disint(); - break; - } - } - spin_unlock(&p->spinlock); - - if (debuglevel > 1) - printk("i"); - return IRQ_HANDLED; -} - -/******************************************************* - * receive-interrupt - */ - -static void ni52_rcv_int(struct net_device *dev) -{ - int status, cnt = 0; - unsigned short totlen; - struct sk_buff *skb; - struct rbd_struct __iomem *rbd; - struct priv *p = netdev_priv(dev); - - if (debuglevel > 0) - printk("R"); - - for (; (status = readb(&p->rfd_top->stat_high)) & RFD_COMPL;) { - rbd = make32(readw(&p->rfd_top->rbd_offset)); - if (status & RFD_OK) { /* frame received without error? */ - totlen = readw(&rbd->status); - if (totlen & RBD_LAST) { - /* the first and the last buffer? */ - totlen &= RBD_MASK; /* length of this frame */ - writew(0x00, &rbd->status); - skb = netdev_alloc_skb(dev, totlen + 2); - if (skb != NULL) { - skb_reserve(skb, 2); - skb_put(skb, totlen); - memcpy_fromio(skb->data, p->base + readl(&rbd->buffer), totlen); - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += totlen; - } else - dev->stats.rx_dropped++; - } else { - int rstat; - /* free all RBD's until RBD_LAST is set */ - totlen = 0; - while (!((rstat = readw(&rbd->status)) & RBD_LAST)) { - totlen += rstat & RBD_MASK; - if (!rstat) { - printk(KERN_ERR "%s: Whoops .. no end mark in RBD list\n", dev->name); - break; - } - writew(0, &rbd->status); - rbd = make32(readw(&rbd->next)); - } - totlen += rstat & RBD_MASK; - writew(0, &rbd->status); - printk(KERN_ERR "%s: received oversized frame! length: %d\n", - dev->name, totlen); - dev->stats.rx_dropped++; - } - } else {/* frame !(ok), only with 'save-bad-frames' */ - printk(KERN_ERR "%s: oops! rfd-error-status: %04x\n", - dev->name, status); - dev->stats.rx_errors++; - } - writeb(0, &p->rfd_top->stat_high); - writeb(RFD_SUSP, &p->rfd_top->last); /* maybe exchange by RFD_LAST */ - writew(0xffff, &p->rfd_top->rbd_offset); - writeb(0, &p->rfd_last->last); /* delete RFD_SUSP */ - p->rfd_last = p->rfd_top; - p->rfd_top = make32(readw(&p->rfd_top->next)); /* step to next RFD */ - writew(make16(p->rfd_top), &p->scb->rfa_offset); - - if (debuglevel > 0) - printk("%d", cnt++); - } - - if (automatic_resume) { - wait_for_scb_cmd(dev); - writeb(RUC_RESUME, &p->scb->cmd_ruc); - ni_attn586(); - wait_for_scb_cmd_ruc(dev); - } - -#ifdef WAIT_4_BUSY - { - int i; - for (i = 0; i < 1024; i++) { - if (p->rfd_top->status) - break; - udelay(16); - if (i == 1023) - printk(KERN_ERR "%s: RU hasn't fetched next RFD (not busy/complete)\n", dev->name); - } - } -#endif - if (debuglevel > 0) - printk("r"); -} - -/********************************************************** - * handle 'Receiver went not ready'. - */ - -static void ni52_rnr_int(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - - dev->stats.rx_errors++; - - wait_for_scb_cmd(dev); /* wait for the last cmd, WAIT_4_FULLSTAT?? */ - writeb(RUC_ABORT, &p->scb->cmd_ruc); /* usually the RU is in the 'no resource'-state .. abort it now. */ - ni_attn586(); - wait_for_scb_cmd_ruc(dev); /* wait for accept cmd. */ - - alloc_rfa(dev, p->rfd_first); - /* maybe add a check here, before restarting the RU */ - startrecv586(dev); /* restart RU */ - - printk(KERN_ERR "%s: Receive-Unit restarted. Status: %04x\n", - dev->name, readb(&p->scb->rus)); - -} - -/********************************************************** - * handle xmit - interrupt - */ - -static void ni52_xmt_int(struct net_device *dev) -{ - int status; - struct priv *p = netdev_priv(dev); - - if (debuglevel > 0) - printk("X"); - - status = readw(&p->xmit_cmds[p->xmit_last]->cmd_status); - if (!(status & STAT_COMPL)) - printk(KERN_ERR "%s: strange .. xmit-int without a 'COMPLETE'\n", dev->name); - - if (status & STAT_OK) { - dev->stats.tx_packets++; - dev->stats.collisions += (status & TCMD_MAXCOLLMASK); - } else { - dev->stats.tx_errors++; - if (status & TCMD_LATECOLL) { - printk(KERN_ERR "%s: late collision detected.\n", - dev->name); - dev->stats.collisions++; - } else if (status & TCMD_NOCARRIER) { - dev->stats.tx_carrier_errors++; - printk(KERN_ERR "%s: no carrier detected.\n", - dev->name); - } else if (status & TCMD_LOSTCTS) - printk(KERN_ERR "%s: loss of CTS detected.\n", - dev->name); - else if (status & TCMD_UNDERRUN) { - dev->stats.tx_fifo_errors++; - printk(KERN_ERR "%s: DMA underrun detected.\n", - dev->name); - } else if (status & TCMD_MAXCOLL) { - printk(KERN_ERR "%s: Max. collisions exceeded.\n", - dev->name); - dev->stats.collisions += 16; - } - } -#if (NUM_XMIT_BUFFS > 1) - if ((++p->xmit_last) == NUM_XMIT_BUFFS) - p->xmit_last = 0; -#endif - netif_wake_queue(dev); -} - -/*********************************************************** - * (re)start the receiver - */ - -static void startrecv586(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - - wait_for_scb_cmd(dev); - wait_for_scb_cmd_ruc(dev); - writew(make16(p->rfd_first), &p->scb->rfa_offset); - writeb(RUC_START, &p->scb->cmd_ruc); - ni_attn586(); /* start cmd. */ - wait_for_scb_cmd_ruc(dev); - /* wait for accept cmd. (no timeout!!) */ -} - -static void ni52_timeout(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); -#ifndef NO_NOPCOMMANDS - if (readb(&p->scb->cus) & CU_ACTIVE) { /* COMMAND-UNIT active? */ - netif_wake_queue(dev); -#ifdef DEBUG - printk(KERN_ERR "%s: strange ... timeout with CU active?!?\n", - dev->name); - printk(KERN_ERR "%s: X0: %04x N0: %04x N1: %04x %d\n", - dev->name, (int)p->xmit_cmds[0]->cmd_status, - readw(&p->nop_cmds[0]->cmd_status), - readw(&p->nop_cmds[1]->cmd_status), - p->nop_point); -#endif - writeb(CUC_ABORT, &p->scb->cmd_cuc); - ni_attn586(); - wait_for_scb_cmd(dev); - writew(make16(p->nop_cmds[p->nop_point]), &p->scb->cbl_offset); - writeb(CUC_START, &p->scb->cmd_cuc); - ni_attn586(); - wait_for_scb_cmd(dev); - dev->trans_start = jiffies; /* prevent tx timeout */ - return 0; - } -#endif - { -#ifdef DEBUG - printk(KERN_ERR "%s: xmitter timed out, try to restart! stat: %02x\n", - dev->name, readb(&p->scb->cus)); - printk(KERN_ERR "%s: command-stats: %04x %04x\n", - dev->name, - readw(&p->xmit_cmds[0]->cmd_status), - readw(&p->xmit_cmds[1]->cmd_status)); - printk(KERN_ERR "%s: check, whether you set the right interrupt number!\n", - dev->name); -#endif - ni52_close(dev); - ni52_open(dev); - } - dev->trans_start = jiffies; /* prevent tx timeout */ -} - -/****************************************************** - * send frame - */ - -static netdev_tx_t ni52_send_packet(struct sk_buff *skb, - struct net_device *dev) -{ - int len, i; -#ifndef NO_NOPCOMMANDS - int next_nop; -#endif - struct priv *p = netdev_priv(dev); - - if (skb->len > XMIT_BUFF_SIZE) { - printk(KERN_ERR "%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n", dev->name, XMIT_BUFF_SIZE, skb->len); - return NETDEV_TX_OK; - } - - netif_stop_queue(dev); - - memcpy_toio(p->xmit_cbuffs[p->xmit_count], skb->data, skb->len); - len = skb->len; - if (len < ETH_ZLEN) { - len = ETH_ZLEN; - memset_io(p->xmit_cbuffs[p->xmit_count]+skb->len, 0, - len - skb->len); - } - -#if (NUM_XMIT_BUFFS == 1) -# ifdef NO_NOPCOMMANDS - -#ifdef DEBUG - if (readb(&p->scb->cus) & CU_ACTIVE) { - printk(KERN_ERR "%s: Hmmm .. CU is still running and we wanna send a new packet.\n", dev->name); - printk(KERN_ERR "%s: stat: %04x %04x\n", - dev->name, readb(&p->scb->cus), - readw(&p->xmit_cmds[0]->cmd_status)); - } -#endif - writew(TBD_LAST | len, &p->xmit_buffs[0]->size); - for (i = 0; i < 16; i++) { - writew(0, &p->xmit_cmds[0]->cmd_status); - wait_for_scb_cmd(dev); - if ((readb(&p->scb->cus) & CU_STATUS) == CU_SUSPEND) - writeb(CUC_RESUME, &p->scb->cmd_cuc); - else { - writew(make16(p->xmit_cmds[0]), &p->scb->cbl_offset); - writeb(CUC_START, &p->scb->cmd_cuc); - } - ni_attn586(); - if (!i) - dev_kfree_skb(skb); - wait_for_scb_cmd(dev); - /* test it, because CU sometimes doesn't start immediately */ - if (readb(&p->scb->cus) & CU_ACTIVE) - break; - if (readw(&p->xmit_cmds[0]->cmd_status)) - break; - if (i == 15) - printk(KERN_WARNING "%s: Can't start transmit-command.\n", dev->name); - } -# else - next_nop = (p->nop_point + 1) & 0x1; - writew(TBD_LAST | len, &p->xmit_buffs[0]->size); - writew(make16(p->nop_cmds[next_nop]), &p->xmit_cmds[0]->cmd_link); - writew(make16(p->nop_cmds[next_nop]), - &p->nop_cmds[next_nop]->cmd_link); - writew(0, &p->xmit_cmds[0]->cmd_status); - writew(0, &p->nop_cmds[next_nop]->cmd_status); - - writew(make16(p->xmit_cmds[0]), &p->nop_cmds[p->nop_point]->cmd_link); - p->nop_point = next_nop; - dev_kfree_skb(skb); -# endif -#else - writew(TBD_LAST | len, &p->xmit_buffs[p->xmit_count]->size); - next_nop = p->xmit_count + 1 - if (next_nop == NUM_XMIT_BUFFS) - next_nop = 0; - writew(0, &p->xmit_cmds[p->xmit_count]->cmd_status); - /* linkpointer of xmit-command already points to next nop cmd */ - writew(make16(p->nop_cmds[next_nop]), - &p->nop_cmds[next_nop]->cmd_link); - writew(0, &p->nop_cmds[next_nop]->cmd_status); - writew(make16(p->xmit_cmds[p->xmit_count]), - &p->nop_cmds[p->xmit_count]->cmd_link); - p->xmit_count = next_nop; - { - unsigned long flags; - spin_lock_irqsave(&p->spinlock); - if (p->xmit_count != p->xmit_last) - netif_wake_queue(dev); - spin_unlock_irqrestore(&p->spinlock); - } - dev_kfree_skb(skb); -#endif - return NETDEV_TX_OK; -} - -/******************************************* - * Someone wanna have the statistics - */ - -static struct net_device_stats *ni52_get_stats(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - unsigned short crc, aln, rsc, ovrn; - - /* Get error-statistics from the ni82586 */ - crc = readw(&p->scb->crc_errs); - writew(0, &p->scb->crc_errs); - aln = readw(&p->scb->aln_errs); - writew(0, &p->scb->aln_errs); - rsc = readw(&p->scb->rsc_errs); - writew(0, &p->scb->rsc_errs); - ovrn = readw(&p->scb->ovrn_errs); - writew(0, &p->scb->ovrn_errs); - - dev->stats.rx_crc_errors += crc; - dev->stats.rx_fifo_errors += ovrn; - dev->stats.rx_frame_errors += aln; - dev->stats.rx_dropped += rsc; - - return &dev->stats; -} - -/******************************************************** - * Set MC list .. - */ - -static void set_multicast_list(struct net_device *dev) -{ - netif_stop_queue(dev); - ni_disint(); - alloc586(dev); - init586(dev); - startrecv586(dev); - ni_enaint(); - netif_wake_queue(dev); -} - -#ifdef MODULE -static struct net_device *dev_ni52; - -module_param(io, int, 0); -module_param(irq, int, 0); -module_param(memstart, long, 0); -module_param(memend, long, 0); -MODULE_PARM_DESC(io, "NI5210 I/O base address,required"); -MODULE_PARM_DESC(irq, "NI5210 IRQ number,required"); -MODULE_PARM_DESC(memstart, "NI5210 memory base address,required"); -MODULE_PARM_DESC(memend, "NI5210 memory end address,required"); - -int __init init_module(void) -{ - if (io <= 0x0 || !memend || !memstart || irq < 2) { - printk(KERN_ERR "ni52: Autoprobing not allowed for modules.\n"); - printk(KERN_ERR "ni52: Set symbols 'io' 'irq' 'memstart' and 'memend'\n"); - return -ENODEV; - } - dev_ni52 = ni52_probe(-1); - if (IS_ERR(dev_ni52)) - return PTR_ERR(dev_ni52); - return 0; -} - -void __exit cleanup_module(void) -{ - struct priv *p = netdev_priv(dev_ni52); - unregister_netdev(dev_ni52); - iounmap(p->mapped); - release_region(dev_ni52->base_addr, NI52_TOTAL_SIZE); - free_netdev(dev_ni52); -} -#endif /* MODULE */ - -MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/i825xx/ni52.h b/drivers/net/ethernet/i825xx/ni52.h deleted file mode 100644 index 0a03b288332..00000000000 --- a/drivers/net/ethernet/i825xx/ni52.h +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Intel i82586 Ethernet definitions - * - * This is an extension to the Linux operating system, and is covered by the - * same GNU General Public License that covers that work. - * - * copyrights (c) 1994 by Michael Hipp (hippm@informatik.uni-tuebingen.de) - * - * I have done a look in the following sources: - * crynwr-packet-driver by Russ Nelson - * Garret A. Wollman's i82586-driver for BSD - */ - - -#define NI52_RESET 0 /* writing to this address, resets the i82586 */ -#define NI52_ATTENTION 1 /* channel attention, kick the 586 */ -#define NI52_TENA 3 /* 2-5 possibly wrong, Xmit enable */ -#define NI52_TDIS 2 /* Xmit disable */ -#define NI52_INTENA 5 /* Interrupt enable */ -#define NI52_INTDIS 4 /* Interrupt disable */ -#define NI52_MAGIC1 6 /* dunno exact function */ -#define NI52_MAGIC2 7 /* dunno exact function */ - -#define NI52_MAGICVAL1 0x00 /* magic-values for ni5210 card */ -#define NI52_MAGICVAL2 0x55 - -/* - * where to find the System Configuration Pointer (SCP) - */ -#define SCP_DEFAULT_ADDRESS 0xfffff4 - - -/* - * System Configuration Pointer Struct - */ - -struct scp_struct -{ - u16 zero_dum0; /* has to be zero */ - u8 sysbus; /* 0=16Bit,1=8Bit */ - u8 zero_dum1; /* has to be zero for 586 */ - u16 zero_dum2; - u16 zero_dum3; - u32 iscp; /* pointer to the iscp-block */ -}; - - -/* - * Intermediate System Configuration Pointer (ISCP) - */ -struct iscp_struct -{ - u8 busy; /* 586 clears after successful init */ - u8 zero_dummy; /* has to be zero */ - u16 scb_offset; /* pointeroffset to the scb_base */ - u32 scb_base; /* base-address of all 16-bit offsets */ -}; - -/* - * System Control Block (SCB) - */ -struct scb_struct -{ - u8 rus; - u8 cus; - u8 cmd_ruc; /* command word: RU part */ - u8 cmd_cuc; /* command word: CU part & ACK */ - u16 cbl_offset; /* pointeroffset, command block list */ - u16 rfa_offset; /* pointeroffset, receive frame area */ - u16 crc_errs; /* CRC-Error counter */ - u16 aln_errs; /* alignmenterror counter */ - u16 rsc_errs; /* Resourceerror counter */ - u16 ovrn_errs; /* OVerrunerror counter */ -}; - -/* - * possible command values for the command word - */ -#define RUC_MASK 0x0070 /* mask for RU commands */ -#define RUC_NOP 0x0000 /* NOP-command */ -#define RUC_START 0x0010 /* start RU */ -#define RUC_RESUME 0x0020 /* resume RU after suspend */ -#define RUC_SUSPEND 0x0030 /* suspend RU */ -#define RUC_ABORT 0x0040 /* abort receiver operation immediately */ - -#define CUC_MASK 0x07 /* mask for CU command */ -#define CUC_NOP 0x00 /* NOP-command */ -#define CUC_START 0x01 /* start execution of 1. cmd on the CBL */ -#define CUC_RESUME 0x02 /* resume after suspend */ -#define CUC_SUSPEND 0x03 /* Suspend CU */ -#define CUC_ABORT 0x04 /* abort command operation immediately */ - -#define ACK_MASK 0xf0 /* mask for ACK command */ -#define ACK_CX 0x80 /* acknowledges STAT_CX */ -#define ACK_FR 0x40 /* ack. STAT_FR */ -#define ACK_CNA 0x20 /* ack. STAT_CNA */ -#define ACK_RNR 0x10 /* ack. STAT_RNR */ - -/* - * possible status values for the status word - */ -#define STAT_MASK 0xf0 /* mask for cause of interrupt */ -#define STAT_CX 0x80 /* CU finished cmd with its I bit set */ -#define STAT_FR 0x40 /* RU finished receiving a frame */ -#define STAT_CNA 0x20 /* CU left active state */ -#define STAT_RNR 0x10 /* RU left ready state */ - -#define CU_STATUS 0x7 /* CU status, 0=idle */ -#define CU_SUSPEND 0x1 /* CU is suspended */ -#define CU_ACTIVE 0x2 /* CU is active */ - -#define RU_STATUS 0x70 /* RU status, 0=idle */ -#define RU_SUSPEND 0x10 /* RU suspended */ -#define RU_NOSPACE 0x20 /* RU no resources */ -#define RU_READY 0x40 /* RU is ready */ - -/* - * Receive Frame Descriptor (RFD) - */ -struct rfd_struct -{ - u8 stat_low; /* status word */ - u8 stat_high; /* status word */ - u8 rfd_sf; /* 82596 mode only */ - u8 last; /* Bit15,Last Frame on List / Bit14,suspend */ - u16 next; /* linkoffset to next RFD */ - u16 rbd_offset; /* pointeroffset to RBD-buffer */ - u8 dest[6]; /* ethernet-address, destination */ - u8 source[6]; /* ethernet-address, source */ - u16 length; /* 802.3 frame-length */ - u16 zero_dummy; /* dummy */ -}; - -#define RFD_LAST 0x80 /* last: last rfd in the list */ -#define RFD_SUSP 0x40 /* last: suspend RU after */ -#define RFD_COMPL 0x80 -#define RFD_OK 0x20 -#define RFD_BUSY 0x40 -#define RFD_ERR_LEN 0x10 /* Length error (if enabled length-checking */ -#define RFD_ERR_CRC 0x08 /* CRC error */ -#define RFD_ERR_ALGN 0x04 /* Alignment error */ -#define RFD_ERR_RNR 0x02 /* status: receiver out of resources */ -#define RFD_ERR_OVR 0x01 /* DMA Overrun! */ - -#define RFD_ERR_FTS 0x0080 /* Frame to short */ -#define RFD_ERR_NEOP 0x0040 /* No EOP flag (for bitstuffing only) */ -#define RFD_ERR_TRUN 0x0020 /* (82596 only/SF mode) indicates truncated frame */ -#define RFD_MATCHADD 0x0002 /* status: Destinationaddress !matches IA (only 82596) */ -#define RFD_COLLDET 0x0001 /* Detected collision during reception */ - -/* - * Receive Buffer Descriptor (RBD) - */ -struct rbd_struct -{ - u16 status; /* status word,number of used bytes in buff */ - u16 next; /* pointeroffset to next RBD */ - u32 buffer; /* receive buffer address pointer */ - u16 size; /* size of this buffer */ - u16 zero_dummy; /* dummy */ -}; - -#define RBD_LAST 0x8000 /* last buffer */ -#define RBD_USED 0x4000 /* this buffer has data */ -#define RBD_MASK 0x3fff /* size-mask for length */ - -/* - * Statusvalues for Commands/RFD - */ -#define STAT_COMPL 0x8000 /* status: frame/command is complete */ -#define STAT_BUSY 0x4000 /* status: frame/command is busy */ -#define STAT_OK 0x2000 /* status: frame/command is ok */ - -/* - * Action-Commands - */ -#define CMD_NOP 0x0000 /* NOP */ -#define CMD_IASETUP 0x0001 /* initial address setup command */ -#define CMD_CONFIGURE 0x0002 /* configure command */ -#define CMD_MCSETUP 0x0003 /* MC setup command */ -#define CMD_XMIT 0x0004 /* transmit command */ -#define CMD_TDR 0x0005 /* time domain reflectometer (TDR) command */ -#define CMD_DUMP 0x0006 /* dump command */ -#define CMD_DIAGNOSE 0x0007 /* diagnose command */ - -/* - * Action command bits - */ -#define CMD_LAST 0x8000 /* indicates last command in the CBL */ -#define CMD_SUSPEND 0x4000 /* suspend CU after this CB */ -#define CMD_INT 0x2000 /* generate interrupt after execution */ - -/* - * NOP - command - */ -struct nop_cmd_struct -{ - u16 cmd_status; /* status of this command */ - u16 cmd_cmd; /* the command itself (+bits) */ - u16 cmd_link; /* offsetpointer to next command */ -}; - -/* - * IA Setup command - */ -struct iasetup_cmd_struct -{ - u16 cmd_status; - u16 cmd_cmd; - u16 cmd_link; - u8 iaddr[6]; -}; - -/* - * Configure command - */ -struct configure_cmd_struct -{ - u16 cmd_status; - u16 cmd_cmd; - u16 cmd_link; - u8 byte_cnt; /* size of the config-cmd */ - u8 fifo; /* fifo/recv monitor */ - u8 sav_bf; /* save bad frames (bit7=1)*/ - u8 adr_len; /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/ - u8 priority; /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */ - u8 ifs; /* inter frame spacing */ - u8 time_low; /* slot time low */ - u8 time_high; /* slot time high(0-2) and max. retries(4-7) */ - u8 promisc; /* promisc-mode(0) , et al (1-7) */ - u8 carr_coll; /* carrier(0-3)/collision(4-7) stuff */ - u8 fram_len; /* minimal frame len */ - u8 dummy; /* dummy */ -}; - -/* - * Multicast Setup command - */ -struct mcsetup_cmd_struct -{ - u16 cmd_status; - u16 cmd_cmd; - u16 cmd_link; - u16 mc_cnt; /* number of bytes in the MC-List */ - u8 mc_list[0][6]; /* pointer to 6 bytes entries */ -}; - -/* - * DUMP command - */ -struct dump_cmd_struct -{ - u16 cmd_status; - u16 cmd_cmd; - u16 cmd_link; - u16 dump_offset; /* pointeroffset to DUMP space */ -}; - -/* - * transmit command - */ -struct transmit_cmd_struct -{ - u16 cmd_status; - u16 cmd_cmd; - u16 cmd_link; - u16 tbd_offset; /* pointeroffset to TBD */ - u8 dest[6]; /* destination address of the frame */ - u16 length; /* user defined: 802.3 length / Ether type */ -}; - -#define TCMD_ERRMASK 0x0fa0 -#define TCMD_MAXCOLLMASK 0x000f -#define TCMD_MAXCOLL 0x0020 -#define TCMD_HEARTBEAT 0x0040 -#define TCMD_DEFERRED 0x0080 -#define TCMD_UNDERRUN 0x0100 -#define TCMD_LOSTCTS 0x0200 -#define TCMD_NOCARRIER 0x0400 -#define TCMD_LATECOLL 0x0800 - -struct tdr_cmd_struct -{ - u16 cmd_status; - u16 cmd_cmd; - u16 cmd_link; - u16 status; -}; - -#define TDR_LNK_OK 0x8000 /* No link problem identified */ -#define TDR_XCVR_PRB 0x4000 /* indicates a transceiver problem */ -#define TDR_ET_OPN 0x2000 /* open, no correct termination */ -#define TDR_ET_SRT 0x1000 /* TDR detected a short circuit */ -#define TDR_TIMEMASK 0x07ff /* mask for the time field */ - -/* - * Transmit Buffer Descriptor (TBD) - */ -struct tbd_struct -{ - u16 size; /* size + EOF-Flag(15) */ - u16 next; /* pointeroffset to next TBD */ - u32 buffer; /* pointer to buffer */ -}; - -#define TBD_LAST 0x8000 /* EOF-Flag, indicates last buffer in list */ - - - - -- cgit v1.2.3-70-g09d2