diff options
Diffstat (limited to 'drivers/net/ethernet/i825xx')
-rw-r--r-- | drivers/net/ethernet/i825xx/3c523.c | 1312 | ||||
-rw-r--r-- | drivers/net/ethernet/i825xx/3c523.h | 355 | ||||
-rw-r--r-- | drivers/net/ethernet/i825xx/3c527.c | 1660 | ||||
-rw-r--r-- | drivers/net/ethernet/i825xx/3c527.h | 81 | ||||
-rw-r--r-- | drivers/net/ethernet/i825xx/Kconfig | 22 | ||||
-rw-r--r-- | drivers/net/ethernet/i825xx/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/i825xx/eexpress.c | 60 |
7 files changed, 1 insertions, 3491 deletions
diff --git a/drivers/net/ethernet/i825xx/3c523.c b/drivers/net/ethernet/i825xx/3c523.c deleted file mode 100644 index 8451ecd4c1ec..000000000000 --- a/drivers/net/ethernet/i825xx/3c523.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* - net-3-driver for the 3c523 Etherlink/MC 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. - - Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca) - - This is basically Michael Hipp's ni52 driver, with a new probing - algorithm and some minor changes to the 82586 CA and reset routines. - Thanks a lot Michael for a really clean i82586 implementation! Unless - otherwise documented in ni52.c, any bugs are mine. - - Contrary to the Ethernet-HOWTO, this isn't based on the 3c507 driver in - any way. The ni52 is a lot easier to modify. - - sources: - ni52.c - - Crynwr packet driver collection was a great reference for my first - attempt at this sucker. The 3c507 driver also helped, until I noticed - that ni52.c was a lot nicer. - - EtherLink/MC: Micro Channel Ethernet Adapter Technical Reference - Manual, courtesy of 3Com CardFacts, documents the 3c523-specific - stuff. Information on CardFacts is found in the Ethernet HOWTO. - Also see <a href="http://www.3com.com/"> - - Microprocessor Communications Support Chips, T.J. Byers, ISBN - 0-444-01224-9, has a section on the i82586. It tells you just enough - to know that you really don't want to learn how to program the chip. - - The original device probe code was stolen from ps2esdi.c - - Known Problems: - Since most of the code was stolen from ni52.c, you'll run across the - same bugs in the 0.62 version of ni52.c, plus maybe a few because of - the 3c523 idiosynchacies. The 3c523 has 16K of RAM though, so there - shouldn't be the overrun problem that the 8K ni52 has. - - This driver is for a 16K adapter. It should work fine on the 64K - adapters, but it will only use one of the 4 banks of RAM. Modifying - this for the 64K version would require a lot of heinous bank - switching, which I'm sure not interested in doing. If you try to - implement a bank switching version, you'll basically have to remember - what bank is enabled and do a switch every time you access a memory - location that's not current. You'll also have to remap pointers on - the driver side, because it only knows about 16K of the memory. - Anyone desperate or masochistic enough to try? - - It seems to be stable now when multiple transmit buffers are used. I - can't see any performance difference, but then I'm working on a 386SX. - - Multicast doesn't work. It doesn't even pretend to work. Don't use - it. Don't compile your kernel with multicast support. I don't know - why. - - Features: - This driver is useable as a loadable module. If you try to specify an - IRQ or a IO address (via insmod 3c523.o irq=xx io=0xyyy), it will - search the MCA slots until it finds a 3c523 with the specified - parameters. - - This driver does support multiple ethernet cards when used as a module - (up to MAX_3C523_CARDS, the default being 4) - - This has been tested with both BNC and TP versions, internal and - external transceivers. Haven't tested with the 64K version (that I - know of). - - History: - Jan 1st, 1996 - first public release - Feb 4th, 1996 - update to 1.3.59, incorporated multicast diffs from ni52.c - Feb 15th, 1996 - added shared irq support - Apr 1999 - added support for multiple cards when used as a module - added option to disable multicast as is causes problems - Ganesh Sittampalam <ganesh.sittampalam@magdalen.oxford.ac.uk> - Stuart Adamson <stuart.adamson@compsoc.net> - Nov 2001 - added support for ethtool (jgarzik) - - $Header: /fsys2/home/chrisb/linux-1.3.59-MCA/drivers/net/RCS/3c523.c,v 1.1 1996/02/05 01:53:46 chrisb Exp chrisb $ - */ - -#define DRV_NAME "3c523" -#define DRV_VERSION "17-Nov-2001" - -#include <linux/init.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/string.h> -#include <linux/errno.h> -#include <linux/ioport.h> -#include <linux/skbuff.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/mca-legacy.h> -#include <linux/ethtool.h> -#include <linux/bitops.h> -#include <linux/jiffies.h> - -#include <asm/uaccess.h> -#include <asm/processor.h> -#include <asm/io.h> - -#include "3c523.h" - -/*************************************************************************/ -#define DEBUG /* debug on */ -#define SYSBUSVAL 0 /* 1 = 8 Bit, 0 = 16 bit - 3c523 only does 16 bit */ -#undef ELMC_MULTICAST /* Disable multicast support as it is somewhat seriously broken at the moment */ - -#define make32(ptr16) (p->memtop + (short) (ptr16) ) -#define make24(ptr32) ((char *) (ptr32) - p->base) -#define make16(ptr32) ((unsigned short) ((unsigned long) (ptr32) - (unsigned long) p->memtop )) - -/*************************************************************************/ -/* - Tables to which we can map values in the configuration registers. - */ -static int irq_table[] __initdata = { - 12, 7, 3, 9 -}; - -static int csr_table[] __initdata = { - 0x300, 0x1300, 0x2300, 0x3300 -}; - -static int shm_table[] __initdata = { - 0x0c0000, 0x0c8000, 0x0d0000, 0x0d8000 -}; - -/******************* 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 this 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 */ - -#if (NUM_XMIT_BUFFS == 1) -#define NO_NOPCOMMANDS /* only possible with NUM_XMIT_BUFFS=1 */ -#endif - -/**************************************************************************/ - -#define DELAY(x) { mdelay(32 * x); } - -/* a much shorter delay: */ -#define DELAY_16(); { udelay(16) ; } - -/* wait for command with timeout: */ -#define WAIT_4_SCB_CMD() { int i; \ - for(i=0;i<1024;i++) { \ - if(!p->scb->cmd) break; \ - DELAY_16(); \ - if(i == 1023) { \ - pr_warning("%s:%d: scb_cmd timed out .. resetting i82586\n",\ - dev->name,__LINE__); \ - elmc_id_reset586(); } } } - -static irqreturn_t elmc_interrupt(int irq, void *dev_id); -static int elmc_open(struct net_device *dev); -static int elmc_close(struct net_device *dev); -static netdev_tx_t elmc_send_packet(struct sk_buff *, struct net_device *); -static struct net_device_stats *elmc_get_stats(struct net_device *dev); -static void elmc_timeout(struct net_device *dev); -#ifdef ELMC_MULTICAST -static void set_multicast_list(struct net_device *dev); -#endif -static const struct ethtool_ops netdev_ethtool_ops; - -/* helper-functions */ -static int init586(struct net_device *dev); -static int check586(struct net_device *dev, unsigned long where, unsigned size); -static void alloc586(struct net_device *dev); -static void startrecv586(struct net_device *dev); -static void *alloc_rfa(struct net_device *dev, void *ptr); -static void elmc_rcv_int(struct net_device *dev); -static void elmc_xmt_int(struct net_device *dev); -static void elmc_rnr_int(struct net_device *dev); - -struct priv { - unsigned long base; - char *memtop; - unsigned long mapped_start; /* Start of ioremap */ - volatile struct rfd_struct *rfd_last, *rfd_top, *rfd_first; - volatile struct scp_struct *scp; /* volatile is important */ - volatile struct iscp_struct *iscp; /* volatile is important */ - volatile struct scb_struct *scb; /* volatile is important */ - volatile struct tbd_struct *xmit_buffs[NUM_XMIT_BUFFS]; -#if (NUM_XMIT_BUFFS == 1) - volatile struct transmit_cmd_struct *xmit_cmds[2]; - volatile struct nop_cmd_struct *nop_cmds[2]; -#else - volatile struct transmit_cmd_struct *xmit_cmds[NUM_XMIT_BUFFS]; - volatile struct nop_cmd_struct *nop_cmds[NUM_XMIT_BUFFS]; -#endif - volatile int nop_point, num_recv_buffs; - volatile char *xmit_cbuffs[NUM_XMIT_BUFFS]; - volatile int xmit_count, xmit_last; - volatile int slot; -}; - -#define elmc_attn586() {elmc_do_attn586(dev->base_addr,ELMC_CTRL_INTE);} -#define elmc_reset586() {elmc_do_reset586(dev->base_addr,ELMC_CTRL_INTE);} - -/* with interrupts disabled - this will clear the interrupt bit in the - 3c523 control register, and won't put it back. This effectively - disables interrupts on the card. */ -#define elmc_id_attn586() {elmc_do_attn586(dev->base_addr,0);} -#define elmc_id_reset586() {elmc_do_reset586(dev->base_addr,0);} - -/*************************************************************************/ -/* - Do a Channel Attention on the 3c523. This is extremely board dependent. - */ -static void elmc_do_attn586(int ioaddr, int ints) -{ - /* the 3c523 requires a minimum of 500 ns. The delays here might be - a little too large, and hence they may cut the performance of the - card slightly. If someone who knows a little more about Linux - timing would care to play with these, I'd appreciate it. */ - - /* this bit masking stuff is crap. I'd rather have separate - registers with strobe triggers for each of these functions. <sigh> - Ya take what ya got. */ - - outb(ELMC_CTRL_RST | 0x3 | ELMC_CTRL_CA | ints, ioaddr + ELMC_CTRL); - DELAY_16(); /* > 500 ns */ - outb(ELMC_CTRL_RST | 0x3 | ints, ioaddr + ELMC_CTRL); -} - -/*************************************************************************/ -/* - Reset the 82586 on the 3c523. Also very board dependent. - */ -static void elmc_do_reset586(int ioaddr, int ints) -{ - /* toggle the RST bit low then high */ - outb(0x3 | ELMC_CTRL_LBK, ioaddr + ELMC_CTRL); - DELAY_16(); /* > 500 ns */ - outb(ELMC_CTRL_RST | ELMC_CTRL_LBK | 0x3, ioaddr + ELMC_CTRL); - - elmc_do_attn586(ioaddr, ints); -} - -/********************************************** - * close device - */ - -static int elmc_close(struct net_device *dev) -{ - netif_stop_queue(dev); - elmc_id_reset586(); /* the hard way to stop the receiver */ - free_irq(dev->irq, dev); - return 0; -} - -/********************************************** - * open device - */ - -static int elmc_open(struct net_device *dev) -{ - int ret; - - elmc_id_attn586(); /* disable interrupts */ - - ret = request_irq(dev->irq, elmc_interrupt, IRQF_SHARED, - dev->name, dev); - if (ret) { - pr_err("%s: couldn't get irq %d\n", dev->name, dev->irq); - elmc_id_reset586(); - return ret; - } - alloc586(dev); - init586(dev); - startrecv586(dev); - netif_start_queue(dev); - return 0; /* most done by init */ -} - -/********************************************** - * Check to see if there's an 82586 out there. - */ - -static int __init check586(struct net_device *dev, unsigned long where, unsigned size) -{ - struct priv *p = netdev_priv(dev); - char *iscp_addrs[2]; - int i = 0; - - p->base = (unsigned long) isa_bus_to_virt((unsigned long)where) + size - 0x01000000; - p->memtop = isa_bus_to_virt((unsigned long)where) + size; - p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS); - memset((char *) p->scp, 0, sizeof(struct scp_struct)); - p->scp->sysbus = SYSBUSVAL; /* 1 = 8Bit-Bus, 0 = 16 Bit */ - - iscp_addrs[0] = isa_bus_to_virt((unsigned long)where); - iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct); - - for (i = 0; i < 2; i++) { - p->iscp = (struct iscp_struct *) iscp_addrs[i]; - memset((char *) p->iscp, 0, sizeof(struct iscp_struct)); - - p->scp->iscp = make24(p->iscp); - p->iscp->busy = 1; - - elmc_id_reset586(); - - /* reset586 does an implicit CA */ - - /* apparently, you sometimes have to kick the 82586 twice... */ - elmc_id_attn586(); - DELAY(1); - - if (p->iscp->busy) { /* i82586 clears 'busy' after successful init */ - return 0; - } - } - return 1; -} - -/****************************************************************** - * set iscp at the right place, called by elmc_probe and open586. - */ - -static void alloc586(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - - elmc_id_reset586(); - DELAY(2); - - p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS); - p->scb = (struct scb_struct *) isa_bus_to_virt(dev->mem_start); - p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct)); - - memset((char *) p->iscp, 0, sizeof(struct iscp_struct)); - memset((char *) p->scp, 0, sizeof(struct scp_struct)); - - p->scp->iscp = make24(p->iscp); - p->scp->sysbus = SYSBUSVAL; - p->iscp->scb_offset = make16(p->scb); - - p->iscp->busy = 1; - elmc_id_reset586(); - elmc_id_attn586(); - - DELAY(2); - - if (p->iscp->busy) - pr_err("%s: Init-Problems (alloc).\n", dev->name); - - memset((char *) p->scb, 0, sizeof(struct scb_struct)); -} - -/*****************************************************************/ - -static int elmc_getinfo(char *buf, int slot, void *d) -{ - int len = 0; - struct net_device *dev = d; - - if (dev == NULL) - return len; - - len += sprintf(buf + len, "Revision: 0x%x\n", - inb(dev->base_addr + ELMC_REVISION) & 0xf); - len += sprintf(buf + len, "IRQ: %d\n", dev->irq); - len += sprintf(buf + len, "IO Address: %#lx-%#lx\n", dev->base_addr, - dev->base_addr + ELMC_IO_EXTENT); - len += sprintf(buf + len, "Memory: %#lx-%#lx\n", dev->mem_start, - dev->mem_end - 1); - len += sprintf(buf + len, "Transceiver: %s\n", dev->if_port ? - "External" : "Internal"); - len += sprintf(buf + len, "Device: %s\n", dev->name); - len += sprintf(buf + len, "Hardware Address: %pM\n", - dev->dev_addr); - - return len; -} /* elmc_getinfo() */ - -static const struct net_device_ops netdev_ops = { - .ndo_open = elmc_open, - .ndo_stop = elmc_close, - .ndo_get_stats = elmc_get_stats, - .ndo_start_xmit = elmc_send_packet, - .ndo_tx_timeout = elmc_timeout, -#ifdef ELMC_MULTICAST - .ndo_set_rx_mode = set_multicast_list, -#endif - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/*****************************************************************/ - -static int __init do_elmc_probe(struct net_device *dev) -{ - static int slot; - int base_addr = dev->base_addr; - int irq = dev->irq; - u_char status = 0; - u_char revision = 0; - int i = 0; - unsigned int size = 0; - int retval; - struct priv *pr = netdev_priv(dev); - - if (MCA_bus == 0) { - return -ENODEV; - } - /* search through the slots for the 3c523. */ - slot = mca_find_adapter(ELMC_MCA_ID, 0); - while (slot != -1) { - status = mca_read_stored_pos(slot, 2); - - dev->irq=irq_table[(status & ELMC_STATUS_IRQ_SELECT) >> 6]; - dev->base_addr=csr_table[(status & ELMC_STATUS_CSR_SELECT) >> 1]; - - /* - If we're trying to match a specified irq or IO address, - we'll reject a match unless it's what we're looking for. - Also reject it if the card is already in use. - */ - - if ((irq && irq != dev->irq) || - (base_addr && base_addr != dev->base_addr)) { - slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); - continue; - } - if (!request_region(dev->base_addr, ELMC_IO_EXTENT, DRV_NAME)) { - slot = mca_find_adapter(ELMC_MCA_ID, slot + 1); - continue; - } - - /* found what we're looking for... */ - break; - } - - /* we didn't find any 3c523 in the slots we checked for */ - if (slot == MCA_NOTFOUND) - return (base_addr || irq) ? -ENXIO : -ENODEV; - - mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC"); - mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev); - - /* if we get this far, adapter has been found - carry on */ - pr_info("%s: 3c523 adapter found in slot %d\n", dev->name, slot + 1); - - /* Now we extract configuration info from the card. - The 3c523 provides information in two of the POS registers, but - the second one is only needed if we want to tell the card what IRQ - to use. I suspect that whoever sets the thing up initially would - prefer we don't screw with those things. - - Note that we read the status info when we found the card... - - See 3c523.h for more details. - */ - - /* revision is stored in the first 4 bits of the revision register */ - revision = inb(dev->base_addr + ELMC_REVISION) & 0xf; - - /* according to docs, we read the interrupt and write it back to - the IRQ select register, since the POST might not configure the IRQ - properly. */ - switch (dev->irq) { - case 3: - mca_write_pos(slot, 3, 0x04); - break; - case 7: - mca_write_pos(slot, 3, 0x02); - break; - case 9: - mca_write_pos(slot, 3, 0x08); - break; - case 12: - mca_write_pos(slot, 3, 0x01); - break; - } - - pr->slot = slot; - - pr_info("%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision, - dev->base_addr); - - /* Determine if we're using the on-board transceiver (i.e. coax) or - an external one. The information is pretty much useless, but I - guess it's worth brownie points. */ - dev->if_port = (status & ELMC_STATUS_DISABLE_THIN); - - /* The 3c523 has a 24K chunk of memory. The first 16K is the - shared memory, while the last 8K is for the EtherStart BIOS ROM. - Which we don't care much about here. We'll just tell Linux that - we're using 16K. MCA won't permit address space conflicts caused - by not mapping the other 8K. */ - dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]; - - /* We're using MCA, so it's a given that the information about memory - size is correct. The Crynwr drivers do something like this. */ - - elmc_id_reset586(); /* seems like a good idea before checking it... */ - - size = 0x4000; /* check for 16K mem */ - if (!check586(dev, dev->mem_start, size)) { - pr_err("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name, - dev->mem_start); - retval = -ENODEV; - goto err_out; - } - dev->mem_end = dev->mem_start + size; /* set mem_end showed by 'ifconfig' */ - - pr->memtop = isa_bus_to_virt(dev->mem_start) + size; - pr->base = (unsigned long) isa_bus_to_virt(dev->mem_start) + size - 0x01000000; - alloc586(dev); - - elmc_id_reset586(); /* make sure it doesn't generate spurious ints */ - - /* set number of receive-buffs according to memsize */ - pr->num_recv_buffs = NUM_RECV_BUFFS_16; - - /* dump all the assorted information */ - pr_info("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name, - dev->irq, dev->if_port ? "ex" : "in", - dev->mem_start, dev->mem_end - 1); - - /* The hardware address for the 3c523 is stored in the first six - bytes of the IO address. */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = inb(dev->base_addr + i); - - pr_info("%s: hardware address %pM\n", - dev->name, dev->dev_addr); - - dev->netdev_ops = &netdev_ops; - dev->watchdog_timeo = HZ; - dev->ethtool_ops = &netdev_ethtool_ops; - - /* note that we haven't actually requested the IRQ from the kernel. - That gets done in elmc_open(). I'm not sure that's such a good idea, - but it works, so I'll go with it. */ - -#ifndef ELMC_MULTICAST - dev->flags&=~IFF_MULTICAST; /* Multicast doesn't work */ -#endif - - retval = register_netdev(dev); - if (retval) - goto err_out; - - return 0; -err_out: - mca_set_adapter_procfn(slot, NULL, NULL); - release_region(dev->base_addr, ELMC_IO_EXTENT); - return retval; -} - -#ifdef MODULE -static void cleanup_card(struct net_device *dev) -{ - mca_set_adapter_procfn(((struct priv *)netdev_priv(dev))->slot, - NULL, NULL); - release_region(dev->base_addr, ELMC_IO_EXTENT); -} -#else -struct net_device * __init elmc_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct priv)); - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - err = do_elmc_probe(dev); - if (err) - goto out; - return dev; -out: - free_netdev(dev); - return ERR_PTR(err); -} -#endif - -/********************************************** - * init the chip (elmc-interrupt should be disabled?!) - * needs a correct 'allocated' memory - */ - -static int init586(struct net_device *dev) -{ - void *ptr; - unsigned long s; - int i, result = 0; - struct priv *p = netdev_priv(dev); - volatile struct configure_cmd_struct *cfg_cmd; - volatile struct iasetup_cmd_struct *ias_cmd; - volatile struct tdr_cmd_struct *tdr_cmd; - volatile struct mcsetup_cmd_struct *mc_cmd; - struct netdev_hw_addr *ha; - int num_addrs = netdev_mc_count(dev); - - ptr = (void *) ((char *) p->scb + sizeof(struct scb_struct)); - - cfg_cmd = (struct configure_cmd_struct *) ptr; /* configure-command */ - cfg_cmd->cmd_status = 0; - cfg_cmd->cmd_cmd = CMD_CONFIGURE | CMD_LAST; - cfg_cmd->cmd_link = 0xffff; - - cfg_cmd->byte_cnt = 0x0a; /* number of cfg bytes */ - cfg_cmd->fifo = 0x08; /* fifo-limit (8=tx:32/rx:64) */ - cfg_cmd->sav_bf = 0x40; /* hold or discard bad recv frames (bit 7) */ - cfg_cmd->adr_len = 0x2e; /* addr_len |!src_insert |pre-len |loopback */ - cfg_cmd->priority = 0x00; - cfg_cmd->ifs = 0x60; - cfg_cmd->time_low = 0x00; - cfg_cmd->time_high = 0xf2; - cfg_cmd->promisc = 0; - if (dev->flags & (IFF_ALLMULTI | IFF_PROMISC)) - cfg_cmd->promisc = 1; - cfg_cmd->carr_coll = 0x00; - - p->scb->cbl_offset = make16(cfg_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - elmc_id_attn586(); - - s = jiffies; /* warning: only active with interrupts on !! */ - while (!(cfg_cmd->cmd_status & STAT_COMPL)) { - if (time_after(jiffies, s + 30*HZ/100)) - break; - } - - if ((cfg_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_COMPL | STAT_OK)) { - pr_warning("%s (elmc): configure command failed: %x\n", dev->name, cfg_cmd->cmd_status); - return 1; - } - /* - * individual address setup - */ - ias_cmd = (struct iasetup_cmd_struct *) ptr; - - ias_cmd->cmd_status = 0; - ias_cmd->cmd_cmd = CMD_IASETUP | CMD_LAST; - ias_cmd->cmd_link = 0xffff; - - memcpy((char *) &ias_cmd->iaddr, (char *) dev->dev_addr, ETH_ALEN); - - p->scb->cbl_offset = make16(ias_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - elmc_id_attn586(); - - s = jiffies; - while (!(ias_cmd->cmd_status & STAT_COMPL)) { - if (time_after(jiffies, s + 30*HZ/100)) - break; - } - - if ((ias_cmd->cmd_status & (STAT_OK | STAT_COMPL)) != (STAT_OK | STAT_COMPL)) { - pr_warning("%s (elmc): individual address setup command failed: %04x\n", - dev->name, ias_cmd->cmd_status); - return 1; - } - /* - * TDR, wire check .. e.g. no resistor e.t.c - */ - tdr_cmd = (struct tdr_cmd_struct *) ptr; - - tdr_cmd->cmd_status = 0; - tdr_cmd->cmd_cmd = CMD_TDR | CMD_LAST; - tdr_cmd->cmd_link = 0xffff; - tdr_cmd->status = 0; - - p->scb->cbl_offset = make16(tdr_cmd); - - p->scb->cmd = CUC_START; /* cmd.-unit start */ - elmc_attn586(); - - s = jiffies; - while (!(tdr_cmd->cmd_status & STAT_COMPL)) { - if (time_after(jiffies, s + 30*HZ/100)) { - pr_warning("%s: %d Problems while running the TDR.\n", dev->name, __LINE__); - result = 1; - break; - } - } - - if (!result) { - DELAY(2); /* wait for result */ - result = tdr_cmd->status; - - p->scb->cmd = p->scb->status & STAT_MASK; - elmc_id_attn586(); /* ack the interrupts */ - - if (result & TDR_LNK_OK) { - /* empty */ - } else if (result & TDR_XCVR_PRB) { - pr_warning("%s: TDR: Transceiver problem!\n", dev->name); - } else if (result & TDR_ET_OPN) { - pr_warning("%s: TDR: No correct termination %d clocks away.\n", dev->name, result & TDR_TIMEMASK); - } else if (result & TDR_ET_SRT) { - if (result & TDR_TIMEMASK) /* time == 0 -> strange :-) */ - pr_warning("%s: TDR: Detected a short circuit %d clocks away.\n", dev->name, result & TDR_TIMEMASK); - } else { - pr_warning("%s: TDR: Unknown status %04x\n", dev->name, result); - } - } - /* - * ack interrupts - */ - p->scb->cmd = p->scb->status & STAT_MASK; - elmc_id_attn586(); - - /* - * alloc nop/xmit-cmds - */ -#if (NUM_XMIT_BUFFS == 1) - for (i = 0; i < 2; i++) { - p->nop_cmds[i] = (struct nop_cmd_struct *) ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); - ptr = (char *) ptr + sizeof(struct nop_cmd_struct); - } - p->xmit_cmds[0] = (struct transmit_cmd_struct *) ptr; /* transmit cmd/buff 0 */ - ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); -#else - for (i = 0; i < NUM_XMIT_BUFFS; i++) { - p->nop_cmds[i] = (struct nop_cmd_struct *) ptr; - p->nop_cmds[i]->cmd_cmd = CMD_NOP; - p->nop_cmds[i]->cmd_status = 0; - p->nop_cmds[i]->cmd_link = make16((p->nop_cmds[i])); - ptr = (char *) ptr + sizeof(struct nop_cmd_struct); - p->xmit_cmds[i] = (struct transmit_cmd_struct *) ptr; /*transmit cmd/buff 0 */ - ptr = (char *) ptr + sizeof(struct transmit_cmd_struct); - } -#endif - - ptr = alloc_rfa(dev, (void *) ptr); /* init receive-frame-area */ - - /* - * Multicast setup - */ - - if (num_addrs) { - /* I don't understand this: do we really need memory after the init? */ - int len = ((char *) p->iscp - (char *) ptr - 8) / 6; - if (len <= 0) { - pr_err("%s: Ooooops, no memory for MC-Setup!\n", dev->name); - } else { - if (len < num_addrs) { - num_addrs = len; - pr_warning("%s: Sorry, can only apply %d MC-Address(es).\n", - dev->name, num_addrs); - } - mc_cmd = (struct mcsetup_cmd_struct *) ptr; - mc_cmd->cmd_status = 0; - mc_cmd->cmd_cmd = CMD_MCSETUP | CMD_LAST; - mc_cmd->cmd_link = 0xffff; - mc_cmd->mc_cnt = num_addrs * 6; - i = 0; - netdev_for_each_mc_addr(ha, dev) - memcpy((char *) mc_cmd->mc_list[i++], - ha->addr, 6); - p->scb->cbl_offset = make16(mc_cmd); - p->scb->cmd = CUC_START; - elmc_id_attn586(); - s = jiffies; - while (!(mc_cmd->cmd_status & STAT_COMPL)) { - if (time_after(jiffies, s + 30*HZ/100)) - break; - } - if (!(mc_cmd->cmd_status & STAT_COMPL)) { - pr_warning("%s: Can't apply multicast-address-list.\n", dev->name); - } - } - } - /* - * alloc xmit-buffs / init xmit_cmds - */ - for (i = 0; i < NUM_XMIT_BUFFS; i++) { - p->xmit_cbuffs[i] = (char *) ptr; /* char-buffs */ - ptr = (char *) ptr + XMIT_BUFF_SIZE; - p->xmit_buffs[i] = (struct tbd_struct *) ptr; /* TBD */ - ptr = (char *) ptr + sizeof(struct tbd_struct); - if ((void *) ptr > (void *) p->iscp) { - pr_err("%s: not enough shared-mem for your configuration!\n", dev->name); - return 1; - } - memset((char *) (p->xmit_cmds[i]), 0, sizeof(struct transmit_cmd_struct)); - memset((char *) (p->xmit_buffs[i]), 0, sizeof(struct tbd_struct)); - p->xmit_cmds[i]->cmd_status = STAT_COMPL; - p->xmit_cmds[i]->cmd_cmd = CMD_XMIT | CMD_INT; - p->xmit_cmds[i]->tbd_offset = make16((p->xmit_buffs[i])); - p->xmit_buffs[i]->next = 0xffff; - p->xmit_buffs[i]->buffer = make24((p->xmit_cbuffs[i])); - } - - p->xmit_count = 0; - p->xmit_last = 0; -#ifndef NO_NOPCOMMANDS - p->nop_point = 0; -#endif - - /* - * 'start transmitter' (nop-loop) - */ -#ifndef NO_NOPCOMMANDS - p->scb->cbl_offset = make16(p->nop_cmds[0]); - p->scb->cmd = CUC_START; - elmc_id_attn586(); - WAIT_4_SCB_CMD(); -#else - p->xmit_cmds[0]->cmd_link = 0xffff; - p->xmit_cmds[0]->cmd_cmd = CMD_XMIT | CMD_LAST | CMD_INT; -#endif - - return 0; -} - -/****************************************************** - * This is a helper routine for elmc_rnr_int() and init586(). - * It sets up the Receive Frame Area (RFA). - */ - -static void *alloc_rfa(struct net_device *dev, void *ptr) -{ - volatile struct rfd_struct *rfd = (struct rfd_struct *) ptr; - volatile struct rbd_struct *rbd; - int i; - struct priv *p = netdev_priv(dev); - - memset((char *) rfd, 0, sizeof(struct rfd_struct) * p->num_recv_buffs); - p->rfd_first = rfd; - - for (i = 0; i < p->num_recv_buffs; i++) { - rfd[i].next = make16(rfd + (i + 1) % p->num_recv_buffs); - } - rfd[p->num_recv_buffs - 1].last = RFD_SUSP; /* RU suspend */ - - ptr = (void *) (rfd + p->num_recv_buffs); - - rbd = (struct rbd_struct *) ptr; - ptr = (void *) (rbd + p->num_recv_buffs); - - /* clr descriptors */ - memset((char *) rbd, 0, sizeof(struct rbd_struct) * p->num_recv_buffs); - - for (i = 0; i < p->num_recv_buffs; i++) { - rbd[i].next = make16((rbd + (i + 1) % p->num_recv_buffs)); - rbd[i].size = RECV_BUFF_SIZE; - rbd[i].buffer = make24(ptr); - ptr = (char *) ptr + RECV_BUFF_SIZE; - } - - p->rfd_top = p->rfd_first; - p->rfd_last = p->rfd_first + p->num_recv_buffs - 1; - - p->scb->rfa_offset = make16(p->rfd_first); - p->rfd_first->rbd_offset = make16(rbd); - - return ptr; -} - - -/************************************************** - * Interrupt Handler ... - */ - -static irqreturn_t -elmc_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - unsigned short stat; - struct priv *p; - - if (!netif_running(dev)) { - /* The 3c523 has this habit of generating interrupts during the - reset. I'm not sure if the ni52 has this same problem, but it's - really annoying if we haven't finished initializing it. I was - hoping all the elmc_id_* commands would disable this, but I - might have missed a few. */ - - elmc_id_attn586(); /* ack inter. and disable any more */ - return IRQ_HANDLED; - } else if (!(ELMC_CTRL_INT & inb(dev->base_addr + ELMC_CTRL))) { - /* wasn't this device */ - return IRQ_NONE; - } - /* reading ELMC_CTRL also clears the INT bit. */ - - p = netdev_priv(dev); - - while ((stat = p->scb->status & STAT_MASK)) - { - p->scb->cmd = stat; - elmc_attn586(); /* ack inter. */ - - if (stat & STAT_CX) { - /* command with I-bit set complete */ - elmc_xmt_int(dev); - } - if (stat & STAT_FR) { - /* received a frame */ - elmc_rcv_int(dev); - } -#ifndef NO_NOPCOMMANDS - if (stat & STAT_CNA) { - /* CU went 'not ready' */ - if (netif_running(dev)) { - pr_warning("%s: oops! CU has left active state. stat: %04x/%04x.\n", - dev->name, (int) stat, (int) p->scb->status); - } - } -#endif - - if (stat & STAT_RNR) { - /* RU went 'not ready' */ - - if (p->scb->status & RU_SUSPEND) { - /* special case: RU_SUSPEND */ - - WAIT_4_SCB_CMD(); - p->scb->cmd = RUC_RESUME; - elmc_attn586(); - } else { - pr_warning("%s: Receiver-Unit went 'NOT READY': %04x/%04x.\n", - dev->name, (int) stat, (int) p->scb->status); - elmc_rnr_int(dev); - } - } - WAIT_4_SCB_CMD(); /* wait for ack. (elmc_xmt_int can be faster than ack!!) */ - if (p->scb->cmd) { /* timed out? */ - break; - } - } - return IRQ_HANDLED; -} - -/******************************************************* - * receive-interrupt - */ - -static void elmc_rcv_int(struct net_device *dev) -{ - int status; - unsigned short totlen; - struct sk_buff *skb; - struct rbd_struct *rbd; - struct priv *p = netdev_priv(dev); - - for (; (status = p->rfd_top->status) & STAT_COMPL;) { - rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset); - - if (status & STAT_OK) { /* frame received without error? */ - if ((totlen = rbd->status) & RBD_LAST) { /* the first and the last buffer? */ - totlen &= RBD_MASK; /* length of this frame */ - rbd->status = 0; - skb = netdev_alloc_skb(dev, totlen + 2); - if (skb != NULL) { - skb_reserve(skb, 2); /* 16 byte alignment */ - skb_put(skb,totlen); - skb_copy_to_linear_data(skb, (char *) p->base+(unsigned long) 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 { - pr_warning("%s: received oversized frame.\n", dev->name); - dev->stats.rx_dropped++; - } - } else { /* frame !(ok), only with 'save-bad-frames' */ - pr_warning("%s: oops! rfd-error-status: %04x\n", dev->name, status); - dev->stats.rx_errors++; - } - p->rfd_top->status = 0; - p->rfd_top->last = RFD_SUSP; - p->rfd_last->last = 0; /* delete RU_SUSP */ - p->rfd_last = p->rfd_top; - p->rfd_top = (struct rfd_struct *) make32(p->rfd_top->next); /* step to next RFD */ - } -} - -/********************************************************** - * handle 'Receiver went not ready'. - */ - -static void elmc_rnr_int(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - - dev->stats.rx_errors++; - - WAIT_4_SCB_CMD(); /* wait for the last cmd */ - p->scb->cmd = RUC_ABORT; /* usually the RU is in the 'no resource'-state .. abort it now. */ - elmc_attn586(); - WAIT_4_SCB_CMD(); /* wait for accept cmd. */ - - alloc_rfa(dev, (char *) p->rfd_first); - startrecv586(dev); /* restart RU */ - - pr_warning("%s: Receive-Unit restarted. Status: %04x\n", dev->name, p->scb->status); - -} - -/********************************************************** - * handle xmit - interrupt - */ - -static void elmc_xmt_int(struct net_device *dev) -{ - int status; - struct priv *p = netdev_priv(dev); - - status = p->xmit_cmds[p->xmit_last]->cmd_status; - if (!(status & STAT_COMPL)) { - pr_warning("%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) { - pr_warning("%s: late collision detected.\n", dev->name); - dev->stats.collisions++; - } else if (status & TCMD_NOCARRIER) { - dev->stats.tx_carrier_errors++; - pr_warning("%s: no carrier detected.\n", dev->name); - } else if (status & TCMD_LOSTCTS) { - pr_warning("%s: loss of CTS detected.\n", dev->name); - } else if (status & TCMD_UNDERRUN) { - dev->stats.tx_fifo_errors++; - pr_warning("%s: DMA underrun detected.\n", dev->name); - } else if (status & TCMD_MAXCOLL) { - pr_warning("%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); - - p->scb->rfa_offset = make16(p->rfd_first); - p->scb->cmd = RUC_START; - elmc_attn586(); /* start cmd. */ - WAIT_4_SCB_CMD(); /* wait for accept cmd. (no timeout!!) */ -} - -/****************************************************** - * timeout - */ - -static void elmc_timeout(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - /* COMMAND-UNIT active? */ - if (p->scb->status & CU_ACTIVE) { - pr_debug("%s: strange ... timeout with CU active?!?\n", dev->name); - pr_debug("%s: X0: %04x N0: %04x N1: %04x %d\n", dev->name, - (int)p->xmit_cmds[0]->cmd_status, - (int)p->nop_cmds[0]->cmd_status, - (int)p->nop_cmds[1]->cmd_status, (int)p->nop_point); - p->scb->cmd = CUC_ABORT; - elmc_attn586(); - WAIT_4_SCB_CMD(); - p->scb->cbl_offset = make16(p->nop_cmds[p->nop_point]); - p->scb->cmd = CUC_START; - elmc_attn586(); - WAIT_4_SCB_CMD(); - netif_wake_queue(dev); - } else { - pr_debug("%s: xmitter timed out, try to restart! stat: %04x\n", - dev->name, p->scb->status); - pr_debug("%s: command-stats: %04x %04x\n", dev->name, - p->xmit_cmds[0]->cmd_status, p->xmit_cmds[1]->cmd_status); - elmc_close(dev); - elmc_open(dev); - } -} - -/****************************************************** - * send frame - */ - -static netdev_tx_t elmc_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - int len; - int i; -#ifndef NO_NOPCOMMANDS - int next_nop; -#endif - struct priv *p = netdev_priv(dev); - - netif_stop_queue(dev); - - len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - - if (len != skb->len) - memset((char *) p->xmit_cbuffs[p->xmit_count], 0, ETH_ZLEN); - skb_copy_from_linear_data(skb, (char *) p->xmit_cbuffs[p->xmit_count], skb->len); - -#if (NUM_XMIT_BUFFS == 1) -#ifdef NO_NOPCOMMANDS - p->xmit_buffs[0]->size = TBD_LAST | len; - for (i = 0; i < 16; i++) { - p->scb->cbl_offset = make16(p->xmit_cmds[0]); - p->scb->cmd = CUC_START; - p->xmit_cmds[0]->cmd_status = 0; - elmc_attn586(); - if (!i) { - dev_kfree_skb(skb); - } - WAIT_4_SCB_CMD(); - if ((p->scb->status & CU_ACTIVE)) { /* test it, because CU sometimes doesn't start immediately */ - break; - } - if (p->xmit_cmds[0]->cmd_status) { - break; - } - if (i == 15) { - pr_warning("%s: Can't start transmit-command.\n", dev->name); - } - } -#else - next_nop = (p->nop_point + 1) & 0x1; - p->xmit_buffs[0]->size = TBD_LAST | len; - - p->xmit_cmds[0]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->xmit_cmds[0]->cmd_status = p->nop_cmds[next_nop]->cmd_status = 0; - - p->nop_cmds[p->nop_point]->cmd_link = make16((p->xmit_cmds[0])); - p->nop_point = next_nop; - dev_kfree_skb(skb); -#endif -#else - p->xmit_buffs[p->xmit_count]->size = TBD_LAST | len; - if ((next_nop = p->xmit_count + 1) == NUM_XMIT_BUFFS) { - next_nop = 0; - } - p->xmit_cmds[p->xmit_count]->cmd_status = 0; - p->xmit_cmds[p->xmit_count]->cmd_link = p->nop_cmds[next_nop]->cmd_link - = make16((p->nop_cmds[next_nop])); - p->nop_cmds[next_nop]->cmd_status = 0; - p->nop_cmds[p->xmit_count]->cmd_link = make16((p->xmit_cmds[p->xmit_count])); - p->xmit_count = next_nop; - if (p->xmit_count != p->xmit_last) - netif_wake_queue(dev); - dev_kfree_skb(skb); -#endif - return NETDEV_TX_OK; -} - -/******************************************* - * Someone wanna have the statistics - */ - -static struct net_device_stats *elmc_get_stats(struct net_device *dev) -{ - struct priv *p = netdev_priv(dev); - unsigned short crc, aln, rsc, ovrn; - - crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */ - p->scb->crc_errs -= crc; - aln = p->scb->aln_errs; - p->scb->aln_errs -= aln; - rsc = p->scb->rsc_errs; - p->scb->rsc_errs -= rsc; - ovrn = p->scb->ovrn_errs; - p->scb->ovrn_errs -= ovrn; - - 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 .. - */ - -#ifdef ELMC_MULTICAST -static void set_multicast_list(struct net_device *dev) -{ - if (!dev->start) { - /* without a running interface, promiscuous doesn't work */ - return; - } - dev->start = 0; - alloc586(dev); - init586(dev); - startrecv586(dev); - dev->start = 1; -} -#endif - -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - -#ifdef MODULE - -/* Increase if needed ;) */ -#define MAX_3C523_CARDS 4 - -static struct net_device *dev_elmc[MAX_3C523_CARDS]; -static int irq[MAX_3C523_CARDS]; -static int io[MAX_3C523_CARDS]; -module_param_array(irq, int, NULL, 0); -module_param_array(io, int, NULL, 0); -MODULE_PARM_DESC(io, "EtherLink/MC I/O base address(es)"); -MODULE_PARM_DESC(irq, "EtherLink/MC IRQ number(s)"); -MODULE_LICENSE("GPL"); - -int __init init_module(void) -{ - int this_dev,found = 0; - - /* Loop until we either can't find any more cards, or we have MAX_3C523_CARDS */ - for(this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) { - struct net_device *dev = alloc_etherdev(sizeof(struct priv)); - if (!dev) - break; - dev->irq=irq[this_dev]; - dev->base_addr=io[this_dev]; - if (do_elmc_probe(dev) == 0) { - dev_elmc[this_dev] = dev; - found++; - continue; - } - free_netdev(dev); - if (io[this_dev]==0) - break; - pr_warning("3c523.c: No 3c523 card found at io=%#x\n",io[this_dev]); - } - - if(found==0) { - if (io[0]==0) - pr_notice("3c523.c: No 3c523 cards found\n"); - return -ENXIO; - } else return 0; -} - -void __exit cleanup_module(void) -{ - int this_dev; - for (this_dev=0; this_dev<MAX_3C523_CARDS; this_dev++) { - struct net_device *dev = dev_elmc[this_dev]; - if (dev) { - unregister_netdev(dev); - cleanup_card(dev); - free_netdev(dev); - } - } -} - -#endif /* MODULE */ diff --git a/drivers/net/ethernet/i825xx/3c523.h b/drivers/net/ethernet/i825xx/3c523.h deleted file mode 100644 index 6956441687b9..000000000000 --- a/drivers/net/ethernet/i825xx/3c523.h +++ /dev/null @@ -1,355 +0,0 @@ -#ifndef _3c523_INCLUDE_ -#define _3c523_INCLUDE_ -/* - This is basically a hacked version of ni52.h, for the 3c523 - Etherlink/MC. -*/ - -/* - * 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. - * - * Copyright 1995 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca) - * - * See 3c523.c for details. - * - * $Header: /home/chrisb/linux-1.2.13-3c523/drivers/net/RCS/3c523.h,v 1.6 1996/01/20 05:09:00 chrisb Exp chrisb $ - */ - -/* - * where to find the System Configuration Pointer (SCP) - */ -#define SCP_DEFAULT_ADDRESS 0xfffff4 - - -/* - * System Configuration Pointer Struct - */ - -struct scp_struct -{ - unsigned short zero_dum0; /* has to be zero */ - unsigned char sysbus; /* 0=16Bit,1=8Bit */ - unsigned char zero_dum1; /* has to be zero for 586 */ - unsigned short zero_dum2; - unsigned short zero_dum3; - char *iscp; /* pointer to the iscp-block */ -}; - - -/* - * Intermediate System Configuration Pointer (ISCP) - */ -struct iscp_struct -{ - unsigned char busy; /* 586 clears after successful init */ - unsigned char zero_dummy; /* hast to be zero */ - unsigned short scb_offset; /* pointeroffset to the scb_base */ - char *scb_base; /* base-address of all 16-bit offsets */ -}; - -/* - * System Control Block (SCB) - */ -struct scb_struct -{ - unsigned short status; /* status word */ - unsigned short cmd; /* command word */ - unsigned short cbl_offset; /* pointeroffset, command block list */ - unsigned short rfa_offset; /* pointeroffset, receive frame area */ - unsigned short crc_errs; /* CRC-Error counter */ - unsigned short aln_errs; /* alignmenterror counter */ - unsigned short rsc_errs; /* Resourceerror counter */ - unsigned short 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 0x0700 /* mask for CU command */ -#define CUC_NOP 0x0000 /* NOP-command */ -#define CUC_START 0x0100 /* start execution of 1. cmd on the CBL */ -#define CUC_RESUME 0x0200 /* resume after suspend */ -#define CUC_SUSPEND 0x0300 /* Suspend CU */ -#define CUC_ABORT 0x0400 /* abort command operation immediately */ - -#define ACK_MASK 0xf000 /* mask for ACK command */ -#define ACK_CX 0x8000 /* acknowledges STAT_CX */ -#define ACK_FR 0x4000 /* ack. STAT_FR */ -#define ACK_CNA 0x2000 /* ack. STAT_CNA */ -#define ACK_RNR 0x1000 /* ack. STAT_RNR */ - -/* - * possible status values for the status word - */ -#define STAT_MASK 0xf000 /* mask for cause of interrupt */ -#define STAT_CX 0x8000 /* CU finished cmd with its I bit set */ -#define STAT_FR 0x4000 /* RU finished receiving a frame */ -#define STAT_CNA 0x2000 /* CU left active state */ -#define STAT_RNR 0x1000 /* RU left ready state */ - -#define CU_STATUS 0x700 /* CU status, 0=idle */ -#define CU_SUSPEND 0x100 /* CU is suspended */ -#define CU_ACTIVE 0x200 /* 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 -{ - unsigned short status; /* status word */ - unsigned short last; /* Bit15,Last Frame on List / Bit14,suspend */ - unsigned short next; /* linkoffset to next RFD */ - unsigned short rbd_offset; /* pointeroffset to RBD-buffer */ - unsigned char dest[6]; /* ethernet-address, destination */ - unsigned char source[6]; /* ethernet-address, source */ - unsigned short length; /* 802.3 frame-length */ - unsigned short zero_dummy; /* dummy */ -}; - -#define RFD_LAST 0x8000 /* last: last rfd in the list */ -#define RFD_SUSP 0x4000 /* last: suspend RU after */ -#define RFD_ERRMASK 0x0fe1 /* status: errormask */ -#define RFD_MATCHADD 0x0002 /* status: Destinationaddress !matches IA */ -#define RFD_RNR 0x0200 /* status: receiver out of resources */ - -/* - * Receive Buffer Descriptor (RBD) - */ -struct rbd_struct -{ - unsigned short status; /* status word,number of used bytes in buff */ - unsigned short next; /* pointeroffset to next RBD */ - char *buffer; /* receive buffer address pointer */ - unsigned short size; /* size of this buffer */ - unsigned short 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 -{ - unsigned short cmd_status; /* status of this command */ - unsigned short cmd_cmd; /* the command itself (+bits) */ - unsigned short cmd_link; /* offsetpointer to next command */ -}; - -/* - * IA Setup command - */ -struct iasetup_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned char iaddr[6]; -}; - -/* - * Configure command - */ -struct configure_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned char byte_cnt; /* size of the config-cmd */ - unsigned char fifo; /* fifo/recv monitor */ - unsigned char sav_bf; /* save bad frames (bit7=1)*/ - unsigned char adr_len; /* adr_len(0-2),al_loc(3),pream(4-5),loopbak(6-7)*/ - unsigned char priority; /* lin_prio(0-2),exp_prio(4-6),bof_metd(7) */ - unsigned char ifs; /* inter frame spacing */ - unsigned char time_low; /* slot time low */ - unsigned char time_high; /* slot time high(0-2) and max. retries(4-7) */ - unsigned char promisc; /* promisc-mode(0) , et al (1-7) */ - unsigned char carr_coll; /* carrier(0-3)/collision(4-7) stuff */ - unsigned char fram_len; /* minimal frame len */ - unsigned char dummy; /* dummy */ -}; - -/* - * Multicast Setup command - */ -struct mcsetup_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short mc_cnt; /* number of bytes in the MC-List */ - unsigned char mc_list[0][6]; /* pointer to 6 bytes entries */ -}; - -/* - * transmit command - */ -struct transmit_cmd_struct -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short tbd_offset; /* pointeroffset to TBD */ - unsigned char dest[6]; /* destination address of the frame */ - unsigned short 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 -{ - unsigned short cmd_status; - unsigned short cmd_cmd; - unsigned short cmd_link; - unsigned short 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 -{ - unsigned short size; /* size + EOF-Flag(15) */ - unsigned short next; /* pointeroffset to next TBD */ - char *buffer; /* pointer to buffer */ -}; - -#define TBD_LAST 0x8000 /* EOF-Flag, indicates last buffer in list */ - -/*************************************************************************/ -/* -Verbatim from the Crynwyr stuff: - - The 3c523 responds with adapter code 0x6042 at slot -registers xxx0 and xxx1. The setup register is at xxx2 and -contains the following bits: - -0: card enable -2,1: csr address select - 00 = 0300 - 01 = 1300 - 10 = 2300 - 11 = 3300 -4,3: shared memory address select - 00 = 0c0000 - 01 = 0c8000 - 10 = 0d0000 - 11 = 0d8000 -5: set to disable on-board thinnet -7,6: (read-only) shows selected irq - 00 = 12 - 01 = 7 - 10 = 3 - 11 = 9 - -The interrupt-select register is at xxx3 and uses one bit per irq. - -0: int 12 -1: int 7 -2: int 3 -3: int 9 - - Again, the documentation stresses that the setup register -should never be written. The interrupt-select register may be -written with the value corresponding to bits 7.6 in -the setup register to insure corret setup. -*/ - -/* Offsets from the base I/O address. */ -#define ELMC_SA 0 /* first 6 bytes are IEEE network address */ -#define ELMC_CTRL 6 /* control & status register */ -#define ELMC_REVISION 7 /* revision register, first 4 bits only */ -#define ELMC_IO_EXTENT 8 - -/* these are the bit selects for the port register 2 */ -#define ELMC_STATUS_ENABLED 0x01 -#define ELMC_STATUS_CSR_SELECT 0x06 -#define ELMC_STATUS_MEMORY_SELECT 0x18 -#define ELMC_STATUS_DISABLE_THIN 0x20 -#define ELMC_STATUS_IRQ_SELECT 0xc0 - -/* this is the card id used in the detection code. You might recognize -it from @6042.adf */ -#define ELMC_MCA_ID 0x6042 - -/* - The following define the bits for the control & status register - - The bank select registers can be used if more than 16K of memory is - on the card. For some stupid reason, bank 3 is the one for the - bottom 16K, and the card defaults to bank 0. So we have to set the - bank to 3 before the card will even think of operating. To get bank - 3, set BS0 and BS1 to high (of course...) -*/ -#define ELMC_CTRL_BS0 0x01 /* RW bank select */ -#define ELMC_CTRL_BS1 0x02 /* RW bank select */ -#define ELMC_CTRL_INTE 0x04 /* RW interrupt enable, assert high */ -#define ELMC_CTRL_INT 0x08 /* R interrupt active, assert high */ -/*#define ELMC_CTRL_* 0x10*/ /* reserved */ -#define ELMC_CTRL_LBK 0x20 /* RW loopback enable, assert high */ -#define ELMC_CTRL_CA 0x40 /* RW channel attention, assert high */ -#define ELMC_CTRL_RST 0x80 /* RW 82586 reset, assert low */ - -/* some handy compound bits */ - -/* normal operation should have bank 3 and RST high, ints enabled */ -#define ELMC_NORMAL (ELMC_CTRL_INTE|ELMC_CTRL_RST|0x3) - -#endif /* _3c523_INCLUDE_ */ diff --git a/drivers/net/ethernet/i825xx/3c527.c b/drivers/net/ethernet/i825xx/3c527.c deleted file mode 100644 index 278e791afe00..000000000000 --- a/drivers/net/ethernet/i825xx/3c527.c +++ /dev/null @@ -1,1660 +0,0 @@ -/* 3c527.c: 3Com Etherlink/MC32 driver for Linux 2.4 and 2.6. - * - * (c) Copyright 1998 Red Hat Software Inc - * Written by Alan Cox. - * Further debugging by Carl Drougge. - * Initial SMP support by Felipe W Damasio <felipewd@terra.com.br> - * Heavily modified by Richard Procter <rnp@paradise.net.nz> - * - * Based on skeleton.c written 1993-94 by Donald Becker and ne2.c - * (for the MCA stuff) written by Wim Dumon. - * - * Thanks to 3Com for making this possible by providing me with the - * documentation. - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#define DRV_NAME "3c527" -#define DRV_VERSION "0.7-SMP" -#define DRV_RELDATE "2003/09/21" - -static const char *version = -DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter <rnp@paradise.net.nz>\n"; - -/** - * DOC: Traps for the unwary - * - * The diagram (Figure 1-1) and the POS summary disagree with the - * "Interrupt Level" section in the manual. - * - * The manual contradicts itself when describing the minimum number - * buffers in the 'configure lists' command. - * My card accepts a buffer config of 4/4. - * - * Setting the SAV BP bit does not save bad packets, but - * only enables RX on-card stats collection. - * - * The documentation in places seems to miss things. In actual fact - * I've always eventually found everything is documented, it just - * requires careful study. - * - * DOC: Theory Of Operation - * - * The 3com 3c527 is a 32bit MCA bus mastering adapter with a large - * amount of on board intelligence that housekeeps a somewhat dumber - * Intel NIC. For performance we want to keep the transmit queue deep - * as the card can transmit packets while fetching others from main - * memory by bus master DMA. Transmission and reception are driven by - * circular buffer queues. - * - * The mailboxes can be used for controlling how the card traverses - * its buffer rings, but are used only for initial setup in this - * implementation. The exec mailbox allows a variety of commands to - * be executed. Each command must complete before the next is - * executed. Primarily we use the exec mailbox for controlling the - * multicast lists. We have to do a certain amount of interesting - * hoop jumping as the multicast list changes can occur in interrupt - * state when the card has an exec command pending. We defer such - * events until the command completion interrupt. - * - * A copy break scheme (taken from 3c59x.c) is employed whereby - * received frames exceeding a configurable length are passed - * directly to the higher networking layers without incuring a copy, - * in what amounts to a time/space trade-off. - * - * The card also keeps a large amount of statistical information - * on-board. In a perfect world, these could be used safely at no - * cost. However, lacking information to the contrary, processing - * them without races would involve so much extra complexity as to - * make it unworthwhile to do so. In the end, a hybrid SW/HW - * implementation was made necessary --- see mc32_update_stats(). - * - * DOC: Notes - * - * It should be possible to use two or more cards, but at this stage - * only by loading two copies of the same module. - * - * The on-board 82586 NIC has trouble receiving multiple - * back-to-back frames and so is likely to drop packets from fast - * senders. -**/ - -#include <linux/module.h> - -#include <linux/errno.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/if_ether.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/fcntl.h> -#include <linux/interrupt.h> -#include <linux/mca-legacy.h> -#include <linux/ioport.h> -#include <linux/in.h> -#include <linux/skbuff.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/wait.h> -#include <linux/ethtool.h> -#include <linux/completion.h> -#include <linux/bitops.h> -#include <linux/semaphore.h> - -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/dma.h> - -#include "3c527.h" - -MODULE_LICENSE("GPL"); - -/* - * The name of the card. Is used for messages and in the requests for - * io regions, irqs and dma channels - */ -static const char* cardname = DRV_NAME; - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef NET_DEBUG -#define NET_DEBUG 2 -#endif - -static unsigned int mc32_debug = NET_DEBUG; - -/* The number of low I/O ports used by the ethercard. */ -#define MC32_IO_EXTENT 8 - -/* As implemented, values must be a power-of-2 -- 4/8/16/32 */ -#define TX_RING_LEN 32 /* Typically the card supports 37 */ -#define RX_RING_LEN 8 /* " " " */ - -/* Copy break point, see above for details. - * Setting to > 1512 effectively disables this feature. */ -#define RX_COPYBREAK 200 /* Value from 3c59x.c */ - -/* Issue the 82586 workaround command - this is for "busy lans", but - * basically means for all lans now days - has a performance (latency) - * cost, but best set. */ -static const int WORKAROUND_82586=1; - -/* Pointers to buffers and their on-card records */ -struct mc32_ring_desc -{ - volatile struct skb_header *p; - struct sk_buff *skb; -}; - -/* Information that needs to be kept for each board. */ -struct mc32_local -{ - int slot; - - u32 base; - volatile struct mc32_mailbox *rx_box; - volatile struct mc32_mailbox *tx_box; - volatile struct mc32_mailbox *exec_box; - volatile struct mc32_stats *stats; /* Start of on-card statistics */ - u16 tx_chain; /* Transmit list start offset */ - u16 rx_chain; /* Receive list start offset */ - u16 tx_len; /* Transmit list count */ - u16 rx_len; /* Receive list count */ - - u16 xceiver_desired_state; /* HALTED or RUNNING */ - u16 cmd_nonblocking; /* Thread is uninterested in command result */ - u16 mc_reload_wait; /* A multicast load request is pending */ - u32 mc_list_valid; /* True when the mclist is set */ - - struct mc32_ring_desc tx_ring[TX_RING_LEN]; /* Host Transmit ring */ - struct mc32_ring_desc rx_ring[RX_RING_LEN]; /* Host Receive ring */ - - atomic_t tx_count; /* buffers left */ - atomic_t tx_ring_head; /* index to tx en-queue end */ - u16 tx_ring_tail; /* index to tx de-queue end */ - - u16 rx_ring_tail; /* index to rx de-queue end */ - - struct semaphore cmd_mutex; /* Serialises issuing of execute commands */ - struct completion execution_cmd; /* Card has completed an execute command */ - struct completion xceiver_cmd; /* Card has completed a tx or rx command */ -}; - -/* The station (ethernet) address prefix, used for a sanity check. */ -#define SA_ADDR0 0x02 -#define SA_ADDR1 0x60 -#define SA_ADDR2 0xAC - -struct mca_adapters_t { - unsigned int id; - char *name; -}; - -static const struct mca_adapters_t mc32_adapters[] = { - { 0x0041, "3COM EtherLink MC/32" }, - { 0x8EF5, "IBM High Performance Lan Adapter" }, - { 0x0000, NULL } -}; - - -/* Macros for ring index manipulations */ -static inline u16 next_rx(u16 rx) { return (rx+1)&(RX_RING_LEN-1); }; -static inline u16 prev_rx(u16 rx) { return (rx-1)&(RX_RING_LEN-1); }; - -static inline u16 next_tx(u16 tx) { return (tx+1)&(TX_RING_LEN-1); }; - - -/* Index to functions, as function prototypes. */ -static int mc32_probe1(struct net_device *dev, int ioaddr); -static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len); -static int mc32_open(struct net_device *dev); -static void mc32_timeout(struct net_device *dev); -static netdev_tx_t mc32_send_packet(struct sk_buff *skb, - struct net_device *dev); -static irqreturn_t mc32_interrupt(int irq, void *dev_id); -static int mc32_close(struct net_device *dev); -static struct net_device_stats *mc32_get_stats(struct net_device *dev); -static void mc32_set_multicast_list(struct net_device *dev); -static void mc32_reset_multicast_list(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; - -static void cleanup_card(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - unsigned slot = lp->slot; - mca_mark_as_unused(slot); - mca_set_adapter_name(slot, NULL); - free_irq(dev->irq, dev); - release_region(dev->base_addr, MC32_IO_EXTENT); -} - -/** - * mc32_probe - Search for supported boards - * @unit: interface number to use - * - * Because MCA bus is a real bus and we can scan for cards we could do a - * single scan for all boards here. Right now we use the passed in device - * structure and scan for only one board. This needs fixing for modules - * in particular. - */ - -struct net_device *__init mc32_probe(int unit) -{ - struct net_device *dev = alloc_etherdev(sizeof(struct mc32_local)); - static int current_mca_slot = -1; - int i; - int err; - - if (!dev) - return ERR_PTR(-ENOMEM); - - if (unit >= 0) - sprintf(dev->name, "eth%d", unit); - - /* Do not check any supplied i/o locations. - POS registers usually don't fail :) */ - - /* MCA cards have POS registers. - Autodetecting MCA cards is extremely simple. - Just search for the card. */ - - for(i = 0; (mc32_adapters[i].name != NULL); i++) { - current_mca_slot = - mca_find_unused_adapter(mc32_adapters[i].id, 0); - - if(current_mca_slot != MCA_NOTFOUND) { - if(!mc32_probe1(dev, current_mca_slot)) - { - mca_set_adapter_name(current_mca_slot, - mc32_adapters[i].name); - mca_mark_as_used(current_mca_slot); - err = register_netdev(dev); - if (err) { - cleanup_card(dev); - free_netdev(dev); - dev = ERR_PTR(err); - } - return dev; - } - - } - } - free_netdev(dev); - return ERR_PTR(-ENODEV); -} - -static const struct net_device_ops netdev_ops = { - .ndo_open = mc32_open, - .ndo_stop = mc32_close, - .ndo_start_xmit = mc32_send_packet, - .ndo_get_stats = mc32_get_stats, - .ndo_set_rx_mode = mc32_set_multicast_list, - .ndo_tx_timeout = mc32_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/** - * mc32_probe1 - Check a given slot for a board and test the card - * @dev: Device structure to fill in - * @slot: The MCA bus slot being used by this card - * - * Decode the slot data and configure the card structures. Having done this we - * can reset the card and configure it. The card does a full self test cycle - * in firmware so we have to wait for it to return and post us either a - * failure case or some addresses we use to find the board internals. - */ - -static int __init mc32_probe1(struct net_device *dev, int slot) -{ - static unsigned version_printed; - int i, err; - u8 POS; - u32 base; - struct mc32_local *lp = netdev_priv(dev); - static const u16 mca_io_bases[] = { - 0x7280,0x7290, - 0x7680,0x7690, - 0x7A80,0x7A90, - 0x7E80,0x7E90 - }; - static const u32 mca_mem_bases[] = { - 0x00C0000, - 0x00C4000, - 0x00C8000, - 0x00CC000, - 0x00D0000, - 0x00D4000, - 0x00D8000, - 0x00DC000 - }; - static const char * const failures[] = { - "Processor instruction", - "Processor data bus", - "Processor data bus", - "Processor data bus", - "Adapter bus", - "ROM checksum", - "Base RAM", - "Extended RAM", - "82586 internal loopback", - "82586 initialisation failure", - "Adapter list configuration error" - }; - - /* Time to play MCA games */ - - if (mc32_debug && version_printed++ == 0) - pr_debug("%s", version); - - pr_info("%s: %s found in slot %d: ", dev->name, cardname, slot); - - POS = mca_read_stored_pos(slot, 2); - - if(!(POS&1)) - { - pr_cont("disabled.\n"); - return -ENODEV; - } - - /* Fill in the 'dev' fields. */ - dev->base_addr = mca_io_bases[(POS>>1)&7]; - dev->mem_start = mca_mem_bases[(POS>>4)&7]; - - POS = mca_read_stored_pos(slot, 4); - if(!(POS&1)) - { - pr_cont("memory window disabled.\n"); - return -ENODEV; - } - - POS = mca_read_stored_pos(slot, 5); - - i=(POS>>4)&3; - if(i==3) - { - pr_cont("invalid memory window.\n"); - return -ENODEV; - } - - i*=16384; - i+=16384; - - dev->mem_end=dev->mem_start + i; - - dev->irq = ((POS>>2)&3)+9; - - if(!request_region(dev->base_addr, MC32_IO_EXTENT, cardname)) - { - pr_cont("io 0x%3lX, which is busy.\n", dev->base_addr); - return -EBUSY; - } - - pr_cont("io 0x%3lX irq %d mem 0x%lX (%dK)\n", - dev->base_addr, dev->irq, dev->mem_start, i/1024); - - - /* We ought to set the cache line size here.. */ - - - /* - * Go PROM browsing - */ - - /* Retrieve and print the ethernet address. */ - for (i = 0; i < 6; i++) - { - mca_write_pos(slot, 6, i+12); - mca_write_pos(slot, 7, 0); - - dev->dev_addr[i] = mca_read_pos(slot,3); - } - - pr_info("%s: Address %pM ", dev->name, dev->dev_addr); - - mca_write_pos(slot, 6, 0); - mca_write_pos(slot, 7, 0); - - POS = mca_read_stored_pos(slot, 4); - - if(POS&2) - pr_cont(": BNC port selected.\n"); - else - pr_cont(": AUI port selected.\n"); - - POS=inb(dev->base_addr+HOST_CTRL); - POS|=HOST_CTRL_ATTN|HOST_CTRL_RESET; - POS&=~HOST_CTRL_INTE; - outb(POS, dev->base_addr+HOST_CTRL); - /* Reset adapter */ - udelay(100); - /* Reset off */ - POS&=~(HOST_CTRL_ATTN|HOST_CTRL_RESET); - outb(POS, dev->base_addr+HOST_CTRL); - - udelay(300); - - /* - * Grab the IRQ - */ - - err = request_irq(dev->irq, mc32_interrupt, IRQF_SHARED, DRV_NAME, dev); - if (err) { - release_region(dev->base_addr, MC32_IO_EXTENT); - pr_err("%s: unable to get IRQ %d.\n", DRV_NAME, dev->irq); - goto err_exit_ports; - } - - memset(lp, 0, sizeof(struct mc32_local)); - lp->slot = slot; - - i=0; - - base = inb(dev->base_addr); - - while(base == 0xFF) - { - i++; - if(i == 1000) - { - pr_err("%s: failed to boot adapter.\n", dev->name); - err = -ENODEV; - goto err_exit_irq; - } - udelay(1000); - if(inb(dev->base_addr+2)&(1<<5)) - base = inb(dev->base_addr); - } - - if(base>0) - { - if(base < 0x0C) - pr_err("%s: %s%s.\n", dev->name, failures[base-1], - base<0x0A?" test failure":""); - else - pr_err("%s: unknown failure %d.\n", dev->name, base); - err = -ENODEV; - goto err_exit_irq; - } - - base=0; - for(i=0;i<4;i++) - { - int n=0; - - while(!(inb(dev->base_addr+2)&(1<<5))) - { - n++; - udelay(50); - if(n>100) - { - pr_err("%s: mailbox read fail (%d).\n", dev->name, i); - err = -ENODEV; - goto err_exit_irq; - } - } - - base|=(inb(dev->base_addr)<<(8*i)); - } - - lp->exec_box=isa_bus_to_virt(dev->mem_start+base); - - base=lp->exec_box->data[1]<<16|lp->exec_box->data[0]; - - lp->base = dev->mem_start+base; - - lp->rx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[2]); - lp->tx_box=isa_bus_to_virt(lp->base + lp->exec_box->data[3]); - - lp->stats = isa_bus_to_virt(lp->base + lp->exec_box->data[5]); - - /* - * Descriptor chains (card relative) - */ - - lp->tx_chain = lp->exec_box->data[8]; /* Transmit list start offset */ - lp->rx_chain = lp->exec_box->data[10]; /* Receive list start offset */ - lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */ - lp->rx_len = lp->exec_box->data[11]; /* Receive list count */ - - sema_init(&lp->cmd_mutex, 0); - init_completion(&lp->execution_cmd); - init_completion(&lp->xceiver_cmd); - - pr_info("%s: Firmware Rev %d. %d RX buffers, %d TX buffers. Base of 0x%08X.\n", - dev->name, lp->exec_box->data[12], lp->rx_len, lp->tx_len, lp->base); - - dev->netdev_ops = &netdev_ops; - dev->watchdog_timeo = HZ*5; /* Board does all the work */ - dev->ethtool_ops = &netdev_ethtool_ops; - - return 0; - -err_exit_irq: - free_irq(dev->irq, dev); -err_exit_ports: - release_region(dev->base_addr, MC32_IO_EXTENT); - return err; -} - - -/** - * mc32_ready_poll - wait until we can feed it a command - * @dev: The device to wait for - * - * Wait until the card becomes ready to accept a command via the - * command register. This tells us nothing about the completion - * status of any pending commands and takes very little time at all. - */ - -static inline void mc32_ready_poll(struct net_device *dev) -{ - int ioaddr = dev->base_addr; - while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR)); -} - - -/** - * mc32_command_nowait - send a command non blocking - * @dev: The 3c527 to issue the command to - * @cmd: The command word to write to the mailbox - * @data: A data block if the command expects one - * @len: Length of the data block - * - * Send a command from interrupt state. If there is a command - * currently being executed then we return an error of -1. It - * simply isn't viable to wait around as commands may be - * slow. This can theoretically be starved on SMP, but it's hard - * to see a realistic situation. We do not wait for the command - * to complete --- we rely on the interrupt handler to tidy up - * after us. - */ - -static int mc32_command_nowait(struct net_device *dev, u16 cmd, void *data, int len) -{ - struct mc32_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - int ret = -1; - - if (down_trylock(&lp->cmd_mutex) == 0) - { - lp->cmd_nonblocking=1; - lp->exec_box->mbox=0; - lp->exec_box->mbox=cmd; - memcpy((void *)lp->exec_box->data, data, len); - barrier(); /* the memcpy forgot the volatile so be sure */ - - /* Send the command */ - mc32_ready_poll(dev); - outb(1<<6, ioaddr+HOST_CMD); - - ret = 0; - - /* Interrupt handler will signal mutex on completion */ - } - - return ret; -} - - -/** - * mc32_command - send a command and sleep until completion - * @dev: The 3c527 card to issue the command to - * @cmd: The command word to write to the mailbox - * @data: A data block if the command expects one - * @len: Length of the data block - * - * Sends exec commands in a user context. This permits us to wait around - * for the replies and also to wait for the command buffer to complete - * from a previous command before we execute our command. After our - * command completes we will attempt any pending multicast reload - * we blocked off by hogging the exec buffer. - * - * You feed the card a command, you wait, it interrupts you get a - * reply. All well and good. The complication arises because you use - * commands for filter list changes which come in at bh level from things - * like IPV6 group stuff. - */ - -static int mc32_command(struct net_device *dev, u16 cmd, void *data, int len) -{ - struct mc32_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - int ret = 0; - - down(&lp->cmd_mutex); - - /* - * My Turn - */ - - lp->cmd_nonblocking=0; - lp->exec_box->mbox=0; - lp->exec_box->mbox=cmd; - memcpy((void *)lp->exec_box->data, data, len); - barrier(); /* the memcpy forgot the volatile so be sure */ - - mc32_ready_poll(dev); - outb(1<<6, ioaddr+HOST_CMD); - - wait_for_completion(&lp->execution_cmd); - - if(lp->exec_box->mbox&(1<<13)) - ret = -1; - - up(&lp->cmd_mutex); - - /* - * A multicast set got blocked - try it now - */ - - if(lp->mc_reload_wait) - { - mc32_reset_multicast_list(dev); - } - - return ret; -} - - -/** - * mc32_start_transceiver - tell board to restart tx/rx - * @dev: The 3c527 card to issue the command to - * - * This may be called from the interrupt state, where it is used - * to restart the rx ring if the card runs out of rx buffers. - * - * We must first check if it's ok to (re)start the transceiver. See - * mc32_close for details. - */ - -static void mc32_start_transceiver(struct net_device *dev) { - - struct mc32_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - - /* Ignore RX overflow on device closure */ - if (lp->xceiver_desired_state==HALTED) - return; - - /* Give the card the offset to the post-EOL-bit RX descriptor */ - mc32_ready_poll(dev); - lp->rx_box->mbox=0; - lp->rx_box->data[0]=lp->rx_ring[prev_rx(lp->rx_ring_tail)].p->next; - outb(HOST_CMD_START_RX, ioaddr+HOST_CMD); - - mc32_ready_poll(dev); - lp->tx_box->mbox=0; - outb(HOST_CMD_RESTRT_TX, ioaddr+HOST_CMD); /* card ignores this on RX restart */ - - /* We are not interrupted on start completion */ -} - - -/** - * mc32_halt_transceiver - tell board to stop tx/rx - * @dev: The 3c527 card to issue the command to - * - * We issue the commands to halt the card's transceiver. In fact, - * after some experimenting we now simply tell the card to - * suspend. When issuing aborts occasionally odd things happened. - * - * We then sleep until the card has notified us that both rx and - * tx have been suspended. - */ - -static void mc32_halt_transceiver(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - - mc32_ready_poll(dev); - lp->rx_box->mbox=0; - outb(HOST_CMD_SUSPND_RX, ioaddr+HOST_CMD); - wait_for_completion(&lp->xceiver_cmd); - - mc32_ready_poll(dev); - lp->tx_box->mbox=0; - outb(HOST_CMD_SUSPND_TX, ioaddr+HOST_CMD); - wait_for_completion(&lp->xceiver_cmd); -} - - -/** - * mc32_load_rx_ring - load the ring of receive buffers - * @dev: 3c527 to build the ring for - * - * This initialises the on-card and driver datastructures to - * the point where mc32_start_transceiver() can be called. - * - * The card sets up the receive ring for us. We are required to use the - * ring it provides, although the size of the ring is configurable. - * - * We allocate an sk_buff for each ring entry in turn and - * initialise its house-keeping info. At the same time, we read - * each 'next' pointer in our rx_ring array. This reduces slow - * shared-memory reads and makes it easy to access predecessor - * descriptors. - * - * We then set the end-of-list bit for the last entry so that the - * card will know when it has run out of buffers. - */ - -static int mc32_load_rx_ring(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - int i; - u16 rx_base; - volatile struct skb_header *p; - - rx_base=lp->rx_chain; - - for(i=0; i<RX_RING_LEN; i++) { - lp->rx_ring[i].skb=alloc_skb(1532, GFP_KERNEL); - if (lp->rx_ring[i].skb==NULL) { - for (;i>=0;i--) - kfree_skb(lp->rx_ring[i].skb); - return -ENOBUFS; - } - skb_reserve(lp->rx_ring[i].skb, 18); - - p=isa_bus_to_virt(lp->base+rx_base); - - p->control=0; - p->data=isa_virt_to_bus(lp->rx_ring[i].skb->data); - p->status=0; - p->length=1532; - - lp->rx_ring[i].p=p; - rx_base=p->next; - } - - lp->rx_ring[i-1].p->control |= CONTROL_EOL; - - lp->rx_ring_tail=0; - - return 0; -} - - -/** - * mc32_flush_rx_ring - free the ring of receive buffers - * @lp: Local data of 3c527 to flush the rx ring of - * - * Free the buffer for each ring slot. This may be called - * before mc32_load_rx_ring(), eg. on error in mc32_open(). - * Requires rx skb pointers to point to a valid skb, or NULL. - */ - -static void mc32_flush_rx_ring(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - int i; - - for(i=0; i < RX_RING_LEN; i++) - { - if (lp->rx_ring[i].skb) { - dev_kfree_skb(lp->rx_ring[i].skb); - lp->rx_ring[i].skb = NULL; - } - lp->rx_ring[i].p=NULL; - } -} - - -/** - * mc32_load_tx_ring - load transmit ring - * @dev: The 3c527 card to issue the command to - * - * This sets up the host transmit data-structures. - * - * First, we obtain from the card it's current position in the tx - * ring, so that we will know where to begin transmitting - * packets. - * - * Then, we read the 'next' pointers from the on-card tx ring into - * our tx_ring array to reduce slow shared-mem reads. Finally, we - * intitalise the tx house keeping variables. - * - */ - -static void mc32_load_tx_ring(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - volatile struct skb_header *p; - int i; - u16 tx_base; - - tx_base=lp->tx_box->data[0]; - - for(i=0 ; i<TX_RING_LEN ; i++) - { - p=isa_bus_to_virt(lp->base+tx_base); - lp->tx_ring[i].p=p; - lp->tx_ring[i].skb=NULL; - - tx_base=p->next; - } - - /* -1 so that tx_ring_head cannot "lap" tx_ring_tail */ - /* see mc32_tx_ring */ - - atomic_set(&lp->tx_count, TX_RING_LEN-1); - atomic_set(&lp->tx_ring_head, 0); - lp->tx_ring_tail=0; -} - - -/** - * mc32_flush_tx_ring - free transmit ring - * @lp: Local data of 3c527 to flush the tx ring of - * - * If the ring is non-empty, zip over the it, freeing any - * allocated skb_buffs. The tx ring house-keeping variables are - * then reset. Requires rx skb pointers to point to a valid skb, - * or NULL. - */ - -static void mc32_flush_tx_ring(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - int i; - - for (i=0; i < TX_RING_LEN; i++) - { - if (lp->tx_ring[i].skb) - { - dev_kfree_skb(lp->tx_ring[i].skb); - lp->tx_ring[i].skb = NULL; - } - } - - atomic_set(&lp->tx_count, 0); - atomic_set(&lp->tx_ring_head, 0); - lp->tx_ring_tail=0; -} - - -/** - * mc32_open - handle 'up' of card - * @dev: device to open - * - * The user is trying to bring the card into ready state. This requires - * a brief dialogue with the card. Firstly we enable interrupts and then - * 'indications'. Without these enabled the card doesn't bother telling - * us what it has done. This had me puzzled for a week. - * - * We configure the number of card descriptors, then load the network - * address and multicast filters. Turn on the workaround mode. This - * works around a bug in the 82586 - it asks the firmware to do - * so. It has a performance (latency) hit but is needed on busy - * [read most] lans. We load the ring with buffers then we kick it - * all off. - */ - -static int mc32_open(struct net_device *dev) -{ - int ioaddr = dev->base_addr; - struct mc32_local *lp = netdev_priv(dev); - u8 one=1; - u8 regs; - u16 descnumbuffs[2] = {TX_RING_LEN, RX_RING_LEN}; - - /* - * Interrupts enabled - */ - - regs=inb(ioaddr+HOST_CTRL); - regs|=HOST_CTRL_INTE; - outb(regs, ioaddr+HOST_CTRL); - - /* - * Allow ourselves to issue commands - */ - - up(&lp->cmd_mutex); - - - /* - * Send the indications on command - */ - - mc32_command(dev, 4, &one, 2); - - /* - * Poke it to make sure it's really dead. - */ - - mc32_halt_transceiver(dev); - mc32_flush_tx_ring(dev); - - /* - * Ask card to set up on-card descriptors to our spec - */ - - if(mc32_command(dev, 8, descnumbuffs, 4)) { - pr_info("%s: %s rejected our buffer configuration!\n", - dev->name, cardname); - mc32_close(dev); - return -ENOBUFS; - } - - /* Report new configuration */ - mc32_command(dev, 6, NULL, 0); - - lp->tx_chain = lp->exec_box->data[8]; /* Transmit list start offset */ - lp->rx_chain = lp->exec_box->data[10]; /* Receive list start offset */ - lp->tx_len = lp->exec_box->data[9]; /* Transmit list count */ - lp->rx_len = lp->exec_box->data[11]; /* Receive list count */ - - /* Set Network Address */ - mc32_command(dev, 1, dev->dev_addr, 6); - - /* Set the filters */ - mc32_set_multicast_list(dev); - - if (WORKAROUND_82586) { - u16 zero_word=0; - mc32_command(dev, 0x0D, &zero_word, 2); /* 82586 bug workaround on */ - } - - mc32_load_tx_ring(dev); - - if(mc32_load_rx_ring(dev)) - { - mc32_close(dev); - return -ENOBUFS; - } - - lp->xceiver_desired_state = RUNNING; - - /* And finally, set the ball rolling... */ - mc32_start_transceiver(dev); - - netif_start_queue(dev); - - return 0; -} - - -/** - * mc32_timeout - handle a timeout from the network layer - * @dev: 3c527 that timed out - * - * Handle a timeout on transmit from the 3c527. This normally means - * bad things as the hardware handles cable timeouts and mess for - * us. - * - */ - -static void mc32_timeout(struct net_device *dev) -{ - pr_warning("%s: transmit timed out?\n", dev->name); - /* Try to restart the adaptor. */ - netif_wake_queue(dev); -} - - -/** - * mc32_send_packet - queue a frame for transmit - * @skb: buffer to transmit - * @dev: 3c527 to send it out of - * - * Transmit a buffer. This normally means throwing the buffer onto - * the transmit queue as the queue is quite large. If the queue is - * full then we set tx_busy and return. Once the interrupt handler - * gets messages telling it to reclaim transmit queue entries, we will - * clear tx_busy and the kernel will start calling this again. - * - * We do not disable interrupts or acquire any locks; this can - * run concurrently with mc32_tx_ring(), and the function itself - * is serialised at a higher layer. However, similarly for the - * card itself, we must ensure that we update tx_ring_head only - * after we've established a valid packet on the tx ring (and - * before we let the card "see" it, to prevent it racing with the - * irq handler). - * - */ - -static netdev_tx_t mc32_send_packet(struct sk_buff *skb, - struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - u32 head = atomic_read(&lp->tx_ring_head); - - volatile struct skb_header *p, *np; - - netif_stop_queue(dev); - - if(atomic_read(&lp->tx_count)==0) { - return NETDEV_TX_BUSY; - } - - if (skb_padto(skb, ETH_ZLEN)) { - netif_wake_queue(dev); - return NETDEV_TX_OK; - } - - atomic_dec(&lp->tx_count); - - /* P is the last sending/sent buffer as a pointer */ - p=lp->tx_ring[head].p; - - head = next_tx(head); - - /* NP is the buffer we will be loading */ - np=lp->tx_ring[head].p; - - /* We will need this to flush the buffer out */ - lp->tx_ring[head].skb=skb; - - np->length = unlikely(skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len; - np->data = isa_virt_to_bus(skb->data); - np->status = 0; - np->control = CONTROL_EOP | CONTROL_EOL; - wmb(); - - /* - * The new frame has been setup; we can now - * let the interrupt handler and card "see" it - */ - - atomic_set(&lp->tx_ring_head, head); - p->control &= ~CONTROL_EOL; - - netif_wake_queue(dev); - return NETDEV_TX_OK; -} - - -/** - * mc32_update_stats - pull off the on board statistics - * @dev: 3c527 to service - * - * - * Query and reset the on-card stats. There's the small possibility - * of a race here, which would result in an underestimation of - * actual errors. As such, we'd prefer to keep all our stats - * collection in software. As a rule, we do. However it can't be - * used for rx errors and collisions as, by default, the card discards - * bad rx packets. - * - * Setting the SAV BP in the rx filter command supposedly - * stops this behaviour. However, testing shows that it only seems to - * enable the collation of on-card rx statistics --- the driver - * never sees an RX descriptor with an error status set. - * - */ - -static void mc32_update_stats(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - volatile struct mc32_stats *st = lp->stats; - - u32 rx_errors=0; - - rx_errors+=dev->stats.rx_crc_errors +=st->rx_crc_errors; - st->rx_crc_errors=0; - rx_errors+=dev->stats.rx_fifo_errors +=st->rx_overrun_errors; - st->rx_overrun_errors=0; - rx_errors+=dev->stats.rx_frame_errors +=st->rx_alignment_errors; - st->rx_alignment_errors=0; - rx_errors+=dev->stats.rx_length_errors+=st->rx_tooshort_errors; - st->rx_tooshort_errors=0; - rx_errors+=dev->stats.rx_missed_errors+=st->rx_outofresource_errors; - st->rx_outofresource_errors=0; - dev->stats.rx_errors=rx_errors; - - /* Number of packets which saw one collision */ - dev->stats.collisions+=st->dataC[10]; - st->dataC[10]=0; - - /* Number of packets which saw 2--15 collisions */ - dev->stats.collisions+=st->dataC[11]; - st->dataC[11]=0; -} - - -/** - * mc32_rx_ring - process the receive ring - * @dev: 3c527 that needs its receive ring processing - * - * - * We have received one or more indications from the card that a - * receive has completed. The buffer ring thus contains dirty - * entries. We walk the ring by iterating over the circular rx_ring - * array, starting at the next dirty buffer (which happens to be the - * one we finished up at last time around). - * - * For each completed packet, we will either copy it and pass it up - * the stack or, if the packet is near MTU sized, we allocate - * another buffer and flip the old one up the stack. - * - * We must succeed in keeping a buffer on the ring. If necessary we - * will toss a received packet rather than lose a ring entry. Once - * the first uncompleted descriptor is found, we move the - * End-Of-List bit to include the buffers just processed. - * - */ - -static void mc32_rx_ring(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - volatile struct skb_header *p; - u16 rx_ring_tail; - u16 rx_old_tail; - int x=0; - - rx_old_tail = rx_ring_tail = lp->rx_ring_tail; - - do - { - p=lp->rx_ring[rx_ring_tail].p; - - if(!(p->status & (1<<7))) { /* Not COMPLETED */ - break; - } - if(p->status & (1<<6)) /* COMPLETED_OK */ - { - - u16 length=p->length; - struct sk_buff *skb; - struct sk_buff *newskb; - - /* Try to save time by avoiding a copy on big frames */ - - if ((length > RX_COPYBREAK) && - ((newskb = netdev_alloc_skb(dev, 1532)) != NULL)) - { - skb=lp->rx_ring[rx_ring_tail].skb; - skb_put(skb, length); - - skb_reserve(newskb,18); - lp->rx_ring[rx_ring_tail].skb=newskb; - p->data=isa_virt_to_bus(newskb->data); - } - else - { - skb = netdev_alloc_skb(dev, length + 2); - - if(skb==NULL) { - dev->stats.rx_dropped++; - goto dropped; - } - - skb_reserve(skb,2); - memcpy(skb_put(skb, length), - lp->rx_ring[rx_ring_tail].skb->data, length); - } - - skb->protocol=eth_type_trans(skb,dev); - dev->stats.rx_packets++; - dev->stats.rx_bytes += length; - netif_rx(skb); - } - - dropped: - p->length = 1532; - p->status = 0; - - rx_ring_tail=next_rx(rx_ring_tail); - } - while(x++<48); - - /* If there was actually a frame to be processed, place the EOL bit */ - /* at the descriptor prior to the one to be filled next */ - - if (rx_ring_tail != rx_old_tail) - { - lp->rx_ring[prev_rx(rx_ring_tail)].p->control |= CONTROL_EOL; - lp->rx_ring[prev_rx(rx_old_tail)].p->control &= ~CONTROL_EOL; - - lp->rx_ring_tail=rx_ring_tail; - } -} - - -/** - * mc32_tx_ring - process completed transmits - * @dev: 3c527 that needs its transmit ring processing - * - * - * This operates in a similar fashion to mc32_rx_ring. We iterate - * over the transmit ring. For each descriptor which has been - * processed by the card, we free its associated buffer and note - * any errors. This continues until the transmit ring is emptied - * or we reach a descriptor that hasn't yet been processed by the - * card. - * - */ - -static void mc32_tx_ring(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - volatile struct skb_header *np; - - /* - * We rely on head==tail to mean 'queue empty'. - * This is why lp->tx_count=TX_RING_LEN-1: in order to prevent - * tx_ring_head wrapping to tail and confusing a 'queue empty' - * condition with 'queue full' - */ - - while (lp->tx_ring_tail != atomic_read(&lp->tx_ring_head)) - { - u16 t; - - t=next_tx(lp->tx_ring_tail); - np=lp->tx_ring[t].p; - - if(!(np->status & (1<<7))) - { - /* Not COMPLETED */ - break; - } - dev->stats.tx_packets++; - if(!(np->status & (1<<6))) /* Not COMPLETED_OK */ - { - dev->stats.tx_errors++; - - switch(np->status&0x0F) - { - case 1: - dev->stats.tx_aborted_errors++; - break; /* Max collisions */ - case 2: - dev->stats.tx_fifo_errors++; - break; - case 3: - dev->stats.tx_carrier_errors++; - break; - case 4: - dev->stats.tx_window_errors++; - break; /* CTS Lost */ - case 5: - dev->stats.tx_aborted_errors++; - break; /* Transmit timeout */ - } - } - /* Packets are sent in order - this is - basically a FIFO queue of buffers matching - the card ring */ - dev->stats.tx_bytes+=lp->tx_ring[t].skb->len; - dev_kfree_skb_irq(lp->tx_ring[t].skb); - lp->tx_ring[t].skb=NULL; - atomic_inc(&lp->tx_count); - netif_wake_queue(dev); - - lp->tx_ring_tail=t; - } - -} - - -/** - * mc32_interrupt - handle an interrupt from a 3c527 - * @irq: Interrupt number - * @dev_id: 3c527 that requires servicing - * @regs: Registers (unused) - * - * - * An interrupt is raised whenever the 3c527 writes to the command - * register. This register contains the message it wishes to send us - * packed into a single byte field. We keep reading status entries - * until we have processed all the control items, but simply count - * transmit and receive reports. When all reports are in we empty the - * transceiver rings as appropriate. This saves the overhead of - * multiple command requests. - * - * Because MCA is level-triggered, we shouldn't miss indications. - * Therefore, we needn't ask the card to suspend interrupts within - * this handler. The card receives an implicit acknowledgment of the - * current interrupt when we read the command register. - * - */ - -static irqreturn_t mc32_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct mc32_local *lp; - int ioaddr, status, boguscount = 0; - int rx_event = 0; - int tx_event = 0; - - ioaddr = dev->base_addr; - lp = netdev_priv(dev); - - /* See whats cooking */ - - while((inb(ioaddr+HOST_STATUS)&HOST_STATUS_CWR) && boguscount++<2000) - { - status=inb(ioaddr+HOST_CMD); - - pr_debug("Status TX%d RX%d EX%d OV%d BC%d\n", - (status&7), (status>>3)&7, (status>>6)&1, - (status>>7)&1, boguscount); - - switch(status&7) - { - case 0: - break; - case 6: /* TX fail */ - case 2: /* TX ok */ - tx_event = 1; - break; - case 3: /* Halt */ - case 4: /* Abort */ - complete(&lp->xceiver_cmd); - break; - default: - pr_notice("%s: strange tx ack %d\n", dev->name, status&7); - } - status>>=3; - switch(status&7) - { - case 0: - break; - case 2: /* RX */ - rx_event=1; - break; - case 3: /* Halt */ - case 4: /* Abort */ - complete(&lp->xceiver_cmd); - break; - case 6: - /* Out of RX buffers stat */ - /* Must restart rx */ - dev->stats.rx_dropped++; - mc32_rx_ring(dev); - mc32_start_transceiver(dev); - break; - default: - pr_notice("%s: strange rx ack %d\n", - dev->name, status&7); - } - status>>=3; - if(status&1) - { - /* - * No thread is waiting: we need to tidy - * up ourself. - */ - - if (lp->cmd_nonblocking) { - up(&lp->cmd_mutex); - if (lp->mc_reload_wait) - mc32_reset_multicast_list(dev); - } - else complete(&lp->execution_cmd); - } - if(status&2) - { - /* - * We get interrupted once per - * counter that is about to overflow. - */ - - mc32_update_stats(dev); - } - } - - - /* - * Process the transmit and receive rings - */ - - if(tx_event) - mc32_tx_ring(dev); - - if(rx_event) - mc32_rx_ring(dev); - - return IRQ_HANDLED; -} - - -/** - * mc32_close - user configuring the 3c527 down - * @dev: 3c527 card to shut down - * - * The 3c527 is a bus mastering device. We must be careful how we - * shut it down. It may also be running shared interrupt so we have - * to be sure to silence it properly - * - * We indicate that the card is closing to the rest of the - * driver. Otherwise, it is possible that the card may run out - * of receive buffers and restart the transceiver while we're - * trying to close it. - * - * We abort any receive and transmits going on and then wait until - * any pending exec commands have completed in other code threads. - * In theory we can't get here while that is true, in practice I am - * paranoid - * - * We turn off the interrupt enable for the board to be sure it can't - * intefere with other devices. - */ - -static int mc32_close(struct net_device *dev) -{ - struct mc32_local *lp = netdev_priv(dev); - int ioaddr = dev->base_addr; - - u8 regs; - u16 one=1; - - lp->xceiver_desired_state = HALTED; - netif_stop_queue(dev); - - /* - * Send the indications on command (handy debug check) - */ - - mc32_command(dev, 4, &one, 2); - - /* Shut down the transceiver */ - - mc32_halt_transceiver(dev); - - /* Ensure we issue no more commands beyond this point */ - - down(&lp->cmd_mutex); - - /* Ok the card is now stopping */ - - regs=inb(ioaddr+HOST_CTRL); - regs&=~HOST_CTRL_INTE; - outb(regs, ioaddr+HOST_CTRL); - - mc32_flush_rx_ring(dev); - mc32_flush_tx_ring(dev); - - mc32_update_stats(dev); - - return 0; -} - - -/** - * mc32_get_stats - hand back stats to network layer - * @dev: The 3c527 card to handle - * - * We've collected all the stats we can in software already. Now - * it's time to update those kept on-card and return the lot. - * - */ - -static struct net_device_stats *mc32_get_stats(struct net_device *dev) -{ - mc32_update_stats(dev); - return &dev->stats; -} - - -/** - * do_mc32_set_multicast_list - attempt to update multicasts - * @dev: 3c527 device to load the list on - * @retry: indicates this is not the first call. - * - * - * Actually set or clear the multicast filter for this adaptor. The - * locking issues are handled by this routine. We have to track - * state as it may take multiple calls to get the command sequence - * completed. We just keep trying to schedule the loads until we - * manage to process them all. - * - * num_addrs == -1 Promiscuous mode, receive all packets - * - * num_addrs == 0 Normal mode, clear multicast list - * - * num_addrs > 0 Multicast mode, receive normal and MC packets, - * and do best-effort filtering. - * - * See mc32_update_stats() regards setting the SAV BP bit. - * - */ - -static void do_mc32_set_multicast_list(struct net_device *dev, int retry) -{ - struct mc32_local *lp = netdev_priv(dev); - u16 filt = (1<<2); /* Save Bad Packets, for stats purposes */ - - if ((dev->flags&IFF_PROMISC) || - (dev->flags&IFF_ALLMULTI) || - netdev_mc_count(dev) > 10) - /* Enable promiscuous mode */ - filt |= 1; - else if (!netdev_mc_empty(dev)) - { - unsigned char block[62]; - unsigned char *bp; - struct netdev_hw_addr *ha; - - if(retry==0) - lp->mc_list_valid = 0; - if(!lp->mc_list_valid) - { - block[1]=0; - block[0]=netdev_mc_count(dev); - bp=block+2; - - netdev_for_each_mc_addr(ha, dev) { - memcpy(bp, ha->addr, 6); - bp+=6; - } - if(mc32_command_nowait(dev, 2, block, - 2+6*netdev_mc_count(dev))==-1) - { - lp->mc_reload_wait = 1; - return; - } - lp->mc_list_valid=1; - } - } - - if(mc32_command_nowait(dev, 0, &filt, 2)==-1) - { - lp->mc_reload_wait = 1; - } - else { - lp->mc_reload_wait = 0; - } -} - - -/** - * mc32_set_multicast_list - queue multicast list update - * @dev: The 3c527 to use - * - * Commence loading the multicast list. This is called when the kernel - * changes the lists. It will override any pending list we are trying to - * load. - */ - -static void mc32_set_multicast_list(struct net_device *dev) -{ - do_mc32_set_multicast_list(dev,0); -} - - -/** - * mc32_reset_multicast_list - reset multicast list - * @dev: The 3c527 to use - * - * Attempt the next step in loading the multicast lists. If this attempt - * fails to complete then it will be scheduled and this function called - * again later from elsewhere. - */ - -static void mc32_reset_multicast_list(struct net_device *dev) -{ - do_mc32_set_multicast_list(dev,1); -} - -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - sprintf(info->bus_info, "MCA 0x%lx", dev->base_addr); -} - -static u32 netdev_get_msglevel(struct net_device *dev) -{ - return mc32_debug; -} - -static void netdev_set_msglevel(struct net_device *dev, u32 level) -{ - mc32_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 *this_device; - -/** - * init_module - entry point - * - * Probe and locate a 3c527 card. This really should probe and locate - * all the 3c527 cards in the machine not just one of them. Yes you can - * insmod multiple modules for now but it's a hack. - */ - -int __init init_module(void) -{ - this_device = mc32_probe(-1); - if (IS_ERR(this_device)) - return PTR_ERR(this_device); - return 0; -} - -/** - * cleanup_module - free resources for an unload - * - * Unloading time. We release the MCA bus resources and the interrupt - * at which point everything is ready to unload. The card must be stopped - * at this point or we would not have been called. When we unload we - * leave the card stopped but not totally shut down. When the card is - * initialized it must be rebooted or the rings reloaded before any - * transmit operations are allowed to start scribbling into memory. - */ - -void __exit cleanup_module(void) -{ - unregister_netdev(this_device); - cleanup_card(this_device); - free_netdev(this_device); -} - -#endif /* MODULE */ diff --git a/drivers/net/ethernet/i825xx/3c527.h b/drivers/net/ethernet/i825xx/3c527.h deleted file mode 100644 index d693b8d15cde..000000000000 --- a/drivers/net/ethernet/i825xx/3c527.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * 3COM "EtherLink MC/32" Descriptions - */ - -/* - * Registers - */ - -#define HOST_CMD 0 -#define HOST_CMD_START_RX (1<<3) -#define HOST_CMD_SUSPND_RX (3<<3) -#define HOST_CMD_RESTRT_RX (5<<3) - -#define HOST_CMD_SUSPND_TX 3 -#define HOST_CMD_RESTRT_TX 5 - - -#define HOST_STATUS 2 -#define HOST_STATUS_CRR (1<<6) -#define HOST_STATUS_CWR (1<<5) - - -#define HOST_CTRL 6 -#define HOST_CTRL_ATTN (1<<7) -#define HOST_CTRL_RESET (1<<6) -#define HOST_CTRL_INTE (1<<2) - -#define HOST_RAMPAGE 8 - -#define HALTED 0 -#define RUNNING 1 - -struct mc32_mailbox -{ - u16 mbox; - u16 data[1]; -} __packed; - -struct skb_header -{ - u8 status; - u8 control; - u16 next; /* Do not change! */ - u16 length; - u32 data; -} __packed; - -struct mc32_stats -{ - /* RX Errors */ - u32 rx_crc_errors; - u32 rx_alignment_errors; - u32 rx_overrun_errors; - u32 rx_tooshort_errors; - u32 rx_toolong_errors; - u32 rx_outofresource_errors; - - u32 rx_discarded; /* via card pattern match filter */ - - /* TX Errors */ - u32 tx_max_collisions; - u32 tx_carrier_errors; - u32 tx_underrun_errors; - u32 tx_cts_errors; - u32 tx_timeout_errors; - - /* various cruft */ - u32 dataA[6]; - u16 dataB[5]; - u32 dataC[14]; -} __packed; - -#define STATUS_MASK 0x0F -#define COMPLETED (1<<7) -#define COMPLETED_OK (1<<6) -#define BUFFER_BUSY (1<<5) - -#define CONTROL_EOP (1<<7) /* End Of Packet */ -#define CONTROL_EOL (1<<6) /* End of List */ - -#define MCA_MC32_ID 0x0041 /* Our MCA ident */ diff --git a/drivers/net/ethernet/i825xx/Kconfig b/drivers/net/ethernet/i825xx/Kconfig index ca1ae985c6df..fed5080a6b62 100644 --- a/drivers/net/ethernet/i825xx/Kconfig +++ b/drivers/net/ethernet/i825xx/Kconfig @@ -43,28 +43,6 @@ config EL16 To compile this driver as a module, choose M here. The module will be called 3c507. -config ELMC - tristate "3c523 \"EtherLink/MC\" support" - depends on MCA_LEGACY - ---help--- - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - To compile this driver as a module, choose M here. The module - will be called 3c523. - -config ELMC_II - tristate "3c527 \"EtherLink/MC 32\" support (EXPERIMENTAL)" - depends on MCA && MCA_LEGACY - ---help--- - If you have a network (Ethernet) card of this type, say Y and read - the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. - - To compile this driver as a module, choose M here. The module - will be called 3c527. - 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 f68a3694968a..6adff85e8ecc 100644 --- a/drivers/net/ethernet/i825xx/Makefile +++ b/drivers/net/ethernet/i825xx/Makefile @@ -7,8 +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_ELMC) += 3c523.o -obj-$(CONFIG_ELMC_II) += 3c527.o obj-$(CONFIG_LP486E) += lp486e.o obj-$(CONFIG_NI52) += ni52.o obj-$(CONFIG_SUN3_82586) += sun3_82586.o diff --git a/drivers/net/ethernet/i825xx/eexpress.c b/drivers/net/ethernet/i825xx/eexpress.c index cc2e66ad4436..7a6a2f04c5b1 100644 --- a/drivers/net/ethernet/i825xx/eexpress.c +++ b/drivers/net/ethernet/i825xx/eexpress.c @@ -9,7 +9,7 @@ * Many modifications, and currently maintained, by * Philip Blundell <philb@gnu.org> * Added the Compaq LTE Alan Cox <alan@lxorguk.ukuu.org.uk> - * Added MCA support Adam Fritzler + * 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 @@ -111,7 +111,6 @@ #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> -#include <linux/mca-legacy.h> #include <linux/spinlock.h> #include <linux/bitops.h> #include <linux/jiffies.h> @@ -227,16 +226,6 @@ static unsigned short start_code[] = { /* 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 }; -#ifdef CONFIG_MCA_LEGACY -/* mapping of the first four bits of the second POS register */ -static unsigned short mca_iomap[] = { - 0x270, 0x260, 0x250, 0x240, 0x230, 0x220, 0x210, 0x200, - 0x370, 0x360, 0x350, 0x340, 0x330, 0x320, 0x310, 0x300 -}; -/* bits 5-7 of the second POS register */ -static char mca_irqmap[] = { 12, 9, 3, 4, 5, 10, 11, 15 }; -#endif - /* * Prototypes for Linux interface */ @@ -340,53 +329,6 @@ static int __init do_express_probe(struct net_device *dev) dev->if_port = 0xff; /* not set */ -#ifdef CONFIG_MCA_LEGACY - if (MCA_bus) { - int slot = 0; - - /* - * Only find one card at a time. Subsequent calls - * will find others, however, proper multicard MCA - * probing and setup can't be done with the - * old-style Space.c init routines. -- ASF - */ - while (slot != MCA_NOTFOUND) { - int pos0, pos1; - - slot = mca_find_unused_adapter(0x628B, slot); - if (slot == MCA_NOTFOUND) - break; - - pos0 = mca_read_stored_pos(slot, 2); - pos1 = mca_read_stored_pos(slot, 3); - ioaddr = mca_iomap[pos1&0xf]; - - dev->irq = mca_irqmap[(pos1>>4)&0x7]; - - /* - * XXX: Transceiver selection is done - * differently on the MCA version. - * How to get it to select something - * other than external/AUI is currently - * unknown. This code is just for looks. -- ASF - */ - if ((pos0 & 0x7) == 0x1) - dev->if_port = AUI; - else if ((pos0 & 0x7) == 0x5) { - if (pos1 & 0x80) - dev->if_port = BNC; - else - dev->if_port = TPE; - } - - mca_set_adapter_name(slot, "Intel EtherExpress 16 MCA"); - mca_set_adapter_procfn(slot, NULL, dev); - mca_mark_as_used(slot); - - break; - } - } -#endif if (ioaddr&0xfe00) { if (!request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress")) return -EBUSY; |