diff options
Diffstat (limited to 'drivers/net/pcmcia')
| -rw-r--r-- | drivers/net/pcmcia/3c574_cs.c | 1181 | ||||
| -rw-r--r-- | drivers/net/pcmcia/3c589_cs.c | 943 | ||||
| -rw-r--r-- | drivers/net/pcmcia/Kconfig | 123 | ||||
| -rw-r--r-- | drivers/net/pcmcia/Makefile | 16 | ||||
| -rw-r--r-- | drivers/net/pcmcia/axnet_cs.c | 1726 | ||||
| -rw-r--r-- | drivers/net/pcmcia/com20020_cs.c | 349 | ||||
| -rw-r--r-- | drivers/net/pcmcia/fmvj18x_cs.c | 1186 | ||||
| -rw-r--r-- | drivers/net/pcmcia/ibmtr_cs.c | 371 | ||||
| -rw-r--r-- | drivers/net/pcmcia/nmclan_cs.c | 1525 | ||||
| -rw-r--r-- | drivers/net/pcmcia/pcnet_cs.c | 1710 | ||||
| -rw-r--r-- | drivers/net/pcmcia/smc91c92_cs.c | 2070 | ||||
| -rw-r--r-- | drivers/net/pcmcia/xirc2ps_cs.c | 1813 | 
12 files changed, 0 insertions, 13013 deletions
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c deleted file mode 100644 index 321b12f8264..00000000000 --- a/drivers/net/pcmcia/3c574_cs.c +++ /dev/null @@ -1,1181 +0,0 @@ -/* 3c574.c: A PCMCIA ethernet driver for the 3com 3c574 "RoadRunner". - -	Written 1993-1998 by -	Donald Becker, becker@scyld.com, (driver core) and -	David Hinds, dahinds@users.sourceforge.net (from his PC card code). -	Locking fixes (C) Copyright 2003 Red Hat Inc - -	This software may be used and distributed according to the terms of -	the GNU General Public License, incorporated herein by reference. - -	This driver derives from Donald Becker's 3c509 core, which has the -	following copyright: -	Copyright 1993 United States Government as represented by the -	Director, National Security Agency. -	 - -*/ - -/* -				Theory of Operation - -I. Board Compatibility - -This device driver is designed for the 3Com 3c574 PC card Fast Ethernet -Adapter. - -II. Board-specific settings - -None -- PC cards are autoconfigured. - -III. Driver operation - -The 3c574 uses a Boomerang-style interface, without the bus-master capability. -See the Boomerang driver and documentation for most details. - -IV. Notes and chip documentation. - -Two added registers are used to enhance PIO performance, RunnerRdCtrl and -RunnerWrCtrl.  These are 11 bit down-counters that are preloaded with the -count of word (16 bits) reads or writes the driver is about to do to the Rx -or Tx FIFO.  The chip is then able to hide the internal-PCI-bus to PC-card -translation latency by buffering the I/O operations with an 8 word FIFO. -Note: No other chip accesses are permitted when this buffer is used. - -A second enhancement is that both attribute and common memory space -0x0800-0x0fff can translated to the PIO FIFO.  Thus memory operations (faster -with *some* PCcard bridges) may be used instead of I/O operations. -This is enabled by setting the 0x10 bit in the PCMCIA LAN COR. - -Some slow PC card bridges work better if they never see a WAIT signal. -This is configured by setting the 0x20 bit in the PCMCIA LAN COR. -Only do this after testing that it is reliable and improves performance. - -The upper five bits of RunnerRdCtrl are used to window into PCcard -configuration space registers.  Window 0 is the regular Boomerang/Odie -register set, 1-5 are various PC card control registers, and 16-31 are -the (reversed!) CIS table. - -A final note: writing the InternalConfig register in window 3 with an -invalid ramWidth is Very Bad. - -V. References - -http://www.scyld.com/expert/NWay.html -http://www.national.com/opf/DP/DP83840A.html - -Thanks to Terry Murphy of 3Com for providing development information for -earlier 3Com products. - -*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/bitops.h> -#include <linux/mii.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> - -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/system.h> - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); -MODULE_DESCRIPTION("3Com 3c574 series PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -INT_MODULE_PARM(max_interrupt_work, 32); - -/* Force full duplex modes? */ -INT_MODULE_PARM(full_duplex, 0); - -/* Autodetect link polarity reversal? */ -INT_MODULE_PARM(auto_polarity, 1); - - -/*====================================================================*/ - -/* Time in jiffies before concluding the transmitter is hung. */ -#define TX_TIMEOUT  ((800*HZ)/1000) - -/* To minimize the size of the driver source and make the driver more -   readable not all constants are symbolically defined. -   You'll need the manual if you want to understand driver details anyway. */ -/* Offsets from base I/O address. */ -#define EL3_DATA	0x00 -#define EL3_CMD		0x0e -#define EL3_STATUS	0x0e - -#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) - -/* The top five bits written to EL3_CMD are a command, the lower -   11 bits are the parameter, if applicable. */ -enum el3_cmds { -	TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11, -	RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11, -	TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11, -	FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11, -	SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11, -	SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11, -	StatsDisable = 22<<11, StopCoax = 23<<11, -}; - -enum elxl_status { -	IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004, -	TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020, -	IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000 }; - -/* The SetRxFilter command accepts the following classes: */ -enum RxFilter { -	RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 -}; - -enum Window0 { -	Wn0EepromCmd = 10, Wn0EepromData = 12, /* EEPROM command/address, data. */ -	IntrStatus=0x0E,		/* Valid in all windows. */ -}; -/* These assumes the larger EEPROM. */ -enum Win0_EEPROM_cmds { -	EEPROM_Read = 0x200, EEPROM_WRITE = 0x100, EEPROM_ERASE = 0x300, -	EEPROM_EWENB = 0x30,		/* Enable erasing/writing for 10 msec. */ -	EEPROM_EWDIS = 0x00,		/* Disable EWENB before 10 msec timeout. */ -}; - -/* Register window 1 offsets, the window used in normal operation. -   On the "Odie" this window is always mapped at offsets 0x10-0x1f. -   Except for TxFree, which is overlapped by RunnerWrCtrl. */ -enum Window1 { -	TX_FIFO = 0x10,  RX_FIFO = 0x10,  RxErrors = 0x14, -	RxStatus = 0x18,  Timer=0x1A, TxStatus = 0x1B, -	TxFree = 0x0C, /* Remaining free bytes in Tx buffer. */ -	RunnerRdCtrl = 0x16, RunnerWrCtrl = 0x1c, -}; - -enum Window3 {			/* Window 3: MAC/config bits. */ -	Wn3_Config=0, Wn3_MAC_Ctrl=6, Wn3_Options=8, -}; -enum wn3_config { -	Ram_size = 7, -	Ram_width = 8, -	Ram_speed = 0x30, -	Rom_size = 0xc0, -	Ram_split_shift = 16, -	Ram_split = 3 << Ram_split_shift, -	Xcvr_shift = 20, -	Xcvr = 7 << Xcvr_shift, -	Autoselect = 0x1000000, -}; - -enum Window4 {		/* Window 4: Xcvr/media bits. */ -	Wn4_FIFODiag = 4, Wn4_NetDiag = 6, Wn4_PhysicalMgmt=8, Wn4_Media = 10, -}; - -#define MEDIA_TP	0x00C0	/* Enable link beat and jabber for 10baseT. */ - -struct el3_private { -	struct pcmcia_device	*p_dev; -	u16 advertising, partner;		/* NWay media advertisement */ -	unsigned char phys;			/* MII device address */ -	unsigned int autoselect:1, default_media:3;	/* Read from the EEPROM/Wn3_Config. */ -	/* for transceiver monitoring */ -	struct timer_list media; -	unsigned short media_status; -	unsigned short fast_poll; -	unsigned long last_irq; -	spinlock_t window_lock;			/* Guards the Window selection */ -}; - -/* Set iff a MII transceiver on any interface requires mdio preamble. -   This only set with the original DP83840 on older 3c905 boards, so the extra -   code size of a per-interface flag is not worthwhile. */ -static char mii_preamble_required = 0; - -/* Index of functions. */ - -static int tc574_config(struct pcmcia_device *link); -static void tc574_release(struct pcmcia_device *link); - -static void mdio_sync(unsigned int ioaddr, int bits); -static int mdio_read(unsigned int ioaddr, int phy_id, int location); -static void mdio_write(unsigned int ioaddr, int phy_id, int location, -		       int value); -static unsigned short read_eeprom(unsigned int ioaddr, int index); -static void tc574_wait_for_completion(struct net_device *dev, int cmd); - -static void tc574_reset(struct net_device *dev); -static void media_check(unsigned long arg); -static int el3_open(struct net_device *dev); -static netdev_tx_t el3_start_xmit(struct sk_buff *skb, -					struct net_device *dev); -static irqreturn_t el3_interrupt(int irq, void *dev_id); -static void update_stats(struct net_device *dev); -static struct net_device_stats *el3_get_stats(struct net_device *dev); -static int el3_rx(struct net_device *dev, int worklimit); -static int el3_close(struct net_device *dev); -static void el3_tx_timeout(struct net_device *dev); -static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void set_rx_mode(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); - -static void tc574_detach(struct pcmcia_device *p_dev); - -/* -	tc574_attach() creates an "instance" of the driver, allocating -	local data structures for one device.  The device is registered -	with Card Services. -*/ -static const struct net_device_ops el3_netdev_ops = { -	.ndo_open 		= el3_open, -	.ndo_stop 		= el3_close, -	.ndo_start_xmit		= el3_start_xmit, -	.ndo_tx_timeout 	= el3_tx_timeout, -	.ndo_get_stats		= el3_get_stats, -	.ndo_do_ioctl		= el3_ioctl, -	.ndo_set_multicast_list = set_multicast_list, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int tc574_probe(struct pcmcia_device *link) -{ -	struct el3_private *lp; -	struct net_device *dev; - -	dev_dbg(&link->dev, "3c574_attach()\n"); - -	/* Create the PC card device object. */ -	dev = alloc_etherdev(sizeof(struct el3_private)); -	if (!dev) -		return -ENOMEM; -	lp = netdev_priv(dev); -	link->priv = dev; -	lp->p_dev = link; - -	spin_lock_init(&lp->window_lock); -	link->resource[0]->end = 32; -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; -	link->config_flags |= CONF_ENABLE_IRQ; -	link->config_index = 1; - -	dev->netdev_ops = &el3_netdev_ops; -	dev->watchdog_timeo = TX_TIMEOUT; - -	return tc574_config(link); -} - -static void tc574_detach(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	dev_dbg(&link->dev, "3c574_detach()\n"); - -	unregister_netdev(dev); - -	tc574_release(link); - -	free_netdev(dev); -} /* tc574_detach */ - -static const char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; - -static int tc574_config(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; -	struct el3_private *lp = netdev_priv(dev); -	int ret, i, j; -	unsigned int ioaddr; -	__be16 *phys_addr; -	char *cardname; -	__u32 config; -	u8 *buf; -	size_t len; - -	phys_addr = (__be16 *)dev->dev_addr; - -	dev_dbg(&link->dev, "3c574_config()\n"); - -	link->io_lines = 16; - -	for (i = j = 0; j < 0x400; j += 0x20) { -		link->resource[0]->start = j ^ 0x300; -		i = pcmcia_request_io(link); -		if (i == 0) -			break; -	} -	if (i != 0) -		goto failed; - -	ret = pcmcia_request_irq(link, el3_interrupt); -	if (ret) -		goto failed; - -	ret = pcmcia_enable_device(link); -	if (ret) -		goto failed; - -	dev->irq = link->irq; -	dev->base_addr = link->resource[0]->start; - -	ioaddr = dev->base_addr; - -	/* The 3c574 normally uses an EEPROM for configuration info, including -	   the hardware address.  The future products may include a modem chip -	   and put the address in the CIS. */ - -	len = pcmcia_get_tuple(link, 0x88, &buf); -	if (buf && len >= 6) { -		for (i = 0; i < 3; i++) -			phys_addr[i] = htons(le16_to_cpu(buf[i * 2])); -		kfree(buf); -	} else { -		kfree(buf); /* 0 < len < 6 */ -		EL3WINDOW(0); -		for (i = 0; i < 3; i++) -			phys_addr[i] = htons(read_eeprom(ioaddr, i + 10)); -		if (phys_addr[0] == htons(0x6060)) { -			pr_notice("IO port conflict at 0x%03lx-0x%03lx\n", -				  dev->base_addr, dev->base_addr+15); -			goto failed; -		} -	} -	if (link->prod_id[1]) -		cardname = link->prod_id[1]; -	else -		cardname = "3Com 3c574"; - -	{ -		u_char mcr; -		outw(2<<11, ioaddr + RunnerRdCtrl); -		mcr = inb(ioaddr + 2); -		outw(0<<11, ioaddr + RunnerRdCtrl); -		pr_info("  ASIC rev %d,", mcr>>3); -		EL3WINDOW(3); -		config = inl(ioaddr + Wn3_Config); -		lp->default_media = (config & Xcvr) >> Xcvr_shift; -		lp->autoselect = config & Autoselect ? 1 : 0; -	} - -	init_timer(&lp->media); - -	{ -		int phy; -		 -		/* Roadrunner only: Turn on the MII transceiver */ -		outw(0x8040, ioaddr + Wn3_Options); -		mdelay(1); -		outw(0xc040, ioaddr + Wn3_Options); -		tc574_wait_for_completion(dev, TxReset); -		tc574_wait_for_completion(dev, RxReset); -		mdelay(1); -		outw(0x8040, ioaddr + Wn3_Options); -		 -		EL3WINDOW(4); -		for (phy = 1; phy <= 32; phy++) { -			int mii_status; -			mdio_sync(ioaddr, 32); -			mii_status = mdio_read(ioaddr, phy & 0x1f, 1); -			if (mii_status != 0xffff) { -				lp->phys = phy & 0x1f; -				dev_dbg(&link->dev, "  MII transceiver at " -					"index %d, status %x.\n", -					  phy, mii_status); -				if ((mii_status & 0x0040) == 0) -					mii_preamble_required = 1; -				break; -			} -		} -		if (phy > 32) { -			pr_notice("  No MII transceivers found!\n"); -			goto failed; -		} -		i = mdio_read(ioaddr, lp->phys, 16) | 0x40; -		mdio_write(ioaddr, lp->phys, 16, i); -		lp->advertising = mdio_read(ioaddr, lp->phys, 4); -		if (full_duplex) { -			/* Only advertise the FD media types. */ -			lp->advertising &= ~0x02a0; -			mdio_write(ioaddr, lp->phys, 4, lp->advertising); -		} -	} - -	SET_NETDEV_DEV(dev, &link->dev); - -	if (register_netdev(dev) != 0) { -		pr_notice("register_netdev() failed\n"); -		goto failed; -	} - -	netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", -		    cardname, dev->base_addr, dev->irq, dev->dev_addr); -	netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", -		    8 << config & Ram_size, -		    ram_split[(config & Ram_split) >> Ram_split_shift], -		    config & Autoselect ? "autoselect " : ""); - -	return 0; - -failed: -	tc574_release(link); -	return -ENODEV; - -} /* tc574_config */ - -static void tc574_release(struct pcmcia_device *link) -{ -	pcmcia_disable_device(link); -} - -static int tc574_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int tc574_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		tc574_reset(dev); -		netif_device_attach(dev); -	} - -	return 0; -} - -static void dump_status(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	EL3WINDOW(1); -	netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x, tx free %04x\n", -		    inw(ioaddr+EL3_STATUS), -		    inw(ioaddr+RxStatus), inb(ioaddr+TxStatus), -		    inw(ioaddr+TxFree)); -	EL3WINDOW(4); -	netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n", -		    inw(ioaddr+0x04), inw(ioaddr+0x06), -		    inw(ioaddr+0x08), inw(ioaddr+0x0a)); -	EL3WINDOW(1); -} - -/* -  Use this for commands that may take time to finish -*/ -static void tc574_wait_for_completion(struct net_device *dev, int cmd) -{ -	int i = 1500; -	outw(cmd, dev->base_addr + EL3_CMD); -	while (--i > 0) -		if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break; -	if (i == 0) -		netdev_notice(dev, "command 0x%04x did not complete!\n", cmd); -} - -/* Read a word from the EEPROM using the regular EEPROM access register. -   Assume that we are in register window zero. - */ -static unsigned short read_eeprom(unsigned int ioaddr, int index) -{ -	int timer; -	outw(EEPROM_Read + index, ioaddr + Wn0EepromCmd); -	/* Pause for at least 162 usec for the read to take place. */ -	for (timer = 1620; timer >= 0; timer--) { -		if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) -			break; -	} -	return inw(ioaddr + Wn0EepromData); -} - -/* MII transceiver control section. -   Read and write the MII registers using software-generated serial -   MDIO protocol.  See the MII specifications or DP83840A data sheet -   for details. -   The maxium data clock rate is 2.5 Mhz.  The timing is easily met by the -   slow PC card interface. */ - -#define MDIO_SHIFT_CLK	0x01 -#define MDIO_DIR_WRITE	0x04 -#define MDIO_DATA_WRITE0 (0x00 | MDIO_DIR_WRITE) -#define MDIO_DATA_WRITE1 (0x02 | MDIO_DIR_WRITE) -#define MDIO_DATA_READ	0x02 -#define MDIO_ENB_IN		0x00 - -/* Generate the preamble required for initial synchronization and -   a few older transceivers. */ -static void mdio_sync(unsigned int ioaddr, int bits) -{ -	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt; - -	/* Establish sync by sending at least 32 logic ones. */ -	while (-- bits >= 0) { -		outw(MDIO_DATA_WRITE1, mdio_addr); -		outw(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr); -	} -} - -static int mdio_read(unsigned int ioaddr, int phy_id, int location) -{ -	int i; -	int read_cmd = (0xf6 << 10) | (phy_id << 5) | location; -	unsigned int retval = 0; -	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt; - -	if (mii_preamble_required) -		mdio_sync(ioaddr, 32); - -	/* Shift the read command bits out. */ -	for (i = 14; i >= 0; i--) { -		int dataval = (read_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -		outw(dataval, mdio_addr); -		outw(dataval | MDIO_SHIFT_CLK, mdio_addr); -	} -	/* Read the two transition, 16 data, and wire-idle bits. */ -	for (i = 19; i > 0; i--) { -		outw(MDIO_ENB_IN, mdio_addr); -		retval = (retval << 1) | ((inw(mdio_addr) & MDIO_DATA_READ) ? 1 : 0); -		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); -	} -	return (retval>>1) & 0xffff; -} - -static void mdio_write(unsigned int ioaddr, int phy_id, int location, int value) -{ -	int write_cmd = 0x50020000 | (phy_id << 23) | (location << 18) | value; -	unsigned int mdio_addr = ioaddr + Wn4_PhysicalMgmt; -	int i; - -	if (mii_preamble_required) -		mdio_sync(ioaddr, 32); - -	/* Shift the command bits out. */ -	for (i = 31; i >= 0; i--) { -		int dataval = (write_cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -		outw(dataval, mdio_addr); -		outw(dataval | MDIO_SHIFT_CLK, mdio_addr); -	} -	/* Leave the interface idle. */ -	for (i = 1; i >= 0; i--) { -		outw(MDIO_ENB_IN, mdio_addr); -		outw(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr); -	} -} - -/* Reset and restore all of the 3c574 registers. */ -static void tc574_reset(struct net_device *dev) -{ -	struct el3_private *lp = netdev_priv(dev); -	int i; -	unsigned int ioaddr = dev->base_addr; -	unsigned long flags; - -	tc574_wait_for_completion(dev, TotalReset|0x10); - -	spin_lock_irqsave(&lp->window_lock, flags); -	/* Clear any transactions in progress. */ -	outw(0, ioaddr + RunnerWrCtrl); -	outw(0, ioaddr + RunnerRdCtrl); - -	/* Set the station address and mask. */ -	EL3WINDOW(2); -	for (i = 0; i < 6; i++) -		outb(dev->dev_addr[i], ioaddr + i); -	for (; i < 12; i+=2) -		outw(0, ioaddr + i); - -	/* Reset config options */ -	EL3WINDOW(3); -	outb((dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl); -	outl((lp->autoselect ? 0x01000000 : 0) | 0x0062001b, -		 ioaddr + Wn3_Config); -	/* Roadrunner only: Turn on the MII transceiver. */ -	outw(0x8040, ioaddr + Wn3_Options); -	mdelay(1); -	outw(0xc040, ioaddr + Wn3_Options); -	EL3WINDOW(1); -	spin_unlock_irqrestore(&lp->window_lock, flags); -	 -	tc574_wait_for_completion(dev, TxReset); -	tc574_wait_for_completion(dev, RxReset); -	mdelay(1); -	spin_lock_irqsave(&lp->window_lock, flags); -	EL3WINDOW(3); -	outw(0x8040, ioaddr + Wn3_Options); - -	/* Switch to the stats window, and clear all stats by reading. */ -	outw(StatsDisable, ioaddr + EL3_CMD); -	EL3WINDOW(6); -	for (i = 0; i < 10; i++) -		inb(ioaddr + i); -	inw(ioaddr + 10); -	inw(ioaddr + 12); -	EL3WINDOW(4); -	inb(ioaddr + 12); -	inb(ioaddr + 13); - -	/* .. enable any extra statistics bits.. */ -	outw(0x0040, ioaddr + Wn4_NetDiag); -	 -	EL3WINDOW(1); -	spin_unlock_irqrestore(&lp->window_lock, flags); -	 -	/* .. re-sync MII and re-fill what NWay is advertising. */ -	mdio_sync(ioaddr, 32); -	mdio_write(ioaddr, lp->phys, 4, lp->advertising); -	if (!auto_polarity) { -		/* works for TDK 78Q2120 series MII's */ -		i = mdio_read(ioaddr, lp->phys, 16) | 0x20; -		mdio_write(ioaddr, lp->phys, 16, i); -	} - -	spin_lock_irqsave(&lp->window_lock, flags); -	/* Switch to register set 1 for normal use, just for TxFree. */ -	set_rx_mode(dev); -	spin_unlock_irqrestore(&lp->window_lock, flags); -	outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ -	outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ -	outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ -	/* Allow status bits to be seen. */ -	outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); -	/* Ack all pending events, and set active indicator mask. */ -	outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, -		 ioaddr + EL3_CMD); -	outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull -		 | AdapterFailure | RxEarly, ioaddr + EL3_CMD); -} - -static int el3_open(struct net_device *dev) -{ -	struct el3_private *lp = netdev_priv(dev); -	struct pcmcia_device *link = lp->p_dev; - -	if (!pcmcia_dev_present(link)) -		return -ENODEV; -	 -	link->open++; -	netif_start_queue(dev); -	 -	tc574_reset(dev); -	lp->media.function = media_check; -	lp->media.data = (unsigned long) dev; -	lp->media.expires = jiffies + HZ; -	add_timer(&lp->media); -	 -	dev_dbg(&link->dev, "%s: opened, status %4.4x.\n", -		  dev->name, inw(dev->base_addr + EL3_STATUS)); -	 -	return 0; -} - -static void el3_tx_timeout(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	 -	netdev_notice(dev, "Transmit timed out!\n"); -	dump_status(dev); -	dev->stats.tx_errors++; -	dev->trans_start = jiffies; /* prevent tx timeout */ -	/* Issue TX_RESET and TX_START commands. */ -	tc574_wait_for_completion(dev, TxReset); -	outw(TxEnable, ioaddr + EL3_CMD); -	netif_wake_queue(dev); -} - -static void pop_tx_status(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	int i; -     -	/* Clear the Tx status stack. */ -	for (i = 32; i > 0; i--) { -		u_char tx_status = inb(ioaddr + TxStatus); -		if (!(tx_status & 0x84)) -			break; -		/* reset transmitter on jabber error or underrun */ -		if (tx_status & 0x30) -			tc574_wait_for_completion(dev, TxReset); -		if (tx_status & 0x38) { -			pr_debug("%s: transmit error: status 0x%02x\n", -				  dev->name, tx_status); -			outw(TxEnable, ioaddr + EL3_CMD); -			dev->stats.tx_aborted_errors++; -		} -		outb(0x00, ioaddr + TxStatus); /* Pop the status stack. */ -	} -} - -static netdev_tx_t el3_start_xmit(struct sk_buff *skb, -					struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	struct el3_private *lp = netdev_priv(dev); -	unsigned long flags; - -	pr_debug("%s: el3_start_xmit(length = %ld) called, " -		  "status %4.4x.\n", dev->name, (long)skb->len, -		  inw(ioaddr + EL3_STATUS)); - -	spin_lock_irqsave(&lp->window_lock, flags); - -	dev->stats.tx_bytes += skb->len; - -	/* Put out the doubleword header... */ -	outw(skb->len, ioaddr + TX_FIFO); -	outw(0, ioaddr + TX_FIFO); -	/* ... and the packet rounded to a doubleword. */ -	outsl(ioaddr + TX_FIFO, skb->data, (skb->len+3)>>2); - -	/* TxFree appears only in Window 1, not offset 0x1c. */ -	if (inw(ioaddr + TxFree) <= 1536) { -		netif_stop_queue(dev); -		/* Interrupt us when the FIFO has room for max-sized packet.  -		   The threshold is in units of dwords. */ -		outw(SetTxThreshold + (1536>>2), ioaddr + EL3_CMD); -	} - -	pop_tx_status(dev); -	spin_unlock_irqrestore(&lp->window_lock, flags); -	dev_kfree_skb(skb); -	return NETDEV_TX_OK; -} - -/* The EL3 interrupt handler. */ -static irqreturn_t el3_interrupt(int irq, void *dev_id) -{ -	struct net_device *dev = (struct net_device *) dev_id; -	struct el3_private *lp = netdev_priv(dev); -	unsigned int ioaddr; -	unsigned status; -	int work_budget = max_interrupt_work; -	int handled = 0; - -	if (!netif_device_present(dev)) -		return IRQ_NONE; -	ioaddr = dev->base_addr; - -	pr_debug("%s: interrupt, status %4.4x.\n", -		  dev->name, inw(ioaddr + EL3_STATUS)); - -	spin_lock(&lp->window_lock); -	 -	while ((status = inw(ioaddr + EL3_STATUS)) & -		   (IntLatch | RxComplete | RxEarly | StatsFull)) { -		if (!netif_device_present(dev) || -			((status & 0xe000) != 0x2000)) { -			pr_debug("%s: Interrupt from dead card\n", dev->name); -			break; -		} - -		handled = 1; - -		if (status & RxComplete) -			work_budget = el3_rx(dev, work_budget); - -		if (status & TxAvailable) { -			pr_debug("  TX room bit was handled.\n"); -			/* There's room in the FIFO for a full-sized packet. */ -			outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); -			netif_wake_queue(dev); -		} - -		if (status & TxComplete) -			pop_tx_status(dev); - -		if (status & (AdapterFailure | RxEarly | StatsFull)) { -			/* Handle all uncommon interrupts. */ -			if (status & StatsFull) -				update_stats(dev); -			if (status & RxEarly) { -				work_budget = el3_rx(dev, work_budget); -				outw(AckIntr | RxEarly, ioaddr + EL3_CMD); -			} -			if (status & AdapterFailure) { -				u16 fifo_diag; -				EL3WINDOW(4); -				fifo_diag = inw(ioaddr + Wn4_FIFODiag); -				EL3WINDOW(1); -				netdev_notice(dev, "adapter failure, FIFO diagnostic register %04x\n", -					      fifo_diag); -				if (fifo_diag & 0x0400) { -					/* Tx overrun */ -					tc574_wait_for_completion(dev, TxReset); -					outw(TxEnable, ioaddr + EL3_CMD); -				} -				if (fifo_diag & 0x2000) { -					/* Rx underrun */ -					tc574_wait_for_completion(dev, RxReset); -					set_rx_mode(dev); -					outw(RxEnable, ioaddr + EL3_CMD); -				} -				outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); -			} -		} - -		if (--work_budget < 0) { -			pr_debug("%s: Too much work in interrupt, " -				  "status %4.4x.\n", dev->name, status); -			/* Clear all interrupts */ -			outw(AckIntr | 0xFF, ioaddr + EL3_CMD); -			break; -		} -		/* Acknowledge the IRQ. */ -		outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); -	} - -	pr_debug("%s: exiting interrupt, status %4.4x.\n", -		  dev->name, inw(ioaddr + EL3_STATUS)); -		   -	spin_unlock(&lp->window_lock); -	return IRQ_RETVAL(handled); -} - -/* -    This timer serves two purposes: to check for missed interrupts -	(and as a last resort, poll the NIC for events), and to monitor -	the MII, reporting changes in cable status. -*/ -static void media_check(unsigned long arg) -{ -	struct net_device *dev = (struct net_device *) arg; -	struct el3_private *lp = netdev_priv(dev); -	unsigned int ioaddr = dev->base_addr; -	unsigned long flags; -	unsigned short /* cable, */ media, partner; - -	if (!netif_device_present(dev)) -		goto reschedule; -	 -	/* Check for pending interrupt with expired latency timer: with -	   this, we can limp along even if the interrupt is blocked */ -	if ((inw(ioaddr + EL3_STATUS) & IntLatch) && (inb(ioaddr + Timer) == 0xff)) { -		if (!lp->fast_poll) -			netdev_info(dev, "interrupt(s) dropped!\n"); - -		local_irq_save(flags); -		el3_interrupt(dev->irq, dev); -		local_irq_restore(flags); - -		lp->fast_poll = HZ; -	} -	if (lp->fast_poll) { -		lp->fast_poll--; -		lp->media.expires = jiffies + 2*HZ/100; -		add_timer(&lp->media); -		return; -	} - -	spin_lock_irqsave(&lp->window_lock, flags); -	EL3WINDOW(4); -	media = mdio_read(ioaddr, lp->phys, 1); -	partner = mdio_read(ioaddr, lp->phys, 5); -	EL3WINDOW(1); -	 -	if (media != lp->media_status) { -		if ((media ^ lp->media_status) & 0x0004) -			netdev_info(dev, "%s link beat\n", -				    (lp->media_status & 0x0004) ? "lost" : "found"); -		if ((media ^ lp->media_status) & 0x0020) { -			lp->partner = 0; -			if (lp->media_status & 0x0020) { -				netdev_info(dev, "autonegotiation restarted\n"); -			} else if (partner) { -				partner &= lp->advertising; -				lp->partner = partner; -				netdev_info(dev, "autonegotiation complete: " -					    "%dbaseT-%cD selected\n", -					    (partner & 0x0180) ? 100 : 10, -					    (partner & 0x0140) ? 'F' : 'H'); -			} else { -				netdev_info(dev, "link partner did not autonegotiate\n"); -			} - -			EL3WINDOW(3); -			outb((partner & 0x0140 ? 0x20 : 0) | -				 (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl); -			EL3WINDOW(1); - -		} -		if (media & 0x0010) -			netdev_info(dev, "remote fault detected\n"); -		if (media & 0x0002) -			netdev_info(dev, "jabber detected\n"); -		lp->media_status = media; -	} -	spin_unlock_irqrestore(&lp->window_lock, flags); - -reschedule: -	lp->media.expires = jiffies + HZ; -	add_timer(&lp->media); -} - -static struct net_device_stats *el3_get_stats(struct net_device *dev) -{ -	struct el3_private *lp = netdev_priv(dev); - -	if (netif_device_present(dev)) { -		unsigned long flags; -		spin_lock_irqsave(&lp->window_lock, flags); -		update_stats(dev); -		spin_unlock_irqrestore(&lp->window_lock, flags); -	} -	return &dev->stats; -} - -/*  Update statistics. -	Suprisingly this need not be run single-threaded, but it effectively is. -	The counters clear when read, so the adds must merely be atomic. - */ -static void update_stats(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	u8 rx, tx, up; - -	pr_debug("%s: updating the statistics.\n", dev->name); - -	if (inw(ioaddr+EL3_STATUS) == 0xffff) /* No card. */ -		return; -		 -	/* Unlike the 3c509 we need not turn off stats updates while reading. */ -	/* Switch to the stats window, and read everything. */ -	EL3WINDOW(6); -	dev->stats.tx_carrier_errors 		+= inb(ioaddr + 0); -	dev->stats.tx_heartbeat_errors		+= inb(ioaddr + 1); -	/* Multiple collisions. */	   	inb(ioaddr + 2); -	dev->stats.collisions			+= inb(ioaddr + 3); -	dev->stats.tx_window_errors		+= inb(ioaddr + 4); -	dev->stats.rx_fifo_errors		+= inb(ioaddr + 5); -	dev->stats.tx_packets			+= inb(ioaddr + 6); -	up		 			 = inb(ioaddr + 9); -	dev->stats.tx_packets			+= (up&0x30) << 4; -	/* Rx packets   */			   inb(ioaddr + 7); -	/* Tx deferrals */			   inb(ioaddr + 8); -	rx		 			 = inw(ioaddr + 10); -	tx					 = inw(ioaddr + 12); - -	EL3WINDOW(4); -	/* BadSSD */				   inb(ioaddr + 12); -	up					 = inb(ioaddr + 13); - -	EL3WINDOW(1); -} - -static int el3_rx(struct net_device *dev, int worklimit) -{ -	unsigned int ioaddr = dev->base_addr; -	short rx_status; -	 -	pr_debug("%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n", -		  dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RxStatus)); -	while (!((rx_status = inw(ioaddr + RxStatus)) & 0x8000) && -			worklimit > 0) { -		worklimit--; -		if (rx_status & 0x4000) { /* Error, update stats. */ -			short error = rx_status & 0x3800; -			dev->stats.rx_errors++; -			switch (error) { -			case 0x0000:	dev->stats.rx_over_errors++; break; -			case 0x0800:	dev->stats.rx_length_errors++; break; -			case 0x1000:	dev->stats.rx_frame_errors++; break; -			case 0x1800:	dev->stats.rx_length_errors++; break; -			case 0x2000:	dev->stats.rx_frame_errors++; break; -			case 0x2800:	dev->stats.rx_crc_errors++; break; -			} -		} else { -			short pkt_len = rx_status & 0x7ff; -			struct sk_buff *skb; - -			skb = dev_alloc_skb(pkt_len+5); - -			pr_debug("  Receiving packet size %d status %4.4x.\n", -				  pkt_len, rx_status); -			if (skb != NULL) { -				skb_reserve(skb, 2); -				insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len), -						((pkt_len+3)>>2)); -				skb->protocol = eth_type_trans(skb, dev); -				netif_rx(skb); -				dev->stats.rx_packets++; -				dev->stats.rx_bytes += pkt_len; -			} else { -				pr_debug("%s: couldn't allocate a sk_buff of" -					  " size %d.\n", dev->name, pkt_len); -				dev->stats.rx_dropped++; -			} -		} -		tc574_wait_for_completion(dev, RxDiscard); -	} - -	return worklimit; -} - -/* Provide ioctl() calls to examine the MII xcvr state. */ -static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ -	struct el3_private *lp = netdev_priv(dev); -	unsigned int ioaddr = dev->base_addr; -	struct mii_ioctl_data *data = if_mii(rq); -	int phy = lp->phys & 0x1f; - -	pr_debug("%s: In ioct(%-.6s, %#4.4x) %4.4x %4.4x %4.4x %4.4x.\n", -		  dev->name, rq->ifr_ifrn.ifrn_name, cmd, -		  data->phy_id, data->reg_num, data->val_in, data->val_out); - -	switch(cmd) { -	case SIOCGMIIPHY:		/* Get the address of the PHY in use. */ -		data->phy_id = phy; -	case SIOCGMIIREG:		/* Read the specified MII register. */ -		{ -			int saved_window; -			unsigned long flags; - -			spin_lock_irqsave(&lp->window_lock, flags); -			saved_window = inw(ioaddr + EL3_CMD) >> 13; -			EL3WINDOW(4); -			data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, -						  data->reg_num & 0x1f); -			EL3WINDOW(saved_window); -			spin_unlock_irqrestore(&lp->window_lock, flags); -			return 0; -		} -	case SIOCSMIIREG:		/* Write the specified MII register */ -		{ -			int saved_window; -                       unsigned long flags; - -			spin_lock_irqsave(&lp->window_lock, flags); -			saved_window = inw(ioaddr + EL3_CMD) >> 13; -			EL3WINDOW(4); -			mdio_write(ioaddr, data->phy_id & 0x1f, -				   data->reg_num & 0x1f, data->val_in); -			EL3WINDOW(saved_window); -			spin_unlock_irqrestore(&lp->window_lock, flags); -			return 0; -		} -	default: -		return -EOPNOTSUPP; -	} -} - -/* The Odie chip has a 64 bin multicast filter, but the bit layout is not -   documented.  Until it is we revert to receiving all multicast frames when -   any multicast reception is desired. -   Note: My other drivers emit a log message whenever promiscuous mode is -   entered to help detect password sniffers.  This is less desirable on -   typical PC card machines, so we omit the message. -   */ - -static void set_rx_mode(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; - -	if (dev->flags & IFF_PROMISC) -		outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm, -			 ioaddr + EL3_CMD); -	else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) -		outw(SetRxFilter|RxStation|RxMulticast|RxBroadcast, ioaddr + EL3_CMD); -	else -		outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD); -} - -static void set_multicast_list(struct net_device *dev) -{ -	struct el3_private *lp = netdev_priv(dev); -	unsigned long flags; - -	spin_lock_irqsave(&lp->window_lock, flags); -	set_rx_mode(dev); -	spin_unlock_irqrestore(&lp->window_lock, flags); -} - -static int el3_close(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	struct el3_private *lp = netdev_priv(dev); -	struct pcmcia_device *link = lp->p_dev; - -	dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name); -	 -	if (pcmcia_dev_present(link)) { -		unsigned long flags; - -		/* Turn off statistics ASAP.  We update lp->stats below. */ -		outw(StatsDisable, ioaddr + EL3_CMD); -		 -		/* Disable the receiver and transmitter. */ -		outw(RxDisable, ioaddr + EL3_CMD); -		outw(TxDisable, ioaddr + EL3_CMD); -		 -		/* Note: Switching to window 0 may disable the IRQ. */ -		EL3WINDOW(0); -		spin_lock_irqsave(&lp->window_lock, flags); -		update_stats(dev); -		spin_unlock_irqrestore(&lp->window_lock, flags); - -		/* force interrupts off */ -		outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD); -	} - -	link->open--; -	netif_stop_queue(dev); -	del_timer_sync(&lp->media); - -	return 0; -} - -static struct pcmcia_device_id tc574_ids[] = { -	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0574), -	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0556, "cis/3CCFEM556.cis"), -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, tc574_ids); - -static struct pcmcia_driver tc574_driver = { -	.owner		= THIS_MODULE, -	.name		= "3c574_cs", -	.probe		= tc574_probe, -	.remove		= tc574_detach, -	.id_table       = tc574_ids, -	.suspend	= tc574_suspend, -	.resume		= tc574_resume, -}; - -static int __init init_tc574(void) -{ -	return pcmcia_register_driver(&tc574_driver); -} - -static void __exit exit_tc574(void) -{ -	pcmcia_unregister_driver(&tc574_driver); -} - -module_init(init_tc574); -module_exit(exit_tc574); diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c deleted file mode 100644 index 79b9ca0dbdb..00000000000 --- a/drivers/net/pcmcia/3c589_cs.c +++ /dev/null @@ -1,943 +0,0 @@ -/*====================================================================== - -    A PCMCIA ethernet driver for the 3com 3c589 card. - -    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net - -    3c589_cs.c 1.162 2001/10/13 00:08:50 - -    The network driver code is based on Donald Becker's 3c589 code: - -    Written 1994 by Donald Becker. -    Copyright 1993 United States Government as represented by the -    Director, National Security Agency.  This software may be used and -    distributed according to the terms of the GNU General Public License, -    incorporated herein by reference. -    Donald Becker may be reached at becker@scyld.com - -    Updated for 2.5.x by Alan Cox <alan@lxorguk.ukuu.org.uk> - -======================================================================*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME	"3c589_cs" -#define DRV_VERSION	"1.162-ac" - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/delay.h> -#include <linux/ethtool.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/bitops.h> -#include <linux/jiffies.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> - -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/system.h> - -/* To minimize the size of the driver source I only define operating -   constants if they are used several times.  You'll need the manual -   if you want to understand driver details. */ -/* Offsets from base I/O address. */ -#define EL3_DATA	0x00 -#define EL3_TIMER	0x0a -#define EL3_CMD		0x0e -#define EL3_STATUS	0x0e - -#define EEPROM_READ	0x0080 -#define EEPROM_BUSY	0x8000 - -#define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD) - -/* The top five bits written to EL3_CMD are a command, the lower -   11 bits are the parameter, if applicable. */ -enum c509cmd { -	TotalReset	= 0<<11, -	SelectWindow	= 1<<11, -	StartCoax	= 2<<11, -	RxDisable	= 3<<11, -	RxEnable	= 4<<11, -	RxReset		= 5<<11, -	RxDiscard	= 8<<11, -	TxEnable	= 9<<11, -	TxDisable	= 10<<11, -	TxReset		= 11<<11, -	FakeIntr	= 12<<11, -	AckIntr		= 13<<11, -	SetIntrEnb	= 14<<11, -	SetStatusEnb	= 15<<11, -	SetRxFilter	= 16<<11, -	SetRxThreshold	= 17<<11, -	SetTxThreshold	= 18<<11, -	SetTxStart	= 19<<11, -	StatsEnable	= 21<<11, -	StatsDisable	= 22<<11, -	StopCoax	= 23<<11 -}; - -enum c509status { -	IntLatch	= 0x0001, -	AdapterFailure	= 0x0002, -	TxComplete	= 0x0004, -	TxAvailable	= 0x0008, -	RxComplete	= 0x0010, -	RxEarly		= 0x0020, -	IntReq		= 0x0040, -	StatsFull	= 0x0080, -	CmdBusy		= 0x1000 -}; - -/* The SetRxFilter command accepts the following classes: */ -enum RxFilter { -	RxStation	= 1, -	RxMulticast	= 2, -	RxBroadcast	= 4, -	RxProm		= 8 -}; - -/* Register window 1 offsets, the window used in normal operation. */ -#define TX_FIFO		0x00 -#define RX_FIFO		0x00 -#define RX_STATUS	0x08 -#define TX_STATUS	0x0B -#define TX_FREE		0x0C	/* Remaining free bytes in Tx buffer. */ - -#define WN0_IRQ		0x08	/* Window 0: Set IRQ line in bits 12-15. */ -#define WN4_MEDIA	0x0A	/* Window 4: Various transcvr/media bits. */ -#define MEDIA_TP	0x00C0	/* Enable link beat and jabber for 10baseT. */ -#define MEDIA_LED	0x0001	/* Enable link light on 3C589E cards. */ - -/* Time in jiffies before concluding Tx hung */ -#define TX_TIMEOUT	((400*HZ)/1000) - -struct el3_private { -	struct pcmcia_device	*p_dev; -	/* For transceiver monitoring */ -	struct timer_list	media; -	u16			media_status; -	u16			fast_poll; -	unsigned long		last_irq; -	spinlock_t		lock; -}; - -static const char *if_names[] = { "auto", "10baseT", "10base2", "AUI" }; - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); -MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -/* Special hook for setting if_port when module is loaded */ -INT_MODULE_PARM(if_port, 0); - - -/*====================================================================*/ - -static int tc589_config(struct pcmcia_device *link); -static void tc589_release(struct pcmcia_device *link); - -static u16 read_eeprom(unsigned int ioaddr, int index); -static void tc589_reset(struct net_device *dev); -static void media_check(unsigned long arg); -static int el3_config(struct net_device *dev, struct ifmap *map); -static int el3_open(struct net_device *dev); -static netdev_tx_t el3_start_xmit(struct sk_buff *skb, -					struct net_device *dev); -static irqreturn_t el3_interrupt(int irq, void *dev_id); -static void update_stats(struct net_device *dev); -static struct net_device_stats *el3_get_stats(struct net_device *dev); -static int el3_rx(struct net_device *dev); -static int el3_close(struct net_device *dev); -static void el3_tx_timeout(struct net_device *dev); -static void set_rx_mode(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; - -static void tc589_detach(struct pcmcia_device *p_dev); - -static const struct net_device_ops el3_netdev_ops = { -	.ndo_open		= el3_open, -	.ndo_stop		= el3_close, -	.ndo_start_xmit		= el3_start_xmit, -	.ndo_tx_timeout		= el3_tx_timeout, -	.ndo_set_config		= el3_config, -	.ndo_get_stats		= el3_get_stats, -	.ndo_set_multicast_list = set_multicast_list, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int tc589_probe(struct pcmcia_device *link) -{ -    struct el3_private *lp; -    struct net_device *dev; - -    dev_dbg(&link->dev, "3c589_attach()\n"); - -    /* Create new ethernet device */ -    dev = alloc_etherdev(sizeof(struct el3_private)); -    if (!dev) -	 return -ENOMEM; -    lp = netdev_priv(dev); -    link->priv = dev; -    lp->p_dev = link; - -    spin_lock_init(&lp->lock); -    link->resource[0]->end = 16; -    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; - -    link->config_flags |= CONF_ENABLE_IRQ; -    link->config_index = 1; - -    dev->netdev_ops = &el3_netdev_ops; -    dev->watchdog_timeo = TX_TIMEOUT; - -    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - -    return tc589_config(link); -} - -static void tc589_detach(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    dev_dbg(&link->dev, "3c589_detach\n"); - -    unregister_netdev(dev); - -    tc589_release(link); - -    free_netdev(dev); -} /* tc589_detach */ - -static int tc589_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    __be16 *phys_addr; -    int ret, i, j, multi = 0, fifo; -    unsigned int ioaddr; -    static const char * const ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; -    u8 *buf; -    size_t len; - -    dev_dbg(&link->dev, "3c589_config\n"); - -    phys_addr = (__be16 *)dev->dev_addr; -    /* Is this a 3c562? */ -    if (link->manf_id != MANFID_3COM) -	    dev_info(&link->dev, "hmmm, is this really a 3Com card??\n"); -    multi = (link->card_id == PRODID_3COM_3C562); - -    link->io_lines = 16; - -    /* For the 3c562, the base address must be xx00-xx7f */ -    for (i = j = 0; j < 0x400; j += 0x10) { -	if (multi && (j & 0x80)) continue; -	link->resource[0]->start = j ^ 0x300; -	i = pcmcia_request_io(link); -	if (i == 0) -		break; -    } -    if (i != 0) -	goto failed; - -    ret = pcmcia_request_irq(link, el3_interrupt); -    if (ret) -	    goto failed; - -    ret = pcmcia_enable_device(link); -    if (ret) -	    goto failed; - -    dev->irq = link->irq; -    dev->base_addr = link->resource[0]->start; -    ioaddr = dev->base_addr; -    EL3WINDOW(0); - -    /* The 3c589 has an extra EEPROM for configuration info, including -       the hardware address.  The 3c562 puts the address in the CIS. */ -    len = pcmcia_get_tuple(link, 0x88, &buf); -    if (buf && len >= 6) { -	    for (i = 0; i < 3; i++) -		    phys_addr[i] = htons(le16_to_cpu(buf[i*2])); -	    kfree(buf); -    } else { -	kfree(buf); /* 0 < len < 6 */ -	for (i = 0; i < 3; i++) -	    phys_addr[i] = htons(read_eeprom(ioaddr, i)); -	if (phys_addr[0] == htons(0x6060)) { -	    dev_err(&link->dev, "IO port conflict at 0x%03lx-0x%03lx\n", -		    dev->base_addr, dev->base_addr+15); -	    goto failed; -	} -    } - -    /* The address and resource configuration register aren't loaded from -       the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */ -    outw(0x3f00, ioaddr + 8); -    fifo = inl(ioaddr); - -    /* The if_port symbol can be set when the module is loaded */ -    if ((if_port >= 0) && (if_port <= 3)) -	dev->if_port = if_port; -    else -	dev_err(&link->dev, "invalid if_port requested\n"); - -    SET_NETDEV_DEV(dev, &link->dev); - -    if (register_netdev(dev) != 0) { -	    dev_err(&link->dev, "register_netdev() failed\n"); -	goto failed; -    } - -    netdev_info(dev, "3Com 3c%s, io %#3lx, irq %d, hw_addr %pM\n", -		(multi ? "562" : "589"), dev->base_addr, dev->irq, -		dev->dev_addr); -    netdev_info(dev, "  %dK FIFO split %s Rx:Tx, %s xcvr\n", -		(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3], -		if_names[dev->if_port]); -    return 0; - -failed: -    tc589_release(link); -    return -ENODEV; -} /* tc589_config */ - -static void tc589_release(struct pcmcia_device *link) -{ -	pcmcia_disable_device(link); -} - -static int tc589_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int tc589_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		tc589_reset(dev); -		netif_device_attach(dev); -	} - -	return 0; -} - -/*====================================================================*/ - -/* -  Use this for commands that may take time to finish -*/ -static void tc589_wait_for_completion(struct net_device *dev, int cmd) -{ -    int i = 100; -    outw(cmd, dev->base_addr + EL3_CMD); -    while (--i > 0) -	if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break; -    if (i == 0) -	netdev_warn(dev, "command 0x%04x did not complete!\n", cmd); -} - -/* -  Read a word from the EEPROM using the regular EEPROM access register. -  Assume that we are in register window zero. -*/ -static u16 read_eeprom(unsigned int ioaddr, int index) -{ -    int i; -    outw(EEPROM_READ + index, ioaddr + 10); -    /* Reading the eeprom takes 162 us */ -    for (i = 1620; i >= 0; i--) -	if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0) -	    break; -    return inw(ioaddr + 12); -} - -/* -  Set transceiver type, perhaps to something other than what the user -  specified in dev->if_port. -*/ -static void tc589_set_xcvr(struct net_device *dev, int if_port) -{ -    struct el3_private *lp = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; - -    EL3WINDOW(0); -    switch (if_port) { -    case 0: case 1: outw(0, ioaddr + 6); break; -    case 2: outw(3<<14, ioaddr + 6); break; -    case 3: outw(1<<14, ioaddr + 6); break; -    } -    /* On PCMCIA, this just turns on the LED */ -    outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD); -    /* 10baseT interface, enable link beat and jabber check. */ -    EL3WINDOW(4); -    outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA); -    EL3WINDOW(1); -    if (if_port == 2) -	lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000); -    else -	lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800); -} - -static void dump_status(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    EL3WINDOW(1); -    netdev_info(dev, "  irq status %04x, rx status %04x, tx status %02x  tx free %04x\n", -		inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS), -		inb(ioaddr+TX_STATUS), inw(ioaddr+TX_FREE)); -    EL3WINDOW(4); -    netdev_info(dev, "  diagnostics: fifo %04x net %04x ethernet %04x media %04x\n", -		inw(ioaddr+0x04), inw(ioaddr+0x06), inw(ioaddr+0x08), -		inw(ioaddr+0x0a)); -    EL3WINDOW(1); -} - -/* Reset and restore all of the 3c589 registers. */ -static void tc589_reset(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    int i; - -    EL3WINDOW(0); -    outw(0x0001, ioaddr + 4);			/* Activate board. */ -    outw(0x3f00, ioaddr + 8);			/* Set the IRQ line. */ - -    /* Set the station address in window 2. */ -    EL3WINDOW(2); -    for (i = 0; i < 6; i++) -	outb(dev->dev_addr[i], ioaddr + i); - -    tc589_set_xcvr(dev, dev->if_port); - -    /* Switch to the stats window, and clear all stats by reading. */ -    outw(StatsDisable, ioaddr + EL3_CMD); -    EL3WINDOW(6); -    for (i = 0; i < 9; i++) -	inb(ioaddr+i); -    inw(ioaddr + 10); -    inw(ioaddr + 12); - -    /* Switch to register set 1 for normal use. */ -    EL3WINDOW(1); - -    set_rx_mode(dev); -    outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ -    outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ -    outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ -    /* Allow status bits to be seen. */ -    outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD); -    /* Ack all pending events, and set active indicator mask. */ -    outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, -	 ioaddr + EL3_CMD); -    outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull -	 | AdapterFailure, ioaddr + EL3_CMD); -} - -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, "PCMCIA 0x%lx", dev->base_addr); -} - -static const struct ethtool_ops netdev_ethtool_ops = { -	.get_drvinfo		= netdev_get_drvinfo, -}; - -static int el3_config(struct net_device *dev, struct ifmap *map) -{ -    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { -	if (map->port <= 3) { -	    dev->if_port = map->port; -	    netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); -	    tc589_set_xcvr(dev, dev->if_port); -	} else -	    return -EINVAL; -    } -    return 0; -} - -static int el3_open(struct net_device *dev) -{ -    struct el3_private *lp = netdev_priv(dev); -    struct pcmcia_device *link = lp->p_dev; - -    if (!pcmcia_dev_present(link)) -	return -ENODEV; - -    link->open++; -    netif_start_queue(dev); - -    tc589_reset(dev); -    init_timer(&lp->media); -    lp->media.function = media_check; -    lp->media.data = (unsigned long) dev; -    lp->media.expires = jiffies + HZ; -    add_timer(&lp->media); - -    dev_dbg(&link->dev, "%s: opened, status %4.4x.\n", -	  dev->name, inw(dev->base_addr + EL3_STATUS)); - -    return 0; -} - -static void el3_tx_timeout(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; - -    netdev_warn(dev, "Transmit timed out!\n"); -    dump_status(dev); -    dev->stats.tx_errors++; -    dev->trans_start = jiffies; /* prevent tx timeout */ -    /* Issue TX_RESET and TX_START commands. */ -    tc589_wait_for_completion(dev, TxReset); -    outw(TxEnable, ioaddr + EL3_CMD); -    netif_wake_queue(dev); -} - -static void pop_tx_status(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    int i; - -    /* Clear the Tx status stack. */ -    for (i = 32; i > 0; i--) { -	u_char tx_status = inb(ioaddr + TX_STATUS); -	if (!(tx_status & 0x84)) break; -	/* reset transmitter on jabber error or underrun */ -	if (tx_status & 0x30) -		tc589_wait_for_completion(dev, TxReset); -	if (tx_status & 0x38) { -		netdev_dbg(dev, "transmit error: status 0x%02x\n", tx_status); -		outw(TxEnable, ioaddr + EL3_CMD); -		dev->stats.tx_aborted_errors++; -	} -	outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */ -    } -} - -static netdev_tx_t el3_start_xmit(struct sk_buff *skb, -					struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    struct el3_private *priv = netdev_priv(dev); -    unsigned long flags; - -    netdev_dbg(dev, "el3_start_xmit(length = %ld) called, status %4.4x.\n", -	       (long)skb->len, inw(ioaddr + EL3_STATUS)); - -    spin_lock_irqsave(&priv->lock, flags); - -    dev->stats.tx_bytes += skb->len; - -    /* Put out the doubleword header... */ -    outw(skb->len, ioaddr + TX_FIFO); -    outw(0x00, ioaddr + TX_FIFO); -    /* ... and the packet rounded to a doubleword. */ -    outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2); - -    if (inw(ioaddr + TX_FREE) <= 1536) { -	netif_stop_queue(dev); -	/* Interrupt us when the FIFO has room for max-sized packet. */ -	outw(SetTxThreshold + 1536, ioaddr + EL3_CMD); -    } - -    pop_tx_status(dev); -    spin_unlock_irqrestore(&priv->lock, flags); -    dev_kfree_skb(skb); - -    return NETDEV_TX_OK; -} - -/* The EL3 interrupt handler. */ -static irqreturn_t el3_interrupt(int irq, void *dev_id) -{ -    struct net_device *dev = (struct net_device *) dev_id; -    struct el3_private *lp = netdev_priv(dev); -    unsigned int ioaddr; -    __u16 status; -    int i = 0, handled = 1; - -    if (!netif_device_present(dev)) -	return IRQ_NONE; - -    ioaddr = dev->base_addr; - -    netdev_dbg(dev, "interrupt, status %4.4x.\n", inw(ioaddr + EL3_STATUS)); - -    spin_lock(&lp->lock); -    while ((status = inw(ioaddr + EL3_STATUS)) & -	(IntLatch | RxComplete | StatsFull)) { -	if ((status & 0xe000) != 0x2000) { -		netdev_dbg(dev, "interrupt from dead card\n"); -		handled = 0; -		break; -	} -	if (status & RxComplete) -		el3_rx(dev); -	if (status & TxAvailable) { -		netdev_dbg(dev, "    TX room bit was handled.\n"); -		/* There's room in the FIFO for a full-sized packet. */ -		outw(AckIntr | TxAvailable, ioaddr + EL3_CMD); -		netif_wake_queue(dev); -	} -	if (status & TxComplete) -		pop_tx_status(dev); -	if (status & (AdapterFailure | RxEarly | StatsFull)) { -	    /* Handle all uncommon interrupts. */ -	    if (status & StatsFull)		/* Empty statistics. */ -		update_stats(dev); -	    if (status & RxEarly) {		/* Rx early is unused. */ -		el3_rx(dev); -		outw(AckIntr | RxEarly, ioaddr + EL3_CMD); -	    } -	    if (status & AdapterFailure) { -		u16 fifo_diag; -		EL3WINDOW(4); -		fifo_diag = inw(ioaddr + 4); -		EL3WINDOW(1); -		netdev_warn(dev, "adapter failure, FIFO diagnostic register %04x.\n", -			    fifo_diag); -		if (fifo_diag & 0x0400) { -		    /* Tx overrun */ -		    tc589_wait_for_completion(dev, TxReset); -		    outw(TxEnable, ioaddr + EL3_CMD); -		} -		if (fifo_diag & 0x2000) { -		    /* Rx underrun */ -		    tc589_wait_for_completion(dev, RxReset); -		    set_rx_mode(dev); -		    outw(RxEnable, ioaddr + EL3_CMD); -		} -		outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD); -	    } -	} -	if (++i > 10) { -		netdev_err(dev, "infinite loop in interrupt, status %4.4x.\n", -			   status); -		/* Clear all interrupts */ -		outw(AckIntr | 0xFF, ioaddr + EL3_CMD); -		break; -	} -	/* Acknowledge the IRQ. */ -	outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); -    } -    lp->last_irq = jiffies; -    spin_unlock(&lp->lock); -    netdev_dbg(dev, "exiting interrupt, status %4.4x.\n", -	       inw(ioaddr + EL3_STATUS)); -    return IRQ_RETVAL(handled); -} - -static void media_check(unsigned long arg) -{ -    struct net_device *dev = (struct net_device *)(arg); -    struct el3_private *lp = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    u16 media, errs; -    unsigned long flags; - -    if (!netif_device_present(dev)) goto reschedule; - -    /* Check for pending interrupt with expired latency timer: with -       this, we can limp along even if the interrupt is blocked */ -    if ((inw(ioaddr + EL3_STATUS) & IntLatch) && -	(inb(ioaddr + EL3_TIMER) == 0xff)) { -	if (!lp->fast_poll) -		netdev_warn(dev, "interrupt(s) dropped!\n"); - -	local_irq_save(flags); -	el3_interrupt(dev->irq, dev); -	local_irq_restore(flags); - -	lp->fast_poll = HZ; -    } -    if (lp->fast_poll) { -	lp->fast_poll--; -	lp->media.expires = jiffies + HZ/100; -	add_timer(&lp->media); -	return; -    } - -    /* lp->lock guards the EL3 window. Window should always be 1 except -       when the lock is held */ -    spin_lock_irqsave(&lp->lock, flags); -    EL3WINDOW(4); -    media = inw(ioaddr+WN4_MEDIA) & 0xc810; - -    /* Ignore collisions unless we've had no irq's recently */ -    if (time_before(jiffies, lp->last_irq + HZ)) { -	media &= ~0x0010; -    } else { -	/* Try harder to detect carrier errors */ -	EL3WINDOW(6); -	outw(StatsDisable, ioaddr + EL3_CMD); -	errs = inb(ioaddr + 0); -	outw(StatsEnable, ioaddr + EL3_CMD); -	dev->stats.tx_carrier_errors += errs; -	if (errs || (lp->media_status & 0x0010)) media |= 0x0010; -    } - -    if (media != lp->media_status) { -	if ((media & lp->media_status & 0x8000) && -	    ((lp->media_status ^ media) & 0x0800)) -		netdev_info(dev, "%s link beat\n", -			    (lp->media_status & 0x0800 ? "lost" : "found")); -	else if ((media & lp->media_status & 0x4000) && -		 ((lp->media_status ^ media) & 0x0010)) -		netdev_info(dev, "coax cable %s\n", -			    (lp->media_status & 0x0010 ? "ok" : "problem")); -	if (dev->if_port == 0) { -	    if (media & 0x8000) { -		if (media & 0x0800) -			netdev_info(dev, "flipped to 10baseT\n"); -		else -			tc589_set_xcvr(dev, 2); -	    } else if (media & 0x4000) { -		if (media & 0x0010) -		    tc589_set_xcvr(dev, 1); -		else -		    netdev_info(dev, "flipped to 10base2\n"); -	    } -	} -	lp->media_status = media; -    } - -    EL3WINDOW(1); -    spin_unlock_irqrestore(&lp->lock, flags); - -reschedule: -    lp->media.expires = jiffies + HZ; -    add_timer(&lp->media); -} - -static struct net_device_stats *el3_get_stats(struct net_device *dev) -{ -    struct el3_private *lp = netdev_priv(dev); -    unsigned long flags; -    struct pcmcia_device *link = lp->p_dev; - -    if (pcmcia_dev_present(link)) { -	spin_lock_irqsave(&lp->lock, flags); -	update_stats(dev); -	spin_unlock_irqrestore(&lp->lock, flags); -    } -    return &dev->stats; -} - -/* -  Update statistics.  We change to register window 6, so this should be run -  single-threaded if the device is active. This is expected to be a rare -  operation, and it's simpler for the rest of the driver to assume that -  window 1 is always valid rather than use a special window-state variable. - -  Caller must hold the lock for this -*/ -static void update_stats(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; - -    netdev_dbg(dev, "updating the statistics.\n"); -    /* Turn off statistics updates while reading. */ -    outw(StatsDisable, ioaddr + EL3_CMD); -    /* Switch to the stats window, and read everything. */ -    EL3WINDOW(6); -    dev->stats.tx_carrier_errors	+= inb(ioaddr + 0); -    dev->stats.tx_heartbeat_errors	+= inb(ioaddr + 1); -    /* Multiple collisions. */		inb(ioaddr + 2); -    dev->stats.collisions		+= inb(ioaddr + 3); -    dev->stats.tx_window_errors		+= inb(ioaddr + 4); -    dev->stats.rx_fifo_errors		+= inb(ioaddr + 5); -    dev->stats.tx_packets		+= inb(ioaddr + 6); -    /* Rx packets   */			inb(ioaddr + 7); -    /* Tx deferrals */			inb(ioaddr + 8); -    /* Rx octets */			inw(ioaddr + 10); -    /* Tx octets */			inw(ioaddr + 12); - -    /* Back to window 1, and turn statistics back on. */ -    EL3WINDOW(1); -    outw(StatsEnable, ioaddr + EL3_CMD); -} - -static int el3_rx(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    int worklimit = 32; -    short rx_status; - -    netdev_dbg(dev, "in rx_packet(), status %4.4x, rx_status %4.4x.\n", -	       inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS)); -    while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) && -		    worklimit > 0) { -	worklimit--; -	if (rx_status & 0x4000) { /* Error, update stats. */ -	    short error = rx_status & 0x3800; -	    dev->stats.rx_errors++; -	    switch (error) { -	    case 0x0000:	dev->stats.rx_over_errors++; break; -	    case 0x0800:	dev->stats.rx_length_errors++; break; -	    case 0x1000:	dev->stats.rx_frame_errors++; break; -	    case 0x1800:	dev->stats.rx_length_errors++; break; -	    case 0x2000:	dev->stats.rx_frame_errors++; break; -	    case 0x2800:	dev->stats.rx_crc_errors++; break; -	    } -	} else { -	    short pkt_len = rx_status & 0x7ff; -	    struct sk_buff *skb; - -	    skb = dev_alloc_skb(pkt_len+5); - -	    netdev_dbg(dev, "    Receiving packet size %d status %4.4x.\n", -		       pkt_len, rx_status); -	    if (skb != NULL) { -		skb_reserve(skb, 2); -		insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len), -			(pkt_len+3)>>2); -		skb->protocol = eth_type_trans(skb, dev); -		netif_rx(skb); -		dev->stats.rx_packets++; -		dev->stats.rx_bytes += pkt_len; -	    } else { -		netdev_dbg(dev, "couldn't allocate a sk_buff of size %d.\n", -			   pkt_len); -		dev->stats.rx_dropped++; -	    } -	} -	/* Pop the top of the Rx FIFO */ -	tc589_wait_for_completion(dev, RxDiscard); -    } -    if (worklimit == 0) -	netdev_warn(dev, "too much work in el3_rx!\n"); -    return 0; -} - -static void set_rx_mode(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    u16 opts = SetRxFilter | RxStation | RxBroadcast; - -    if (dev->flags & IFF_PROMISC) -	opts |= RxMulticast | RxProm; -    else if (!netdev_mc_empty(dev) || (dev->flags & IFF_ALLMULTI)) -	opts |= RxMulticast; -    outw(opts, ioaddr + EL3_CMD); -} - -static void set_multicast_list(struct net_device *dev) -{ -	struct el3_private *priv = netdev_priv(dev); -	unsigned long flags; - -	spin_lock_irqsave(&priv->lock, flags); -	set_rx_mode(dev); -	spin_unlock_irqrestore(&priv->lock, flags); -} - -static int el3_close(struct net_device *dev) -{ -    struct el3_private *lp = netdev_priv(dev); -    struct pcmcia_device *link = lp->p_dev; -    unsigned int ioaddr = dev->base_addr; - -    dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name); - -    if (pcmcia_dev_present(link)) { -	/* Turn off statistics ASAP.  We update dev->stats below. */ -	outw(StatsDisable, ioaddr + EL3_CMD); - -	/* Disable the receiver and transmitter. */ -	outw(RxDisable, ioaddr + EL3_CMD); -	outw(TxDisable, ioaddr + EL3_CMD); - -	if (dev->if_port == 2) -	    /* Turn off thinnet power.  Green! */ -	    outw(StopCoax, ioaddr + EL3_CMD); -	else if (dev->if_port == 1) { -	    /* Disable link beat and jabber */ -	    EL3WINDOW(4); -	    outw(0, ioaddr + WN4_MEDIA); -	} - -	/* Switching back to window 0 disables the IRQ. */ -	EL3WINDOW(0); -	/* But we explicitly zero the IRQ line select anyway. */ -	outw(0x0f00, ioaddr + WN0_IRQ); - -	/* Check if the card still exists */ -	if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000) -	    update_stats(dev); -    } - -    link->open--; -    netif_stop_queue(dev); -    del_timer_sync(&lp->media); - -    return 0; -} - -static struct pcmcia_device_id tc589_ids[] = { -	PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x0101, 0x0562), -	PCMCIA_MFC_DEVICE_PROD_ID1(0, "Motorola MARQUIS", 0xf03e4e77), -	PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0589), -	PCMCIA_DEVICE_PROD_ID12("Farallon", "ENet", 0x58d93fc4, 0x992c2202), -	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x0035, "cis/3CXEM556.cis"), -	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0101, 0x003d, "cis/3CXEM556.cis"), -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, tc589_ids); - -static struct pcmcia_driver tc589_driver = { -	.owner		= THIS_MODULE, -	.name		= "3c589_cs", -	.probe		= tc589_probe, -	.remove		= tc589_detach, -	.id_table	= tc589_ids, -	.suspend	= tc589_suspend, -	.resume		= tc589_resume, -}; - -static int __init init_tc589(void) -{ -	return pcmcia_register_driver(&tc589_driver); -} - -static void __exit exit_tc589(void) -{ -	pcmcia_unregister_driver(&tc589_driver); -} - -module_init(init_tc589); -module_exit(exit_tc589); diff --git a/drivers/net/pcmcia/Kconfig b/drivers/net/pcmcia/Kconfig deleted file mode 100644 index 9b8f793b1cc..00000000000 --- a/drivers/net/pcmcia/Kconfig +++ /dev/null @@ -1,123 +0,0 @@ -# -# PCMCIA Network device configuration -# - -menuconfig NET_PCMCIA -	bool "PCMCIA network device support" -	depends on PCMCIA -	---help--- -	  Say Y if you would like to include support for any PCMCIA or CardBus -	  network adapters, then say Y to the driver for your particular card -	  below.  PCMCIA- or PC-cards are credit-card size devices often used -	  with laptops computers; CardBus is the newer and faster version of -	  PCMCIA. - -	  To use your PC-cards, you will need supporting software from David -	  Hinds' pcmcia-cs package (see the file <file:Documentation/Changes> -	  for location).  You also want to check out the PCMCIA-HOWTO, -	  available from <http://www.tldp.org/docs.html#howto>. - -	  If unsure, say N. - -if NET_PCMCIA && PCMCIA - -config PCMCIA_3C589 -	tristate "3Com 3c589 PCMCIA support" -	help -	  Say Y here if you intend to attach a 3Com 3c589 or compatible PCMCIA -	  (PC-card) Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called 3c589_cs.  If unsure, say N. - -config PCMCIA_3C574 -	tristate "3Com 3c574 PCMCIA support" -	help -	  Say Y here if you intend to attach a 3Com 3c574 or compatible PCMCIA -	  (PC-card) Fast Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called 3c574_cs.  If unsure, say N. - -config PCMCIA_FMVJ18X -	tristate "Fujitsu FMV-J18x PCMCIA support" -	select CRC32 -	help -	  Say Y here if you intend to attach a Fujitsu FMV-J18x or compatible -	  PCMCIA (PC-card) Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called fmvj18x_cs.  If unsure, say N. - -config PCMCIA_PCNET -	tristate "NE2000 compatible PCMCIA support" -	select CRC32 -	help -	  Say Y here if you intend to attach an NE2000 compatible PCMCIA -	  (PC-card) Ethernet or Fast Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called pcnet_cs.  If unsure, say N. - -config PCMCIA_NMCLAN -	tristate "New Media PCMCIA support" -	help -	  Say Y here if you intend to attach a New Media Ethernet or LiveWire -	  PCMCIA (PC-card) Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called nmclan_cs.  If unsure, say N. - -config PCMCIA_SMC91C92 -	tristate "SMC 91Cxx PCMCIA support" -	select CRC32 -	select MII -	help -	  Say Y here if you intend to attach an SMC 91Cxx compatible PCMCIA -	  (PC-card) Ethernet or Fast Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called smc91c92_cs.  If unsure, say N. - -config PCMCIA_XIRC2PS -	tristate "Xircom 16-bit PCMCIA support" -	help -	  Say Y here if you intend to attach a Xircom 16-bit PCMCIA (PC-card) -	  Ethernet or Fast Ethernet card to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called xirc2ps_cs.  If unsure, say N. - -config PCMCIA_AXNET -	tristate "Asix AX88190 PCMCIA support" -	---help--- -	  Say Y here if you intend to attach an Asix AX88190-based PCMCIA -	  (PC-card) Fast Ethernet card to your computer.  These cards are -	  nearly NE2000 compatible but need a separate driver due to a few -	  misfeatures. - -	  To compile this driver as a module, choose M here: the module will be -	  called axnet_cs.  If unsure, say N. - -config ARCNET_COM20020_CS -	tristate "COM20020 ARCnet PCMCIA support" -	depends on ARCNET_COM20020 -	help -	  Say Y here if you intend to attach this type of ARCnet PCMCIA card -	  to your computer. - -	  To compile this driver as a module, choose M here: the module will be -	  called com20020_cs.  If unsure, say N. - -config PCMCIA_IBMTR -	tristate "IBM PCMCIA tokenring adapter support" -	depends on IBMTR!=y && TR -	help -	  Say Y here if you intend to attach this type of Token Ring PCMCIA -	  card to your computer. You then also need to say Y to "Token Ring -	  driver support". - -	  To compile this driver as a module, choose M here: the module will be -	  called ibmtr_cs. - -endif # NET_PCMCIA diff --git a/drivers/net/pcmcia/Makefile b/drivers/net/pcmcia/Makefile deleted file mode 100644 index 87d2d99f4c1..00000000000 --- a/drivers/net/pcmcia/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the Linux PCMCIA network device drivers. -# - -# 16-bit client drivers -obj-$(CONFIG_PCMCIA_3C589)	+= 3c589_cs.o -obj-$(CONFIG_PCMCIA_3C574)	+= 3c574_cs.o -obj-$(CONFIG_PCMCIA_FMVJ18X)	+= fmvj18x_cs.o -obj-$(CONFIG_PCMCIA_NMCLAN)	+= nmclan_cs.o -obj-$(CONFIG_PCMCIA_PCNET)	+= pcnet_cs.o -obj-$(CONFIG_PCMCIA_SMC91C92)	+= smc91c92_cs.o -obj-$(CONFIG_PCMCIA_XIRC2PS)	+= xirc2ps_cs.o -obj-$(CONFIG_ARCNET_COM20020_CS)+= com20020_cs.o -obj-$(CONFIG_PCMCIA_AXNET)	+= axnet_cs.o - -obj-$(CONFIG_PCMCIA_IBMTR)	+= ibmtr_cs.o diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c deleted file mode 100644 index 1a0eb128e60..00000000000 --- a/drivers/net/pcmcia/axnet_cs.c +++ /dev/null @@ -1,1726 +0,0 @@ -/*====================================================================== - -    A PCMCIA ethernet driver for Asix AX88190-based cards - -    The Asix AX88190 is a NS8390-derived chipset with a few nasty -    idiosyncracies that make it very inconvenient to support with a -    standard 8390 driver.  This driver is based on pcnet_cs, with the -    tweaked 8390 code grafted on the end.  Much of what I did was to -    clean up and update a similar driver supplied by Asix, which was -    adapted by William Lee, william@asix.com.tw. - -    Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net - -    axnet_cs.c 1.28 2002/06/29 06:27:37 - -    The network driver code is based on Donald Becker's NE2000 code: - -    Written 1992,1993 by Donald Becker. -    Copyright 1993 United States Government as represented by the -    Director, National Security Agency.  This software may be used and -    distributed according to the terms of the GNU General Public License, -    incorporated herein by reference. -    Donald Becker may be reached at becker@scyld.com - -======================================================================*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/spinlock.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/crc32.h> -#include <linux/mii.h> -#include "../8390.h" - -#include <pcmcia/cistpl.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> -#include <pcmcia/cisreg.h> - -#include <asm/io.h> -#include <asm/system.h> -#include <asm/byteorder.h> -#include <asm/uaccess.h> - -#define AXNET_CMD	0x00 -#define AXNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */ -#define AXNET_RESET	0x1f	/* Issue a read to reset, a write to clear. */ -#define AXNET_MII_EEP	0x14	/* Offset of MII access port */ -#define AXNET_TEST	0x15	/* Offset of TEST Register port */ -#define AXNET_GPIO	0x17	/* Offset of General Purpose Register Port */ - -#define AXNET_START_PG	0x40	/* First page of TX buffer */ -#define AXNET_STOP_PG	0x80	/* Last page +1 of RX ring */ - -#define AXNET_RDC_TIMEOUT 0x02	/* Max wait in jiffies for Tx RDC */ - -#define IS_AX88190	0x0001 -#define IS_AX88790	0x0002 - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); -MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); - - -/*====================================================================*/ - -static int axnet_config(struct pcmcia_device *link); -static void axnet_release(struct pcmcia_device *link); -static int axnet_open(struct net_device *dev); -static int axnet_close(struct net_device *dev); -static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, -					  struct net_device *dev); -static struct net_device_stats *get_stats(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static void axnet_tx_timeout(struct net_device *dev); -static irqreturn_t ei_irq_wrapper(int irq, void *dev_id); -static void ei_watchdog(u_long arg); -static void axnet_reset_8390(struct net_device *dev); - -static int mdio_read(unsigned int addr, int phy_id, int loc); -static void mdio_write(unsigned int addr, int phy_id, int loc, int value); - -static void get_8390_hdr(struct net_device *, -			 struct e8390_pkt_hdr *, int); -static void block_input(struct net_device *dev, int count, -			struct sk_buff *skb, int ring_offset); -static void block_output(struct net_device *dev, int count, -			 const u_char *buf, const int start_page); - -static void axnet_detach(struct pcmcia_device *p_dev); - -static void AX88190_init(struct net_device *dev, int startp); -static int ax_open(struct net_device *dev); -static int ax_close(struct net_device *dev); -static irqreturn_t ax_interrupt(int irq, void *dev_id); - -/*====================================================================*/ - -typedef struct axnet_dev_t { -	struct pcmcia_device	*p_dev; -	caddr_t	base; -	struct timer_list	watchdog; -	int	stale, fast_poll; -	u_short	link_status; -	u_char	duplex_flag; -	int	phy_id; -	int	flags; -	int	active_low; -} axnet_dev_t; - -static inline axnet_dev_t *PRIV(struct net_device *dev) -{ -	void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device); -	return p; -} - -static const struct net_device_ops axnet_netdev_ops = { -	.ndo_open 		= axnet_open, -	.ndo_stop		= axnet_close, -	.ndo_do_ioctl		= axnet_ioctl, -	.ndo_start_xmit		= axnet_start_xmit, -	.ndo_tx_timeout		= axnet_tx_timeout, -	.ndo_get_stats		= get_stats, -	.ndo_set_multicast_list = set_multicast_list, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int axnet_probe(struct pcmcia_device *link) -{ -    axnet_dev_t *info; -    struct net_device *dev; -    struct ei_device *ei_local; - -    dev_dbg(&link->dev, "axnet_attach()\n"); - -    dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(axnet_dev_t)); -    if (!dev) -	return -ENOMEM; - -    ei_local = netdev_priv(dev); -    spin_lock_init(&ei_local->page_lock); - -    info = PRIV(dev); -    info->p_dev = link; -    link->priv = dev; -    link->config_flags |= CONF_ENABLE_IRQ; - -    dev->netdev_ops = &axnet_netdev_ops; - -    dev->watchdog_timeo = TX_TIMEOUT; - -    return axnet_config(link); -} /* axnet_attach */ - -static void axnet_detach(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link); - -    unregister_netdev(dev); - -    axnet_release(link); - -    free_netdev(dev); -} /* axnet_detach */ - -/*====================================================================== - -    This probes for a card's hardware address by reading the PROM. - -======================================================================*/ - -static int get_prom(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    unsigned int ioaddr = dev->base_addr; -    int i, j; - -    /* This is based on drivers/net/ne.c */ -    struct { -	u_char value, offset; -    } program_seq[] = { -	{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ -	{0x01,	EN0_DCFG},	/* Set word-wide access. */ -	{0x00,	EN0_RCNTLO},	/* Clear the count regs. */ -	{0x00,	EN0_RCNTHI}, -	{0x00,	EN0_IMR},	/* Mask completion irq. */ -	{0xFF,	EN0_ISR}, -	{E8390_RXOFF|0x40, EN0_RXCR},	/* 0x60  Set to monitor */ -	{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */ -	{0x10,	EN0_RCNTLO}, -	{0x00,	EN0_RCNTHI}, -	{0x00,	EN0_RSARLO},	/* DMA starting at 0x0400. */ -	{0x04,	EN0_RSARHI}, -	{E8390_RREAD+E8390_START, E8390_CMD}, -    }; - -    /* Not much of a test, but the alternatives are messy */ -    if (link->config_base != 0x03c0) -	return 0; - -    axnet_reset_8390(dev); -    mdelay(10); - -    for (i = 0; i < ARRAY_SIZE(program_seq); i++) -	outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); - -    for (i = 0; i < 6; i += 2) { -	j = inw(ioaddr + AXNET_DATAPORT); -	dev->dev_addr[i] = j & 0xff; -	dev->dev_addr[i+1] = j >> 8; -    } -    return 1; -} /* get_prom */ - -static int try_io_port(struct pcmcia_device *link) -{ -    int j, ret; -    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; -    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; -    if (link->resource[0]->end == 32) { -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; -	/* for master/slave multifunction cards */ -	if (link->resource[1]->end > 0) -	    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -    } else { -	/* This should be two 16-port windows */ -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; -	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; -    } -    if (link->resource[0]->start == 0) { -	for (j = 0; j < 0x400; j += 0x20) { -	    link->resource[0]->start = j ^ 0x300; -	    link->resource[1]->start = (j ^ 0x300) + 0x10; -	    link->io_lines = 16; -	    ret = pcmcia_request_io(link); -	    if (ret == 0) -		    return ret; -	} -	return ret; -    } else { -	return pcmcia_request_io(link); -    } -} - -static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data) -{ -	if (p_dev->config_index == 0) -		return -EINVAL; - -	p_dev->config_index = 0x05; -	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32) -		return -ENODEV; - -	return try_io_port(p_dev); -} - -static int axnet_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    axnet_dev_t *info = PRIV(dev); -    int i, j, j2, ret; - -    dev_dbg(&link->dev, "axnet_config(0x%p)\n", link); - -    /* don't trust the CIS on this; Linksys got it wrong */ -    link->config_regs = 0x63; -    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; -    ret = pcmcia_loop_config(link, axnet_configcheck, NULL); -    if (ret != 0) -	goto failed; - -    if (!link->irq) -	    goto failed; - -    if (resource_size(link->resource[1]) == 8) -	link->config_flags |= CONF_ENABLE_SPKR; -     -    ret = pcmcia_enable_device(link); -    if (ret) -	    goto failed; - -    dev->irq = link->irq; -    dev->base_addr = link->resource[0]->start; - -    if (!get_prom(link)) { -	pr_notice("this is not an AX88190 card!\n"); -	pr_notice("use pcnet_cs instead.\n"); -	goto failed; -    } - -    ei_status.name = "AX88190"; -    ei_status.word16 = 1; -    ei_status.tx_start_page = AXNET_START_PG; -    ei_status.rx_start_page = AXNET_START_PG + TX_PAGES; -    ei_status.stop_page = AXNET_STOP_PG; -    ei_status.reset_8390 = axnet_reset_8390; -    ei_status.get_8390_hdr = get_8390_hdr; -    ei_status.block_input = block_input; -    ei_status.block_output = block_output; - -    if (inb(dev->base_addr + AXNET_TEST) != 0) -	info->flags |= IS_AX88790; -    else -	info->flags |= IS_AX88190; - -    if (info->flags & IS_AX88790) -	outb(0x10, dev->base_addr + AXNET_GPIO);  /* select Internal PHY */ - -    info->active_low = 0; - -    for (i = 0; i < 32; i++) { -	j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); -	j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2); -	if (j == j2) continue; -	if ((j != 0) && (j != 0xffff)) break; -    } - -    if (i == 32) { -	/* Maybe PHY is in power down mode. (PPD_SET = 1) -	   Bit 2 of CCSR is active low. */ -	pcmcia_write_config_byte(link, CISREG_CCSR, 0x04); -	for (i = 0; i < 32; i++) { -	    j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1); -	    j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2); -	    if (j == j2) continue; -	    if ((j != 0) && (j != 0xffff)) { -		info->active_low = 1; -		break; -	    } -	} -    } - -    info->phy_id = (i < 32) ? i : -1; -    SET_NETDEV_DEV(dev, &link->dev); - -    if (register_netdev(dev) != 0) { -	pr_notice("register_netdev() failed\n"); -	goto failed; -    } - -    netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n", -		((info->flags & IS_AX88790) ? 7 : 1), -		dev->base_addr, dev->irq, dev->dev_addr); -    if (info->phy_id != -1) { -	netdev_dbg(dev, "  MII transceiver at index %d, status %x\n", -		   info->phy_id, j); -    } else { -	netdev_notice(dev, "  No MII transceivers found!\n"); -    } -    return 0; - -failed: -    axnet_release(link); -    return -ENODEV; -} /* axnet_config */ - -static void axnet_release(struct pcmcia_device *link) -{ -	pcmcia_disable_device(link); -} - -static int axnet_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int axnet_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; -	axnet_dev_t *info = PRIV(dev); - -	if (link->open) { -		if (info->active_low == 1) -			pcmcia_write_config_byte(link, CISREG_CCSR, 0x04); - -		axnet_reset_8390(dev); -		AX88190_init(dev, 1); -		netif_device_attach(dev); -	} - -	return 0; -} - - -/*====================================================================== - -    MII interface support - -======================================================================*/ - -#define MDIO_SHIFT_CLK		0x01 -#define MDIO_DATA_WRITE0	0x00 -#define MDIO_DATA_WRITE1	0x08 -#define MDIO_DATA_READ		0x04 -#define MDIO_MASK		0x0f -#define MDIO_ENB_IN		0x02 - -static void mdio_sync(unsigned int addr) -{ -    int bits; -    for (bits = 0; bits < 32; bits++) { -	outb_p(MDIO_DATA_WRITE1, addr); -	outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); -    } -} - -static int mdio_read(unsigned int addr, int phy_id, int loc) -{ -    u_int cmd = (0xf6<<10)|(phy_id<<5)|loc; -    int i, retval = 0; - -    mdio_sync(addr); -    for (i = 14; i >= 0; i--) { -	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -	outb_p(dat, addr); -	outb_p(dat | MDIO_SHIFT_CLK, addr); -    } -    for (i = 19; i > 0; i--) { -	outb_p(MDIO_ENB_IN, addr); -	retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0); -	outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr); -    } -    return (retval>>1) & 0xffff; -} - -static void mdio_write(unsigned int addr, int phy_id, int loc, int value) -{ -    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; -    int i; - -    mdio_sync(addr); -    for (i = 31; i >= 0; i--) { -	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -	outb_p(dat, addr); -	outb_p(dat | MDIO_SHIFT_CLK, addr); -    } -    for (i = 1; i >= 0; i--) { -	outb_p(MDIO_ENB_IN, addr); -	outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr); -    } -} - -/*====================================================================*/ - -static int axnet_open(struct net_device *dev) -{ -    int ret; -    axnet_dev_t *info = PRIV(dev); -    struct pcmcia_device *link = info->p_dev; -    unsigned int nic_base = dev->base_addr; -     -    dev_dbg(&link->dev, "axnet_open('%s')\n", dev->name); - -    if (!pcmcia_dev_present(link)) -	return -ENODEV; - -    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ -    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev); -    if (ret) -	    return ret; - -    link->open++; - -    info->link_status = 0x00; -    init_timer(&info->watchdog); -    info->watchdog.function = ei_watchdog; -    info->watchdog.data = (u_long)dev; -    info->watchdog.expires = jiffies + HZ; -    add_timer(&info->watchdog); - -    return ax_open(dev); -} /* axnet_open */ - -/*====================================================================*/ - -static int axnet_close(struct net_device *dev) -{ -    axnet_dev_t *info = PRIV(dev); -    struct pcmcia_device *link = info->p_dev; - -    dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name); - -    ax_close(dev); -    free_irq(dev->irq, dev); -     -    link->open--; -    netif_stop_queue(dev); -    del_timer_sync(&info->watchdog); - -    return 0; -} /* axnet_close */ - -/*====================================================================== - -    Hard reset the card.  This used to pause for the same period that -    a 8390 reset command required, but that shouldn't be necessary. - -======================================================================*/ - -static void axnet_reset_8390(struct net_device *dev) -{ -    unsigned int nic_base = dev->base_addr; -    int i; - -    ei_status.txing = ei_status.dmaing = 0; - -    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD); - -    outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET); - -    for (i = 0; i < 100; i++) { -	if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0) -	    break; -	udelay(100); -    } -    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ -     -    if (i == 100) -	netdev_err(dev, "axnet_reset_8390() did not complete\n"); -     -} /* axnet_reset_8390 */ - -/*====================================================================*/ - -static irqreturn_t ei_irq_wrapper(int irq, void *dev_id) -{ -    struct net_device *dev = dev_id; -    PRIV(dev)->stale = 0; -    return ax_interrupt(irq, dev_id); -} - -static void ei_watchdog(u_long arg) -{ -    struct net_device *dev = (struct net_device *)(arg); -    axnet_dev_t *info = PRIV(dev); -    unsigned int nic_base = dev->base_addr; -    unsigned int mii_addr = nic_base + AXNET_MII_EEP; -    u_short link; - -    if (!netif_device_present(dev)) goto reschedule; - -    /* Check for pending interrupt with expired latency timer: with -       this, we can limp along even if the interrupt is blocked */ -    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { -	if (!info->fast_poll) -	    netdev_info(dev, "interrupt(s) dropped!\n"); -	ei_irq_wrapper(dev->irq, dev); -	info->fast_poll = HZ; -    } -    if (info->fast_poll) { -	info->fast_poll--; -	info->watchdog.expires = jiffies + 1; -	add_timer(&info->watchdog); -	return; -    } - -    if (info->phy_id < 0) -	goto reschedule; -    link = mdio_read(mii_addr, info->phy_id, 1); -    if (!link || (link == 0xffff)) { -	netdev_info(dev, "MII is missing!\n"); -	info->phy_id = -1; -	goto reschedule; -    } - -    link &= 0x0004; -    if (link != info->link_status) { -	u_short p = mdio_read(mii_addr, info->phy_id, 5); -	netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); -	if (link) { -	    info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00; -	    if (p) -		netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n", -			    (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H'); -	    else -		netdev_info(dev, "link partner did not autonegotiate\n"); -	    AX88190_init(dev, 1); -	} -	info->link_status = link; -    } - -reschedule: -    info->watchdog.expires = jiffies + HZ; -    add_timer(&info->watchdog); -} - -/*====================================================================*/ - -static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ -    axnet_dev_t *info = PRIV(dev); -    struct mii_ioctl_data *data = if_mii(rq); -    unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP; -    switch (cmd) { -    case SIOCGMIIPHY: -	data->phy_id = info->phy_id; -    case SIOCGMIIREG:		/* Read MII PHY register. */ -	data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f); -	return 0; -    case SIOCSMIIREG:		/* Write MII PHY register. */ -	mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in); -	return 0; -    } -    return -EOPNOTSUPP; -} - -/*====================================================================*/ - -static void get_8390_hdr(struct net_device *dev, -			 struct e8390_pkt_hdr *hdr, -			 int ring_page) -{ -    unsigned int nic_base = dev->base_addr; - -    outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */ -    outb_p(ring_page, nic_base + EN0_RSARHI); -    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD); - -    insw(nic_base + AXNET_DATAPORT, hdr, -	    sizeof(struct e8390_pkt_hdr)>>1); -    /* Fix for big endian systems */ -    hdr->count = le16_to_cpu(hdr->count); - -} - -/*====================================================================*/ - -static void block_input(struct net_device *dev, int count, -			struct sk_buff *skb, int ring_offset) -{ -    unsigned int nic_base = dev->base_addr; -    int xfer_count = count; -    char *buf = skb->data; - -    if ((ei_debug > 4) && (count != 4)) -	    pr_debug("%s: [bi=%d]\n", dev->name, count+4); -    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); -    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); -    outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD); - -    insw(nic_base + AXNET_DATAPORT,buf,count>>1); -    if (count & 0x01) -	buf[count-1] = inb(nic_base + AXNET_DATAPORT), xfer_count++; - -} - -/*====================================================================*/ - -static void block_output(struct net_device *dev, int count, -			 const u_char *buf, const int start_page) -{ -    unsigned int nic_base = dev->base_addr; - -    pr_debug("%s: [bo=%d]\n", dev->name, count); - -    /* Round the count up for word writes.  Do we need to do this? -       What effect will an odd byte count have on the 8390? -       I should check someday. */ -    if (count & 0x01) -	count++; - -    outb_p(0x00, nic_base + EN0_RSARLO); -    outb_p(start_page, nic_base + EN0_RSARHI); -    outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD); -    outsw(nic_base + AXNET_DATAPORT, buf, count>>1); -} - -static struct pcmcia_device_id axnet_ids[] = { -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081), -	PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301), -	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301), -	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303), -	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309), -	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106), -	PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), -	PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202),  -	PCMCIA_DEVICE_MANF_CARD(0xffff, 0x1090), -	PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc), -	PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef), -	PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef), -	PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1), -	PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc), -	PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXM", 0x5261440f, 0x3abbd061), -	PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90), -	PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2), -	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8), -	PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609), -	PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058), -	PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6,  0xab9be5ef), -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, axnet_ids); - -static struct pcmcia_driver axnet_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "axnet_cs", -	.probe		= axnet_probe, -	.remove		= axnet_detach, -	.id_table       = axnet_ids, -	.suspend	= axnet_suspend, -	.resume		= axnet_resume, -}; - -static int __init init_axnet_cs(void) -{ -	return pcmcia_register_driver(&axnet_cs_driver); -} - -static void __exit exit_axnet_cs(void) -{ -	pcmcia_unregister_driver(&axnet_cs_driver); -} - -module_init(init_axnet_cs); -module_exit(exit_axnet_cs); - -/*====================================================================*/ - -/* 8390.c: A general NS8390 ethernet driver core for linux. */ -/* -	Written 1992-94 by Donald Becker. -   -	Copyright 1993 United States Government as represented by the -	Director, National Security Agency. - -	This software may be used and distributed according to the terms -	of the GNU General Public License, incorporated herein by reference. - -	The author may be reached as becker@scyld.com, or C/O -	Scyld Computing Corporation -	410 Severn Ave., Suite 210 -	Annapolis MD 21403 - -  This is the chip-specific code for many 8390-based ethernet adaptors. -  This is not a complete driver, it must be combined with board-specific -  code such as ne.c, wd.c, 3c503.c, etc. - -  Seeing how at least eight drivers use this code, (not counting the -  PCMCIA ones either) it is easy to break some card by what seems like -  a simple innocent change. Please contact me or Donald if you think -  you have found something that needs changing. -- PG - -  Changelog: - -  Paul Gortmaker	: remove set_bit lock, other cleanups. -  Paul Gortmaker	: add ei_get_8390_hdr() so we can pass skb's to  -			  ei_block_input() for eth_io_copy_and_sum(). -  Paul Gortmaker	: exchange static int ei_pingpong for a #define, -			  also add better Tx error handling. -  Paul Gortmaker	: rewrite Rx overrun handling as per NS specs. -  Alexey Kuznetsov	: use the 8390's six bit hash multicast filter. -  Paul Gortmaker	: tweak ANK's above multicast changes a bit. -  Paul Gortmaker	: update packet statistics for v2.1.x -  Alan Cox		: support arbitary stupid port mappings on the -  			  68K Macintosh. Support >16bit I/O spaces -  Paul Gortmaker	: add kmod support for auto-loading of the 8390 -			  module by all drivers that require it. -  Alan Cox		: Spinlocking work, added 'BUG_83C690' -  Paul Gortmaker	: Separate out Tx timeout code from Tx path. - -  Sources: -  The National Semiconductor LAN Databook, and the 3Com 3c503 databook. - -  */ - -#include <linux/bitops.h> -#include <asm/irq.h> -#include <linux/fcntl.h> -#include <linux/in.h> -#include <linux/interrupt.h> - -#define BUG_83C690 - -/* These are the operational function interfaces to board-specific -   routines. -	void reset_8390(struct net_device *dev) -		Resets the board associated with DEV, including a hardware reset of -		the 8390.  This is only called when there is a transmit timeout, and -		it is always followed by 8390_init(). -	void block_output(struct net_device *dev, int count, const unsigned char *buf, -					  int start_page) -		Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The -		"page" value uses the 8390's 256-byte pages. -	void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page) -		Read the 4 byte, page aligned 8390 header. *If* there is a -		subsequent read, it will be of the rest of the packet. -	void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) -		Read COUNT bytes from the packet buffer into the skb data area. Start  -		reading from RING_OFFSET, the address as the 8390 sees it.  This will always -		follow the read of the 8390 header.  -*/ -#define ei_reset_8390 (ei_local->reset_8390) -#define ei_block_output (ei_local->block_output) -#define ei_block_input (ei_local->block_input) -#define ei_get_8390_hdr (ei_local->get_8390_hdr) - -/* use 0 for production, 1 for verification, >2 for debug */ -#ifndef ei_debug -int ei_debug = 1; -#endif - -/* Index to functions. */ -static void ei_tx_intr(struct net_device *dev); -static void ei_tx_err(struct net_device *dev); -static void ei_receive(struct net_device *dev); -static void ei_rx_overrun(struct net_device *dev); - -/* Routines generic to NS8390-based boards. */ -static void NS8390_trigger_send(struct net_device *dev, unsigned int length, -								int start_page); -static void do_set_multicast_list(struct net_device *dev); - -/* - *	SMP and the 8390 setup. - * - *	The 8390 isnt exactly designed to be multithreaded on RX/TX. There is - *	a page register that controls bank and packet buffer access. We guard - *	this with ei_local->page_lock. Nobody should assume or set the page other - *	than zero when the lock is not held. Lock holders must restore page 0 - *	before unlocking. Even pure readers must take the lock to protect in  - *	page 0. - * - *	To make life difficult the chip can also be very slow. We therefore can't - *	just use spinlocks. For the longer lockups we disable the irq the device - *	sits on and hold the lock. We must hold the lock because there is a dual - *	processor case other than interrupts (get stats/set multicast list in - *	parallel with each other and transmit). - * - *	Note: in theory we can just disable the irq on the card _but_ there is - *	a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs" - *	enter lock, take the queued irq. So we waddle instead of flying. - * - *	Finally by special arrangement for the purpose of being generally  - *	annoying the transmit function is called bh atomic. That places - *	restrictions on the user context callers as disable_irq won't save - *	them. - */ -  -/** - * ax_open - Open/initialize the board. - * @dev: network device to initialize - * - * This routine goes all-out, setting everything - * up anew at each open, even though many of these registers should only - * need to be set once at boot. - */ -static int ax_open(struct net_device *dev) -{ -	unsigned long flags; -	struct ei_device *ei_local = netdev_priv(dev); - -	/* -	 *	Grab the page lock so we own the register set, then call -	 *	the init function. -	 */ -       -      	spin_lock_irqsave(&ei_local->page_lock, flags); -	AX88190_init(dev, 1); -	/* Set the flag before we drop the lock, That way the IRQ arrives -	   after its set and we get no silly warnings */ -	netif_start_queue(dev); -      	spin_unlock_irqrestore(&ei_local->page_lock, flags); -	ei_local->irqlock = 0; -	return 0; -} - -#define dev_lock(dev) (((struct ei_device *)netdev_priv(dev))->page_lock) - -/** - * ax_close - shut down network device - * @dev: network device to close - * - * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done. - */ -static int ax_close(struct net_device *dev) -{ -	unsigned long flags; - -	/* -	 *      Hold the page lock during close -	 */ - -	spin_lock_irqsave(&dev_lock(dev), flags); -	AX88190_init(dev, 0); -	spin_unlock_irqrestore(&dev_lock(dev), flags); -	netif_stop_queue(dev); -	return 0; -} - -/** - * axnet_tx_timeout - handle transmit time out condition - * @dev: network device which has apparently fallen asleep - * - * Called by kernel when device never acknowledges a transmit has - * completed (or failed) - i.e. never posted a Tx related interrupt. - */ - -static void axnet_tx_timeout(struct net_device *dev) -{ -	long e8390_base = dev->base_addr; -	struct ei_device *ei_local = netdev_priv(dev); -	int txsr, isr, tickssofar = jiffies - dev_trans_start(dev); -	unsigned long flags; - -	dev->stats.tx_errors++; - -	spin_lock_irqsave(&ei_local->page_lock, flags); -	txsr = inb(e8390_base+EN0_TSR); -	isr = inb(e8390_base+EN0_ISR); -	spin_unlock_irqrestore(&ei_local->page_lock, flags); - -	netdev_printk(KERN_DEBUG, dev, -		      "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", -		      (txsr & ENTSR_ABT) ? "excess collisions." : -		      (isr) ? "lost interrupt?" : "cable problem?", -		      txsr, isr, tickssofar); - -	if (!isr && !dev->stats.tx_packets)  -	{ -		/* The 8390 probably hasn't gotten on the cable yet. */ -		ei_local->interface_num ^= 1;   /* Try a different xcvr.  */ -	} - -	/* Ugly but a reset can be slow, yet must be protected */ -		 -	spin_lock_irqsave(&ei_local->page_lock, flags); -		 -	/* Try to restart the card.  Perhaps the user has fixed something. */ -	ei_reset_8390(dev); -	AX88190_init(dev, 1); -		 -	spin_unlock_irqrestore(&ei_local->page_lock, flags); -	netif_wake_queue(dev); -} -     -/** - * axnet_start_xmit - begin packet transmission - * @skb: packet to be sent - * @dev: network device to which packet is sent - * - * Sends a packet to an 8390 network device. - */ -  -static netdev_tx_t axnet_start_xmit(struct sk_buff *skb, -					  struct net_device *dev) -{ -	long e8390_base = dev->base_addr; -	struct ei_device *ei_local = netdev_priv(dev); -	int length, send_length, output_page; -	unsigned long flags; -	u8 packet[ETH_ZLEN]; -	 -	netif_stop_queue(dev); - -	length = skb->len; - -	/* Mask interrupts from the ethercard.  -	   SMP: We have to grab the lock here otherwise the IRQ handler -	   on another CPU can flip window and race the IRQ mask set. We end -	   up trashing the mcast filter not disabling irqs if we don't lock */ -	    -	spin_lock_irqsave(&ei_local->page_lock, flags); -	outb_p(0x00, e8390_base + EN0_IMR); -	 -	/* -	 *	Slow phase with lock held. -	 */ -	  -	ei_local->irqlock = 1; - -	send_length = max(length, ETH_ZLEN); - -	/* -	 * We have two Tx slots available for use. Find the first free -	 * slot, and then perform some sanity checks. With two Tx bufs, -	 * you get very close to transmitting back-to-back packets. With -	 * only one Tx buf, the transmitter sits idle while you reload the -	 * card, leaving a substantial gap between each transmitted packet. -	 */ - -	if (ei_local->tx1 == 0)  -	{ -		output_page = ei_local->tx_start_page; -		ei_local->tx1 = send_length; -		if (ei_debug  &&  ei_local->tx2 > 0) -			netdev_printk(KERN_DEBUG, dev, -				      "idle transmitter tx2=%d, lasttx=%d, txing=%d\n", -				      ei_local->tx2, ei_local->lasttx, -				      ei_local->txing); -	} -	else if (ei_local->tx2 == 0)  -	{ -		output_page = ei_local->tx_start_page + TX_PAGES/2; -		ei_local->tx2 = send_length; -		if (ei_debug  &&  ei_local->tx1 > 0) -			netdev_printk(KERN_DEBUG, dev, -				      "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n", -				      ei_local->tx1, ei_local->lasttx, -				      ei_local->txing); -	} -	else -	{	/* We should never get here. */ -		if (ei_debug) -			netdev_printk(KERN_DEBUG, dev, -				      "No Tx buffers free! tx1=%d tx2=%d last=%d\n", -				      ei_local->tx1, ei_local->tx2, -				      ei_local->lasttx); -		ei_local->irqlock = 0; -		netif_stop_queue(dev); -		outb_p(ENISR_ALL, e8390_base + EN0_IMR); -		spin_unlock_irqrestore(&ei_local->page_lock, flags); -		dev->stats.tx_errors++; -		return NETDEV_TX_BUSY; -	} - -	/* -	 * Okay, now upload the packet and trigger a send if the transmitter -	 * isn't already sending. If it is busy, the interrupt handler will -	 * trigger the send later, upon receiving a Tx done interrupt. -	 */ - -	if (length == skb->len) -		ei_block_output(dev, length, skb->data, output_page); -	else { -		memset(packet, 0, ETH_ZLEN); -		skb_copy_from_linear_data(skb, packet, skb->len); -		ei_block_output(dev, length, packet, output_page); -	} -	 -	if (! ei_local->txing)  -	{ -		ei_local->txing = 1; -		NS8390_trigger_send(dev, send_length, output_page); -		dev->trans_start = jiffies; -		if (output_page == ei_local->tx_start_page)  -		{ -			ei_local->tx1 = -1; -			ei_local->lasttx = -1; -		} -		else  -		{ -			ei_local->tx2 = -1; -			ei_local->lasttx = -2; -		} -	} -	else ei_local->txqueue++; - -	if (ei_local->tx1  &&  ei_local->tx2) -		netif_stop_queue(dev); -	else -		netif_start_queue(dev); - -	/* Turn 8390 interrupts back on. */ -	ei_local->irqlock = 0; -	outb_p(ENISR_ALL, e8390_base + EN0_IMR); -	 -	spin_unlock_irqrestore(&ei_local->page_lock, flags); - -	dev_kfree_skb (skb); -	dev->stats.tx_bytes += send_length; -     -	return NETDEV_TX_OK; -} - -/** - * ax_interrupt - handle the interrupts from an 8390 - * @irq: interrupt number - * @dev_id: a pointer to the net_device - * - * Handle the ether interface interrupts. We pull packets from - * the 8390 via the card specific functions and fire them at the networking - * stack. We also handle transmit completions and wake the transmit path if - * necessary. We also update the counters and do other housekeeping as - * needed. - */ - -static irqreturn_t ax_interrupt(int irq, void *dev_id) -{ -	struct net_device *dev = dev_id; -	long e8390_base; -	int interrupts, nr_serviced = 0, i; -	struct ei_device *ei_local; -    	int handled = 0; -	unsigned long flags; - -	e8390_base = dev->base_addr; -	ei_local = netdev_priv(dev); - -	/* -	 *	Protect the irq test too. -	 */ -	  -	spin_lock_irqsave(&ei_local->page_lock, flags); - -	if (ei_local->irqlock) { -#if 1 /* This might just be an interrupt for a PCI device sharing this line */ -		const char *msg; -		/* The "irqlock" check is only for testing. */ -		if (ei_local->irqlock) -			msg = "Interrupted while interrupts are masked!"; -		else -			msg = "Reentering the interrupt handler!"; -		netdev_info(dev, "%s, isr=%#2x imr=%#2x\n", -			    msg, -			    inb_p(e8390_base + EN0_ISR), -			    inb_p(e8390_base + EN0_IMR)); -#endif -		spin_unlock_irqrestore(&ei_local->page_lock, flags); -		return IRQ_NONE; -	} -     -	if (ei_debug > 3) -		netdev_printk(KERN_DEBUG, dev, "interrupt(isr=%#2.2x)\n", -			      inb_p(e8390_base + EN0_ISR)); - -	outb_p(0x00, e8390_base + EN0_ISR); -	ei_local->irqlock = 1; -    -	/* !!Assumption!! -- we stay in page 0.	 Don't break this. */ -	while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 && -	       ++nr_serviced < MAX_SERVICE) -	{ -		if (!netif_running(dev) || (interrupts == 0xff)) { -			if (ei_debug > 1) -				netdev_warn(dev, -					    "interrupt from stopped card\n"); -			outb_p(interrupts, e8390_base + EN0_ISR); -			interrupts = 0; -			break; -		} -		handled = 1; - -		/* AX88190 bug fix. */ -		outb_p(interrupts, e8390_base + EN0_ISR); -		for (i = 0; i < 10; i++) { -			if (!(inb(e8390_base + EN0_ISR) & interrupts)) -				break; -			outb_p(0, e8390_base + EN0_ISR); -			outb_p(interrupts, e8390_base + EN0_ISR); -		} -		if (interrupts & ENISR_OVER)  -			ei_rx_overrun(dev); -		else if (interrupts & (ENISR_RX+ENISR_RX_ERR))  -		{ -			/* Got a good (?) packet. */ -			ei_receive(dev); -		} -		/* Push the next to-transmit packet through. */ -		if (interrupts & ENISR_TX) -			ei_tx_intr(dev); -		else if (interrupts & ENISR_TX_ERR) -			ei_tx_err(dev); - -		if (interrupts & ENISR_COUNTERS)  -		{ -			dev->stats.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0); -			dev->stats.rx_crc_errors   += inb_p(e8390_base + EN0_COUNTER1); -			dev->stats.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2); -		} -	} -     -	if (interrupts && ei_debug > 3)  -	{ -		handled = 1; -		if (nr_serviced >= MAX_SERVICE)  -		{ -			/* 0xFF is valid for a card removal */ -			if(interrupts!=0xFF) -				netdev_warn(dev, "Too much work at interrupt, status %#2.2x\n", -					    interrupts); -			outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */ -		} else { -			netdev_warn(dev, "unknown interrupt %#2x\n", -				    interrupts); -			outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ -		} -	} - -	/* Turn 8390 interrupts back on. */ -	ei_local->irqlock = 0; -	outb_p(ENISR_ALL, e8390_base + EN0_IMR); - -	spin_unlock_irqrestore(&ei_local->page_lock, flags); -	return IRQ_RETVAL(handled); -} - -/** - * ei_tx_err - handle transmitter error - * @dev: network device which threw the exception - * - * A transmitter error has happened. Most likely excess collisions (which - * is a fairly normal condition). If the error is one where the Tx will - * have been aborted, we try and send another one right away, instead of - * letting the failed packet sit and collect dust in the Tx buffer. This - * is a much better solution as it avoids kernel based Tx timeouts, and - * an unnecessary card reset. - * - * Called with lock held. - */ - -static void ei_tx_err(struct net_device *dev) -{ -	long e8390_base = dev->base_addr; -	unsigned char txsr = inb_p(e8390_base+EN0_TSR); -	unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU); - -#ifdef VERBOSE_ERROR_DUMP -	netdev_printk(KERN_DEBUG, dev, -		      "transmitter error (%#2x):", txsr); -	if (txsr & ENTSR_ABT) -		pr_cont(" excess-collisions"); -	if (txsr & ENTSR_ND) -		pr_cont(" non-deferral"); -	if (txsr & ENTSR_CRS) -		pr_cont(" lost-carrier"); -	if (txsr & ENTSR_FU) -		pr_cont(" FIFO-underrun"); -	if (txsr & ENTSR_CDH) -		pr_cont(" lost-heartbeat"); -	pr_cont("\n"); -#endif - -	if (tx_was_aborted) -		ei_tx_intr(dev); -	else  -	{ -		dev->stats.tx_errors++; -		if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++; -		if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++; -		if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++; -	} -} - -/** - * ei_tx_intr - transmit interrupt handler - * @dev: network device for which tx intr is handled - * - * We have finished a transmit: check for errors and then trigger the next - * packet to be sent. Called with lock held. - */ - -static void ei_tx_intr(struct net_device *dev) -{ -	long e8390_base = dev->base_addr; -	struct ei_device *ei_local = netdev_priv(dev); -	int status = inb(e8390_base + EN0_TSR); -     -	/* -	 * There are two Tx buffers, see which one finished, and trigger -	 * the send of another one if it exists. -	 */ -	ei_local->txqueue--; - -	if (ei_local->tx1 < 0)  -	{ -		if (ei_local->lasttx != 1 && ei_local->lasttx != -1) -			netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n", -				   ei_local->name, ei_local->lasttx, -				   ei_local->tx1); -		ei_local->tx1 = 0; -		if (ei_local->tx2 > 0)  -		{ -			ei_local->txing = 1; -			NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); -			dev->trans_start = jiffies; -			ei_local->tx2 = -1, -			ei_local->lasttx = 2; -		} -		else ei_local->lasttx = 20, ei_local->txing = 0;	 -	} -	else if (ei_local->tx2 < 0)  -	{ -		if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2) -			netdev_info(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n", -				    ei_local->name, ei_local->lasttx, -				    ei_local->tx2); -		ei_local->tx2 = 0; -		if (ei_local->tx1 > 0)  -		{ -			ei_local->txing = 1; -			NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); -			dev->trans_start = jiffies; -			ei_local->tx1 = -1; -			ei_local->lasttx = 1; -		} -		else -			ei_local->lasttx = 10, ei_local->txing = 0; -	} -//	else -//		netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n", -//			    ei_local->lasttx); - -	/* Minimize Tx latency: update the statistics after we restart TXing. */ -	if (status & ENTSR_COL) -		dev->stats.collisions++; -	if (status & ENTSR_PTX) -		dev->stats.tx_packets++; -	else  -	{ -		dev->stats.tx_errors++; -		if (status & ENTSR_ABT)  -		{ -			dev->stats.tx_aborted_errors++; -			dev->stats.collisions += 16; -		} -		if (status & ENTSR_CRS)  -			dev->stats.tx_carrier_errors++; -		if (status & ENTSR_FU)  -			dev->stats.tx_fifo_errors++; -		if (status & ENTSR_CDH) -			dev->stats.tx_heartbeat_errors++; -		if (status & ENTSR_OWC) -			dev->stats.tx_window_errors++; -	} -	netif_wake_queue(dev); -} - -/** - * ei_receive - receive some packets - * @dev: network device with which receive will be run - * - * We have a good packet(s), get it/them out of the buffers.  - * Called with lock held. - */ - -static void ei_receive(struct net_device *dev) -{ -	long e8390_base = dev->base_addr; -	struct ei_device *ei_local = netdev_priv(dev); -	unsigned char rxing_page, this_frame, next_frame; -	unsigned short current_offset; -	int rx_pkt_count = 0; -	struct e8390_pkt_hdr rx_frame; -     -	while (++rx_pkt_count < 10)  -	{ -		int pkt_len, pkt_stat; -		 -		/* Get the rx page (incoming packet pointer). */ -		rxing_page = inb_p(e8390_base + EN1_CURPAG -1); -		 -		/* Remove one frame from the ring.  Boundary is always a page behind. */ -		this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1; -		if (this_frame >= ei_local->stop_page) -			this_frame = ei_local->rx_start_page; -		 -		/* Someday we'll omit the previous, iff we never get this message. -		   (There is at least one clone claimed to have a problem.)   -		    -		   Keep quiet if it looks like a card removal. One problem here -		   is that some clones crash in roughly the same way. -		 */ -		if (ei_debug > 0  &&  this_frame != ei_local->current_page && (this_frame!=0x0 || rxing_page!=0xFF)) -		    netdev_err(dev, "mismatched read page pointers %2x vs %2x\n", -			       this_frame, ei_local->current_page); -		 -		if (this_frame == rxing_page)	/* Read all the frames? */ -			break;				/* Done for now */ -		 -		current_offset = this_frame << 8; -		ei_get_8390_hdr(dev, &rx_frame, this_frame); -		 -		pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr); -		pkt_stat = rx_frame.status; -		 -		next_frame = this_frame + 1 + ((pkt_len+4)>>8); -		 -		if (pkt_len < 60  ||  pkt_len > 1518)  -		{ -			if (ei_debug) -				netdev_printk(KERN_DEBUG, dev, -					      "bogus packet size: %d, status=%#2x nxpg=%#2x\n", -					      rx_frame.count, rx_frame.status, -					      rx_frame.next); -			dev->stats.rx_errors++; -			dev->stats.rx_length_errors++; -		} -		 else if ((pkt_stat & 0x0F) == ENRSR_RXOK)  -		{ -			struct sk_buff *skb; -			 -			skb = dev_alloc_skb(pkt_len+2); -			if (skb == NULL)  -			{ -				if (ei_debug > 1) -					netdev_printk(KERN_DEBUG, dev, -						      "Couldn't allocate a sk_buff of size %d\n", -						      pkt_len); -				dev->stats.rx_dropped++; -				break; -			} -			else -			{ -				skb_reserve(skb,2);	/* IP headers on 16 byte boundaries */ -				skb_put(skb, pkt_len);	/* Make room */ -				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame)); -				skb->protocol=eth_type_trans(skb,dev); -				netif_rx(skb); -				dev->stats.rx_packets++; -				dev->stats.rx_bytes += pkt_len; -				if (pkt_stat & ENRSR_PHY) -					dev->stats.multicast++; -			} -		}  -		else  -		{ -			if (ei_debug) -				netdev_printk(KERN_DEBUG, dev, -					      "bogus packet: status=%#2x nxpg=%#2x size=%d\n", -					      rx_frame.status, rx_frame.next, -					      rx_frame.count); -			dev->stats.rx_errors++; -			/* NB: The NIC counts CRC, frame and missed errors. */ -			if (pkt_stat & ENRSR_FO) -				dev->stats.rx_fifo_errors++; -		} -		next_frame = rx_frame.next; -		 -		/* This _should_ never happen: it's here for avoiding bad clones. */ -		if (next_frame >= ei_local->stop_page) { -			netdev_info(dev, "next frame inconsistency, %#2x\n", -				    next_frame); -			next_frame = ei_local->rx_start_page; -		} -		ei_local->current_page = next_frame; -		outb_p(next_frame-1, e8390_base+EN0_BOUNDARY); -	} -} - -/** - * ei_rx_overrun - handle receiver overrun - * @dev: network device which threw exception - * - * We have a receiver overrun: we have to kick the 8390 to get it started - * again. Problem is that you have to kick it exactly as NS prescribes in - * the updated datasheets, or "the NIC may act in an unpredictable manner." - * This includes causing "the NIC to defer indefinitely when it is stopped - * on a busy network."  Ugh. - * Called with lock held. Don't call this with the interrupts off or your - * computer will hate you - it takes 10ms or so.  - */ - -static void ei_rx_overrun(struct net_device *dev) -{ -	axnet_dev_t *info = PRIV(dev); -	long e8390_base = dev->base_addr; -	unsigned char was_txing, must_resend = 0; -     -	/* -	 * Record whether a Tx was in progress and then issue the -	 * stop command. -	 */ -	was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS; -	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); -     -	if (ei_debug > 1) -		netdev_printk(KERN_DEBUG, dev, "Receiver overrun\n"); -	dev->stats.rx_over_errors++; -     -	/*  -	 * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. -	 * Early datasheets said to poll the reset bit, but now they say that -	 * it "is not a reliable indicator and subsequently should be ignored." -	 * We wait at least 10ms. -	 */ - -	mdelay(10); - -	/* -	 * Reset RBCR[01] back to zero as per magic incantation. -	 */ -	outb_p(0x00, e8390_base+EN0_RCNTLO); -	outb_p(0x00, e8390_base+EN0_RCNTHI); - -	/* -	 * See if any Tx was interrupted or not. According to NS, this -	 * step is vital, and skipping it will cause no end of havoc. -	 */ - -	if (was_txing) -	{  -		unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR); -		if (!tx_completed) -			must_resend = 1; -	} - -	/* -	 * Have to enter loopback mode and then restart the NIC before -	 * you are allowed to slurp packets up off the ring. -	 */ -	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); -	outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); - -	/* -	 * Clear the Rx ring of all the debris, and ack the interrupt. -	 */ -	ei_receive(dev); - -	/* -	 * Leave loopback mode, and resend any packet that got stopped. -	 */ -	outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR);  -	if (must_resend) -    		outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD); -} - -/* - *	Collect the stats. This is called unlocked and from several contexts. - */ -  -static struct net_device_stats *get_stats(struct net_device *dev) -{ -	long ioaddr = dev->base_addr; -	struct ei_device *ei_local = netdev_priv(dev); -	unsigned long flags; -     -	/* If the card is stopped, just return the present stats. */ -	if (!netif_running(dev)) -		return &dev->stats; - -	spin_lock_irqsave(&ei_local->page_lock,flags); -	/* Read the counter registers, assuming we are in page 0. */ -	dev->stats.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0); -	dev->stats.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1); -	dev->stats.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2); -	spin_unlock_irqrestore(&ei_local->page_lock, flags); -     -	return &dev->stats; -} - -/* - * Form the 64 bit 8390 multicast table from the linked list of addresses - * associated with this dev structure. - */ -  -static inline void make_mc_bits(u8 *bits, struct net_device *dev) -{ -	struct netdev_hw_addr *ha; -	u32 crc; - -	netdev_for_each_mc_addr(ha, dev) { -		crc = ether_crc(ETH_ALEN, ha->addr); -		/*  -		 * The 8390 uses the 6 most significant bits of the -		 * CRC to index the multicast table. -		 */ -		bits[crc>>29] |= (1<<((crc>>26)&7)); -	} -} - -/** - * do_set_multicast_list - set/clear multicast filter - * @dev: net device for which multicast filter is adjusted - * - *	Set or clear the multicast filter for this adaptor. - *	Must be called with lock held.  - */ -  -static void do_set_multicast_list(struct net_device *dev) -{ -	long e8390_base = dev->base_addr; -	int i; -	struct ei_device *ei_local = netdev_priv(dev); - -	if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) { -		memset(ei_local->mcfilter, 0, 8); -		if (!netdev_mc_empty(dev)) -			make_mc_bits(ei_local->mcfilter, dev); -	} else { -		/* set to accept-all */ -		memset(ei_local->mcfilter, 0xFF, 8); -	} - -	outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); -	for(i = 0; i < 8; i++)  -	{ -		outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i)); -	} -	outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD); - -  	if(dev->flags&IFF_PROMISC) -  		outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR); -	else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev)) -  		outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR); -  	else -  		outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); - -	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); -} - -/* - *	Called without lock held. This is invoked from user context and may - *	be parallel to just about everything else. Its also fairly quick and - *	not called too often. Must protect against both bh and irq users - */ - -static void set_multicast_list(struct net_device *dev) -{ -	unsigned long flags; - -	spin_lock_irqsave(&dev_lock(dev), flags); -	do_set_multicast_list(dev); -	spin_unlock_irqrestore(&dev_lock(dev), flags); -}	 - -/* This page of functions should be 8390 generic */ -/* Follow National Semi's recommendations for initializing the "NIC". */ - -/** - * AX88190_init - initialize 8390 hardware - * @dev: network device to initialize - * @startp: boolean.  non-zero value to initiate chip processing - * - *	Must be called with lock held. - */ - -static void AX88190_init(struct net_device *dev, int startp) -{ -	axnet_dev_t *info = PRIV(dev); -	long e8390_base = dev->base_addr; -	struct ei_device *ei_local = netdev_priv(dev); -	int i; -	int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; -     -	if(sizeof(struct e8390_pkt_hdr)!=4) -    		panic("8390.c: header struct mispacked\n");     -	/* Follow National Semi's recommendations for initing the DP83902. */ -	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */ -	outb_p(endcfg, e8390_base + EN0_DCFG);	/* 0x48 or 0x49 */ -	/* Clear the remote byte count registers. */ -	outb_p(0x00,  e8390_base + EN0_RCNTLO); -	outb_p(0x00,  e8390_base + EN0_RCNTHI); -	/* Set to monitor and loopback mode -- this is vital!. */ -	outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */ -	outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ -	/* Set the transmit page and receive ring. */ -	outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); -	ei_local->tx1 = ei_local->tx2 = 0; -	outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); -	outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY);	/* 3c503 says 0x3f,NS0x26*/ -	ei_local->current_page = ei_local->rx_start_page;		/* assert boundary+1 */ -	outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); -	/* Clear the pending interrupts and mask. */ -	outb_p(0xFF, e8390_base + EN0_ISR); -	outb_p(0x00,  e8390_base + EN0_IMR); -     -	/* Copy the station address into the DS8390 registers. */ - -	outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ -	for(i = 0; i < 6; i++)  -	{ -		outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i)); -		if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i]) -			netdev_err(dev, "Hw. address read/write mismap %d\n", i); -	} - -	outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); -	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); - -	netif_start_queue(dev); -	ei_local->tx1 = ei_local->tx2 = 0; -	ei_local->txing = 0; - -	if (info->flags & IS_AX88790)	/* select Internal PHY */ -		outb(0x10, e8390_base + AXNET_GPIO); - -	if (startp)  -	{ -		outb_p(0xff,  e8390_base + EN0_ISR); -		outb_p(ENISR_ALL,  e8390_base + EN0_IMR); -		outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); -		outb_p(E8390_TXCONFIG | info->duplex_flag, -		       e8390_base + EN0_TXCR); /* xmit on. */ -		/* 3c503 TechMan says rxconfig only after the NIC is started. */ -		outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */ -		do_set_multicast_list(dev);	/* (re)load the mcast table */ -	} -} - -/* Trigger a transmit start, assuming the length is valid.  -   Always called with the page lock held */ -    -static void NS8390_trigger_send(struct net_device *dev, unsigned int length, -								int start_page) -{ -	long e8390_base = dev->base_addr; - 	struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev); -     -	if (inb_p(e8390_base) & E8390_TRANS)  -	{ -		netdev_warn(dev, "trigger_send() called with the transmitter busy\n"); -		return; -	} -	outb_p(length & 0xff, e8390_base + EN0_TCNTLO); -	outb_p(length >> 8, e8390_base + EN0_TCNTHI); -	outb_p(start_page, e8390_base + EN0_TPSR); -	outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD); -} diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c deleted file mode 100644 index 27bfad76fc4..00000000000 --- a/drivers/net/pcmcia/com20020_cs.c +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Linux ARCnet driver - COM20020 PCMCIA support - *  - * Written 1994-1999 by Avery Pennarun, - *    based on an ISA version by David Woodhouse. - * Derived from ibmtr_cs.c by Steve Kipisz (pcmcia-cs 3.1.4) - *    which was derived from pcnet_cs.c by David Hinds. - * Some additional portions derived from skeleton.c by Donald Becker. - * - * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) - *  for sponsoring the further development of this driver. - * - * ********************** - * - * The original copyright of skeleton.c was as follows: - * - * skeleton.c Written 1993 by Donald Becker. - * Copyright 1993 United States Government as represented by the - * Director, National Security Agency.  This software may only be used - * and distributed according to the terms of the GNU General Public License as - * modified by SRC, incorporated herein by reference. - *  - * ********************** - * Changes: - * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000 - * - reorganize kmallocs in com20020_attach, checking all for failure - *   and releasing the previous allocations if one fails - * ********************** - *  - * For more details, see drivers/net/arcnet.c - * - * ********************** - */ -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/arcdevice.h> -#include <linux/com20020.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> - -#include <asm/io.h> -#include <asm/system.h> - -#define VERSION "arcnet: COM20020 PCMCIA support loaded.\n" - - -static void regdump(struct net_device *dev) -{ -#ifdef DEBUG -    int ioaddr = dev->base_addr; -    int count; -     -    netdev_dbg(dev, "register dump:\n"); -    for (count = ioaddr; count < ioaddr + 16; count++) -    { -	if (!(count % 16)) -	    pr_cont("%04X:", count); -	pr_cont(" %02X", inb(count)); -    } -    pr_cont("\n"); -     -    netdev_dbg(dev, "buffer0 dump:\n"); -	/* set up the address register */ -        count = 0; -	outb((count >> 8) | RDDATAflag | AUTOINCflag, _ADDR_HI); -	outb(count & 0xff, _ADDR_LO); -     -    for (count = 0; count < 256+32; count++) -    { -	if (!(count % 16)) -	    pr_cont("%04X:", count); -	 -	/* copy the data */ -	pr_cont(" %02X", inb(_MEMDATA)); -    } -    pr_cont("\n"); -#endif -} - - - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -static int node; -static int timeout = 3; -static int backplane; -static int clockp; -static int clockm; - -module_param(node, int, 0); -module_param(timeout, int, 0); -module_param(backplane, int, 0); -module_param(clockp, int, 0); -module_param(clockm, int, 0); - -MODULE_LICENSE("GPL"); - -/*====================================================================*/ - -static int com20020_config(struct pcmcia_device *link); -static void com20020_release(struct pcmcia_device *link); - -static void com20020_detach(struct pcmcia_device *p_dev); - -/*====================================================================*/ - -typedef struct com20020_dev_t { -    struct net_device       *dev; -} com20020_dev_t; - -static int com20020_probe(struct pcmcia_device *p_dev) -{ -    com20020_dev_t *info; -    struct net_device *dev; -    struct arcnet_local *lp; - -    dev_dbg(&p_dev->dev, "com20020_attach()\n"); - -    /* Create new network device */ -    info = kzalloc(sizeof(struct com20020_dev_t), GFP_KERNEL); -    if (!info) -	goto fail_alloc_info; - -    dev = alloc_arcdev(""); -    if (!dev) -	goto fail_alloc_dev; - -    lp = netdev_priv(dev); -    lp->timeout = timeout; -    lp->backplane = backplane; -    lp->clockp = clockp; -    lp->clockm = clockm & 3; -    lp->hw.owner = THIS_MODULE; - -    /* fill in our module parameters as defaults */ -    dev->dev_addr[0] = node; - -    p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; -    p_dev->resource[0]->end = 16; -    p_dev->config_flags |= CONF_ENABLE_IRQ; - -    info->dev = dev; -    p_dev->priv = info; - -    return com20020_config(p_dev); - -fail_alloc_dev: -    kfree(info); -fail_alloc_info: -    return -ENOMEM; -} /* com20020_attach */ - -static void com20020_detach(struct pcmcia_device *link) -{ -    struct com20020_dev_t *info = link->priv; -    struct net_device *dev = info->dev; - -    dev_dbg(&link->dev, "detach...\n"); - -    dev_dbg(&link->dev, "com20020_detach\n"); - -    dev_dbg(&link->dev, "unregister...\n"); - -    unregister_netdev(dev); - -    /* -     * this is necessary because we register our IRQ separately -     * from card services. -     */ -    if (dev->irq) -	    free_irq(dev->irq, dev); - -    com20020_release(link); - -    /* Unlink device structure, free bits */ -    dev_dbg(&link->dev, "unlinking...\n"); -    if (link->priv) -    { -	dev = info->dev; -	if (dev) -	{ -	    dev_dbg(&link->dev, "kfree...\n"); -	    free_netdev(dev); -	} -	dev_dbg(&link->dev, "kfree2...\n"); -	kfree(info); -    } - -} /* com20020_detach */ - -static int com20020_config(struct pcmcia_device *link) -{ -    struct arcnet_local *lp; -    com20020_dev_t *info; -    struct net_device *dev; -    int i, ret; -    int ioaddr; - -    info = link->priv; -    dev = info->dev; - -    dev_dbg(&link->dev, "config...\n"); - -    dev_dbg(&link->dev, "com20020_config\n"); - -    dev_dbg(&link->dev, "baseport1 is %Xh\n", -	    (unsigned int) link->resource[0]->start); - -    i = -ENODEV; -    link->io_lines = 16; - -    if (!link->resource[0]->start) -    { -	for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) -	{ -	    link->resource[0]->start = ioaddr; -	    i = pcmcia_request_io(link); -	    if (i == 0) -		break; -	} -    } -    else -	i = pcmcia_request_io(link); -     -    if (i != 0) -    { -	dev_dbg(&link->dev, "requestIO failed totally!\n"); -	goto failed; -    } -	 -    ioaddr = dev->base_addr = link->resource[0]->start; -    dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr); - -    dev_dbg(&link->dev, "request IRQ %d\n", -	    link->irq); -    if (!link->irq) -    { -	dev_dbg(&link->dev, "requestIRQ failed totally!\n"); -	goto failed; -    } - -    dev->irq = link->irq; - -    ret = pcmcia_enable_device(link); -    if (ret) -	    goto failed; - -    if (com20020_check(dev)) -    { -	regdump(dev); -	goto failed; -    } -     -    lp = netdev_priv(dev); -    lp->card_name = "PCMCIA COM20020"; -    lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */ - -    SET_NETDEV_DEV(dev, &link->dev); - -    i = com20020_found(dev, 0);	/* calls register_netdev */ -     -    if (i != 0) { -	dev_notice(&link->dev, -		   "com20020_found() failed\n"); -	goto failed; -    } - -    netdev_dbg(dev, "port %#3lx, irq %d\n", -	       dev->base_addr, dev->irq); -    return 0; - -failed: -    dev_dbg(&link->dev, "com20020_config failed...\n"); -    com20020_release(link); -    return -ENODEV; -} /* com20020_config */ - -static void com20020_release(struct pcmcia_device *link) -{ -	dev_dbg(&link->dev, "com20020_release\n"); -	pcmcia_disable_device(link); -} - -static int com20020_suspend(struct pcmcia_device *link) -{ -	com20020_dev_t *info = link->priv; -	struct net_device *dev = info->dev; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int com20020_resume(struct pcmcia_device *link) -{ -	com20020_dev_t *info = link->priv; -	struct net_device *dev = info->dev; - -	if (link->open) { -		int ioaddr = dev->base_addr; -		struct arcnet_local *lp = netdev_priv(dev); -		ARCRESET; -	} - -	return 0; -} - -static struct pcmcia_device_id com20020_ids[] = { -	PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.", -			"PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf), -	PCMCIA_DEVICE_PROD_ID12("SoHard AG", -			"SH ARC PCMCIA", 0xf8991729, 0x69dff0c7), -	PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, com20020_ids); - -static struct pcmcia_driver com20020_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "com20020_cs", -	.probe		= com20020_probe, -	.remove		= com20020_detach, -	.id_table	= com20020_ids, -	.suspend	= com20020_suspend, -	.resume		= com20020_resume, -}; - -static int __init init_com20020_cs(void) -{ -	return pcmcia_register_driver(&com20020_cs_driver); -} - -static void __exit exit_com20020_cs(void) -{ -	pcmcia_unregister_driver(&com20020_cs_driver); -} - -module_init(init_com20020_cs); -module_exit(exit_com20020_cs); diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c deleted file mode 100644 index 9226cda4d05..00000000000 --- a/drivers/net/pcmcia/fmvj18x_cs.c +++ /dev/null @@ -1,1186 +0,0 @@ -/*====================================================================== -    fmvj18x_cs.c 2.8 2002/03/23 - -    A fmvj18x (and its compatibles) PCMCIA client driver - -    Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp - -    TDK LAK-CD021 and CONTEC C-NET(PC)C support added by  -    Nobuhiro Katayama, kata-n@po.iijnet.or.jp - -    The PCMCIA client code is based on code written by David Hinds. -    Network code is based on the "FMV-18x driver" by Yutaka TAMIYA -    but is actually largely Donald Becker's AT1700 driver, which -    carries the following attribution: - -    Written 1993-94 by Donald Becker. - -    Copyright 1993 United States Government as represented by the -    Director, National Security Agency. -     -    This software may be used and distributed according to the terms -    of the GNU General Public License, incorporated herein by reference. -     -    The author may be reached as becker@scyld.com, or C/O -    Scyld Computing Corporation -    410 Severn Ave., Suite 210 -    Annapolis MD 21403 -    -======================================================================*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME	"fmvj18x_cs" -#define DRV_VERSION	"2.9" - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/delay.h> -#include <linux/ethtool.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/crc32.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> - -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/system.h> - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -/* SRAM configuration */ -/* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */ -INT_MODULE_PARM(sram_config, 0); - - -/*====================================================================*/ -/* -    PCMCIA event handlers - */ -static int fmvj18x_config(struct pcmcia_device *link); -static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id); -static int fmvj18x_setup_mfc(struct pcmcia_device *link); -static void fmvj18x_release(struct pcmcia_device *link); -static void fmvj18x_detach(struct pcmcia_device *p_dev); - -/* -    LAN controller(MBH86960A) specific routines - */ -static int fjn_config(struct net_device *dev, struct ifmap *map); -static int fjn_open(struct net_device *dev); -static int fjn_close(struct net_device *dev); -static netdev_tx_t fjn_start_xmit(struct sk_buff *skb, -					struct net_device *dev); -static irqreturn_t fjn_interrupt(int irq, void *dev_id); -static void fjn_rx(struct net_device *dev); -static void fjn_reset(struct net_device *dev); -static void set_rx_mode(struct net_device *dev); -static void fjn_tx_timeout(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; - -/* -    card type - */ -typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,  -	       XXX10304, NEC, KME -} cardtype_t; - -/* -    driver specific data structure -*/ -typedef struct local_info_t { -	struct pcmcia_device	*p_dev; -    long open_time; -    uint tx_started:1; -    uint tx_queue; -    u_short tx_queue_len; -    cardtype_t cardtype; -    u_short sent; -    u_char __iomem *base; -} local_info_t; - -#define MC_FILTERBREAK 64 - -/*====================================================================*/ -/*  -    ioport offset from the base address  - */ -#define TX_STATUS               0 /* transmit status register */ -#define RX_STATUS               1 /* receive status register */ -#define TX_INTR                 2 /* transmit interrupt mask register */ -#define RX_INTR                 3 /* receive interrupt mask register */ -#define TX_MODE                 4 /* transmit mode register */ -#define RX_MODE                 5 /* receive mode register */ -#define CONFIG_0                6 /* configuration register 0 */ -#define CONFIG_1                7 /* configuration register 1 */ - -#define NODE_ID                 8 /* node ID register            (bank 0) */ -#define MAR_ADR                 8 /* multicast address registers (bank 1) */ - -#define DATAPORT                8 /* buffer mem port registers   (bank 2) */ -#define TX_START               10 /* transmit start register */ -#define COL_CTRL               11 /* 16 collision control register */ -#define BMPR12                 12 /* reserved */ -#define BMPR13                 13 /* reserved */ -#define RX_SKIP                14 /* skip received packet register */ - -#define LAN_CTRL               16 /* LAN card control register */ - -#define MAC_ID               0x1a /* hardware address */ -#define UNGERMANN_MAC_ID     0x18 /* UNGERMANN-BASS hardware address */ - -/*  -    control bits  - */ -#define ENA_TMT_OK           0x80 -#define ENA_TMT_REC          0x20 -#define ENA_COL              0x04 -#define ENA_16_COL           0x02 -#define ENA_TBUS_ERR         0x01 - -#define ENA_PKT_RDY          0x80 -#define ENA_BUS_ERR          0x40 -#define ENA_LEN_ERR          0x08 -#define ENA_ALG_ERR          0x04 -#define ENA_CRC_ERR          0x02 -#define ENA_OVR_FLO          0x01 - -/* flags */ -#define F_TMT_RDY            0x80 /* can accept new packet */ -#define F_NET_BSY            0x40 /* carrier is detected */ -#define F_TMT_OK             0x20 /* send packet successfully */ -#define F_SRT_PKT            0x10 /* short packet error */ -#define F_COL_ERR            0x04 /* collision error */ -#define F_16_COL             0x02 /* 16 collision error */ -#define F_TBUS_ERR           0x01 /* bus read error */ - -#define F_PKT_RDY            0x80 /* packet(s) in buffer */ -#define F_BUS_ERR            0x40 /* bus read error */ -#define F_LEN_ERR            0x08 /* short packet */ -#define F_ALG_ERR            0x04 /* frame error */ -#define F_CRC_ERR            0x02 /* CRC error */ -#define F_OVR_FLO            0x01 /* overflow error */ - -#define F_BUF_EMP            0x40 /* receive buffer is empty */ - -#define F_SKP_PKT            0x05 /* drop packet in buffer */ - -/* default bitmaps */ -#define D_TX_INTR  ( ENA_TMT_OK ) -#define D_RX_INTR  ( ENA_PKT_RDY | ENA_LEN_ERR \ -		   | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO ) -#define TX_STAT_M  ( F_TMT_RDY ) -#define RX_STAT_M  ( F_PKT_RDY | F_LEN_ERR \ -                   | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO ) - -/* commands */ -#define D_TX_MODE            0x06 /* no tests, detect carrier */ -#define ID_MATCHED           0x02 /* (RX_MODE) */ -#define RECV_ALL             0x03 /* (RX_MODE) */ -#define CONFIG0_DFL          0x5a /* 16bit bus, 4K x 2 Tx queues */ -#define CONFIG0_DFL_1        0x5e /* 16bit bus, 8K x 2 Tx queues */ -#define CONFIG0_RST          0xda /* Data Link Controller off (CONFIG_0) */ -#define CONFIG0_RST_1        0xde /* Data Link Controller off (CONFIG_0) */ -#define BANK_0               0xa0 /* bank 0 (CONFIG_1) */ -#define BANK_1               0xa4 /* bank 1 (CONFIG_1) */ -#define BANK_2               0xa8 /* bank 2 (CONFIG_1) */ -#define CHIP_OFF             0x80 /* contrl chip power off (CONFIG_1) */ -#define DO_TX                0x80 /* do transmit packet */ -#define SEND_PKT             0x81 /* send a packet */ -#define AUTO_MODE            0x07 /* Auto skip packet on 16 col detected */ -#define MANU_MODE            0x03 /* Stop and skip packet on 16 col */ -#define TDK_AUTO_MODE        0x47 /* Auto skip packet on 16 col detected */ -#define TDK_MANU_MODE        0x43 /* Stop and skip packet on 16 col */ -#define INTR_OFF             0x0d /* LAN controller ignores interrupts */ -#define INTR_ON              0x1d /* LAN controller will catch interrupts */ - -#define TX_TIMEOUT		((400*HZ)/1000) - -#define BANK_0U              0x20 /* bank 0 (CONFIG_1) */ -#define BANK_1U              0x24 /* bank 1 (CONFIG_1) */ -#define BANK_2U              0x28 /* bank 2 (CONFIG_1) */ - -static const struct net_device_ops fjn_netdev_ops = { -	.ndo_open 		= fjn_open, -	.ndo_stop		= fjn_close, -	.ndo_start_xmit 	= fjn_start_xmit, -	.ndo_tx_timeout 	= fjn_tx_timeout, -	.ndo_set_config 	= fjn_config, -	.ndo_set_multicast_list = set_rx_mode, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int fmvj18x_probe(struct pcmcia_device *link) -{ -    local_info_t *lp; -    struct net_device *dev; - -    dev_dbg(&link->dev, "fmvj18x_attach()\n"); - -    /* Make up a FMVJ18x specific data structure */ -    dev = alloc_etherdev(sizeof(local_info_t)); -    if (!dev) -	return -ENOMEM; -    lp = netdev_priv(dev); -    link->priv = dev; -    lp->p_dev = link; -    lp->base = NULL; - -    /* The io structure describes IO port mapping */ -    link->resource[0]->end = 32; -    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - -    /* General socket configuration */ -    link->config_flags |= CONF_ENABLE_IRQ; - -    dev->netdev_ops = &fjn_netdev_ops; -    dev->watchdog_timeo = TX_TIMEOUT; - -    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - -    return fmvj18x_config(link); -} /* fmvj18x_attach */ - -/*====================================================================*/ - -static void fmvj18x_detach(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    dev_dbg(&link->dev, "fmvj18x_detach\n"); - -    unregister_netdev(dev); - -    fmvj18x_release(link); - -    free_netdev(dev); -} /* fmvj18x_detach */ - -/*====================================================================*/ - -static int mfc_try_io_port(struct pcmcia_device *link) -{ -    int i, ret; -    static const unsigned int serial_base[5] = -	{ 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; - -    for (i = 0; i < 5; i++) { -	link->resource[1]->start = serial_base[i]; -	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -	if (link->resource[1]->start == 0) { -	    link->resource[1]->end = 0; -	    pr_notice("out of resource for serial\n"); -	} -	ret = pcmcia_request_io(link); -	if (ret == 0) -		return ret; -    } -    return ret; -} - -static int ungermann_try_io_port(struct pcmcia_device *link) -{ -    int ret; -    unsigned int ioaddr; -    /* -	Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360 -	0x380,0x3c0 only for ioport. -    */ -    for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) { -	link->resource[0]->start = ioaddr; -	ret = pcmcia_request_io(link); -	if (ret == 0) { -	    /* calculate ConfigIndex value */ -	    link->config_index = -		((link->resource[0]->start & 0x0f0) >> 3) | 0x22; -	    return ret; -	} -    } -    return ret;	/* RequestIO failed */ -} - -static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data) -{ -	return 0; /* strange, but that's what the code did already before... */ -} - -static int fmvj18x_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    local_info_t *lp = netdev_priv(dev); -    int i, ret; -    unsigned int ioaddr; -    cardtype_t cardtype; -    char *card_name = "unknown"; -    u8 *buf; -    size_t len; -    u_char buggybuf[32]; - -    dev_dbg(&link->dev, "fmvj18x_config\n"); - -    link->io_lines = 5; - -    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); -    kfree(buf); - -    if (len) { -	/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */ -	ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL); -	if (ret != 0) -		goto failed; - -	switch (link->manf_id) { -	case MANFID_TDK: -	    cardtype = TDK; -	    if (link->card_id == PRODID_TDK_GN3410 || -		link->card_id == PRODID_TDK_NP9610 || -		link->card_id == PRODID_TDK_MN3200) { -		/* MultiFunction Card */ -		link->config_base = 0x800; -		link->config_index = 0x47; -		link->resource[1]->end = 8; -	    } -	    break; -	case MANFID_NEC: -	    cardtype = NEC; /* MultiFunction Card */ -	    link->config_base = 0x800; -	    link->config_index = 0x47; -	    link->resource[1]->end = 8; -	    break; -	case MANFID_KME: -	    cardtype = KME; /* MultiFunction Card */ -	    link->config_base = 0x800; -	    link->config_index = 0x47; -	    link->resource[1]->end = 8; -	    break; -	case MANFID_CONTEC: -	    cardtype = CONTEC; -	    break; -	case MANFID_FUJITSU: -	    if (link->config_base == 0x0fe0) -		cardtype = MBH10302; -	    else if (link->card_id == PRODID_FUJITSU_MBH10302)  -                /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302), -                   but these are MBH10304 based card. */  -		cardtype = MBH10304; -	    else if (link->card_id == PRODID_FUJITSU_MBH10304) -		cardtype = MBH10304; -	    else -		cardtype = LA501; -	    break; -	default: -	    cardtype = MBH10304; -	} -    } else { -	/* old type card */ -	switch (link->manf_id) { -	case MANFID_FUJITSU: -	    if (link->card_id == PRODID_FUJITSU_MBH10304) { -		cardtype = XXX10304;    /* MBH10304 with buggy CIS */ -		link->config_index = 0x20; -	    } else { -		cardtype = MBH10302;    /* NextCom NC5310, etc. */ -		link->config_index = 1; -	    } -	    break; -	case MANFID_UNGERMANN: -	    cardtype = UNGERMANN; -	    break; -	default: -	    cardtype = MBH10302; -	    link->config_index = 1; -	} -    } - -    if (link->resource[1]->end != 0) { -	ret = mfc_try_io_port(link); -	if (ret != 0) goto failed; -    } else if (cardtype == UNGERMANN) { -	ret = ungermann_try_io_port(link); -	if (ret != 0) goto failed; -    } else {  -	    ret = pcmcia_request_io(link); -	    if (ret) -		    goto failed; -    } -    ret = pcmcia_request_irq(link, fjn_interrupt); -    if (ret) -	    goto failed; -    ret = pcmcia_enable_device(link); -    if (ret) -	    goto failed; - -    dev->irq = link->irq; -    dev->base_addr = link->resource[0]->start; - -    if (resource_size(link->resource[1]) != 0) { -	ret = fmvj18x_setup_mfc(link); -	if (ret != 0) goto failed; -    } - -    ioaddr = dev->base_addr; - -    /* Reset controller */ -    if (sram_config == 0)  -	outb(CONFIG0_RST, ioaddr + CONFIG_0); -    else -	outb(CONFIG0_RST_1, ioaddr + CONFIG_0); - -    /* Power On chip and select bank 0 */ -    if (cardtype == MBH10302) -	outb(BANK_0, ioaddr + CONFIG_1); -    else -	outb(BANK_0U, ioaddr + CONFIG_1); -     -    /* Set hardware address */ -    switch (cardtype) { -    case MBH10304: -    case TDK: -    case LA501: -    case CONTEC: -    case NEC: -    case KME: -	if (cardtype == MBH10304) { -	    card_name = "FMV-J182"; - -	    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf); -	    if (len < 11) { -		    kfree(buf); -		    goto failed; -	    } -	    /* Read MACID from CIS */ -	    for (i = 5; i < 11; i++) -		    dev->dev_addr[i] = buf[i]; -	    kfree(buf); -	} else { -	    if (pcmcia_get_mac_from_cis(link, dev)) -		goto failed; -	    if( cardtype == TDK ) { -		card_name = "TDK LAK-CD021"; -	    } else if( cardtype == LA501 ) { -		card_name = "LA501"; -	    } else if( cardtype == NEC ) { -		card_name = "PK-UG-J001"; -	    } else if( cardtype == KME ) { -		card_name = "Panasonic"; -	    } else { -		card_name = "C-NET(PC)C"; -	    } -	} -	break; -    case UNGERMANN: -	/* Read MACID from register */ -	for (i = 0; i < 6; i++)  -	    dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i); -	card_name = "Access/CARD"; -	break; -    case XXX10304: -	/* Read MACID from Buggy CIS */ -	if (fmvj18x_get_hwinfo(link, buggybuf) == -1) { -	    pr_notice("unable to read hardware net address\n"); -	    goto failed; -	} -	for (i = 0 ; i < 6; i++) { -	    dev->dev_addr[i] = buggybuf[i]; -	} -	card_name = "FMV-J182"; -	break; -    case MBH10302: -    default: -	/* Read MACID from register */ -	for (i = 0; i < 6; i++)  -	    dev->dev_addr[i] = inb(ioaddr + MAC_ID + i); -	card_name = "FMV-J181"; -	break; -    } - -    lp->cardtype = cardtype; -    SET_NETDEV_DEV(dev, &link->dev); - -    if (register_netdev(dev) != 0) { -	pr_notice("register_netdev() failed\n"); -	goto failed; -    } - -    /* print current configuration */ -    netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n", -		card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", -		dev->base_addr, dev->irq, dev->dev_addr); - -    return 0; -     -failed: -    fmvj18x_release(link); -    return -ENODEV; -} /* fmvj18x_config */ -/*====================================================================*/ - -static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id) -{ -    u_char __iomem *base; -    int i, j; - -    /* Allocate a small memory window */ -    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; -    link->resource[2]->start = 0; link->resource[2]->end = 0; -    i = pcmcia_request_window(link, link->resource[2], 0); -    if (i != 0) -	return -1; - -    base = ioremap(link->resource[2]->start, resource_size(link->resource[2])); -    pcmcia_map_mem_page(link, link->resource[2], 0); - -    /* -     *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format -     *  22 0d xx xx xx 04 06 yy yy yy yy yy yy ff -     *  'xx' is garbage. -     *  'yy' is MAC address. -    */  -    for (i = 0; i < 0x200; i++) { -	if (readb(base+i*2) == 0x22) {	 -		if (readb(base+(i-1)*2) == 0xff && -		    readb(base+(i+5)*2) == 0x04 && -		    readb(base+(i+6)*2) == 0x06 && -		    readb(base+(i+13)*2) == 0xff) -			break; -	} -    } - -    if (i != 0x200) { -	for (j = 0 ; j < 6; j++,i++) { -	    node_id[j] = readb(base+(i+7)*2); -	} -    } - -    iounmap(base); -    j = pcmcia_release_window(link, link->resource[2]); -    return (i != 0x200) ? 0 : -1; - -} /* fmvj18x_get_hwinfo */ -/*====================================================================*/ - -static int fmvj18x_setup_mfc(struct pcmcia_device *link) -{ -    int i; -    struct net_device *dev = link->priv; -    unsigned int ioaddr; -    local_info_t *lp = netdev_priv(dev); - -    /* Allocate a small memory window */ -    link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; -    link->resource[3]->start = link->resource[3]->end = 0; -    i = pcmcia_request_window(link, link->resource[3], 0); -    if (i != 0) -	return -1; - -    lp->base = ioremap(link->resource[3]->start, -		       resource_size(link->resource[3])); -    if (lp->base == NULL) { -	netdev_notice(dev, "ioremap failed\n"); -	return -1; -    } - -    i = pcmcia_map_mem_page(link, link->resource[3], 0); -    if (i != 0) { -	iounmap(lp->base); -	lp->base = NULL; -	return -1; -    } -     -    ioaddr = dev->base_addr; -    writeb(0x47, lp->base+0x800);	/* Config Option Register of LAN */ -    writeb(0x0,  lp->base+0x802);	/* Config and Status Register */ - -    writeb(ioaddr & 0xff, lp->base+0x80a);	  /* I/O Base(Low) of LAN */ -    writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */ -    -    writeb(0x45, lp->base+0x820);	/* Config Option Register of Modem */ -    writeb(0x8,  lp->base+0x822);	/* Config and Status Register */ - -    return 0; - -} -/*====================================================================*/ - -static void fmvj18x_release(struct pcmcia_device *link) -{ - -    struct net_device *dev = link->priv; -    local_info_t *lp = netdev_priv(dev); -    u_char __iomem *tmp; - -    dev_dbg(&link->dev, "fmvj18x_release\n"); - -    if (lp->base != NULL) { -	tmp = lp->base; -	lp->base = NULL;    /* set NULL before iounmap */ -	iounmap(tmp); -    } - -    pcmcia_disable_device(link); - -} - -static int fmvj18x_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int fmvj18x_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		fjn_reset(dev); -		netif_device_attach(dev); -	} - -	return 0; -} - -/*====================================================================*/ - -static struct pcmcia_device_id fmvj18x_ids[] = { -	PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004), -	PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59), -	PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922), -	PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922), -	PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db), -	PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e), -	PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2), -	PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4), -	PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0       ", 0x8cef4d3a, 0x075fc7b6), -	PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0        ", 0x8cef4d3a, 0xbccf43e6), -	PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666), -	PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70), -	PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a), -	PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2), -	PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304  ES", 0x2599f454), -	PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da), -	PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101), -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids); - -static struct pcmcia_driver fmvj18x_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "fmvj18x_cs", -	.probe		= fmvj18x_probe, -	.remove		= fmvj18x_detach, -	.id_table       = fmvj18x_ids, -	.suspend	= fmvj18x_suspend, -	.resume		= fmvj18x_resume, -}; - -static int __init init_fmvj18x_cs(void) -{ -	return pcmcia_register_driver(&fmvj18x_cs_driver); -} - -static void __exit exit_fmvj18x_cs(void) -{ -	pcmcia_unregister_driver(&fmvj18x_cs_driver); -} - -module_init(init_fmvj18x_cs); -module_exit(exit_fmvj18x_cs); - -/*====================================================================*/ - -static irqreturn_t fjn_interrupt(int dummy, void *dev_id) -{ -    struct net_device *dev = dev_id; -    local_info_t *lp = netdev_priv(dev); -    unsigned int ioaddr; -    unsigned short tx_stat, rx_stat; - -    ioaddr = dev->base_addr; - -    /* avoid multiple interrupts */ -    outw(0x0000, ioaddr + TX_INTR); - -    /* wait for a while */ -    udelay(1); - -    /* get status */ -    tx_stat = inb(ioaddr + TX_STATUS); -    rx_stat = inb(ioaddr + RX_STATUS); - -    /* clear status */ -    outb(tx_stat, ioaddr + TX_STATUS); -    outb(rx_stat, ioaddr + RX_STATUS); -     -    pr_debug("%s: interrupt, rx_status %02x.\n", dev->name, rx_stat); -    pr_debug("               tx_status %02x.\n", tx_stat); -     -    if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { -	/* there is packet(s) in rx buffer */ -	fjn_rx(dev); -    } -    if (tx_stat & F_TMT_RDY) { -	dev->stats.tx_packets += lp->sent ; -        lp->sent = 0 ; -	if (lp->tx_queue) { -	    outb(DO_TX | lp->tx_queue, ioaddr + TX_START); -	    lp->sent = lp->tx_queue ; -	    lp->tx_queue = 0; -	    lp->tx_queue_len = 0; -	    dev->trans_start = jiffies; -	} else { -	    lp->tx_started = 0; -	} -	netif_wake_queue(dev); -    } -    pr_debug("%s: exiting interrupt,\n", dev->name); -    pr_debug("    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat); - -    outb(D_TX_INTR, ioaddr + TX_INTR); -    outb(D_RX_INTR, ioaddr + RX_INTR); - -    if (lp->base != NULL) { -	/* Ack interrupt for multifunction card */ -	writeb(0x01, lp->base+0x802); -	writeb(0x09, lp->base+0x822); -    } - -    return IRQ_HANDLED; - -} /* fjn_interrupt */ - -/*====================================================================*/ - -static void fjn_tx_timeout(struct net_device *dev) -{ -    struct local_info_t *lp = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; - -    netdev_notice(dev, "transmit timed out with status %04x, %s?\n", -		  htons(inw(ioaddr + TX_STATUS)), -		  inb(ioaddr + TX_STATUS) & F_TMT_RDY -		  ? "IRQ conflict" : "network cable problem"); -    netdev_notice(dev, "timeout registers: %04x %04x %04x " -		  "%04x %04x %04x %04x %04x.\n", -		  htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)), -		  htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)), -		  htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)), -		  htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14))); -    dev->stats.tx_errors++; -    /* ToDo: We should try to restart the adaptor... */ -    local_irq_disable(); -    fjn_reset(dev); - -    lp->tx_started = 0; -    lp->tx_queue = 0; -    lp->tx_queue_len = 0; -    lp->sent = 0; -    lp->open_time = jiffies; -    local_irq_enable(); -    netif_wake_queue(dev); -} - -static netdev_tx_t fjn_start_xmit(struct sk_buff *skb, -					struct net_device *dev) -{ -    struct local_info_t *lp = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    short length = skb->len; -     -    if (length < ETH_ZLEN) -    { -    	if (skb_padto(skb, ETH_ZLEN)) -    		return NETDEV_TX_OK; -    	length = ETH_ZLEN; -    } - -    netif_stop_queue(dev); - -    { -	unsigned char *buf = skb->data; - -	if (length > ETH_FRAME_LEN) { -	    netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n", -			  length); -	    return NETDEV_TX_BUSY; -	} - -	netdev_dbg(dev, "Transmitting a packet of length %lu\n", -		   (unsigned long)skb->len); -	dev->stats.tx_bytes += skb->len; - -	/* Disable both interrupts. */ -	outw(0x0000, ioaddr + TX_INTR); - -	/* wait for a while */ -	udelay(1); - -	outw(length, ioaddr + DATAPORT); -	outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); - -	lp->tx_queue++; -	lp->tx_queue_len += ((length+3) & ~1); - -	if (lp->tx_started == 0) { -	    /* If the Tx is idle, always trigger a transmit. */ -	    outb(DO_TX | lp->tx_queue, ioaddr + TX_START); -	    lp->sent = lp->tx_queue ; -	    lp->tx_queue = 0; -	    lp->tx_queue_len = 0; -	    lp->tx_started = 1; -	    netif_start_queue(dev); -	} else { -	    if( sram_config == 0 ) { -		if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) ) -		    /* Yes, there is room for one more packet. */ -		    netif_start_queue(dev); -	    } else { -		if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&  -						lp->tx_queue < 127 ) -		    /* Yes, there is room for one more packet. */ -		    netif_start_queue(dev); -	    } -	} - -	/* Re-enable interrupts */ -	outb(D_TX_INTR, ioaddr + TX_INTR); -	outb(D_RX_INTR, ioaddr + RX_INTR); -    } -    dev_kfree_skb (skb); - -    return NETDEV_TX_OK; -} /* fjn_start_xmit */ - -/*====================================================================*/ - -static void fjn_reset(struct net_device *dev) -{ -    struct local_info_t *lp = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    int i; - -    netdev_dbg(dev, "fjn_reset() called\n"); - -    /* Reset controller */ -    if( sram_config == 0 )  -	outb(CONFIG0_RST, ioaddr + CONFIG_0); -    else -	outb(CONFIG0_RST_1, ioaddr + CONFIG_0); - -    /* Power On chip and select bank 0 */ -    if (lp->cardtype == MBH10302) -	outb(BANK_0, ioaddr + CONFIG_1); -    else -	outb(BANK_0U, ioaddr + CONFIG_1); - -    /* Set Tx modes */ -    outb(D_TX_MODE, ioaddr + TX_MODE); -    /* set Rx modes */ -    outb(ID_MATCHED, ioaddr + RX_MODE); - -    /* Set hardware address */ -    for (i = 0; i < 6; i++)  -        outb(dev->dev_addr[i], ioaddr + NODE_ID + i); - -    /* (re)initialize the multicast table */ -    set_rx_mode(dev); - -    /* Switch to bank 2 (runtime mode) */ -    if (lp->cardtype == MBH10302) -	outb(BANK_2, ioaddr + CONFIG_1); -    else -	outb(BANK_2U, ioaddr + CONFIG_1); - -    /* set 16col ctrl bits */ -    if( lp->cardtype == TDK || lp->cardtype == CONTEC)  -        outb(TDK_AUTO_MODE, ioaddr + COL_CTRL); -    else -        outb(AUTO_MODE, ioaddr + COL_CTRL); - -    /* clear Reserved Regs */ -    outb(0x00, ioaddr + BMPR12); -    outb(0x00, ioaddr + BMPR13); - -    /* reset Skip packet reg. */ -    outb(0x01, ioaddr + RX_SKIP); - -    /* Enable Tx and Rx */ -    if( sram_config == 0 ) -	outb(CONFIG0_DFL, ioaddr + CONFIG_0); -    else -	outb(CONFIG0_DFL_1, ioaddr + CONFIG_0); - -    /* Init receive pointer ? */ -    inw(ioaddr + DATAPORT); -    inw(ioaddr + DATAPORT); - -    /* Clear all status */ -    outb(0xff, ioaddr + TX_STATUS); -    outb(0xff, ioaddr + RX_STATUS); - -    if (lp->cardtype == MBH10302) -	outb(INTR_OFF, ioaddr + LAN_CTRL); - -    /* Turn on Rx interrupts */ -    outb(D_TX_INTR, ioaddr + TX_INTR); -    outb(D_RX_INTR, ioaddr + RX_INTR); - -    /* Turn on interrupts from LAN card controller */ -    if (lp->cardtype == MBH10302) -	outb(INTR_ON, ioaddr + LAN_CTRL); -} /* fjn_reset */ - -/*====================================================================*/ - -static void fjn_rx(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    int boguscount = 10;	/* 5 -> 10: by agy 19940922 */ - -    pr_debug("%s: in rx_packet(), rx_status %02x.\n", -	  dev->name, inb(ioaddr + RX_STATUS)); - -    while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { -	u_short status = inw(ioaddr + DATAPORT); - -	netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n", -		   inb(ioaddr + RX_MODE), status); -#ifndef final_version -	if (status == 0) { -	    outb(F_SKP_PKT, ioaddr + RX_SKIP); -	    break; -	} -#endif -	if ((status & 0xF0) != 0x20) {	/* There was an error. */ -	    dev->stats.rx_errors++; -	    if (status & F_LEN_ERR) dev->stats.rx_length_errors++; -	    if (status & F_ALG_ERR) dev->stats.rx_frame_errors++; -	    if (status & F_CRC_ERR) dev->stats.rx_crc_errors++; -	    if (status & F_OVR_FLO) dev->stats.rx_over_errors++; -	} else { -	    u_short pkt_len = inw(ioaddr + DATAPORT); -	    /* Malloc up new buffer. */ -	    struct sk_buff *skb; - -	    if (pkt_len > 1550) { -		netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n", -			      pkt_len); -		outb(F_SKP_PKT, ioaddr + RX_SKIP); -		dev->stats.rx_errors++; -		break; -	    } -	    skb = dev_alloc_skb(pkt_len+2); -	    if (skb == NULL) { -		netdev_notice(dev, "Memory squeeze, dropping packet (len %d)\n", -			      pkt_len); -		outb(F_SKP_PKT, ioaddr + RX_SKIP); -		dev->stats.rx_dropped++; -		break; -	    } - -	    skb_reserve(skb, 2); -	    insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), -		 (pkt_len + 1) >> 1); -	    skb->protocol = eth_type_trans(skb, dev); - -	    { -		int i; -		pr_debug("%s: Rxed packet of length %d: ", -			dev->name, pkt_len); -		for (i = 0; i < 14; i++) -			pr_debug(" %02x", skb->data[i]); -		pr_debug(".\n"); -	    } - -	    netif_rx(skb); -	    dev->stats.rx_packets++; -	    dev->stats.rx_bytes += pkt_len; -	} -	if (--boguscount <= 0) -	    break; -    } - -    /* If any worth-while packets have been received, dev_rint() -	   has done a netif_wake_queue() for us and will work on them -	   when we get to the bottom-half routine. */ -/* -    if (lp->cardtype != TDK) { -	int i; -	for (i = 0; i < 20; i++) { -	    if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP) -		break; -	    (void)inw(ioaddr + DATAPORT);  /+ dummy status read +/ -	    outb(F_SKP_PKT, ioaddr + RX_SKIP); -	} - -	if (i > 0) -	    pr_debug("%s: Exint Rx packet with mode %02x after " -		  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i); -    } -*/ -} /* fjn_rx */ - -/*====================================================================*/ - -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, "PCMCIA 0x%lx", dev->base_addr); -} - -static const struct ethtool_ops netdev_ethtool_ops = { -	.get_drvinfo		= netdev_get_drvinfo, -}; - -static int fjn_config(struct net_device *dev, struct ifmap *map){ -    return 0; -} - -static int fjn_open(struct net_device *dev) -{ -    struct local_info_t *lp = netdev_priv(dev); -    struct pcmcia_device *link = lp->p_dev; - -    pr_debug("fjn_open('%s').\n", dev->name); - -    if (!pcmcia_dev_present(link)) -	return -ENODEV; -     -    link->open++; -     -    fjn_reset(dev); -     -    lp->tx_started = 0; -    lp->tx_queue = 0; -    lp->tx_queue_len = 0; -    lp->open_time = jiffies; -    netif_start_queue(dev); -     -    return 0; -} /* fjn_open */ - -/*====================================================================*/ - -static int fjn_close(struct net_device *dev) -{ -    struct local_info_t *lp = netdev_priv(dev); -    struct pcmcia_device *link = lp->p_dev; -    unsigned int ioaddr = dev->base_addr; - -    pr_debug("fjn_close('%s').\n", dev->name); - -    lp->open_time = 0; -    netif_stop_queue(dev); - -    /* Set configuration register 0 to disable Tx and Rx. */ -    if( sram_config == 0 )  -	outb(CONFIG0_RST ,ioaddr + CONFIG_0); -    else -	outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0); - -    /* Update the statistics -- ToDo. */ - -    /* Power-down the chip.  Green, green, green! */ -    outb(CHIP_OFF ,ioaddr + CONFIG_1); - -    /* Set the ethernet adaptor disable IRQ */ -    if (lp->cardtype == MBH10302) -	outb(INTR_OFF, ioaddr + LAN_CTRL); - -    link->open--; - -    return 0; -} /* fjn_close */ - -/*====================================================================*/ - -/* -  Set the multicast/promiscuous mode for this adaptor. -*/ - -static void set_rx_mode(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    u_char mc_filter[8];		 /* Multicast hash filter */ -    u_long flags; -    int i; -     -    int saved_bank; -    int saved_config_0 = inb(ioaddr + CONFIG_0); -      -    local_irq_save(flags);  - -    /* Disable Tx and Rx */ -    if (sram_config == 0)  -	outb(CONFIG0_RST, ioaddr + CONFIG_0); -    else -	outb(CONFIG0_RST_1, ioaddr + CONFIG_0); - -    if (dev->flags & IFF_PROMISC) { -	memset(mc_filter, 0xff, sizeof(mc_filter)); -	outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */ -    } else if (netdev_mc_count(dev) > MC_FILTERBREAK || -	       (dev->flags & IFF_ALLMULTI)) { -	/* Too many to filter perfectly -- accept all multicasts. */ -	memset(mc_filter, 0xff, sizeof(mc_filter)); -	outb(2, ioaddr + RX_MODE);	/* Use normal mode. */ -    } else if (netdev_mc_empty(dev)) { -	memset(mc_filter, 0x00, sizeof(mc_filter)); -	outb(1, ioaddr + RX_MODE);	/* Ignore almost all multicasts. */ -    } else { -	struct netdev_hw_addr *ha; - -	memset(mc_filter, 0, sizeof(mc_filter)); -	netdev_for_each_mc_addr(ha, dev) { -	    unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26; -	    mc_filter[bit >> 3] |= (1 << (bit & 7)); -	} -	outb(2, ioaddr + RX_MODE);	/* Use normal mode. */ -    } - -    /* Switch to bank 1 and set the multicast table. */ -    saved_bank = inb(ioaddr + CONFIG_1); -    outb(0xe4, ioaddr + CONFIG_1); - -    for (i = 0; i < 8; i++) -	outb(mc_filter[i], ioaddr + MAR_ADR + i); -    outb(saved_bank, ioaddr + CONFIG_1); - -    outb(saved_config_0, ioaddr + CONFIG_0); - -    local_irq_restore(flags); -} diff --git a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c deleted file mode 100644 index 15d57f5b6f2..00000000000 --- a/drivers/net/pcmcia/ibmtr_cs.c +++ /dev/null @@ -1,371 +0,0 @@ -/*====================================================================== - -    A PCMCIA token-ring driver for IBM-based cards - -    This driver supports the IBM PCMCIA Token-Ring Card. -    Written by Steve Kipisz, kipisz@vnet.ibm.com or -                             bungy@ibm.net - -    Written 1995,1996. - -    This code is based on pcnet_cs.c from David Hinds. -     -    V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com - -    Linux V2.2.x presented significant changes to the underlying -    ibmtr.c code.  Mainly the code became a lot more organized and -    modular. - -    This caused the old PCMCIA Token Ring driver to give up and go  -    home early. Instead of just patching the old code to make it  -    work, the PCMCIA code has been streamlined, updated and possibly -    improved. - -    This code now only contains code required for the Card Services. -    All we do here is set the card up enough so that the real ibmtr.c -    driver can find it and work with it properly. - -    i.e. We set up the io port, irq, mmio memory and shared ram -    memory.  This enables ibmtr_probe in ibmtr.c to find the card and -    configure it as though it was a normal ISA and/or PnP card. - -    CHANGES - -    v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com) -    Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c -     -    v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com) -    Updated to version 2.2.7 to match the first version of the kernel -    that the modification to ibmtr.c were incorporated into. -     -    v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com) -    Address translation feature of PCMCIA controller is usable so -    memory windows can be placed in High memory (meaning above -    0xFFFFF.) - -======================================================================*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/module.h> -#include <linux/netdevice.h> -#include <linux/trdevice.h> -#include <linux/ibmtr.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> - -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/system.h> - -#define PCMCIA -#include "../tokenring/ibmtr.c" - - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* MMIO base address */ -static u_long mmiobase = 0xce000; - -/* SRAM base address */ -static u_long srambase = 0xd0000; - -/* SRAM size 8,16,32,64 */ -static u_long sramsize = 64; - -/* Ringspeed 4,16 */ -static int ringspeed = 16; - -module_param(mmiobase, ulong, 0); -module_param(srambase, ulong, 0); -module_param(sramsize, ulong, 0); -module_param(ringspeed, int, 0); -MODULE_LICENSE("GPL"); - -/*====================================================================*/ - -static int ibmtr_config(struct pcmcia_device *link); -static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase); -static void ibmtr_release(struct pcmcia_device *link); -static void ibmtr_detach(struct pcmcia_device *p_dev); - -/*====================================================================*/ - -typedef struct ibmtr_dev_t { -	struct pcmcia_device	*p_dev; -	struct net_device	*dev; -	struct tok_info		*ti; -} ibmtr_dev_t; - -static irqreturn_t ibmtr_interrupt(int irq, void *dev_id) { -	ibmtr_dev_t *info = dev_id; -	struct net_device *dev = info->dev; -	return tok_interrupt(irq, dev); -}; - -static int __devinit ibmtr_attach(struct pcmcia_device *link) -{ -    ibmtr_dev_t *info; -    struct net_device *dev; - -    dev_dbg(&link->dev, "ibmtr_attach()\n"); - -    /* Create new token-ring device */ -    info = kzalloc(sizeof(*info), GFP_KERNEL); -    if (!info) return -ENOMEM; -    dev = alloc_trdev(sizeof(struct tok_info)); -    if (!dev) { -	kfree(info); -	return -ENOMEM; -    } - -    info->p_dev = link; -    link->priv = info; -    info->ti = netdev_priv(dev); - -    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; -    link->resource[0]->end = 4; -    link->config_flags |= CONF_ENABLE_IRQ; -    link->config_regs = PRESENT_OPTION; - -    info->dev = dev; - -    return ibmtr_config(link); -} /* ibmtr_attach */ - -static void ibmtr_detach(struct pcmcia_device *link) -{ -    struct ibmtr_dev_t *info = link->priv; -    struct net_device *dev = info->dev; -     struct tok_info *ti = netdev_priv(dev); - -    dev_dbg(&link->dev, "ibmtr_detach\n"); -     -    /*  -     * When the card removal interrupt hits tok_interrupt(),  -     * bail out early, so we don't crash the machine  -     */ -    ti->sram_phys |= 1; - -    unregister_netdev(dev); -     -    del_timer_sync(&(ti->tr_timer)); - -    ibmtr_release(link); - -    free_netdev(dev); -    kfree(info); -} /* ibmtr_detach */ - -static int __devinit ibmtr_config(struct pcmcia_device *link) -{ -    ibmtr_dev_t *info = link->priv; -    struct net_device *dev = info->dev; -    struct tok_info *ti = netdev_priv(dev); -    int i, ret; - -    dev_dbg(&link->dev, "ibmtr_config\n"); - -    link->io_lines = 16; -    link->config_index = 0x61; - -    /* Determine if this is PRIMARY or ALTERNATE. */ - -    /* Try PRIMARY card at 0xA20-0xA23 */ -    link->resource[0]->start = 0xA20; -    i = pcmcia_request_io(link); -    if (i != 0) { -	/* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */ -	link->resource[0]->start = 0xA24; -	ret = pcmcia_request_io(link); -	if (ret) -		goto failed; -    } -    dev->base_addr = link->resource[0]->start; - -    ret = pcmcia_request_exclusive_irq(link, ibmtr_interrupt); -    if (ret) -	    goto failed; -    dev->irq = link->irq; -    ti->irq = link->irq; -    ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq); - -    /* Allocate the MMIO memory window */ -    link->resource[2]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; -    link->resource[2]->flags |= WIN_USE_WAIT; -    link->resource[2]->start = 0; -    link->resource[2]->end = 0x2000; -    ret = pcmcia_request_window(link, link->resource[2], 250); -    if (ret) -	    goto failed; - -    ret = pcmcia_map_mem_page(link, link->resource[2], mmiobase); -    if (ret) -	    goto failed; -    ti->mmio = ioremap(link->resource[2]->start, -		    resource_size(link->resource[2])); - -    /* Allocate the SRAM memory window */ -    link->resource[3]->flags = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; -    link->resource[3]->flags |= WIN_USE_WAIT; -    link->resource[3]->start = 0; -    link->resource[3]->end = sramsize * 1024; -    ret = pcmcia_request_window(link, link->resource[3], 250); -    if (ret) -	    goto failed; - -    ret = pcmcia_map_mem_page(link, link->resource[3], srambase); -    if (ret) -	    goto failed; - -    ti->sram_base = srambase >> 12; -    ti->sram_virt = ioremap(link->resource[3]->start, -		    resource_size(link->resource[3])); -    ti->sram_phys = link->resource[3]->start; - -    ret = pcmcia_enable_device(link); -    if (ret) -	    goto failed; - -    /*  Set up the Token-Ring Controller Configuration Register and -        turn on the card.  Check the "Local Area Network Credit Card -        Adapters Technical Reference"  SC30-3585 for this info.  */ -    ibmtr_hw_setup(dev, mmiobase); - -    SET_NETDEV_DEV(dev, &link->dev); - -    i = ibmtr_probe_card(dev); -    if (i != 0) { -	pr_notice("register_netdev() failed\n"); -	goto failed; -    } - -    netdev_info(dev, "port %#3lx, irq %d, mmio %#5lx, sram %#5lx, hwaddr=%pM\n", -		dev->base_addr, dev->irq, -		(u_long)ti->mmio, (u_long)(ti->sram_base << 12), -		dev->dev_addr); -    return 0; - -failed: -    ibmtr_release(link); -    return -ENODEV; -} /* ibmtr_config */ - -static void ibmtr_release(struct pcmcia_device *link) -{ -	ibmtr_dev_t *info = link->priv; -	struct net_device *dev = info->dev; - -	dev_dbg(&link->dev, "ibmtr_release\n"); - -	if (link->resource[2]->end) { -		struct tok_info *ti = netdev_priv(dev); -		iounmap(ti->mmio); -	} -	pcmcia_disable_device(link); -} - -static int ibmtr_suspend(struct pcmcia_device *link) -{ -	ibmtr_dev_t *info = link->priv; -	struct net_device *dev = info->dev; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int __devinit ibmtr_resume(struct pcmcia_device *link) -{ -	ibmtr_dev_t *info = link->priv; -	struct net_device *dev = info->dev; - -	if (link->open) { -		ibmtr_probe(dev);	/* really? */ -		netif_device_attach(dev); -	} - -	return 0; -} - - -/*====================================================================*/ - -static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase) -{ -    int i; - -    /* Bizarre IBM behavior, there are 16 bits of information we -       need to set, but the card only allows us to send 4 bits at a  -       time.  For each byte sent to base_addr, bits 7-4 tell the -       card which part of the 16 bits we are setting, bits 3-0 contain  -       the actual information */ - -    /* First nibble provides 4 bits of mmio */ -    i = (mmiobase >> 16) & 0x0F; -    outb(i, dev->base_addr); - -    /* Second nibble provides 3 bits of mmio */ -    i = 0x10 | ((mmiobase >> 12) & 0x0E); -    outb(i, dev->base_addr); - -    /* Third nibble, hard-coded values */ -    i = 0x26; -    outb(i, dev->base_addr); - -    /* Fourth nibble sets shared ram page size */ - -    /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */           -    i = (sramsize >> 4) & 0x07; -    i = ((i == 4) ? 3 : i) << 2; -    i |= 0x30; - -    if (ringspeed == 16) -	i |= 2; -    if (dev->base_addr == 0xA24) -	i |= 1; -    outb(i, dev->base_addr); - -    /* 0x40 will release the card for use */ -    outb(0x40, dev->base_addr); -} - -static struct pcmcia_device_id ibmtr_ids[] = { -	PCMCIA_DEVICE_PROD_ID12("3Com", "TokenLink Velocity PC Card", 0x41240e5b, 0x82c3734e), -	PCMCIA_DEVICE_PROD_ID12("IBM", "TOKEN RING", 0xb569a6e5, 0xbf8eed47), -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, ibmtr_ids); - -static struct pcmcia_driver ibmtr_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "ibmtr_cs", -	.probe		= ibmtr_attach, -	.remove		= ibmtr_detach, -	.id_table       = ibmtr_ids, -	.suspend	= ibmtr_suspend, -	.resume		= ibmtr_resume, -}; - -static int __init init_ibmtr_cs(void) -{ -	return pcmcia_register_driver(&ibmtr_cs_driver); -} - -static void __exit exit_ibmtr_cs(void) -{ -	pcmcia_unregister_driver(&ibmtr_cs_driver); -} - -module_init(init_ibmtr_cs); -module_exit(exit_ibmtr_cs); diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c deleted file mode 100644 index 0a2b0f9cdf3..00000000000 --- a/drivers/net/pcmcia/nmclan_cs.c +++ /dev/null @@ -1,1525 +0,0 @@ -/* ---------------------------------------------------------------------------- -Linux PCMCIA ethernet adapter driver for the New Media Ethernet LAN. -  nmclan_cs.c,v 0.16 1995/07/01 06:42:17 rpao Exp rpao - -  The Ethernet LAN uses the Advanced Micro Devices (AMD) Am79C940 Media -  Access Controller for Ethernet (MACE).  It is essentially the Am2150 -  PCMCIA Ethernet card contained in the Am2150 Demo Kit. - -Written by Roger C. Pao <rpao@paonet.org> -  Copyright 1995 Roger C. Pao -  Linux 2.5 cleanups Copyright Red Hat 2003 - -  This software may be used and distributed according to the terms of -  the GNU General Public License. - -Ported to Linux 1.3.* network driver environment by -  Matti Aarnio <mea@utu.fi> - -References - -  Am2150 Technical Reference Manual, Revision 1.0, August 17, 1993 -  Am79C940 (MACE) Data Sheet, 1994 -  Am79C90 (C-LANCE) Data Sheet, 1994 -  Linux PCMCIA Programmer's Guide v1.17 -  /usr/src/linux/net/inet/dev.c, Linux kernel 1.2.8 - -  Eric Mears, New Media Corporation -  Tom Pollard, New Media Corporation -  Dean Siasoyco, New Media Corporation -  Ken Lesniak, Silicon Graphics, Inc. <lesniak@boston.sgi.com> -  Donald Becker <becker@scyld.com> -  David Hinds <dahinds@users.sourceforge.net> - -  The Linux client driver is based on the 3c589_cs.c client driver by -  David Hinds. - -  The Linux network driver outline is based on the 3c589_cs.c driver, -  the 8390.c driver, and the example skeleton.c kernel code, which are -  by Donald Becker. - -  The Am2150 network driver hardware interface code is based on the -  OS/9000 driver for the New Media Ethernet LAN by Eric Mears. - -  Special thanks for testing and help in debugging this driver goes -  to Ken Lesniak. - -------------------------------------------------------------------------------- -Driver Notes and Issues -------------------------------------------------------------------------------- - -1. Developed on a Dell 320SLi -   PCMCIA Card Services 2.6.2 -   Linux dell 1.2.10 #1 Thu Jun 29 20:23:41 PDT 1995 i386 - -2. rc.pcmcia may require loading pcmcia_core with io_speed=300: -   'insmod pcmcia_core.o io_speed=300'. -   This will avoid problems with fast systems which causes rx_framecnt -   to return random values. - -3. If hot extraction does not work for you, use 'ifconfig eth0 down' -   before extraction. - -4. There is a bad slow-down problem in this driver. - -5. Future: Multicast processing.  In the meantime, do _not_ compile your -   kernel with multicast ip enabled. - -------------------------------------------------------------------------------- -History -------------------------------------------------------------------------------- -Log: nmclan_cs.c,v - * 2.5.75-ac1 2003/07/11 Alan Cox <alan@lxorguk.ukuu.org.uk> - * Fixed hang on card eject as we probe it - * Cleaned up to use new style locking. - * - * Revision 0.16  1995/07/01  06:42:17  rpao - * Bug fix: nmclan_reset() called CardServices incorrectly. - * - * Revision 0.15  1995/05/24  08:09:47  rpao - * Re-implement MULTI_TX dev->tbusy handling. - * - * Revision 0.14  1995/05/23  03:19:30  rpao - * Added, in nmclan_config(), "tuple.Attributes = 0;". - * Modified MACE ID check to ignore chip revision level. - * Avoid tx_free_frames race condition between _start_xmit and _interrupt. - * - * Revision 0.13  1995/05/18  05:56:34  rpao - * Statistics changes. - * Bug fix: nmclan_reset did not enable TX and RX: call restore_multicast_list. - * Bug fix: mace_interrupt checks ~MACE_IMR_DEFAULT.  Fixes driver lockup. - * - * Revision 0.12  1995/05/14  00:12:23  rpao - * Statistics overhaul. - * - -95/05/13 rpao	V0.10a -		Bug fix: MACE statistics counters used wrong I/O ports. -		Bug fix: mace_interrupt() needed to allow statistics to be -		processed without RX or TX interrupts pending. -95/05/11 rpao	V0.10 -		Multiple transmit request processing. -		Modified statistics to use MACE counters where possible. -95/05/10 rpao	V0.09 Bug fix: Must use IO_DATA_PATH_WIDTH_AUTO. -		*Released -95/05/10 rpao	V0.08 -		Bug fix: Make all non-exported functions private by using -		static keyword. -		Bug fix: Test IntrCnt _before_ reading MACE_IR. -95/05/10 rpao	V0.07 Statistics. -95/05/09 rpao	V0.06 Fix rx_framecnt problem by addition of PCIC wait states. - ----------------------------------------------------------------------------- */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#define DRV_NAME	"nmclan_cs" -#define DRV_VERSION	"0.16" - - -/* ---------------------------------------------------------------------------- -Conditional Compilation Options ----------------------------------------------------------------------------- */ - -#define MULTI_TX			0 -#define RESET_ON_TIMEOUT		1 -#define TX_INTERRUPTABLE		1 -#define RESET_XILINX			0 - -/* ---------------------------------------------------------------------------- -Include Files ----------------------------------------------------------------------------- */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/delay.h> -#include <linux/ethtool.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/bitops.h> - -#include <pcmcia/cisreg.h> -#include <pcmcia/cistpl.h> -#include <pcmcia/ds.h> - -#include <asm/uaccess.h> -#include <asm/io.h> -#include <asm/system.h> - -/* ---------------------------------------------------------------------------- -Defines ----------------------------------------------------------------------------- */ - -#define ETHER_ADDR_LEN			ETH_ALEN -					/* 6 bytes in an Ethernet Address */ -#define MACE_LADRF_LEN			8 -					/* 8 bytes in Logical Address Filter */ - -/* Loop Control Defines */ -#define MACE_MAX_IR_ITERATIONS		10 -#define MACE_MAX_RX_ITERATIONS		12 -	/* -	TBD: Dean brought this up, and I assumed the hardware would -	handle it: - -	If MACE_MAX_RX_ITERATIONS is > 1, rx_framecnt may still be -	non-zero when the isr exits.  We may not get another interrupt -	to process the remaining packets for some time. -	*/ - -/* -The Am2150 has a Xilinx XC3042 field programmable gate array (FPGA) -which manages the interface between the MACE and the PCMCIA bus.  It -also includes buffer management for the 32K x 8 SRAM to control up to -four transmit and 12 receive frames at a time. -*/ -#define AM2150_MAX_TX_FRAMES		4 -#define AM2150_MAX_RX_FRAMES		12 - -/* Am2150 Ethernet Card I/O Mapping */ -#define AM2150_RCV			0x00 -#define AM2150_XMT			0x04 -#define AM2150_XMT_SKIP			0x09 -#define AM2150_RCV_NEXT			0x0A -#define AM2150_RCV_FRAME_COUNT		0x0B -#define AM2150_MACE_BANK		0x0C -#define AM2150_MACE_BASE		0x10 - -/* MACE Registers */ -#define MACE_RCVFIFO			0 -#define MACE_XMTFIFO			1 -#define MACE_XMTFC			2 -#define MACE_XMTFS			3 -#define MACE_XMTRC			4 -#define MACE_RCVFC			5 -#define MACE_RCVFS			6 -#define MACE_FIFOFC			7 -#define MACE_IR				8 -#define MACE_IMR			9 -#define MACE_PR				10 -#define MACE_BIUCC			11 -#define MACE_FIFOCC			12 -#define MACE_MACCC			13 -#define MACE_PLSCC			14 -#define MACE_PHYCC			15 -#define MACE_CHIPIDL			16 -#define MACE_CHIPIDH			17 -#define MACE_IAC			18 -/* Reserved */ -#define MACE_LADRF			20 -#define MACE_PADR			21 -/* Reserved */ -/* Reserved */ -#define MACE_MPC			24 -/* Reserved */ -#define MACE_RNTPC			26 -#define MACE_RCVCC			27 -/* Reserved */ -#define MACE_UTR			29 -#define MACE_RTR1			30 -#define MACE_RTR2			31 - -/* MACE Bit Masks */ -#define MACE_XMTRC_EXDEF		0x80 -#define MACE_XMTRC_XMTRC		0x0F - -#define MACE_XMTFS_XMTSV		0x80 -#define MACE_XMTFS_UFLO			0x40 -#define MACE_XMTFS_LCOL			0x20 -#define MACE_XMTFS_MORE			0x10 -#define MACE_XMTFS_ONE			0x08 -#define MACE_XMTFS_DEFER		0x04 -#define MACE_XMTFS_LCAR			0x02 -#define MACE_XMTFS_RTRY			0x01 - -#define MACE_RCVFS_RCVSTS		0xF000 -#define MACE_RCVFS_OFLO			0x8000 -#define MACE_RCVFS_CLSN			0x4000 -#define MACE_RCVFS_FRAM			0x2000 -#define MACE_RCVFS_FCS			0x1000 - -#define MACE_FIFOFC_RCVFC		0xF0 -#define MACE_FIFOFC_XMTFC		0x0F - -#define MACE_IR_JAB			0x80 -#define MACE_IR_BABL			0x40 -#define MACE_IR_CERR			0x20 -#define MACE_IR_RCVCCO			0x10 -#define MACE_IR_RNTPCO			0x08 -#define MACE_IR_MPCO			0x04 -#define MACE_IR_RCVINT			0x02 -#define MACE_IR_XMTINT			0x01 - -#define MACE_MACCC_PROM			0x80 -#define MACE_MACCC_DXMT2PD		0x40 -#define MACE_MACCC_EMBA			0x20 -#define MACE_MACCC_RESERVED		0x10 -#define MACE_MACCC_DRCVPA		0x08 -#define MACE_MACCC_DRCVBC		0x04 -#define MACE_MACCC_ENXMT		0x02 -#define MACE_MACCC_ENRCV		0x01 - -#define MACE_PHYCC_LNKFL		0x80 -#define MACE_PHYCC_DLNKTST		0x40 -#define MACE_PHYCC_REVPOL		0x20 -#define MACE_PHYCC_DAPC			0x10 -#define MACE_PHYCC_LRT			0x08 -#define MACE_PHYCC_ASEL			0x04 -#define MACE_PHYCC_RWAKE		0x02 -#define MACE_PHYCC_AWAKE		0x01 - -#define MACE_IAC_ADDRCHG		0x80 -#define MACE_IAC_PHYADDR		0x04 -#define MACE_IAC_LOGADDR		0x02 - -#define MACE_UTR_RTRE			0x80 -#define MACE_UTR_RTRD			0x40 -#define MACE_UTR_RPA			0x20 -#define MACE_UTR_FCOLL			0x10 -#define MACE_UTR_RCVFCSE		0x08 -#define MACE_UTR_LOOP_INCL_MENDEC	0x06 -#define MACE_UTR_LOOP_NO_MENDEC		0x04 -#define MACE_UTR_LOOP_EXTERNAL		0x02 -#define MACE_UTR_LOOP_NONE		0x00 -#define MACE_UTR_RESERVED		0x01 - -/* Switch MACE register bank (only 0 and 1 are valid) */ -#define MACEBANK(win_num) outb((win_num), ioaddr + AM2150_MACE_BANK) - -#define MACE_IMR_DEFAULT \ -  (0xFF - \ -    ( \ -      MACE_IR_CERR | \ -      MACE_IR_RCVCCO | \ -      MACE_IR_RNTPCO | \ -      MACE_IR_MPCO | \ -      MACE_IR_RCVINT | \ -      MACE_IR_XMTINT \ -    ) \ -  ) -#undef MACE_IMR_DEFAULT -#define MACE_IMR_DEFAULT 0x00 /* New statistics handling: grab everything */ - -#define TX_TIMEOUT		((400*HZ)/1000) - -/* ---------------------------------------------------------------------------- -Type Definitions ----------------------------------------------------------------------------- */ - -typedef struct _mace_statistics { -    /* MACE_XMTFS */ -    int xmtsv; -    int uflo; -    int lcol; -    int more; -    int one; -    int defer; -    int lcar; -    int rtry; - -    /* MACE_XMTRC */ -    int exdef; -    int xmtrc; - -    /* RFS1--Receive Status (RCVSTS) */ -    int oflo; -    int clsn; -    int fram; -    int fcs; - -    /* RFS2--Runt Packet Count (RNTPC) */ -    int rfs_rntpc; - -    /* RFS3--Receive Collision Count (RCVCC) */ -    int rfs_rcvcc; - -    /* MACE_IR */ -    int jab; -    int babl; -    int cerr; -    int rcvcco; -    int rntpco; -    int mpco; - -    /* MACE_MPC */ -    int mpc; - -    /* MACE_RNTPC */ -    int rntpc; - -    /* MACE_RCVCC */ -    int rcvcc; -} mace_statistics; - -typedef struct _mace_private { -	struct pcmcia_device	*p_dev; -    struct net_device_stats linux_stats; /* Linux statistics counters */ -    mace_statistics mace_stats; /* MACE chip statistics counters */ - -    /* restore_multicast_list() state variables */ -    int multicast_ladrf[MACE_LADRF_LEN]; /* Logical address filter */ -    int multicast_num_addrs; - -    char tx_free_frames; /* Number of free transmit frame buffers */ -    char tx_irq_disabled; /* MACE TX interrupt disabled */ -     -    spinlock_t bank_lock; /* Must be held if you step off bank 0 */ -} mace_private; - -/* ---------------------------------------------------------------------------- -Private Global Variables ----------------------------------------------------------------------------- */ - -static const char *if_names[]={ -    "Auto", "10baseT", "BNC", -}; - -/* ---------------------------------------------------------------------------- -Parameters -	These are the parameters that can be set during loading with -	'insmod'. ----------------------------------------------------------------------------- */ - -MODULE_DESCRIPTION("New Media PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -/* 0=auto, 1=10baseT, 2 = 10base2, default=auto */ -INT_MODULE_PARM(if_port, 0); - - -/* ---------------------------------------------------------------------------- -Function Prototypes ----------------------------------------------------------------------------- */ - -static int nmclan_config(struct pcmcia_device *link); -static void nmclan_release(struct pcmcia_device *link); - -static void nmclan_reset(struct net_device *dev); -static int mace_config(struct net_device *dev, struct ifmap *map); -static int mace_open(struct net_device *dev); -static int mace_close(struct net_device *dev); -static netdev_tx_t mace_start_xmit(struct sk_buff *skb, -					 struct net_device *dev); -static void mace_tx_timeout(struct net_device *dev); -static irqreturn_t mace_interrupt(int irq, void *dev_id); -static struct net_device_stats *mace_get_stats(struct net_device *dev); -static int mace_rx(struct net_device *dev, unsigned char RxCnt); -static void restore_multicast_list(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static const struct ethtool_ops netdev_ethtool_ops; - - -static void nmclan_detach(struct pcmcia_device *p_dev); - -static const struct net_device_ops mace_netdev_ops = { -	.ndo_open		= mace_open, -	.ndo_stop		= mace_close, -	.ndo_start_xmit		= mace_start_xmit, -	.ndo_tx_timeout		= mace_tx_timeout, -	.ndo_set_config		= mace_config, -	.ndo_get_stats		= mace_get_stats, -	.ndo_set_multicast_list	= set_multicast_list, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int nmclan_probe(struct pcmcia_device *link) -{ -    mace_private *lp; -    struct net_device *dev; - -    dev_dbg(&link->dev, "nmclan_attach()\n"); - -    /* Create new ethernet device */ -    dev = alloc_etherdev(sizeof(mace_private)); -    if (!dev) -	    return -ENOMEM; -    lp = netdev_priv(dev); -    lp->p_dev = link; -    link->priv = dev; -     -    spin_lock_init(&lp->bank_lock); -    link->resource[0]->end = 32; -    link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; -    link->config_flags |= CONF_ENABLE_IRQ; -    link->config_index = 1; -    link->config_regs = PRESENT_OPTION; - -    lp->tx_free_frames=AM2150_MAX_TX_FRAMES; - -    dev->netdev_ops = &mace_netdev_ops; -    SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); -    dev->watchdog_timeo = TX_TIMEOUT; - -    return nmclan_config(link); -} /* nmclan_attach */ - -static void nmclan_detach(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    dev_dbg(&link->dev, "nmclan_detach\n"); - -    unregister_netdev(dev); - -    nmclan_release(link); - -    free_netdev(dev); -} /* nmclan_detach */ - -/* ---------------------------------------------------------------------------- -mace_read -	Reads a MACE register.  This is bank independent; however, the -	caller must ensure that this call is not interruptable.  We are -	assuming that during normal operation, the MACE is always in -	bank 0. ----------------------------------------------------------------------------- */ -static int mace_read(mace_private *lp, unsigned int ioaddr, int reg) -{ -  int data = 0xFF; -  unsigned long flags; - -  switch (reg >> 4) { -    case 0: /* register 0-15 */ -      data = inb(ioaddr + AM2150_MACE_BASE + reg); -      break; -    case 1: /* register 16-31 */ -      spin_lock_irqsave(&lp->bank_lock, flags); -      MACEBANK(1); -      data = inb(ioaddr + AM2150_MACE_BASE + (reg & 0x0F)); -      MACEBANK(0); -      spin_unlock_irqrestore(&lp->bank_lock, flags); -      break; -  } -  return data & 0xFF; -} /* mace_read */ - -/* ---------------------------------------------------------------------------- -mace_write -	Writes to a MACE register.  This is bank independent; however, -	the caller must ensure that this call is not interruptable.  We -	are assuming that during normal operation, the MACE is always in -	bank 0. ----------------------------------------------------------------------------- */ -static void mace_write(mace_private *lp, unsigned int ioaddr, int reg, -		       int data) -{ -  unsigned long flags; - -  switch (reg >> 4) { -    case 0: /* register 0-15 */ -      outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + reg); -      break; -    case 1: /* register 16-31 */ -      spin_lock_irqsave(&lp->bank_lock, flags); -      MACEBANK(1); -      outb(data & 0xFF, ioaddr + AM2150_MACE_BASE + (reg & 0x0F)); -      MACEBANK(0); -      spin_unlock_irqrestore(&lp->bank_lock, flags); -      break; -  } -} /* mace_write */ - -/* ---------------------------------------------------------------------------- -mace_init -	Resets the MACE chip. ----------------------------------------------------------------------------- */ -static int mace_init(mace_private *lp, unsigned int ioaddr, char *enet_addr) -{ -  int i; -  int ct = 0; - -  /* MACE Software reset */ -  mace_write(lp, ioaddr, MACE_BIUCC, 1); -  while (mace_read(lp, ioaddr, MACE_BIUCC) & 0x01) { -    /* Wait for reset bit to be cleared automatically after <= 200ns */; -    if(++ct > 500) -    { -	pr_err("reset failed, card removed?\n"); -    	return -1; -    } -    udelay(1); -  } -  mace_write(lp, ioaddr, MACE_BIUCC, 0); - -  /* The Am2150 requires that the MACE FIFOs operate in burst mode. */ -  mace_write(lp, ioaddr, MACE_FIFOCC, 0x0F); - -  mace_write(lp,ioaddr, MACE_RCVFC, 0); /* Disable Auto Strip Receive */ -  mace_write(lp, ioaddr, MACE_IMR, 0xFF); /* Disable all interrupts until _open */ - -  /* -   * Bit 2-1 PORTSEL[1-0] Port Select. -   * 00 AUI/10Base-2 -   * 01 10Base-T -   * 10 DAI Port (reserved in Am2150) -   * 11 GPSI -   * For this card, only the first two are valid. -   * So, PLSCC should be set to -   * 0x00 for 10Base-2 -   * 0x02 for 10Base-T -   * Or just set ASEL in PHYCC below! -   */ -  switch (if_port) { -    case 1: -      mace_write(lp, ioaddr, MACE_PLSCC, 0x02); -      break; -    case 2: -      mace_write(lp, ioaddr, MACE_PLSCC, 0x00); -      break; -    default: -      mace_write(lp, ioaddr, MACE_PHYCC, /* ASEL */ 4); -      /* ASEL Auto Select.  When set, the PORTSEL[1-0] bits are overridden, -	 and the MACE device will automatically select the operating media -	 interface port. */ -      break; -  } - -  mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_PHYADDR); -  /* Poll ADDRCHG bit */ -  ct = 0; -  while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) -  { -  	if(++ ct > 500) -  	{ -		pr_err("ADDRCHG timeout, card removed?\n"); -  		return -1; -  	} -  } -  /* Set PADR register */ -  for (i = 0; i < ETHER_ADDR_LEN; i++) -    mace_write(lp, ioaddr, MACE_PADR, enet_addr[i]); - -  /* MAC Configuration Control Register should be written last */ -  /* Let set_multicast_list set this. */ -  /* mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); */ -  mace_write(lp, ioaddr, MACE_MACCC, 0x00); -  return 0; -} /* mace_init */ - -static int nmclan_config(struct pcmcia_device *link) -{ -  struct net_device *dev = link->priv; -  mace_private *lp = netdev_priv(dev); -  u8 *buf; -  size_t len; -  int i, ret; -  unsigned int ioaddr; - -  dev_dbg(&link->dev, "nmclan_config\n"); - -  link->io_lines = 5; -  ret = pcmcia_request_io(link); -  if (ret) -	  goto failed; -  ret = pcmcia_request_exclusive_irq(link, mace_interrupt); -  if (ret) -	  goto failed; -  ret = pcmcia_enable_device(link); -  if (ret) -	  goto failed; - -  dev->irq = link->irq; -  dev->base_addr = link->resource[0]->start; - -  ioaddr = dev->base_addr; - -  /* Read the ethernet address from the CIS. */ -  len = pcmcia_get_tuple(link, 0x80, &buf); -  if (!buf || len < ETHER_ADDR_LEN) { -	  kfree(buf); -	  goto failed; -  } -  memcpy(dev->dev_addr, buf, ETHER_ADDR_LEN); -  kfree(buf); - -  /* Verify configuration by reading the MACE ID. */ -  { -    char sig[2]; - -    sig[0] = mace_read(lp, ioaddr, MACE_CHIPIDL); -    sig[1] = mace_read(lp, ioaddr, MACE_CHIPIDH); -    if ((sig[0] == 0x40) && ((sig[1] & 0x0F) == 0x09)) { -      dev_dbg(&link->dev, "nmclan_cs configured: mace id=%x %x\n", -	    sig[0], sig[1]); -    } else { -      pr_notice("mace id not found: %x %x should be 0x40 0x?9\n", -		sig[0], sig[1]); -      return -ENODEV; -    } -  } - -  if(mace_init(lp, ioaddr, dev->dev_addr) == -1) -  	goto failed; - -  /* The if_port symbol can be set when the module is loaded */ -  if (if_port <= 2) -    dev->if_port = if_port; -  else -    pr_notice("invalid if_port requested\n"); - -  SET_NETDEV_DEV(dev, &link->dev); - -  i = register_netdev(dev); -  if (i != 0) { -    pr_notice("register_netdev() failed\n"); -    goto failed; -  } - -  netdev_info(dev, "nmclan: port %#3lx, irq %d, %s port, hw_addr %pM\n", -	      dev->base_addr, dev->irq, if_names[dev->if_port], dev->dev_addr); -  return 0; - -failed: -	nmclan_release(link); -	return -ENODEV; -} /* nmclan_config */ - -static void nmclan_release(struct pcmcia_device *link) -{ -	dev_dbg(&link->dev, "nmclan_release\n"); -	pcmcia_disable_device(link); -} - -static int nmclan_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int nmclan_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		nmclan_reset(dev); -		netif_device_attach(dev); -	} - -	return 0; -} - - -/* ---------------------------------------------------------------------------- -nmclan_reset -	Reset and restore all of the Xilinx and MACE registers. ----------------------------------------------------------------------------- */ -static void nmclan_reset(struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); - -#if RESET_XILINX -  struct pcmcia_device *link = &lp->link; -  u8 OrigCorValue; - -  /* Save original COR value */ -  pcmcia_read_config_byte(link, CISREG_COR, &OrigCorValue); - -  /* Reset Xilinx */ -  dev_dbg(&link->dev, "nmclan_reset: OrigCorValue=0x%x, resetting...\n", -	OrigCorValue); -  pcmcia_write_config_byte(link, CISREG_COR, COR_SOFT_RESET); -  /* Need to wait for 20 ms for PCMCIA to finish reset. */ - -  /* Restore original COR configuration index */ -  pcmcia_write_config_byte(link, CISREG_COR, -			  (COR_LEVEL_REQ | (OrigCorValue & COR_CONFIG_MASK))); -  /* Xilinx is now completely reset along with the MACE chip. */ -  lp->tx_free_frames=AM2150_MAX_TX_FRAMES; - -#endif /* #if RESET_XILINX */ - -  /* Xilinx is now completely reset along with the MACE chip. */ -  lp->tx_free_frames=AM2150_MAX_TX_FRAMES; - -  /* Reinitialize the MACE chip for operation. */ -  mace_init(lp, dev->base_addr, dev->dev_addr); -  mace_write(lp, dev->base_addr, MACE_IMR, MACE_IMR_DEFAULT); - -  /* Restore the multicast list and enable TX and RX. */ -  restore_multicast_list(dev); -} /* nmclan_reset */ - -/* ---------------------------------------------------------------------------- -mace_config -	[Someone tell me what this is supposed to do?  Is if_port a defined -	standard?  If so, there should be defines to indicate 1=10Base-T, -	2=10Base-2, etc. including limited automatic detection.] ----------------------------------------------------------------------------- */ -static int mace_config(struct net_device *dev, struct ifmap *map) -{ -  if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { -    if (map->port <= 2) { -      dev->if_port = map->port; -      netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); -    } else -      return -EINVAL; -  } -  return 0; -} /* mace_config */ - -/* ---------------------------------------------------------------------------- -mace_open -	Open device driver. ----------------------------------------------------------------------------- */ -static int mace_open(struct net_device *dev) -{ -  unsigned int ioaddr = dev->base_addr; -  mace_private *lp = netdev_priv(dev); -  struct pcmcia_device *link = lp->p_dev; - -  if (!pcmcia_dev_present(link)) -    return -ENODEV; - -  link->open++; - -  MACEBANK(0); - -  netif_start_queue(dev); -  nmclan_reset(dev); - -  return 0; /* Always succeed */ -} /* mace_open */ - -/* ---------------------------------------------------------------------------- -mace_close -	Closes device driver. ----------------------------------------------------------------------------- */ -static int mace_close(struct net_device *dev) -{ -  unsigned int ioaddr = dev->base_addr; -  mace_private *lp = netdev_priv(dev); -  struct pcmcia_device *link = lp->p_dev; - -  dev_dbg(&link->dev, "%s: shutting down ethercard.\n", dev->name); - -  /* Mask off all interrupts from the MACE chip. */ -  outb(0xFF, ioaddr + AM2150_MACE_BASE + MACE_IMR); - -  link->open--; -  netif_stop_queue(dev); - -  return 0; -} /* mace_close */ - -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, "PCMCIA 0x%lx", dev->base_addr); -} - -static const struct ethtool_ops netdev_ethtool_ops = { -	.get_drvinfo		= netdev_get_drvinfo, -}; - -/* ---------------------------------------------------------------------------- -mace_start_xmit -	This routine begins the packet transmit function.  When completed, -	it will generate a transmit interrupt. - -	According to /usr/src/linux/net/inet/dev.c, if _start_xmit -	returns 0, the "packet is now solely the responsibility of the -	driver."  If _start_xmit returns non-zero, the "transmission -	failed, put skb back into a list." ----------------------------------------------------------------------------- */ - -static void mace_tx_timeout(struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); -  struct pcmcia_device *link = lp->p_dev; - -  netdev_notice(dev, "transmit timed out -- "); -#if RESET_ON_TIMEOUT -  pr_cont("resetting card\n"); -  pcmcia_reset_card(link->socket); -#else /* #if RESET_ON_TIMEOUT */ -  pr_cont("NOT resetting card\n"); -#endif /* #if RESET_ON_TIMEOUT */ -  dev->trans_start = jiffies; /* prevent tx timeout */ -  netif_wake_queue(dev); -} - -static netdev_tx_t mace_start_xmit(struct sk_buff *skb, -					 struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); -  unsigned int ioaddr = dev->base_addr; - -  netif_stop_queue(dev); - -  pr_debug("%s: mace_start_xmit(length = %ld) called.\n", -	dev->name, (long)skb->len); - -#if (!TX_INTERRUPTABLE) -  /* Disable MACE TX interrupts. */ -  outb(MACE_IMR_DEFAULT | MACE_IR_XMTINT, -    ioaddr + AM2150_MACE_BASE + MACE_IMR); -  lp->tx_irq_disabled=1; -#endif /* #if (!TX_INTERRUPTABLE) */ - -  { -    /* This block must not be interrupted by another transmit request! -       mace_tx_timeout will take care of timer-based retransmissions from -       the upper layers.  The interrupt handler is guaranteed never to -       service a transmit interrupt while we are in here. -    */ - -    lp->linux_stats.tx_bytes += skb->len; -    lp->tx_free_frames--; - -    /* WARNING: Write the _exact_ number of bytes written in the header! */ -    /* Put out the word header [must be an outw()] . . . */ -    outw(skb->len, ioaddr + AM2150_XMT); -    /* . . . and the packet [may be any combination of outw() and outb()] */ -    outsw(ioaddr + AM2150_XMT, skb->data, skb->len >> 1); -    if (skb->len & 1) { -      /* Odd byte transfer */ -      outb(skb->data[skb->len-1], ioaddr + AM2150_XMT); -    } - -#if MULTI_TX -    if (lp->tx_free_frames > 0) -      netif_start_queue(dev); -#endif /* #if MULTI_TX */ -  } - -#if (!TX_INTERRUPTABLE) -  /* Re-enable MACE TX interrupts. */ -  lp->tx_irq_disabled=0; -  outb(MACE_IMR_DEFAULT, ioaddr + AM2150_MACE_BASE + MACE_IMR); -#endif /* #if (!TX_INTERRUPTABLE) */ - -  dev_kfree_skb(skb); - -  return NETDEV_TX_OK; -} /* mace_start_xmit */ - -/* ---------------------------------------------------------------------------- -mace_interrupt -	The interrupt handler. ----------------------------------------------------------------------------- */ -static irqreturn_t mace_interrupt(int irq, void *dev_id) -{ -  struct net_device *dev = (struct net_device *) dev_id; -  mace_private *lp = netdev_priv(dev); -  unsigned int ioaddr; -  int status; -  int IntrCnt = MACE_MAX_IR_ITERATIONS; - -  if (dev == NULL) { -    pr_debug("mace_interrupt(): irq 0x%X for unknown device.\n", -	  irq); -    return IRQ_NONE; -  } - -  ioaddr = dev->base_addr; - -  if (lp->tx_irq_disabled) { -    const char *msg; -    if (lp->tx_irq_disabled) -      msg = "Interrupt with tx_irq_disabled"; -    else -      msg = "Re-entering the interrupt handler"; -    netdev_notice(dev, "%s [isr=%02X, imr=%02X]\n", -		  msg, -		  inb(ioaddr + AM2150_MACE_BASE + MACE_IR), -		  inb(ioaddr + AM2150_MACE_BASE + MACE_IMR)); -    /* WARNING: MACE_IR has been read! */ -    return IRQ_NONE; -  } - -  if (!netif_device_present(dev)) { -    netdev_dbg(dev, "interrupt from dead card\n"); -    return IRQ_NONE; -  } - -  do { -    /* WARNING: MACE_IR is a READ/CLEAR port! */ -    status = inb(ioaddr + AM2150_MACE_BASE + MACE_IR); - -    pr_debug("mace_interrupt: irq 0x%X status 0x%X.\n", irq, status); - -    if (status & MACE_IR_RCVINT) { -      mace_rx(dev, MACE_MAX_RX_ITERATIONS); -    } - -    if (status & MACE_IR_XMTINT) { -      unsigned char fifofc; -      unsigned char xmtrc; -      unsigned char xmtfs; - -      fifofc = inb(ioaddr + AM2150_MACE_BASE + MACE_FIFOFC); -      if ((fifofc & MACE_FIFOFC_XMTFC)==0) { -	lp->linux_stats.tx_errors++; -	outb(0xFF, ioaddr + AM2150_XMT_SKIP); -      } - -      /* Transmit Retry Count (XMTRC, reg 4) */ -      xmtrc = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTRC); -      if (xmtrc & MACE_XMTRC_EXDEF) lp->mace_stats.exdef++; -      lp->mace_stats.xmtrc += (xmtrc & MACE_XMTRC_XMTRC); - -      if ( -        (xmtfs = inb(ioaddr + AM2150_MACE_BASE + MACE_XMTFS)) & -        MACE_XMTFS_XMTSV /* Transmit Status Valid */ -      ) { -	lp->mace_stats.xmtsv++; - -	if (xmtfs & ~MACE_XMTFS_XMTSV) { -	  if (xmtfs & MACE_XMTFS_UFLO) { -	    /* Underflow.  Indicates that the Transmit FIFO emptied before -	       the end of frame was reached. */ -	    lp->mace_stats.uflo++; -	  } -	  if (xmtfs & MACE_XMTFS_LCOL) { -	    /* Late Collision */ -	    lp->mace_stats.lcol++; -	  } -	  if (xmtfs & MACE_XMTFS_MORE) { -	    /* MORE than one retry was needed */ -	    lp->mace_stats.more++; -	  } -	  if (xmtfs & MACE_XMTFS_ONE) { -	    /* Exactly ONE retry occurred */ -	    lp->mace_stats.one++; -	  } -	  if (xmtfs & MACE_XMTFS_DEFER) { -	    /* Transmission was defered */ -	    lp->mace_stats.defer++; -	  } -	  if (xmtfs & MACE_XMTFS_LCAR) { -	    /* Loss of carrier */ -	    lp->mace_stats.lcar++; -	  } -	  if (xmtfs & MACE_XMTFS_RTRY) { -	    /* Retry error: transmit aborted after 16 attempts */ -	    lp->mace_stats.rtry++; -	  } -        } /* if (xmtfs & ~MACE_XMTFS_XMTSV) */ - -      } /* if (xmtfs & MACE_XMTFS_XMTSV) */ - -      lp->linux_stats.tx_packets++; -      lp->tx_free_frames++; -      netif_wake_queue(dev); -    } /* if (status & MACE_IR_XMTINT) */ - -    if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) { -      if (status & MACE_IR_JAB) { -        /* Jabber Error.  Excessive transmit duration (20-150ms). */ -        lp->mace_stats.jab++; -      } -      if (status & MACE_IR_BABL) { -        /* Babble Error.  >1518 bytes transmitted. */ -        lp->mace_stats.babl++; -      } -      if (status & MACE_IR_CERR) { -	/* Collision Error.  CERR indicates the absence of the -	   Signal Quality Error Test message after a packet -	   transmission. */ -        lp->mace_stats.cerr++; -      } -      if (status & MACE_IR_RCVCCO) { -        /* Receive Collision Count Overflow; */ -        lp->mace_stats.rcvcco++; -      } -      if (status & MACE_IR_RNTPCO) { -        /* Runt Packet Count Overflow */ -        lp->mace_stats.rntpco++; -      } -      if (status & MACE_IR_MPCO) { -        /* Missed Packet Count Overflow */ -        lp->mace_stats.mpco++; -      } -    } /* if (status & ~MACE_IMR_DEFAULT & ~MACE_IR_RCVINT & ~MACE_IR_XMTINT) */ - -  } while ((status & ~MACE_IMR_DEFAULT) && (--IntrCnt)); - -  return IRQ_HANDLED; -} /* mace_interrupt */ - -/* ---------------------------------------------------------------------------- -mace_rx -	Receives packets. ----------------------------------------------------------------------------- */ -static int mace_rx(struct net_device *dev, unsigned char RxCnt) -{ -  mace_private *lp = netdev_priv(dev); -  unsigned int ioaddr = dev->base_addr; -  unsigned char rx_framecnt; -  unsigned short rx_status; - -  while ( -    ((rx_framecnt = inb(ioaddr + AM2150_RCV_FRAME_COUNT)) > 0) && -    (rx_framecnt <= 12) && /* rx_framecnt==0xFF if card is extracted. */ -    (RxCnt--) -  ) { -    rx_status = inw(ioaddr + AM2150_RCV); - -    pr_debug("%s: in mace_rx(), framecnt 0x%X, rx_status" -	  " 0x%X.\n", dev->name, rx_framecnt, rx_status); - -    if (rx_status & MACE_RCVFS_RCVSTS) { /* Error, update stats. */ -      lp->linux_stats.rx_errors++; -      if (rx_status & MACE_RCVFS_OFLO) { -        lp->mace_stats.oflo++; -      } -      if (rx_status & MACE_RCVFS_CLSN) { -        lp->mace_stats.clsn++; -      } -      if (rx_status & MACE_RCVFS_FRAM) { -	lp->mace_stats.fram++; -      } -      if (rx_status & MACE_RCVFS_FCS) { -        lp->mace_stats.fcs++; -      } -    } else { -      short pkt_len = (rx_status & ~MACE_RCVFS_RCVSTS) - 4; -        /* Auto Strip is off, always subtract 4 */ -      struct sk_buff *skb; - -      lp->mace_stats.rfs_rntpc += inb(ioaddr + AM2150_RCV); -        /* runt packet count */ -      lp->mace_stats.rfs_rcvcc += inb(ioaddr + AM2150_RCV); -        /* rcv collision count */ - -      pr_debug("    receiving packet size 0x%X rx_status" -	    " 0x%X.\n", pkt_len, rx_status); - -      skb = dev_alloc_skb(pkt_len+2); - -      if (skb != NULL) { -	skb_reserve(skb, 2); -	insw(ioaddr + AM2150_RCV, skb_put(skb, pkt_len), pkt_len>>1); -	if (pkt_len & 1) -	    *(skb_tail_pointer(skb) - 1) = inb(ioaddr + AM2150_RCV); -	skb->protocol = eth_type_trans(skb, dev); -	 -	netif_rx(skb); /* Send the packet to the upper (protocol) layers. */ - -	lp->linux_stats.rx_packets++; -	lp->linux_stats.rx_bytes += pkt_len; -	outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ -	continue; -      } else { -	pr_debug("%s: couldn't allocate a sk_buff of size" -	      " %d.\n", dev->name, pkt_len); -	lp->linux_stats.rx_dropped++; -      } -    } -    outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ -  } /* while */ - -  return 0; -} /* mace_rx */ - -/* ---------------------------------------------------------------------------- -pr_linux_stats ----------------------------------------------------------------------------- */ -static void pr_linux_stats(struct net_device_stats *pstats) -{ -  pr_debug("pr_linux_stats\n"); -  pr_debug(" rx_packets=%-7ld        tx_packets=%ld\n", -	(long)pstats->rx_packets, (long)pstats->tx_packets); -  pr_debug(" rx_errors=%-7ld         tx_errors=%ld\n", -	(long)pstats->rx_errors, (long)pstats->tx_errors); -  pr_debug(" rx_dropped=%-7ld        tx_dropped=%ld\n", -	(long)pstats->rx_dropped, (long)pstats->tx_dropped); -  pr_debug(" multicast=%-7ld         collisions=%ld\n", -	(long)pstats->multicast, (long)pstats->collisions); - -  pr_debug(" rx_length_errors=%-7ld  rx_over_errors=%ld\n", -	(long)pstats->rx_length_errors, (long)pstats->rx_over_errors); -  pr_debug(" rx_crc_errors=%-7ld     rx_frame_errors=%ld\n", -	(long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors); -  pr_debug(" rx_fifo_errors=%-7ld    rx_missed_errors=%ld\n", -	(long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors); - -  pr_debug(" tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n", -	(long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors); -  pr_debug(" tx_fifo_errors=%-7ld    tx_heartbeat_errors=%ld\n", -	(long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors); -  pr_debug(" tx_window_errors=%ld\n", -	(long)pstats->tx_window_errors); -} /* pr_linux_stats */ - -/* ---------------------------------------------------------------------------- -pr_mace_stats ----------------------------------------------------------------------------- */ -static void pr_mace_stats(mace_statistics *pstats) -{ -  pr_debug("pr_mace_stats\n"); - -  pr_debug(" xmtsv=%-7d             uflo=%d\n", -	pstats->xmtsv, pstats->uflo); -  pr_debug(" lcol=%-7d              more=%d\n", -	pstats->lcol, pstats->more); -  pr_debug(" one=%-7d               defer=%d\n", -	pstats->one, pstats->defer); -  pr_debug(" lcar=%-7d              rtry=%d\n", -	pstats->lcar, pstats->rtry); - -  /* MACE_XMTRC */ -  pr_debug(" exdef=%-7d             xmtrc=%d\n", -	pstats->exdef, pstats->xmtrc); - -  /* RFS1--Receive Status (RCVSTS) */ -  pr_debug(" oflo=%-7d              clsn=%d\n", -	pstats->oflo, pstats->clsn); -  pr_debug(" fram=%-7d              fcs=%d\n", -	pstats->fram, pstats->fcs); - -  /* RFS2--Runt Packet Count (RNTPC) */ -  /* RFS3--Receive Collision Count (RCVCC) */ -  pr_debug(" rfs_rntpc=%-7d         rfs_rcvcc=%d\n", -	pstats->rfs_rntpc, pstats->rfs_rcvcc); - -  /* MACE_IR */ -  pr_debug(" jab=%-7d               babl=%d\n", -	pstats->jab, pstats->babl); -  pr_debug(" cerr=%-7d              rcvcco=%d\n", -	pstats->cerr, pstats->rcvcco); -  pr_debug(" rntpco=%-7d            mpco=%d\n", -	pstats->rntpco, pstats->mpco); - -  /* MACE_MPC */ -  pr_debug(" mpc=%d\n", pstats->mpc); - -  /* MACE_RNTPC */ -  pr_debug(" rntpc=%d\n", pstats->rntpc); - -  /* MACE_RCVCC */ -  pr_debug(" rcvcc=%d\n", pstats->rcvcc); - -} /* pr_mace_stats */ - -/* ---------------------------------------------------------------------------- -update_stats -	Update statistics.  We change to register window 1, so this -	should be run single-threaded if the device is active. This is -	expected to be a rare operation, and it's simpler for the rest -	of the driver to assume that window 0 is always valid rather -	than use a special window-state variable. - -	oflo & uflo should _never_ occur since it would mean the Xilinx -	was not able to transfer data between the MACE FIFO and the -	card's SRAM fast enough.  If this happens, something is -	seriously wrong with the hardware. ----------------------------------------------------------------------------- */ -static void update_stats(unsigned int ioaddr, struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); - -  lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC); -  lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC); -  lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC); -  /* At this point, mace_stats is fully updated for this call. -     We may now update the linux_stats. */ - -  /* The MACE has no equivalent for linux_stats field which are commented -     out. */ - -  /* lp->linux_stats.multicast; */ -  lp->linux_stats.collisions =  -    lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc; -    /* Collision: The MACE may retry sending a packet 15 times -       before giving up.  The retry count is in XMTRC. -       Does each retry constitute a collision? -       If so, why doesn't the RCVCC record these collisions? */ - -  /* detailed rx_errors: */ -  lp->linux_stats.rx_length_errors =  -    lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc; -  /* lp->linux_stats.rx_over_errors */ -  lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs; -  lp->linux_stats.rx_frame_errors = lp->mace_stats.fram; -  lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo; -  lp->linux_stats.rx_missed_errors =  -    lp->mace_stats.mpco * 256 + lp->mace_stats.mpc; - -  /* detailed tx_errors */ -  lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry; -  lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar; -    /* LCAR usually results from bad cabling. */ -  lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo; -  lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr; -  /* lp->linux_stats.tx_window_errors; */ -} /* update_stats */ - -/* ---------------------------------------------------------------------------- -mace_get_stats -	Gathers ethernet statistics from the MACE chip. ----------------------------------------------------------------------------- */ -static struct net_device_stats *mace_get_stats(struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); - -  update_stats(dev->base_addr, dev); - -  pr_debug("%s: updating the statistics.\n", dev->name); -  pr_linux_stats(&lp->linux_stats); -  pr_mace_stats(&lp->mace_stats); - -  return &lp->linux_stats; -} /* net_device_stats */ - -/* ---------------------------------------------------------------------------- -updateCRC -	Modified from Am79C90 data sheet. ----------------------------------------------------------------------------- */ - -#ifdef BROKEN_MULTICAST - -static void updateCRC(int *CRC, int bit) -{ -  int poly[]={ -    1,1,1,0, 1,1,0,1, -    1,0,1,1, 1,0,0,0, -    1,0,0,0, 0,0,1,1, -    0,0,1,0, 0,0,0,0 -  }; /* CRC polynomial.  poly[n] = coefficient of the x**n term of the -	CRC generator polynomial. */ - -  int j; - -  /* shift CRC and control bit (CRC[32]) */ -  for (j = 32; j > 0; j--) -    CRC[j] = CRC[j-1]; -  CRC[0] = 0; - -  /* If bit XOR(control bit) = 1, set CRC = CRC XOR polynomial. */ -  if (bit ^ CRC[32]) -    for (j = 0; j < 32; j++) -      CRC[j] ^= poly[j]; -} /* updateCRC */ - -/* ---------------------------------------------------------------------------- -BuildLAF -	Build logical address filter. -	Modified from Am79C90 data sheet. - -Input -	ladrf: logical address filter (contents initialized to 0) -	adr: ethernet address ----------------------------------------------------------------------------- */ -static void BuildLAF(int *ladrf, int *adr) -{ -  int CRC[33]={1}; /* CRC register, 1 word/bit + extra control bit */ - -  int i, byte; /* temporary array indices */ -  int hashcode; /* the output object */ - -  CRC[32]=0; - -  for (byte = 0; byte < 6; byte++) -    for (i = 0; i < 8; i++) -      updateCRC(CRC, (adr[byte] >> i) & 1); - -  hashcode = 0; -  for (i = 0; i < 6; i++) -    hashcode = (hashcode << 1) + CRC[i]; - -  byte = hashcode >> 3; -  ladrf[byte] |= (1 << (hashcode & 7)); - -#ifdef PCMCIA_DEBUG -  if (0) -    printk(KERN_DEBUG "    adr =%pM\n", adr); -  printk(KERN_DEBUG "    hashcode = %d(decimal), ladrf[0:63] =", hashcode); -  for (i = 0; i < 8; i++) -    pr_cont(" %02X", ladrf[i]); -  pr_cont("\n"); -#endif -} /* BuildLAF */ - -/* ---------------------------------------------------------------------------- -restore_multicast_list -	Restores the multicast filter for MACE chip to the last -	set_multicast_list() call. - -Input -	multicast_num_addrs -	multicast_ladrf[] ----------------------------------------------------------------------------- */ -static void restore_multicast_list(struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); -  int num_addrs = lp->multicast_num_addrs; -  int *ladrf = lp->multicast_ladrf; -  unsigned int ioaddr = dev->base_addr; -  int i; - -  pr_debug("%s: restoring Rx mode to %d addresses.\n", -	dev->name, num_addrs); - -  if (num_addrs > 0) { - -    pr_debug("Attempt to restore multicast list detected.\n"); - -    mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR); -    /* Poll ADDRCHG bit */ -    while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) -      ; -    /* Set LADRF register */ -    for (i = 0; i < MACE_LADRF_LEN; i++) -      mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]); - -    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL); -    mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); - -  } else if (num_addrs < 0) { - -    /* Promiscuous mode: receive all packets */ -    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); -    mace_write(lp, ioaddr, MACE_MACCC, -      MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV -    ); - -  } else { - -    /* Normal mode */ -    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); -    mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); - -  } -} /* restore_multicast_list */ - -/* ---------------------------------------------------------------------------- -set_multicast_list -	Set or clear the multicast filter for this adaptor. - -Input -	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. -Output -	multicast_num_addrs -	multicast_ladrf[] ----------------------------------------------------------------------------- */ - -static void set_multicast_list(struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); -  int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */ -  struct netdev_hw_addr *ha; - -#ifdef PCMCIA_DEBUG -  { -    static int old; -    if (netdev_mc_count(dev) != old) { -      old = netdev_mc_count(dev); -      pr_debug("%s: setting Rx mode to %d addresses.\n", -	    dev->name, old); -    } -  } -#endif - -  /* Set multicast_num_addrs. */ -  lp->multicast_num_addrs = netdev_mc_count(dev); - -  /* Set multicast_ladrf. */ -  if (num_addrs > 0) { -    /* Calculate multicast logical address filter */ -    memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); -    netdev_for_each_mc_addr(ha, dev) { -      memcpy(adr, ha->addr, ETHER_ADDR_LEN); -      BuildLAF(lp->multicast_ladrf, adr); -    } -  } - -  restore_multicast_list(dev); - -} /* set_multicast_list */ - -#endif /* BROKEN_MULTICAST */ - -static void restore_multicast_list(struct net_device *dev) -{ -  unsigned int ioaddr = dev->base_addr; -  mace_private *lp = netdev_priv(dev); - -  pr_debug("%s: restoring Rx mode to %d addresses.\n", dev->name, -	lp->multicast_num_addrs); - -  if (dev->flags & IFF_PROMISC) { -    /* Promiscuous mode: receive all packets */ -    mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); -    mace_write(lp, ioaddr, MACE_MACCC, -      MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV -    ); -  } else { -    /* Normal mode */ -    mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); -    mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); -  } -} /* restore_multicast_list */ - -static void set_multicast_list(struct net_device *dev) -{ -  mace_private *lp = netdev_priv(dev); - -#ifdef PCMCIA_DEBUG -  { -    static int old; -    if (netdev_mc_count(dev) != old) { -      old = netdev_mc_count(dev); -      pr_debug("%s: setting Rx mode to %d addresses.\n", -	    dev->name, old); -    } -  } -#endif - -  lp->multicast_num_addrs = netdev_mc_count(dev); -  restore_multicast_list(dev); - -} /* set_multicast_list */ - -static struct pcmcia_device_id nmclan_ids[] = { -	PCMCIA_DEVICE_PROD_ID12("New Media Corporation", "Ethernet", 0x085a850b, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID12("Portable Add-ons", "Ethernet+", 0xebf1d60, 0xad673aaf), -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, nmclan_ids); - -static struct pcmcia_driver nmclan_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "nmclan_cs", -	.probe		= nmclan_probe, -	.remove		= nmclan_detach, -	.id_table       = nmclan_ids, -	.suspend	= nmclan_suspend, -	.resume		= nmclan_resume, -}; - -static int __init init_nmclan_cs(void) -{ -	return pcmcia_register_driver(&nmclan_cs_driver); -} - -static void __exit exit_nmclan_cs(void) -{ -	pcmcia_unregister_driver(&nmclan_cs_driver); -} - -module_init(init_nmclan_cs); -module_exit(exit_nmclan_cs); diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c deleted file mode 100644 index d05c44692f0..00000000000 --- a/drivers/net/pcmcia/pcnet_cs.c +++ /dev/null @@ -1,1710 +0,0 @@ -/*====================================================================== - -    A PCMCIA ethernet driver for NS8390-based cards - -    This driver supports the D-Link DE-650 and Linksys EthernetCard -    cards, the newer D-Link and Linksys combo cards, Accton EN2212 -    cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory -    mode, and the IBM Credit Card Adapter, the NE4100, the Thomas -    Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory -    mode.  It will also handle the Socket EA card in either mode. - -    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net - -    pcnet_cs.c 1.153 2003/11/09 18:53:09 - -    The network driver code is based on Donald Becker's NE2000 code: - -    Written 1992,1993 by Donald Becker. -    Copyright 1993 United States Government as represented by the -    Director, National Security Agency.  This software may be used and -    distributed according to the terms of the GNU General Public License, -    incorporated herein by reference. -    Donald Becker may be reached at becker@scyld.com - -    Based also on Keith Moore's changes to Don Becker's code, for IBM -    CCAE support.  Drivers merged back together, and shared-memory -    Socket EA support added, by Ken Raeburn, September 1995. - -======================================================================*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/delay.h> -#include <linux/netdevice.h> -#include <linux/log2.h> -#include <linux/etherdevice.h> -#include <linux/mii.h> -#include "../8390.h" - -#include <pcmcia/cistpl.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> -#include <pcmcia/cisreg.h> - -#include <asm/io.h> -#include <asm/system.h> -#include <asm/byteorder.h> -#include <asm/uaccess.h> - -#define PCNET_CMD	0x00 -#define PCNET_DATAPORT	0x10	/* NatSemi-defined port window offset. */ -#define PCNET_RESET	0x1f	/* Issue a read to reset, a write to clear. */ -#define PCNET_MISC	0x18	/* For IBM CCAE and Socket EA cards */ - -#define PCNET_START_PG	0x40	/* First page of TX buffer */ -#define PCNET_STOP_PG	0x80	/* Last page +1 of RX ring */ - -/* Socket EA cards have a larger packet buffer */ -#define SOCKET_START_PG	0x01 -#define SOCKET_STOP_PG	0xff - -#define PCNET_RDC_TIMEOUT (2*HZ/100)	/* Max wait in jiffies for Tx RDC */ - -static const char *if_names[] = { "auto", "10baseT", "10base2"}; - - -/*====================================================================*/ - -/* Module parameters */ - -MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>"); -MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -INT_MODULE_PARM(if_port,	1);	/* Transceiver type */ -INT_MODULE_PARM(use_big_buf,	1);	/* use 64K packet buffer? */ -INT_MODULE_PARM(mem_speed,	0);	/* shared mem speed, in ns */ -INT_MODULE_PARM(delay_output,	0);	/* pause after xmit? */ -INT_MODULE_PARM(delay_time,	4);	/* in usec */ -INT_MODULE_PARM(use_shmem,	-1);	/* use shared memory? */ -INT_MODULE_PARM(full_duplex,	0);	/* full duplex? */ - -/* Ugh!  Let the user hardwire the hardware address for queer cards */ -static int hw_addr[6] = { 0, /* ... */ }; -module_param_array(hw_addr, int, NULL, 0); - -/*====================================================================*/ - -static void mii_phy_probe(struct net_device *dev); -static int pcnet_config(struct pcmcia_device *link); -static void pcnet_release(struct pcmcia_device *link); -static int pcnet_open(struct net_device *dev); -static int pcnet_close(struct net_device *dev); -static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static irqreturn_t ei_irq_wrapper(int irq, void *dev_id); -static void ei_watchdog(u_long arg); -static void pcnet_reset_8390(struct net_device *dev); -static int set_config(struct net_device *dev, struct ifmap *map); -static int setup_shmem_window(struct pcmcia_device *link, int start_pg, -			      int stop_pg, int cm_offset); -static int setup_dma_config(struct pcmcia_device *link, int start_pg, -			    int stop_pg); - -static void pcnet_detach(struct pcmcia_device *p_dev); - -/*====================================================================*/ - -typedef struct hw_info_t { -    u_int	offset; -    u_char	a0, a1, a2; -    u_int	flags; -} hw_info_t; - -#define DELAY_OUTPUT	0x01 -#define HAS_MISC_REG	0x02 -#define USE_BIG_BUF	0x04 -#define HAS_IBM_MISC	0x08 -#define IS_DL10019	0x10 -#define IS_DL10022	0x20 -#define HAS_MII		0x40 -#define USE_SHMEM	0x80	/* autodetected */ - -#define AM79C9XX_HOME_PHY	0x00006B90  /* HomePNA PHY */ -#define AM79C9XX_ETH_PHY	0x00006B70  /* 10baseT PHY */ -#define MII_PHYID_REV_MASK	0xfffffff0 -#define MII_PHYID_REG1		0x02 -#define MII_PHYID_REG2		0x03 - -static hw_info_t hw_info[] = { -    { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT }, -    { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 }, -    { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 }, -    { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94, -      DELAY_OUTPUT | HAS_IBM_MISC }, -    { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 }, -    { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 }, -    { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 }, -    { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 }, -    { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 }, -    { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 }, -    { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 }, -    { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 }, -    { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 }, -    { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 }, -    { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 }, -    { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 }, -    { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 }, -    { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 }, -    { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45, -      HAS_MISC_REG | HAS_IBM_MISC }, -    { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 }, -    { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 }, -    { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 }, -    { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b, -      DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF }, -    { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 }, -    { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 }, -    { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 }, -    { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 }, -    { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 } -}; - -#define NR_INFO		ARRAY_SIZE(hw_info) - -static hw_info_t default_info = { 0, 0, 0, 0, 0 }; -static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII }; -static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII }; - -typedef struct pcnet_dev_t { -	struct pcmcia_device	*p_dev; -    u_int		flags; -    void		__iomem *base; -    struct timer_list	watchdog; -    int			stale, fast_poll; -    u_char		phy_id; -    u_char		eth_phy, pna_phy; -    u_short		link_status; -    u_long		mii_reset; -} pcnet_dev_t; - -static inline pcnet_dev_t *PRIV(struct net_device *dev) -{ -	char *p = netdev_priv(dev); -	return (pcnet_dev_t *)(p + sizeof(struct ei_device)); -} - -static const struct net_device_ops pcnet_netdev_ops = { -	.ndo_open		= pcnet_open, -	.ndo_stop		= pcnet_close, -	.ndo_set_config		= set_config, -	.ndo_start_xmit 	= ei_start_xmit, -	.ndo_get_stats		= ei_get_stats, -	.ndo_do_ioctl 		= ei_ioctl, -	.ndo_set_multicast_list = ei_set_multicast_list, -	.ndo_tx_timeout 	= ei_tx_timeout, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -#ifdef CONFIG_NET_POLL_CONTROLLER -	.ndo_poll_controller 	= ei_poll, -#endif -}; - -static int pcnet_probe(struct pcmcia_device *link) -{ -    pcnet_dev_t *info; -    struct net_device *dev; - -    dev_dbg(&link->dev, "pcnet_attach()\n"); - -    /* Create new ethernet device */ -    dev = __alloc_ei_netdev(sizeof(pcnet_dev_t)); -    if (!dev) return -ENOMEM; -    info = PRIV(dev); -    info->p_dev = link; -    link->priv = dev; - -    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - -    dev->netdev_ops = &pcnet_netdev_ops; - -    return pcnet_config(link); -} /* pcnet_attach */ - -static void pcnet_detach(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	dev_dbg(&link->dev, "pcnet_detach\n"); - -	unregister_netdev(dev); - -	pcnet_release(link); - -	free_netdev(dev); -} /* pcnet_detach */ - -/*====================================================================== - -    This probes for a card's hardware address, for card types that -    encode this information in their CIS. - -======================================================================*/ - -static hw_info_t *get_hwinfo(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    u_char __iomem *base, *virt; -    int i, j; - -    /* Allocate a small memory window */ -    link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; -    link->resource[2]->start = 0; link->resource[2]->end = 0; -    i = pcmcia_request_window(link, link->resource[2], 0); -    if (i != 0) -	return NULL; - -    virt = ioremap(link->resource[2]->start, -	    resource_size(link->resource[2])); -    for (i = 0; i < NR_INFO; i++) { -	pcmcia_map_mem_page(link, link->resource[2], -		hw_info[i].offset & ~(resource_size(link->resource[2])-1)); -	base = &virt[hw_info[i].offset & (resource_size(link->resource[2])-1)]; -	if ((readb(base+0) == hw_info[i].a0) && -	    (readb(base+2) == hw_info[i].a1) && -	    (readb(base+4) == hw_info[i].a2)) { -		for (j = 0; j < 6; j++) -		    dev->dev_addr[j] = readb(base + (j<<1)); -		break; -	} -    } - -    iounmap(virt); -    j = pcmcia_release_window(link, link->resource[2]); -    return (i < NR_INFO) ? hw_info+i : NULL; -} /* get_hwinfo */ - -/*====================================================================== - -    This probes for a card's hardware address by reading the PROM. -    It checks the address against a list of known types, then falls -    back to a simple NE2000 clone signature check. - -======================================================================*/ - -static hw_info_t *get_prom(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    unsigned int ioaddr = dev->base_addr; -    u_char prom[32]; -    int i, j; - -    /* This is lifted straight from drivers/net/ne.c */ -    struct { -	u_char value, offset; -    } program_seq[] = { -	{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ -	{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */ -	{0x00,	EN0_RCNTLO},	/* Clear the count regs. */ -	{0x00,	EN0_RCNTHI}, -	{0x00,	EN0_IMR},	/* Mask completion irq. */ -	{0xFF,	EN0_ISR}, -	{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */ -	{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */ -	{32,	EN0_RCNTLO}, -	{0x00,	EN0_RCNTHI}, -	{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */ -	{0x00,	EN0_RSARHI}, -	{E8390_RREAD+E8390_START, E8390_CMD}, -    }; - -    pcnet_reset_8390(dev); -    mdelay(10); - -    for (i = 0; i < ARRAY_SIZE(program_seq); i++) -	outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); - -    for (i = 0; i < 32; i++) -	prom[i] = inb(ioaddr + PCNET_DATAPORT); -    for (i = 0; i < NR_INFO; i++) { -	if ((prom[0] == hw_info[i].a0) && -	    (prom[2] == hw_info[i].a1) && -	    (prom[4] == hw_info[i].a2)) -	    break; -    } -    if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) { -	for (j = 0; j < 6; j++) -	    dev->dev_addr[j] = prom[j<<1]; -	return (i < NR_INFO) ? hw_info+i : &default_info; -    } -    return NULL; -} /* get_prom */ - -/*====================================================================== - -    For DL10019 based cards, like the Linksys EtherFast - -======================================================================*/ - -static hw_info_t *get_dl10019(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    int i; -    u_char sum; - -    for (sum = 0, i = 0x14; i < 0x1c; i++) -	sum += inb_p(dev->base_addr + i); -    if (sum != 0xff) -	return NULL; -    for (i = 0; i < 6; i++) -	dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i); -    i = inb(dev->base_addr + 0x1f); -    return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info; -} - -/*====================================================================== - -    For Asix AX88190 based cards - -======================================================================*/ - -static hw_info_t *get_ax88190(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    unsigned int ioaddr = dev->base_addr; -    int i, j; - -    /* Not much of a test, but the alternatives are messy */ -    if (link->config_base != 0x03c0) -	return NULL; - -    outb_p(0x01, ioaddr + EN0_DCFG);	/* Set word-wide access. */ -    outb_p(0x00, ioaddr + EN0_RSARLO);	/* DMA starting at 0x0400. */ -    outb_p(0x04, ioaddr + EN0_RSARHI); -    outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD); - -    for (i = 0; i < 6; i += 2) { -	j = inw(ioaddr + PCNET_DATAPORT); -	dev->dev_addr[i] = j & 0xff; -	dev->dev_addr[i+1] = j >> 8; -    } -    return NULL; -} - -/*====================================================================== - -    This should be totally unnecessary... but when we can't figure -    out the hardware address any other way, we'll let the user hard -    wire it when the module is initialized. - -======================================================================*/ - -static hw_info_t *get_hwired(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    int i; - -    for (i = 0; i < 6; i++) -	if (hw_addr[i] != 0) break; -    if (i == 6) -	return NULL; - -    for (i = 0; i < 6; i++) -	dev->dev_addr[i] = hw_addr[i]; - -    return &default_info; -} /* get_hwired */ - -static int try_io_port(struct pcmcia_device *link) -{ -    int j, ret; -    link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; -    link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; -    if (link->resource[0]->end == 32) { -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; -	if (link->resource[1]->end > 0) { -	    /* for master/slave multifunction cards */ -	    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -	} -    } else { -	/* This should be two 16-port windows */ -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8; -	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16; -    } -    if (link->resource[0]->start == 0) { -	for (j = 0; j < 0x400; j += 0x20) { -	    link->resource[0]->start = j ^ 0x300; -	    link->resource[1]->start = (j ^ 0x300) + 0x10; -	    link->io_lines = 16; -	    ret = pcmcia_request_io(link); -	    if (ret == 0) -		    return ret; -	} -	return ret; -    } else { -	return pcmcia_request_io(link); -    } -} - -static int pcnet_confcheck(struct pcmcia_device *p_dev, void *priv_data) -{ -	int *priv = priv_data; -	int try = (*priv & 0x1); - -	*priv &= (p_dev->resource[2]->end >= 0x4000) ? 0x10 : ~0x10; - -	if (p_dev->config_index == 0) -		return -EINVAL; - -	if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32) -		return -EINVAL; - -	if (try) -		p_dev->io_lines = 16; -	return try_io_port(p_dev); -} - -static hw_info_t *pcnet_try_config(struct pcmcia_device *link, -				   int *has_shmem, int try) -{ -	struct net_device *dev = link->priv; -	hw_info_t *local_hw_info; -	pcnet_dev_t *info = PRIV(dev); -	int priv = try; -	int ret; - -	ret = pcmcia_loop_config(link, pcnet_confcheck, &priv); -	if (ret) { -		dev_warn(&link->dev, "no useable port range found\n"); -		return NULL; -	} -	*has_shmem = (priv & 0x10); - -	if (!link->irq) -		return NULL; - -	if (resource_size(link->resource[1]) == 8) -		link->config_flags |= CONF_ENABLE_SPKR; - -	if ((link->manf_id == MANFID_IBM) && -	    (link->card_id == PRODID_IBM_HOME_AND_AWAY)) -		link->config_index |= 0x10; - -	ret = pcmcia_enable_device(link); -	if (ret) -		return NULL; - -	dev->irq = link->irq; -	dev->base_addr = link->resource[0]->start; - -	if (info->flags & HAS_MISC_REG) { -		if ((if_port == 1) || (if_port == 2)) -			dev->if_port = if_port; -		else -			dev_notice(&link->dev, "invalid if_port requested\n"); -	} else -		dev->if_port = 0; - -	if ((link->config_base == 0x03c0) && -	    (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) { -		dev_info(&link->dev, -			"this is an AX88190 card - use axnet_cs instead.\n"); -		return NULL; -	} - -	local_hw_info = get_hwinfo(link); -	if (!local_hw_info) -		local_hw_info = get_prom(link); -	if (!local_hw_info) -		local_hw_info = get_dl10019(link); -	if (!local_hw_info) -		local_hw_info = get_ax88190(link); -	if (!local_hw_info) -		local_hw_info = get_hwired(link); - -	return local_hw_info; -} - -static int pcnet_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    pcnet_dev_t *info = PRIV(dev); -    int start_pg, stop_pg, cm_offset; -    int has_shmem = 0; -    hw_info_t *local_hw_info; - -    dev_dbg(&link->dev, "pcnet_config\n"); - -    local_hw_info = pcnet_try_config(link, &has_shmem, 0); -    if (!local_hw_info) { -	    /* check whether forcing io_lines to 16 helps... */ -	    pcmcia_disable_device(link); -	    local_hw_info = pcnet_try_config(link, &has_shmem, 1); -	    if (local_hw_info == NULL) { -		    dev_notice(&link->dev, "unable to read hardware net" -			    " address for io base %#3lx\n", dev->base_addr); -		    goto failed; -	    } -    } - -    info->flags = local_hw_info->flags; -    /* Check for user overrides */ -    info->flags |= (delay_output) ? DELAY_OUTPUT : 0; -    if ((link->manf_id == MANFID_SOCKET) && -	((link->card_id == PRODID_SOCKET_LPE) || -	 (link->card_id == PRODID_SOCKET_LPE_CF) || -	 (link->card_id == PRODID_SOCKET_EIO))) -	info->flags &= ~USE_BIG_BUF; -    if (!use_big_buf) -	info->flags &= ~USE_BIG_BUF; - -    if (info->flags & USE_BIG_BUF) { -	start_pg = SOCKET_START_PG; -	stop_pg = SOCKET_STOP_PG; -	cm_offset = 0x10000; -    } else { -	start_pg = PCNET_START_PG; -	stop_pg = PCNET_STOP_PG; -	cm_offset = 0; -    } - -    /* has_shmem is ignored if use_shmem != -1 */ -    if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) || -	(setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0)) -	setup_dma_config(link, start_pg, stop_pg); - -    ei_status.name = "NE2000"; -    ei_status.word16 = 1; -    ei_status.reset_8390 = pcnet_reset_8390; - -    if (info->flags & (IS_DL10019|IS_DL10022)) -	mii_phy_probe(dev); - -    SET_NETDEV_DEV(dev, &link->dev); - -    if (register_netdev(dev) != 0) { -	pr_notice("register_netdev() failed\n"); -	goto failed; -    } - -    if (info->flags & (IS_DL10019|IS_DL10022)) { -	u_char id = inb(dev->base_addr + 0x1a); -	netdev_info(dev, "NE2000 (DL100%d rev %02x): ", -	       (info->flags & IS_DL10022) ? 22 : 19, id); -	if (info->pna_phy) -	    pr_cont("PNA, "); -    } else { -	netdev_info(dev, "NE2000 Compatible: "); -    } -    pr_cont("io %#3lx, irq %d,", dev->base_addr, dev->irq); -    if (info->flags & USE_SHMEM) -	pr_cont(" mem %#5lx,", dev->mem_start); -    if (info->flags & HAS_MISC_REG) -	pr_cont(" %s xcvr,", if_names[dev->if_port]); -    pr_cont(" hw_addr %pM\n", dev->dev_addr); -    return 0; - -failed: -    pcnet_release(link); -    return -ENODEV; -} /* pcnet_config */ - -static void pcnet_release(struct pcmcia_device *link) -{ -	pcnet_dev_t *info = PRIV(link->priv); - -	dev_dbg(&link->dev, "pcnet_release\n"); - -	if (info->flags & USE_SHMEM) -		iounmap(info->base); - -	pcmcia_disable_device(link); -} - -static int pcnet_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int pcnet_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		pcnet_reset_8390(dev); -		NS8390_init(dev, 1); -		netif_device_attach(dev); -	} - -	return 0; -} - - -/*====================================================================== - -    MII interface support for DL10019 and DL10022 based cards - -    On the DL10019, the MII IO direction bit is 0x10; on the DL10022 -    it is 0x20.  Setting both bits seems to work on both card types. - -======================================================================*/ - -#define DLINK_GPIO		0x1c -#define DLINK_DIAG		0x1d -#define DLINK_EEPROM		0x1e - -#define MDIO_SHIFT_CLK		0x80 -#define MDIO_DATA_OUT		0x40 -#define MDIO_DIR_WRITE		0x30 -#define MDIO_DATA_WRITE0	(MDIO_DIR_WRITE) -#define MDIO_DATA_WRITE1	(MDIO_DIR_WRITE | MDIO_DATA_OUT) -#define MDIO_DATA_READ		0x10 -#define MDIO_MASK		0x0f - -static void mdio_sync(unsigned int addr) -{ -    int bits, mask = inb(addr) & MDIO_MASK; -    for (bits = 0; bits < 32; bits++) { -	outb(mask | MDIO_DATA_WRITE1, addr); -	outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); -    } -} - -static int mdio_read(unsigned int addr, int phy_id, int loc) -{ -    u_int cmd = (0x06<<10)|(phy_id<<5)|loc; -    int i, retval = 0, mask = inb(addr) & MDIO_MASK; - -    mdio_sync(addr); -    for (i = 13; i >= 0; i--) { -	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -	outb(mask | dat, addr); -	outb(mask | dat | MDIO_SHIFT_CLK, addr); -    } -    for (i = 19; i > 0; i--) { -	outb(mask, addr); -	retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0); -	outb(mask | MDIO_SHIFT_CLK, addr); -    } -    return (retval>>1) & 0xffff; -} - -static void mdio_write(unsigned int addr, int phy_id, int loc, int value) -{ -    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; -    int i, mask = inb(addr) & MDIO_MASK; - -    mdio_sync(addr); -    for (i = 31; i >= 0; i--) { -	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -	outb(mask | dat, addr); -	outb(mask | dat | MDIO_SHIFT_CLK, addr); -    } -    for (i = 1; i >= 0; i--) { -	outb(mask, addr); -	outb(mask | MDIO_SHIFT_CLK, addr); -    } -} - -/*====================================================================== - -    EEPROM access routines for DL10019 and DL10022 based cards - -======================================================================*/ - -#define EE_EEP		0x40 -#define EE_ASIC		0x10 -#define EE_CS		0x08 -#define EE_CK		0x04 -#define EE_DO		0x02 -#define EE_DI		0x01 -#define EE_ADOT		0x01	/* DataOut for ASIC */ -#define EE_READ_CMD	0x06 - -#define DL19FDUPLX	0x0400	/* DL10019 Full duplex mode */ - -static int read_eeprom(unsigned int ioaddr, int location) -{ -    int i, retval = 0; -    unsigned int ee_addr = ioaddr + DLINK_EEPROM; -    int read_cmd = location | (EE_READ_CMD << 8); - -    outb(0, ee_addr); -    outb(EE_EEP|EE_CS, ee_addr); - -    /* Shift the read command bits out. */ -    for (i = 10; i >= 0; i--) { -	short dataval = (read_cmd & (1 << i)) ? EE_DO : 0; -	outb_p(EE_EEP|EE_CS|dataval, ee_addr); -	outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr); -    } -    outb(EE_EEP|EE_CS, ee_addr); - -    for (i = 16; i > 0; i--) { -	outb_p(EE_EEP|EE_CS | EE_CK, ee_addr); -	retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0); -	outb_p(EE_EEP|EE_CS, ee_addr); -    } - -    /* Terminate the EEPROM access. */ -    outb(0, ee_addr); -    return retval; -} - -/* -    The internal ASIC registers can be changed by EEPROM READ access -    with EE_ASIC bit set. -    In ASIC mode, EE_ADOT is used to output the data to the ASIC. -*/ - -static void write_asic(unsigned int ioaddr, int location, short asic_data) -{ -	int i; -	unsigned int ee_addr = ioaddr + DLINK_EEPROM; -	short dataval; -	int read_cmd = location | (EE_READ_CMD << 8); - -	asic_data |= read_eeprom(ioaddr, location); - -	outb(0, ee_addr); -	outb(EE_ASIC|EE_CS|EE_DI, ee_addr); - -	read_cmd = read_cmd >> 1; - -	/* Shift the read command bits out. */ -	for (i = 9; i >= 0; i--) { -		dataval = (read_cmd & (1 << i)) ? EE_DO : 0; -		outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr); -		outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr); -		outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr); -	} -	// sync -	outb(EE_ASIC|EE_CS, ee_addr); -	outb(EE_ASIC|EE_CS|EE_CK, ee_addr); -	outb(EE_ASIC|EE_CS, ee_addr); - -	for (i = 15; i >= 0; i--) { -		dataval = (asic_data & (1 << i)) ? EE_ADOT : 0; -		outb_p(EE_ASIC|EE_CS|dataval, ee_addr); -		outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr); -		outb_p(EE_ASIC|EE_CS|dataval, ee_addr); -	} - -	/* Terminate the ASIC access. */ -	outb(EE_ASIC|EE_DI, ee_addr); -	outb(EE_ASIC|EE_DI| EE_CK, ee_addr); -	outb(EE_ASIC|EE_DI, ee_addr); - -	outb(0, ee_addr); -} - -/*====================================================================*/ - -static void set_misc_reg(struct net_device *dev) -{ -    unsigned int nic_base = dev->base_addr; -    pcnet_dev_t *info = PRIV(dev); -    u_char tmp; - -    if (info->flags & HAS_MISC_REG) { -	tmp = inb_p(nic_base + PCNET_MISC) & ~3; -	if (dev->if_port == 2) -	    tmp |= 1; -	if (info->flags & USE_BIG_BUF) -	    tmp |= 2; -	if (info->flags & HAS_IBM_MISC) -	    tmp |= 8; -	outb_p(tmp, nic_base + PCNET_MISC); -    } -    if (info->flags & IS_DL10022) { -	if (info->flags & HAS_MII) { -	    /* Advertise 100F, 100H, 10F, 10H */ -	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1); -	    /* Restart MII autonegotiation */ -	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000); -	    mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200); -	    info->mii_reset = jiffies; -	} else { -	    outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG); -	} -    } else if (info->flags & IS_DL10019) { -	/* Advertise 100F, 100H, 10F, 10H */ -	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1); -	/* Restart MII autonegotiation */ -	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000); -	mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200); -    } -} - -/*====================================================================*/ - -static void mii_phy_probe(struct net_device *dev) -{ -    pcnet_dev_t *info = PRIV(dev); -    unsigned int mii_addr = dev->base_addr + DLINK_GPIO; -    int i; -    u_int tmp, phyid; - -    for (i = 31; i >= 0; i--) { -	tmp = mdio_read(mii_addr, i, 1); -	if ((tmp == 0) || (tmp == 0xffff)) -	    continue; -	tmp = mdio_read(mii_addr, i, MII_PHYID_REG1); -	phyid = tmp << 16; -	phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2); -	phyid &= MII_PHYID_REV_MASK; -	netdev_dbg(dev, "MII at %d is 0x%08x\n", i, phyid); -	if (phyid == AM79C9XX_HOME_PHY) { -	    info->pna_phy = i; -	} else if (phyid != AM79C9XX_ETH_PHY) { -	    info->eth_phy = i; -	} -    } -} - -static int pcnet_open(struct net_device *dev) -{ -    int ret; -    pcnet_dev_t *info = PRIV(dev); -    struct pcmcia_device *link = info->p_dev; -    unsigned int nic_base = dev->base_addr; - -    dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name); - -    if (!pcmcia_dev_present(link)) -	return -ENODEV; - -    set_misc_reg(dev); - -    outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */ -    ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev); -    if (ret) -	    return ret; - -    link->open++; - -    info->phy_id = info->eth_phy; -    info->link_status = 0x00; -    init_timer(&info->watchdog); -    info->watchdog.function = ei_watchdog; -    info->watchdog.data = (u_long)dev; -    info->watchdog.expires = jiffies + HZ; -    add_timer(&info->watchdog); - -    return ei_open(dev); -} /* pcnet_open */ - -/*====================================================================*/ - -static int pcnet_close(struct net_device *dev) -{ -    pcnet_dev_t *info = PRIV(dev); -    struct pcmcia_device *link = info->p_dev; - -    dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name); - -    ei_close(dev); -    free_irq(dev->irq, dev); - -    link->open--; -    netif_stop_queue(dev); -    del_timer_sync(&info->watchdog); - -    return 0; -} /* pcnet_close */ - -/*====================================================================== - -    Hard reset the card.  This used to pause for the same period that -    a 8390 reset command required, but that shouldn't be necessary. - -======================================================================*/ - -static void pcnet_reset_8390(struct net_device *dev) -{ -    unsigned int nic_base = dev->base_addr; -    int i; - -    ei_status.txing = ei_status.dmaing = 0; - -    outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD); - -    outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET); - -    for (i = 0; i < 100; i++) { -	if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0) -	    break; -	udelay(100); -    } -    outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */ - -    if (i == 100) -	netdev_err(dev, "pcnet_reset_8390() did not complete.\n"); - -    set_misc_reg(dev); - -} /* pcnet_reset_8390 */ - -/*====================================================================*/ - -static int set_config(struct net_device *dev, struct ifmap *map) -{ -    pcnet_dev_t *info = PRIV(dev); -    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { -	if (!(info->flags & HAS_MISC_REG)) -	    return -EOPNOTSUPP; -	else if ((map->port < 1) || (map->port > 2)) -	    return -EINVAL; -	dev->if_port = map->port; -	netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); -	NS8390_init(dev, 1); -    } -    return 0; -} - -/*====================================================================*/ - -static irqreturn_t ei_irq_wrapper(int irq, void *dev_id) -{ -    struct net_device *dev = dev_id; -    pcnet_dev_t *info; -    irqreturn_t ret = ei_interrupt(irq, dev_id); - -    if (ret == IRQ_HANDLED) { -	    info = PRIV(dev); -	    info->stale = 0; -    } -    return ret; -} - -static void ei_watchdog(u_long arg) -{ -    struct net_device *dev = (struct net_device *)arg; -    pcnet_dev_t *info = PRIV(dev); -    unsigned int nic_base = dev->base_addr; -    unsigned int mii_addr = nic_base + DLINK_GPIO; -    u_short link; - -    if (!netif_device_present(dev)) goto reschedule; - -    /* Check for pending interrupt with expired latency timer: with -       this, we can limp along even if the interrupt is blocked */ -    if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { -	if (!info->fast_poll) -	    netdev_info(dev, "interrupt(s) dropped!\n"); -	ei_irq_wrapper(dev->irq, dev); -	info->fast_poll = HZ; -    } -    if (info->fast_poll) { -	info->fast_poll--; -	info->watchdog.expires = jiffies + 1; -	add_timer(&info->watchdog); -	return; -    } - -    if (!(info->flags & HAS_MII)) -	goto reschedule; - -    mdio_read(mii_addr, info->phy_id, 1); -    link = mdio_read(mii_addr, info->phy_id, 1); -    if (!link || (link == 0xffff)) { -	if (info->eth_phy) { -	    info->phy_id = info->eth_phy = 0; -	} else { -	    netdev_info(dev, "MII is missing!\n"); -	    info->flags &= ~HAS_MII; -	} -	goto reschedule; -    } - -    link &= 0x0004; -    if (link != info->link_status) { -	u_short p = mdio_read(mii_addr, info->phy_id, 5); -	netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); -	if (link && (info->flags & IS_DL10022)) { -	    /* Disable collision detection on full duplex links */ -	    outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG); -	} else if (link && (info->flags & IS_DL10019)) { -	    /* Disable collision detection on full duplex links */ -	    write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0); -	} -	if (link) { -	    if (info->phy_id == info->eth_phy) { -		if (p) -		    netdev_info(dev, "autonegotiation complete: " -			   "%sbaseT-%cD selected\n", -			   ((p & 0x0180) ? "100" : "10"), -			   ((p & 0x0140) ? 'F' : 'H')); -		else -		    netdev_info(dev, "link partner did not autonegotiate\n"); -	    } -	    NS8390_init(dev, 1); -	} -	info->link_status = link; -    } -    if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) { -	link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004; -	if (((info->phy_id == info->pna_phy) && link) || -	    ((info->phy_id != info->pna_phy) && !link)) { -	    /* isolate this MII and try flipping to the other one */ -	    mdio_write(mii_addr, info->phy_id, 0, 0x0400); -	    info->phy_id ^= info->pna_phy ^ info->eth_phy; -	    netdev_info(dev, "switched to %s transceiver\n", -		   (info->phy_id == info->eth_phy) ? "ethernet" : "PNA"); -	    mdio_write(mii_addr, info->phy_id, 0, -		       (info->phy_id == info->eth_phy) ? 0x1000 : 0); -	    info->link_status = 0; -	    info->mii_reset = jiffies; -	} -    } - -reschedule: -    info->watchdog.expires = jiffies + HZ; -    add_timer(&info->watchdog); -} - -/*====================================================================*/ - - -static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ -    pcnet_dev_t *info = PRIV(dev); -    struct mii_ioctl_data *data = if_mii(rq); -    unsigned int mii_addr = dev->base_addr + DLINK_GPIO; - -    if (!(info->flags & (IS_DL10019|IS_DL10022))) -	return -EINVAL; - -    switch (cmd) { -    case SIOCGMIIPHY: -	data->phy_id = info->phy_id; -    case SIOCGMIIREG:		/* Read MII PHY register. */ -	data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f); -	return 0; -    case SIOCSMIIREG:		/* Write MII PHY register. */ -	mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in); -	return 0; -    } -    return -EOPNOTSUPP; -} - -/*====================================================================*/ - -static void dma_get_8390_hdr(struct net_device *dev, -			     struct e8390_pkt_hdr *hdr, -			     int ring_page) -{ -    unsigned int nic_base = dev->base_addr; - -    if (ei_status.dmaing) { -	netdev_notice(dev, "DMAing conflict in dma_block_input." -	       "[DMAstat:%1x][irqlock:%1x]\n", -	       ei_status.dmaing, ei_status.irqlock); -	return; -    } - -    ei_status.dmaing |= 0x01; -    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD); -    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); -    outb_p(0, nic_base + EN0_RCNTHI); -    outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */ -    outb_p(ring_page, nic_base + EN0_RSARHI); -    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD); - -    insw(nic_base + PCNET_DATAPORT, hdr, -	    sizeof(struct e8390_pkt_hdr)>>1); -    /* Fix for big endian systems */ -    hdr->count = le16_to_cpu(hdr->count); - -    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */ -    ei_status.dmaing &= ~0x01; -} - -/*====================================================================*/ - -static void dma_block_input(struct net_device *dev, int count, -			    struct sk_buff *skb, int ring_offset) -{ -    unsigned int nic_base = dev->base_addr; -    int xfer_count = count; -    char *buf = skb->data; - -    if ((ei_debug > 4) && (count != 4)) -	netdev_dbg(dev, "[bi=%d]\n", count+4); -    if (ei_status.dmaing) { -	netdev_notice(dev, "DMAing conflict in dma_block_input." -	       "[DMAstat:%1x][irqlock:%1x]\n", -	       ei_status.dmaing, ei_status.irqlock); -	return; -    } -    ei_status.dmaing |= 0x01; -    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD); -    outb_p(count & 0xff, nic_base + EN0_RCNTLO); -    outb_p(count >> 8, nic_base + EN0_RCNTHI); -    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); -    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); -    outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD); - -    insw(nic_base + PCNET_DATAPORT,buf,count>>1); -    if (count & 0x01) -	buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++; - -    /* This was for the ALPHA version only, but enough people have been -       encountering problems that it is still here. */ -#ifdef PCMCIA_DEBUG -    if (ei_debug > 4) {		/* DMA termination address check... */ -	int addr, tries = 20; -	do { -	    /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -	       -- it's broken for Rx on some cards! */ -	    int high = inb_p(nic_base + EN0_RSARHI); -	    int low = inb_p(nic_base + EN0_RSARLO); -	    addr = (high << 8) + low; -	    if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff)) -		break; -	} while (--tries > 0); -	if (tries <= 0) -	    netdev_notice(dev, "RX transfer address mismatch," -		   "%#4.4x (expected) vs. %#4.4x (actual).\n", -		   ring_offset + xfer_count, addr); -    } -#endif -    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */ -    ei_status.dmaing &= ~0x01; -} /* dma_block_input */ - -/*====================================================================*/ - -static void dma_block_output(struct net_device *dev, int count, -			     const u_char *buf, const int start_page) -{ -    unsigned int nic_base = dev->base_addr; -    pcnet_dev_t *info = PRIV(dev); -#ifdef PCMCIA_DEBUG -    int retries = 0; -#endif -    u_long dma_start; - -#ifdef PCMCIA_DEBUG -    if (ei_debug > 4) -	netdev_dbg(dev, "[bo=%d]\n", count); -#endif - -    /* Round the count up for word writes.  Do we need to do this? -       What effect will an odd byte count have on the 8390? -       I should check someday. */ -    if (count & 0x01) -	count++; -    if (ei_status.dmaing) { -	netdev_notice(dev, "DMAing conflict in dma_block_output." -	       "[DMAstat:%1x][irqlock:%1x]\n", -	       ei_status.dmaing, ei_status.irqlock); -	return; -    } -    ei_status.dmaing |= 0x01; -    /* We should already be in page 0, but to be safe... */ -    outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD); - -#ifdef PCMCIA_DEBUG -  retry: -#endif - -    outb_p(ENISR_RDC, nic_base + EN0_ISR); - -    /* Now the normal output. */ -    outb_p(count & 0xff, nic_base + EN0_RCNTLO); -    outb_p(count >> 8,   nic_base + EN0_RCNTHI); -    outb_p(0x00, nic_base + EN0_RSARLO); -    outb_p(start_page, nic_base + EN0_RSARHI); - -    outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD); -    outsw(nic_base + PCNET_DATAPORT, buf, count>>1); - -    dma_start = jiffies; - -#ifdef PCMCIA_DEBUG -    /* This was for the ALPHA version only, but enough people have been -       encountering problems that it is still here. */ -    if (ei_debug > 4) {	/* DMA termination address check... */ -	int addr, tries = 20; -	do { -	    int high = inb_p(nic_base + EN0_RSARHI); -	    int low = inb_p(nic_base + EN0_RSARLO); -	    addr = (high << 8) + low; -	    if ((start_page << 8) + count == addr) -		break; -	} while (--tries > 0); -	if (tries <= 0) { -	    netdev_notice(dev, "Tx packet transfer address mismatch," -		   "%#4.4x (expected) vs. %#4.4x (actual).\n", -		   (start_page << 8) + count, addr); -	    if (retries++ == 0) -		goto retry; -	} -    } -#endif - -    while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) -	if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) { -	    netdev_notice(dev, "timeout waiting for Tx RDC.\n"); -	    pcnet_reset_8390(dev); -	    NS8390_init(dev, 1); -	    break; -	} - -    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */ -    if (info->flags & DELAY_OUTPUT) -	udelay((long)delay_time); -    ei_status.dmaing &= ~0x01; -} - -/*====================================================================*/ - -static int setup_dma_config(struct pcmcia_device *link, int start_pg, -			    int stop_pg) -{ -    struct net_device *dev = link->priv; - -    ei_status.tx_start_page = start_pg; -    ei_status.rx_start_page = start_pg + TX_PAGES; -    ei_status.stop_page = stop_pg; - -    /* set up block i/o functions */ -    ei_status.get_8390_hdr = dma_get_8390_hdr; -    ei_status.block_input = dma_block_input; -    ei_status.block_output = dma_block_output; - -    return 0; -} - -/*====================================================================*/ - -static void copyin(void *dest, void __iomem *src, int c) -{ -    u_short *d = dest; -    u_short __iomem *s = src; -    int odd; - -    if (c <= 0) -	return; -    odd = (c & 1); c >>= 1; - -    if (c) { -	do { *d++ = __raw_readw(s++); } while (--c); -    } -    /* get last byte by fetching a word and masking */ -    if (odd) -	*((u_char *)d) = readw(s) & 0xff; -} - -static void copyout(void __iomem *dest, const void *src, int c) -{ -    u_short __iomem *d = dest; -    const u_short *s = src; -    int odd; - -    if (c <= 0) -	return; -    odd = (c & 1); c >>= 1; - -    if (c) { -	do { __raw_writew(*s++, d++); } while (--c); -    } -    /* copy last byte doing a read-modify-write */ -    if (odd) -	writew((readw(d) & 0xff00) | *(u_char *)s, d); -} - -/*====================================================================*/ - -static void shmem_get_8390_hdr(struct net_device *dev, -			       struct e8390_pkt_hdr *hdr, -			       int ring_page) -{ -    void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8) -				+ (ring_page << 8) -				- (ei_status.rx_start_page << 8); - -    copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr)); -    /* Fix for big endian systems */ -    hdr->count = le16_to_cpu(hdr->count); -} - -/*====================================================================*/ - -static void shmem_block_input(struct net_device *dev, int count, -			      struct sk_buff *skb, int ring_offset) -{ -    void __iomem *base = ei_status.mem; -    unsigned long offset = (TX_PAGES<<8) + ring_offset -				- (ei_status.rx_start_page << 8); -    char *buf = skb->data; - -    if (offset + count > ei_status.priv) { -	/* We must wrap the input move. */ -	int semi_count = ei_status.priv - offset; -	copyin(buf, base + offset, semi_count); -	buf += semi_count; -	offset = TX_PAGES<<8; -	count -= semi_count; -    } -    copyin(buf, base + offset, count); -} - -/*====================================================================*/ - -static void shmem_block_output(struct net_device *dev, int count, -			       const u_char *buf, const int start_page) -{ -    void __iomem *shmem = ei_status.mem + (start_page << 8); -    shmem -= ei_status.tx_start_page << 8; -    copyout(shmem, buf, count); -} - -/*====================================================================*/ - -static int setup_shmem_window(struct pcmcia_device *link, int start_pg, -			      int stop_pg, int cm_offset) -{ -    struct net_device *dev = link->priv; -    pcnet_dev_t *info = PRIV(dev); -    int i, window_size, offset, ret; - -    window_size = (stop_pg - start_pg) << 8; -    if (window_size > 32 * 1024) -	window_size = 32 * 1024; - -    /* Make sure it's a power of two.  */ -    window_size = roundup_pow_of_two(window_size); - -    /* Allocate a memory window */ -    link->resource[3]->flags |= WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE; -    link->resource[3]->flags |= WIN_USE_WAIT; -    link->resource[3]->start = 0; link->resource[3]->end = window_size; -    ret = pcmcia_request_window(link, link->resource[3], mem_speed); -    if (ret) -	    goto failed; - -    offset = (start_pg << 8) + cm_offset; -    offset -= offset % window_size; -    ret = pcmcia_map_mem_page(link, link->resource[3], offset); -    if (ret) -	    goto failed; - -    /* Try scribbling on the buffer */ -    info->base = ioremap(link->resource[3]->start, -			resource_size(link->resource[3])); -    for (i = 0; i < (TX_PAGES<<8); i += 2) -	__raw_writew((i>>1), info->base+offset+i); -    udelay(100); -    for (i = 0; i < (TX_PAGES<<8); i += 2) -	if (__raw_readw(info->base+offset+i) != (i>>1)) break; -    pcnet_reset_8390(dev); -    if (i != (TX_PAGES<<8)) { -	iounmap(info->base); -	pcmcia_release_window(link, link->resource[3]); -	info->base = NULL; -	goto failed; -    } - -    ei_status.mem = info->base + offset; -    ei_status.priv = resource_size(link->resource[3]); -    dev->mem_start = (u_long)ei_status.mem; -    dev->mem_end = dev->mem_start + resource_size(link->resource[3]); - -    ei_status.tx_start_page = start_pg; -    ei_status.rx_start_page = start_pg + TX_PAGES; -    ei_status.stop_page = start_pg + ( -	    (resource_size(link->resource[3]) - offset) >> 8); - -    /* set up block i/o functions */ -    ei_status.get_8390_hdr = shmem_get_8390_hdr; -    ei_status.block_input = shmem_block_input; -    ei_status.block_output = shmem_block_output; - -    info->flags |= USE_SHMEM; -    return 0; - -failed: -    return 1; -} - -/*====================================================================*/ - -static struct pcmcia_device_id pcnet_ids[] = { -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f), -	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card       ", 0xb569a6e5, 0x5bd4ff2c), -	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3), -	PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15), -	PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f), -	PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302), -	PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004), -	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d), -	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075), -	PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145), -	PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230), -	PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530), -	PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab), -	PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110), -	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328), -	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041), -	PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452), -	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300), -	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307), -	PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a), -	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103), -	PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121), -	PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e), -	PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b), -	PCMCIA_DEVICE_PROD_ID123("CNet  ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b), -	PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e), -	PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0), -	PCMCIA_DEVICE_PROD_ID123("EFA   ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b), -	PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b), -	PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b), -	PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0), -	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82), -	PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8), -	PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab), -	PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11), -	PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff), -	PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68), -	PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997), -  	PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8), -	PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96), -	PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96), -	PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224), -	PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb), -	PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247), -	PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96), -	PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1), -	PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd), -	PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190), -	PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504), -	PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a), -	PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79), -	PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7), -	PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a), -	PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9), -	PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722), -	PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2), -	PCMCIA_DEVICE_PROD_ID12("corega", "Ether CF-TD", 0x0a21501a, 0x6589340a), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d), -	PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9), -	PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2), -	PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2), -	PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88), -	PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04), -	PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d), -	PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814), -	PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0), -	PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf), -	PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995), -	PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233), -	PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e), -	PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398), -	PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b), -	PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec), -	PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9), -	PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84), -	PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9), -	PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1), -	PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1), -	PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb), -	PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11), -	PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6), -	PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c), -	PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e), -	PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61), -	PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517), -	PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e), -	PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb), -	PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327), -	PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947), -	PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6), -	PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494), -	PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b), -	PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0), -	PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956), -	PCMCIA_DEVICE_PROD_ID12("KENTRONICS", "KEP-230", 0xaf8144c9, 0x868f6616), -	PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64), -	PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5), -	PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3), -	PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2), -	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c), -	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40), -	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7), -	PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab), -	PCMCIA_DEVICE_PROD_ID12("LEMEL", "LM-N89TX PRO", 0xbbefb52f, 0xd2897a97), -	PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78), -	PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11), -	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d), -	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389), -	PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9), -	PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a), -	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737), -	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee), -	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922), -	PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c), -	PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0), -	PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578), -	PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307), -	PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4), -	PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8), -	PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3), -	PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c), -	PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6), -	PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472), -	PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7), -	PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9), -	PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8), -	PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76), -	PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e), -	PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f), -	PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641), -	PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "    Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1), -	PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80), -	PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50), -	PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110), -	PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826), -	PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df), -	PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0), -	PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd), -	PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388), -	PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c), -	PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941), -	PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265), -	PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e), -	PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8), -	PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa), -	PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f), -	PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a), -	PCMCIA_DEVICE_PROD_ID13("Hypertec",  "EP401", 0x8787bec7, 0xf6e4a31e), -	PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0), -	PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e), -	PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89), -	PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360), -	PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de), -	PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f), -	PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a), -	PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078), -	/* too generic! */ -	/* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */ -	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"), -	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"), -	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), -	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), -	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), -	PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"), -	PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"), -	PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"), -	PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"), -	PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"), -	PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"), -	PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"), -	PCMCIA_DEVICE_CIS_PROD_ID12("PMX   ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"), -	PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"), -	PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b), -	PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", -		0xb4be14e3, 0x43ac239b, 0x0877b627), -	PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, pcnet_ids); -MODULE_FIRMWARE("cis/PCMLM28.cis"); -MODULE_FIRMWARE("cis/DP83903.cis"); -MODULE_FIRMWARE("cis/LA-PCM.cis"); -MODULE_FIRMWARE("cis/PE520.cis"); -MODULE_FIRMWARE("cis/NE2K.cis"); -MODULE_FIRMWARE("cis/PE-200.cis"); -MODULE_FIRMWARE("cis/tamarack.cis"); - -static struct pcmcia_driver pcnet_driver = { -	.name		= "pcnet_cs", -	.probe		= pcnet_probe, -	.remove		= pcnet_detach, -	.owner		= THIS_MODULE, -	.id_table	= pcnet_ids, -	.suspend	= pcnet_suspend, -	.resume		= pcnet_resume, -}; - -static int __init init_pcnet_cs(void) -{ -    return pcmcia_register_driver(&pcnet_driver); -} - -static void __exit exit_pcnet_cs(void) -{ -    pcmcia_unregister_driver(&pcnet_driver); -} - -module_init(init_pcnet_cs); -module_exit(exit_pcnet_cs); diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c deleted file mode 100644 index 8a9ff531892..00000000000 --- a/drivers/net/pcmcia/smc91c92_cs.c +++ /dev/null @@ -1,2070 +0,0 @@ -/*====================================================================== - -    A PCMCIA ethernet driver for SMC91c92-based cards. - -    This driver supports Megahertz PCMCIA ethernet cards; and -    Megahertz, Motorola, Ositech, and Psion Dacom ethernet/modem -    multifunction cards. - -    Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net - -    smc91c92_cs.c 1.122 2002/10/25 06:26:39 - -    This driver contains code written by Donald Becker -    (becker@scyld.com), Rowan Hughes (x-csrdh@jcu.edu.au), -    David Hinds (dahinds@users.sourceforge.net), and Erik Stahlman -    (erik@vt.edu).  Donald wrote the SMC 91c92 code using parts of -    Erik's SMC 91c94 driver.  Rowan wrote a similar driver, and I've -    incorporated some parts of his driver here.  I (Dave) wrote most -    of the PCMCIA glue code, and the Ositech support code.  Kelly -    Stephens (kstephen@holli.com) added support for the Motorola -    Mariner, with help from Allen Brost. - -    This software may be used and distributed according to the terms of -    the GNU General Public License, incorporated herein by reference. - -======================================================================*/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/crc32.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/ethtool.h> -#include <linux/mii.h> -#include <linux/jiffies.h> -#include <linux/firmware.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ciscode.h> -#include <pcmcia/ds.h> -#include <pcmcia/ss.h> - -#include <asm/io.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -/*====================================================================*/ - -static const char *if_names[] = { "auto", "10baseT", "10base2"}; - -/* Firmware name */ -#define FIRMWARE_NAME		"ositech/Xilinx7OD.bin" - -/* Module parameters */ - -MODULE_DESCRIPTION("SMC 91c92 series PCMCIA ethernet driver"); -MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(FIRMWARE_NAME); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -/* -  Transceiver/media type. -   0 = auto -   1 = 10baseT (and autoselect if #define AUTOSELECT), -   2 = AUI/10base2, -*/ -INT_MODULE_PARM(if_port, 0); - - -#define DRV_NAME	"smc91c92_cs" -#define DRV_VERSION	"1.123" - -/*====================================================================*/ - -/* Operational parameter that usually are not changed. */ - -/* Time in jiffies before concluding Tx hung */ -#define TX_TIMEOUT		((400*HZ)/1000) - -/* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -#define INTR_WORK		4 - -/* Times to check the check the chip before concluding that it doesn't -   currently have room for another Tx packet. */ -#define MEMORY_WAIT_TIME       	8 - -struct smc_private { -	struct pcmcia_device	*p_dev; -    spinlock_t			lock; -    u_short			manfid; -    u_short			cardid; - -    struct sk_buff		*saved_skb; -    int				packets_waiting; -    void			__iomem *base; -    u_short			cfg; -    struct timer_list		media; -    int				watchdog, tx_err; -    u_short			media_status; -    u_short			fast_poll; -    u_short			link_status; -    struct mii_if_info		mii_if; -    int				duplex; -    int				rx_ovrn; -}; - -/* Special definitions for Megahertz multifunction cards */ -#define MEGAHERTZ_ISR		0x0380 - -/* Special function registers for Motorola Mariner */ -#define MOT_LAN			0x0000 -#define MOT_UART		0x0020 -#define MOT_EEPROM		0x20 - -#define MOT_NORMAL \ -(COR_LEVEL_REQ | COR_FUNC_ENA | COR_ADDR_DECODE | COR_IREQ_ENA) - -/* Special function registers for Ositech cards */ -#define OSITECH_AUI_CTL		0x0c -#define OSITECH_PWRDOWN		0x0d -#define OSITECH_RESET		0x0e -#define OSITECH_ISR		0x0f -#define OSITECH_AUI_PWR		0x0c -#define OSITECH_RESET_ISR	0x0e - -#define OSI_AUI_PWR		0x40 -#define OSI_LAN_PWRDOWN		0x02 -#define OSI_MODEM_PWRDOWN	0x01 -#define OSI_LAN_RESET		0x02 -#define OSI_MODEM_RESET		0x01 - -/* Symbolic constants for the SMC91c9* series chips, from Erik Stahlman. */ -#define	BANK_SELECT		14		/* Window select register. */ -#define SMC_SELECT_BANK(x)  { outw(x, ioaddr + BANK_SELECT); } - -/* Bank 0 registers. */ -#define	TCR 		0	/* transmit control register */ -#define	 TCR_CLEAR	0	/* do NOTHING */ -#define  TCR_ENABLE	0x0001	/* if this is 1, we can transmit */ -#define	 TCR_PAD_EN	0x0080	/* pads short packets to 64 bytes */ -#define  TCR_MONCSN	0x0400  /* Monitor Carrier. */ -#define  TCR_FDUPLX	0x0800  /* Full duplex mode. */ -#define	 TCR_NORMAL TCR_ENABLE | TCR_PAD_EN - -#define EPH		2	/* Ethernet Protocol Handler report. */ -#define  EPH_TX_SUC	0x0001 -#define  EPH_SNGLCOL	0x0002 -#define  EPH_MULCOL	0x0004 -#define  EPH_LTX_MULT	0x0008 -#define  EPH_16COL	0x0010 -#define  EPH_SQET	0x0020 -#define  EPH_LTX_BRD	0x0040 -#define  EPH_TX_DEFR	0x0080 -#define  EPH_LAT_COL	0x0200 -#define  EPH_LOST_CAR	0x0400 -#define  EPH_EXC_DEF	0x0800 -#define  EPH_CTR_ROL	0x1000 -#define  EPH_RX_OVRN	0x2000 -#define  EPH_LINK_OK	0x4000 -#define  EPH_TX_UNRN	0x8000 -#define MEMINFO		8	/* Memory Information Register */ -#define MEMCFG		10	/* Memory Configuration Register */ - -/* Bank 1 registers. */ -#define CONFIG			0 -#define  CFG_MII_SELECT		0x8000	/* 91C100 only */ -#define  CFG_NO_WAIT		0x1000 -#define  CFG_FULL_STEP		0x0400 -#define  CFG_SET_SQLCH		0x0200 -#define  CFG_AUI_SELECT	 	0x0100 -#define  CFG_16BIT		0x0080 -#define  CFG_DIS_LINK		0x0040 -#define  CFG_STATIC		0x0030 -#define  CFG_IRQ_SEL_1		0x0004 -#define  CFG_IRQ_SEL_0		0x0002 -#define BASE_ADDR		2 -#define	ADDR0			4 -#define	GENERAL			10 -#define	CONTROL			12 -#define  CTL_STORE		0x0001 -#define  CTL_RELOAD		0x0002 -#define  CTL_EE_SELECT		0x0004 -#define  CTL_TE_ENABLE		0x0020 -#define  CTL_CR_ENABLE		0x0040 -#define  CTL_LE_ENABLE		0x0080 -#define  CTL_AUTO_RELEASE	0x0800 -#define	 CTL_POWERDOWN		0x2000 - -/* Bank 2 registers. */ -#define MMU_CMD		0 -#define	 MC_ALLOC	0x20  	/* or with number of 256 byte packets */ -#define	 MC_RESET	0x40 -#define  MC_RELEASE  	0x80  	/* remove and release the current rx packet */ -#define  MC_FREEPKT  	0xA0  	/* Release packet in PNR register */ -#define  MC_ENQUEUE	0xC0 	/* Enqueue the packet for transmit */ -#define	PNR_ARR		2 -#define FIFO_PORTS	4 -#define  FP_RXEMPTY	0x8000 -#define	POINTER		6 -#define  PTR_AUTO_INC	0x0040 -#define  PTR_READ	0x2000 -#define	 PTR_AUTOINC 	0x4000 -#define	 PTR_RCV	0x8000 -#define	DATA_1		8 -#define	INTERRUPT	12 -#define  IM_RCV_INT		0x1 -#define	 IM_TX_INT		0x2 -#define	 IM_TX_EMPTY_INT	0x4 -#define	 IM_ALLOC_INT		0x8 -#define	 IM_RX_OVRN_INT		0x10 -#define	 IM_EPH_INT		0x20 - -#define	RCR		4 -enum RxCfg { RxAllMulti = 0x0004, RxPromisc = 0x0002, -	     RxEnable = 0x0100, RxStripCRC = 0x0200}; -#define  RCR_SOFTRESET	0x8000 	/* resets the chip */ -#define	 RCR_STRIP_CRC	0x200	/* strips CRC */ -#define  RCR_ENABLE	0x100	/* IFF this is set, we can receive packets */ -#define  RCR_ALMUL	0x4 	/* receive all multicast packets */ -#define	 RCR_PROMISC	0x2	/* enable promiscuous mode */ - -/* the normal settings for the RCR register : */ -#define	 RCR_NORMAL	(RCR_STRIP_CRC | RCR_ENABLE) -#define  RCR_CLEAR	0x0		/* set it to a base state */ -#define	COUNTER		6 - -/* BANK 3 -- not the same values as in smc9194! */ -#define	MULTICAST0	0 -#define	MULTICAST2	2 -#define	MULTICAST4	4 -#define	MULTICAST6	6 -#define MGMT    	8 -#define REVISION	0x0a - -/* Transmit status bits. */ -#define TS_SUCCESS 0x0001 -#define TS_16COL   0x0010 -#define TS_LATCOL  0x0200 -#define TS_LOSTCAR 0x0400 - -/* Receive status bits. */ -#define RS_ALGNERR	0x8000 -#define RS_BADCRC	0x2000 -#define RS_ODDFRAME	0x1000 -#define RS_TOOLONG	0x0800 -#define RS_TOOSHORT	0x0400 -#define RS_MULTICAST	0x0001 -#define RS_ERRORS	(RS_ALGNERR | RS_BADCRC | RS_TOOLONG | RS_TOOSHORT) - -#define set_bits(v, p) outw(inw(p)|(v), (p)) -#define mask_bits(v, p) outw(inw(p)&(v), (p)) - -/*====================================================================*/ - -static void smc91c92_detach(struct pcmcia_device *p_dev); -static int smc91c92_config(struct pcmcia_device *link); -static void smc91c92_release(struct pcmcia_device *link); - -static int smc_open(struct net_device *dev); -static int smc_close(struct net_device *dev); -static int smc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void smc_tx_timeout(struct net_device *dev); -static netdev_tx_t smc_start_xmit(struct sk_buff *skb, -					struct net_device *dev); -static irqreturn_t smc_interrupt(int irq, void *dev_id); -static void smc_rx(struct net_device *dev); -static void set_rx_mode(struct net_device *dev); -static int s9k_config(struct net_device *dev, struct ifmap *map); -static void smc_set_xcvr(struct net_device *dev, int if_port); -static void smc_reset(struct net_device *dev); -static void media_check(u_long arg); -static void mdio_sync(unsigned int addr); -static int mdio_read(struct net_device *dev, int phy_id, int loc); -static void mdio_write(struct net_device *dev, int phy_id, int loc, int value); -static int smc_link_ok(struct net_device *dev); -static const struct ethtool_ops ethtool_ops; - -static const struct net_device_ops smc_netdev_ops = { -	.ndo_open		= smc_open, -	.ndo_stop		= smc_close, -	.ndo_start_xmit		= smc_start_xmit, -	.ndo_tx_timeout 	= smc_tx_timeout, -	.ndo_set_config 	= s9k_config, -	.ndo_set_multicast_list = set_rx_mode, -	.ndo_do_ioctl		= smc_ioctl, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int smc91c92_probe(struct pcmcia_device *link) -{ -    struct smc_private *smc; -    struct net_device *dev; - -    dev_dbg(&link->dev, "smc91c92_attach()\n"); - -    /* Create new ethernet device */ -    dev = alloc_etherdev(sizeof(struct smc_private)); -    if (!dev) -	return -ENOMEM; -    smc = netdev_priv(dev); -    smc->p_dev = link; -    link->priv = dev; - -    spin_lock_init(&smc->lock); - -    /* The SMC91c92-specific entries in the device structure. */ -    dev->netdev_ops = &smc_netdev_ops; -    SET_ETHTOOL_OPS(dev, ðtool_ops); -    dev->watchdog_timeo = TX_TIMEOUT; - -    smc->mii_if.dev = dev; -    smc->mii_if.mdio_read = mdio_read; -    smc->mii_if.mdio_write = mdio_write; -    smc->mii_if.phy_id_mask = 0x1f; -    smc->mii_if.reg_num_mask = 0x1f; - -    return smc91c92_config(link); -} /* smc91c92_attach */ - -static void smc91c92_detach(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    dev_dbg(&link->dev, "smc91c92_detach\n"); - -    unregister_netdev(dev); - -    smc91c92_release(link); - -    free_netdev(dev); -} /* smc91c92_detach */ - -/*====================================================================*/ - -static int cvt_ascii_address(struct net_device *dev, char *s) -{ -    int i, j, da, c; - -    if (strlen(s) != 12) -	return -1; -    for (i = 0; i < 6; i++) { -	da = 0; -	for (j = 0; j < 2; j++) { -	    c = *s++; -	    da <<= 4; -	    da += ((c >= '0') && (c <= '9')) ? -		(c - '0') : ((c & 0x0f) + 9); -	} -	dev->dev_addr[i] = da; -    } -    return 0; -} - -/*==================================================================== - -    Configuration stuff for Megahertz cards - -    mhz_3288_power() is used to power up a 3288's ethernet chip. -    mhz_mfc_config() handles socket setup for multifunction (1144 -    and 3288) cards.  mhz_setup() gets a card's hardware ethernet -    address. - -======================================================================*/ - -static int mhz_3288_power(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    struct smc_private *smc = netdev_priv(dev); -    u_char tmp; - -    /* Read the ISR twice... */ -    readb(smc->base+MEGAHERTZ_ISR); -    udelay(5); -    readb(smc->base+MEGAHERTZ_ISR); - -    /* Pause 200ms... */ -    mdelay(200); - -    /* Now read and write the COR... */ -    tmp = readb(smc->base + link->config_base + CISREG_COR); -    udelay(5); -    writeb(tmp, smc->base + link->config_base + CISREG_COR); - -    return 0; -} - -static int mhz_mfc_config_check(struct pcmcia_device *p_dev, void *priv_data) -{ -	int k; -	p_dev->io_lines = 16; -	p_dev->resource[1]->start = p_dev->resource[0]->start; -	p_dev->resource[1]->end = 8; -	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -	p_dev->resource[0]->end = 16; -	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; -	for (k = 0; k < 0x400; k += 0x10) { -		if (k & 0x80) -			continue; -		p_dev->resource[0]->start = k ^ 0x300; -		if (!pcmcia_request_io(p_dev)) -			return 0; -	} -	return -ENODEV; -} - -static int mhz_mfc_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    struct smc_private *smc = netdev_priv(dev); -    unsigned int offset; -    int i; - -    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ | -	    CONF_AUTO_SET_IO; - -    /* The Megahertz combo cards have modem-like CIS entries, so -       we have to explicitly try a bunch of port combinations. */ -    if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL)) -	    return -ENODEV; - -    dev->base_addr = link->resource[0]->start; - -    /* Allocate a memory window, for accessing the ISR */ -    link->resource[2]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; -    link->resource[2]->start = link->resource[2]->end = 0; -    i = pcmcia_request_window(link, link->resource[2], 0); -    if (i != 0) -	    return -ENODEV; - -    smc->base = ioremap(link->resource[2]->start, -		    resource_size(link->resource[2])); -    offset = (smc->manfid == MANFID_MOTOROLA) ? link->config_base : 0; -    i = pcmcia_map_mem_page(link, link->resource[2], offset); -    if ((i == 0) && -	(smc->manfid == MANFID_MEGAHERTZ) && -	(smc->cardid == PRODID_MEGAHERTZ_EM3288)) -	    mhz_3288_power(link); - -    return 0; -} - -static int pcmcia_get_versmac(struct pcmcia_device *p_dev, -			      tuple_t *tuple, -			      void *priv) -{ -	struct net_device *dev = priv; -	cisparse_t parse; -	u8 *buf; - -	if (pcmcia_parse_tuple(tuple, &parse)) -		return -EINVAL; - -	buf = parse.version_1.str + parse.version_1.ofs[3]; - -	if ((parse.version_1.ns > 3) && (cvt_ascii_address(dev, buf) == 0)) -		return 0; - -	return -EINVAL; -}; - -static int mhz_setup(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    size_t len; -    u8 *buf; -    int rc; - -    /* Read the station address from the CIS.  It is stored as the last -       (fourth) string in the Version 1 Version/ID tuple. */ -    if ((link->prod_id[3]) && -	(cvt_ascii_address(dev, link->prod_id[3]) == 0)) -	    return 0; - -    /* Workarounds for broken cards start here. */ -    /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */ -    if (!pcmcia_loop_tuple(link, CISTPL_VERS_1, pcmcia_get_versmac, dev)) -	    return 0; - -    /* Another possibility: for the EM3288, in a special tuple */ -    rc = -1; -    len = pcmcia_get_tuple(link, 0x81, &buf); -    if (buf && len >= 13) { -	    buf[12] = '\0'; -	    if (cvt_ascii_address(dev, buf) == 0) -		    rc = 0; -    } -    kfree(buf); - -    return rc; -}; - -/*====================================================================== - -    Configuration stuff for the Motorola Mariner - -    mot_config() writes directly to the Mariner configuration -    registers because the CIS is just bogus. - -======================================================================*/ - -static void mot_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    unsigned int iouart = link->resource[1]->start; - -    /* Set UART base address and force map with COR bit 1 */ -    writeb(iouart & 0xff,        smc->base + MOT_UART + CISREG_IOBASE_0); -    writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1); -    writeb(MOT_NORMAL,           smc->base + MOT_UART + CISREG_COR); - -    /* Set SMC base address and force map with COR bit 1 */ -    writeb(ioaddr & 0xff,        smc->base + MOT_LAN + CISREG_IOBASE_0); -    writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1); -    writeb(MOT_NORMAL,           smc->base + MOT_LAN + CISREG_COR); - -    /* Wait for things to settle down */ -    mdelay(100); -} - -static int mot_setup(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    unsigned int ioaddr = dev->base_addr; -    int i, wait, loop; -    u_int addr; - -    /* Read Ethernet address from Serial EEPROM */ - -    for (i = 0; i < 3; i++) { -	SMC_SELECT_BANK(2); -	outw(MOT_EEPROM + i, ioaddr + POINTER); -	SMC_SELECT_BANK(1); -	outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL); - -	for (loop = wait = 0; loop < 200; loop++) { -	    udelay(10); -	    wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL)); -	    if (wait == 0) break; -	} -	 -	if (wait) -	    return -1; -	 -	addr = inw(ioaddr + GENERAL); -	dev->dev_addr[2*i]   = addr & 0xff; -	dev->dev_addr[2*i+1] = (addr >> 8) & 0xff; -    } - -    return 0; -} - -/*====================================================================*/ - -static int smc_configcheck(struct pcmcia_device *p_dev, void *priv_data) -{ -	p_dev->resource[0]->end = 16; -	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; - -	return pcmcia_request_io(p_dev); -} - -static int smc_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    int i; - -    link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; - -    i = pcmcia_loop_config(link, smc_configcheck, NULL); -    if (!i) -	    dev->base_addr = link->resource[0]->start; - -    return i; -} - - -static int smc_setup(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    /* Check for a LAN function extension tuple */ -    if (!pcmcia_get_mac_from_cis(link, dev)) -	    return 0; - -    /* Try the third string in the Version 1 Version/ID tuple. */ -    if (link->prod_id[2]) { -	    if (cvt_ascii_address(dev, link->prod_id[2]) == 0) -		    return 0; -    } -    return -1; -} - -/*====================================================================*/ - -static int osi_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    static const unsigned int com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; -    int i, j; - -    link->config_flags |= CONF_ENABLE_SPKR | CONF_ENABLE_IRQ; -    link->resource[0]->end = 64; -    link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -    link->resource[1]->end = 8; - -    /* Enable Hard Decode, LAN, Modem */ -    link->io_lines = 16; -    link->config_index = 0x23; - -    for (i = j = 0; j < 4; j++) { -	link->resource[1]->start = com[j]; -	i = pcmcia_request_io(link); -	if (i == 0) -		break; -    } -    if (i != 0) { -	/* Fallback: turn off hard decode */ -	link->config_index = 0x03; -	link->resource[1]->end = 0; -	i = pcmcia_request_io(link); -    } -    dev->base_addr = link->resource[0]->start + 0x10; -    return i; -} - -static int osi_load_firmware(struct pcmcia_device *link) -{ -	const struct firmware *fw; -	int i, err; - -	err = request_firmware(&fw, FIRMWARE_NAME, &link->dev); -	if (err) { -		pr_err("Failed to load firmware \"%s\"\n", FIRMWARE_NAME); -		return err; -	} - -	/* Download the Seven of Diamonds firmware */ -	for (i = 0; i < fw->size; i++) { -	    outb(fw->data[i], link->resource[0]->start + 2); -	    udelay(50); -	} -	release_firmware(fw); -	return err; -} - -static int pcmcia_osi_mac(struct pcmcia_device *p_dev, -			  tuple_t *tuple, -			  void *priv) -{ -	struct net_device *dev = priv; -	int i; - -	if (tuple->TupleDataLen < 8) -		return -EINVAL; -	if (tuple->TupleData[0] != 0x04) -		return -EINVAL; -	for (i = 0; i < 6; i++) -		dev->dev_addr[i] = tuple->TupleData[i+2]; -	return 0; -}; - - -static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid) -{ -    struct net_device *dev = link->priv; -    int rc; - -    /* Read the station address from tuple 0x90, subtuple 0x04 */ -    if (pcmcia_loop_tuple(link, 0x90, pcmcia_osi_mac, dev)) -	    return -1; - -    if (((manfid == MANFID_OSITECH) && -	 (cardid == PRODID_OSITECH_SEVEN)) || -	((manfid == MANFID_PSION) && -	 (cardid == PRODID_PSION_NET100))) { -	rc = osi_load_firmware(link); -	if (rc) -		return rc; -    } else if (manfid == MANFID_OSITECH) { -	/* Make sure both functions are powered up */ -	set_bits(0x300, link->resource[0]->start + OSITECH_AUI_PWR); -	/* Now, turn on the interrupt for both card functions */ -	set_bits(0x300, link->resource[0]->start + OSITECH_RESET_ISR); -	dev_dbg(&link->dev, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n", -	      inw(link->resource[0]->start + OSITECH_AUI_PWR), -	      inw(link->resource[0]->start + OSITECH_RESET_ISR)); -    } -    return 0; -} - -static int smc91c92_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) -		netif_device_detach(dev); - -	return 0; -} - -static int smc91c92_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; -	struct smc_private *smc = netdev_priv(dev); -	int i; - -	if ((smc->manfid == MANFID_MEGAHERTZ) && -	    (smc->cardid == PRODID_MEGAHERTZ_EM3288)) -		mhz_3288_power(link); -	if (smc->manfid == MANFID_MOTOROLA) -		mot_config(link); -	if ((smc->manfid == MANFID_OSITECH) && -	    (smc->cardid != PRODID_OSITECH_SEVEN)) { -		/* Power up the card and enable interrupts */ -		set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR); -		set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR); -	} -	if (((smc->manfid == MANFID_OSITECH) && -	     (smc->cardid == PRODID_OSITECH_SEVEN)) || -	    ((smc->manfid == MANFID_PSION) && -	     (smc->cardid == PRODID_PSION_NET100))) { -		i = osi_load_firmware(link); -		if (i) { -			pr_err("smc91c92_cs: Failed to load firmware\n"); -			return i; -		} -	} -	if (link->open) { -		smc_reset(dev); -		netif_device_attach(dev); -	} - -	return 0; -} - - -/*====================================================================== - -    This verifies that the chip is some SMC91cXX variant, and returns -    the revision code if successful.  Otherwise, it returns -ENODEV. - -======================================================================*/ - -static int check_sig(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    unsigned int ioaddr = dev->base_addr; -    int width; -    u_short s; - -    SMC_SELECT_BANK(1); -    if (inw(ioaddr + BANK_SELECT) >> 8 != 0x33) { -	/* Try powering up the chip */ -	outw(0, ioaddr + CONTROL); -	mdelay(55); -    } - -    /* Try setting bus width */ -    width = (link->resource[0]->flags == IO_DATA_PATH_WIDTH_AUTO); -    s = inb(ioaddr + CONFIG); -    if (width) -	s |= CFG_16BIT; -    else -	s &= ~CFG_16BIT; -    outb(s, ioaddr + CONFIG); - -    /* Check Base Address Register to make sure bus width is OK */ -    s = inw(ioaddr + BASE_ADDR); -    if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) && -	((s >> 8) != (s & 0xff))) { -	SMC_SELECT_BANK(3); -	s = inw(ioaddr + REVISION); -	return s & 0xff; -    } - -    if (width) { -	    pr_info("using 8-bit IO window\n"); - -	    smc91c92_suspend(link); -	    pcmcia_fixup_iowidth(link); -	    smc91c92_resume(link); -	    return check_sig(link); -    } -    return -ENODEV; -} - -static int smc91c92_config(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    struct smc_private *smc = netdev_priv(dev); -    char *name; -    int i, j, rev; -    unsigned int ioaddr; -    u_long mir; - -    dev_dbg(&link->dev, "smc91c92_config\n"); - -    smc->manfid = link->manf_id; -    smc->cardid = link->card_id; - -    if ((smc->manfid == MANFID_OSITECH) && -	(smc->cardid != PRODID_OSITECH_SEVEN)) { -	i = osi_config(link); -    } else if ((smc->manfid == MANFID_MOTOROLA) || -	       ((smc->manfid == MANFID_MEGAHERTZ) && -		((smc->cardid == PRODID_MEGAHERTZ_VARIOUS) || -		 (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) { -	i = mhz_mfc_config(link); -    } else { -	i = smc_config(link); -    } -    if (i) -	    goto config_failed; - -    i = pcmcia_request_irq(link, smc_interrupt); -    if (i) -	    goto config_failed; -    i = pcmcia_enable_device(link); -    if (i) -	    goto config_failed; - -    if (smc->manfid == MANFID_MOTOROLA) -	mot_config(link); - -    dev->irq = link->irq; - -    if ((if_port >= 0) && (if_port <= 2)) -	dev->if_port = if_port; -    else -	dev_notice(&link->dev, "invalid if_port requested\n"); - -    switch (smc->manfid) { -    case MANFID_OSITECH: -    case MANFID_PSION: -	i = osi_setup(link, smc->manfid, smc->cardid); break; -    case MANFID_SMC: -    case MANFID_NEW_MEDIA: -	i = smc_setup(link); break; -    case 0x128: /* For broken Megahertz cards */ -    case MANFID_MEGAHERTZ: -	i = mhz_setup(link); break; -    case MANFID_MOTOROLA: -    default: /* get the hw address from EEPROM */ -	i = mot_setup(link); break; -    } - -    if (i != 0) { -	dev_notice(&link->dev, "Unable to find hardware address.\n"); -	goto config_failed; -    } - -    smc->duplex = 0; -    smc->rx_ovrn = 0; - -    rev = check_sig(link); -    name = "???"; -    if (rev > 0) -	switch (rev >> 4) { -	case 3: name = "92"; break; -	case 4: name = ((rev & 15) >= 6) ? "96" : "94"; break; -	case 5: name = "95"; break; -	case 7: name = "100"; break; -	case 8: name = "100-FD"; break; -	case 9: name = "110"; break; -	} - -    ioaddr = dev->base_addr; -    if (rev > 0) { -	u_long mcr; -	SMC_SELECT_BANK(0); -	mir = inw(ioaddr + MEMINFO) & 0xff; -	if (mir == 0xff) mir++; -	/* Get scale factor for memory size */ -	mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200; -	mir *= 128 * (1<<((mcr >> 9) & 7)); -	SMC_SELECT_BANK(1); -	smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT; -	smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC; -	if (smc->manfid == MANFID_OSITECH) -	    smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0; -	if ((rev >> 4) >= 7) -	    smc->cfg |= CFG_MII_SELECT; -    } else -	mir = 0; - -    if (smc->cfg & CFG_MII_SELECT) { -	SMC_SELECT_BANK(3); - -	for (i = 0; i < 32; i++) { -	    j = mdio_read(dev, i, 1); -	    if ((j != 0) && (j != 0xffff)) break; -	} -	smc->mii_if.phy_id = (i < 32) ? i : -1; - -	SMC_SELECT_BANK(0); -    } - -    SET_NETDEV_DEV(dev, &link->dev); - -    if (register_netdev(dev) != 0) { -	dev_err(&link->dev, "register_netdev() failed\n"); -	goto config_undo; -    } - -    netdev_info(dev, "smc91c%s rev %d: io %#3lx, irq %d, hw_addr %pM\n", -		name, (rev & 0x0f), dev->base_addr, dev->irq, dev->dev_addr); - -    if (rev > 0) { -	if (mir & 0x3ff) -	    netdev_info(dev, "  %lu byte", mir); -	else -	    netdev_info(dev, "  %lu kb", mir>>10); -	pr_cont(" buffer, %s xcvr\n", -		(smc->cfg & CFG_MII_SELECT) ? "MII" : if_names[dev->if_port]); -    } - -    if (smc->cfg & CFG_MII_SELECT) { -	if (smc->mii_if.phy_id != -1) { -	    netdev_dbg(dev, "  MII transceiver at index %d, status %x\n", -		       smc->mii_if.phy_id, j); -	} else { -	    netdev_notice(dev, "  No MII transceivers found!\n"); -	} -    } -    return 0; - -config_undo: -    unregister_netdev(dev); -config_failed: -    smc91c92_release(link); -    free_netdev(dev); -    return -ENODEV; -} /* smc91c92_config */ - -static void smc91c92_release(struct pcmcia_device *link) -{ -	dev_dbg(&link->dev, "smc91c92_release\n"); -	if (link->resource[2]->end) { -		struct net_device *dev = link->priv; -		struct smc_private *smc = netdev_priv(dev); -		iounmap(smc->base); -	} -	pcmcia_disable_device(link); -} - -/*====================================================================== - -    MII interface support for SMC91cXX based cards -======================================================================*/ - -#define MDIO_SHIFT_CLK		0x04 -#define MDIO_DATA_OUT		0x01 -#define MDIO_DIR_WRITE		0x08 -#define MDIO_DATA_WRITE0	(MDIO_DIR_WRITE) -#define MDIO_DATA_WRITE1	(MDIO_DIR_WRITE | MDIO_DATA_OUT) -#define MDIO_DATA_READ		0x02 - -static void mdio_sync(unsigned int addr) -{ -    int bits; -    for (bits = 0; bits < 32; bits++) { -	outb(MDIO_DATA_WRITE1, addr); -	outb(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr); -    } -} - -static int mdio_read(struct net_device *dev, int phy_id, int loc) -{ -    unsigned int addr = dev->base_addr + MGMT; -    u_int cmd = (0x06<<10)|(phy_id<<5)|loc; -    int i, retval = 0; - -    mdio_sync(addr); -    for (i = 13; i >= 0; i--) { -	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -	outb(dat, addr); -	outb(dat | MDIO_SHIFT_CLK, addr); -    } -    for (i = 19; i > 0; i--) { -	outb(0, addr); -	retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0); -	outb(MDIO_SHIFT_CLK, addr); -    } -    return (retval>>1) & 0xffff; -} - -static void mdio_write(struct net_device *dev, int phy_id, int loc, int value) -{ -    unsigned int addr = dev->base_addr + MGMT; -    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value; -    int i; - -    mdio_sync(addr); -    for (i = 31; i >= 0; i--) { -	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0; -	outb(dat, addr); -	outb(dat | MDIO_SHIFT_CLK, addr); -    } -    for (i = 1; i >= 0; i--) { -	outb(0, addr); -	outb(MDIO_SHIFT_CLK, addr); -    } -} - -/*====================================================================== - -    The driver core code, most of which should be common with a -    non-PCMCIA implementation. - -======================================================================*/ - -#ifdef PCMCIA_DEBUG -static void smc_dump(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    u_short i, w, save; -    save = inw(ioaddr + BANK_SELECT); -    for (w = 0; w < 4; w++) { -	SMC_SELECT_BANK(w); -	netdev_printk(KERN_DEBUG, dev, "bank %d: ", w); -	for (i = 0; i < 14; i += 2) -	    pr_cont(" %04x", inw(ioaddr + i)); -	pr_cont("\n"); -    } -    outw(save, ioaddr + BANK_SELECT); -} -#endif - -static int smc_open(struct net_device *dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    struct pcmcia_device *link = smc->p_dev; - -    dev_dbg(&link->dev, "%s: smc_open(%p), ID/Window %4.4x.\n", -	  dev->name, dev, inw(dev->base_addr + BANK_SELECT)); -#ifdef PCMCIA_DEBUG -    smc_dump(dev); -#endif - -    /* Check that the PCMCIA card is still here. */ -    if (!pcmcia_dev_present(link)) -	return -ENODEV; -    /* Physical device present signature. */ -    if (check_sig(link) < 0) { -	netdev_info(dev, "Yikes!  Bad chip signature!\n"); -	return -ENODEV; -    } -    link->open++; - -    netif_start_queue(dev); -    smc->saved_skb = NULL; -    smc->packets_waiting = 0; - -    smc_reset(dev); -    init_timer(&smc->media); -    smc->media.function = media_check; -    smc->media.data = (u_long) dev; -    smc->media.expires = jiffies + HZ; -    add_timer(&smc->media); - -    return 0; -} /* smc_open */ - -/*====================================================================*/ - -static int smc_close(struct net_device *dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    struct pcmcia_device *link = smc->p_dev; -    unsigned int ioaddr = dev->base_addr; - -    dev_dbg(&link->dev, "%s: smc_close(), status %4.4x.\n", -	  dev->name, inw(ioaddr + BANK_SELECT)); - -    netif_stop_queue(dev); - -    /* Shut off all interrupts, and turn off the Tx and Rx sections. -       Don't bother to check for chip present. */ -    SMC_SELECT_BANK(2);	/* Nominally paranoia, but do no assume... */ -    outw(0, ioaddr + INTERRUPT); -    SMC_SELECT_BANK(0); -    mask_bits(0xff00, ioaddr + RCR); -    mask_bits(0xff00, ioaddr + TCR); - -    /* Put the chip into power-down mode. */ -    SMC_SELECT_BANK(1); -    outw(CTL_POWERDOWN, ioaddr + CONTROL ); - -    link->open--; -    del_timer_sync(&smc->media); - -    return 0; -} /* smc_close */ - -/*====================================================================== - -   Transfer a packet to the hardware and trigger the packet send. -   This may be called at either from either the Tx queue code -   or the interrupt handler. - -======================================================================*/ - -static void smc_hardware_send_packet(struct net_device * dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    struct sk_buff *skb = smc->saved_skb; -    unsigned int ioaddr = dev->base_addr; -    u_char packet_no; - -    if (!skb) { -	netdev_err(dev, "In XMIT with no packet to send\n"); -	return; -    } - -    /* There should be a packet slot waiting. */ -    packet_no = inw(ioaddr + PNR_ARR) >> 8; -    if (packet_no & 0x80) { -	/* If not, there is a hardware problem!  Likely an ejected card. */ -	netdev_warn(dev, "hardware Tx buffer allocation failed, status %#2.2x\n", -		    packet_no); -	dev_kfree_skb_irq(skb); -	smc->saved_skb = NULL; -	netif_start_queue(dev); -	return; -    } - -    dev->stats.tx_bytes += skb->len; -    /* The card should use the just-allocated buffer. */ -    outw(packet_no, ioaddr + PNR_ARR); -    /* point to the beginning of the packet */ -    outw(PTR_AUTOINC , ioaddr + POINTER); - -    /* Send the packet length (+6 for status, length and ctl byte) -       and the status word (set to zeros). */ -    { -	u_char *buf = skb->data; -	u_int length = skb->len; /* The chip will pad to ethernet min. */ - -	netdev_dbg(dev, "Trying to xmit packet of length %d\n", length); -	 -	/* send the packet length: +6 for status word, length, and ctl */ -	outw(0, ioaddr + DATA_1); -	outw(length + 6, ioaddr + DATA_1); -	outsw(ioaddr + DATA_1, buf, length >> 1); -	 -	/* The odd last byte, if there is one, goes in the control word. */ -	outw((length & 1) ? 0x2000 | buf[length-1] : 0, ioaddr + DATA_1); -    } - -    /* Enable the Tx interrupts, both Tx (TxErr) and TxEmpty. */ -    outw(((IM_TX_INT|IM_TX_EMPTY_INT)<<8) | -	 (inw(ioaddr + INTERRUPT) & 0xff00), -	 ioaddr + INTERRUPT); - -    /* The chip does the rest of the work. */ -    outw(MC_ENQUEUE , ioaddr + MMU_CMD); - -    smc->saved_skb = NULL; -    dev_kfree_skb_irq(skb); -    dev->trans_start = jiffies; -    netif_start_queue(dev); -} - -/*====================================================================*/ - -static void smc_tx_timeout(struct net_device *dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; - -    netdev_notice(dev, "transmit timed out, Tx_status %2.2x status %4.4x.\n", -		  inw(ioaddr)&0xff, inw(ioaddr + 2)); -    dev->stats.tx_errors++; -    smc_reset(dev); -    dev->trans_start = jiffies; /* prevent tx timeout */ -    smc->saved_skb = NULL; -    netif_wake_queue(dev); -} - -static netdev_tx_t smc_start_xmit(struct sk_buff *skb, -					struct net_device *dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    u_short num_pages; -    short time_out, ir; -    unsigned long flags; - -    netif_stop_queue(dev); - -    netdev_dbg(dev, "smc_start_xmit(length = %d) called, status %04x\n", -	       skb->len, inw(ioaddr + 2)); - -    if (smc->saved_skb) { -	/* THIS SHOULD NEVER HAPPEN. */ -	dev->stats.tx_aborted_errors++; -	netdev_printk(KERN_DEBUG, dev, -		      "Internal error -- sent packet while busy\n"); -	return NETDEV_TX_BUSY; -    } -    smc->saved_skb = skb; - -    num_pages = skb->len >> 8; - -    if (num_pages > 7) { -	netdev_err(dev, "Far too big packet error: %d pages\n", num_pages); -	dev_kfree_skb (skb); -	smc->saved_skb = NULL; -	dev->stats.tx_dropped++; -	return NETDEV_TX_OK;		/* Do not re-queue this packet. */ -    } -    /* A packet is now waiting. */ -    smc->packets_waiting++; - -    spin_lock_irqsave(&smc->lock, flags); -    SMC_SELECT_BANK(2);	/* Paranoia, we should always be in window 2 */ - -    /* need MC_RESET to keep the memory consistent. errata? */ -    if (smc->rx_ovrn) { -	outw(MC_RESET, ioaddr + MMU_CMD); -	smc->rx_ovrn = 0; -    } - -    /* Allocate the memory; send the packet now if we win. */ -    outw(MC_ALLOC | num_pages, ioaddr + MMU_CMD); -    for (time_out = MEMORY_WAIT_TIME; time_out >= 0; time_out--) { -	ir = inw(ioaddr+INTERRUPT); -	if (ir & IM_ALLOC_INT) { -	    /* Acknowledge the interrupt, send the packet. */ -	    outw((ir&0xff00) | IM_ALLOC_INT, ioaddr + INTERRUPT); -	    smc_hardware_send_packet(dev);	/* Send the packet now.. */ -	    spin_unlock_irqrestore(&smc->lock, flags); -	    return NETDEV_TX_OK; -	} -    } - -    /* Otherwise defer until the Tx-space-allocated interrupt. */ -    pr_debug("%s: memory allocation deferred.\n", dev->name); -    outw((IM_ALLOC_INT << 8) | (ir & 0xff00), ioaddr + INTERRUPT); -    spin_unlock_irqrestore(&smc->lock, flags); - -    return NETDEV_TX_OK; -} - -/*====================================================================== - -    Handle a Tx anomolous event.  Entered while in Window 2. - -======================================================================*/ - -static void smc_tx_err(struct net_device * dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    int saved_packet = inw(ioaddr + PNR_ARR) & 0xff; -    int packet_no = inw(ioaddr + FIFO_PORTS) & 0x7f; -    int tx_status; - -    /* select this as the packet to read from */ -    outw(packet_no, ioaddr + PNR_ARR); - -    /* read the first word from this packet */ -    outw(PTR_AUTOINC | PTR_READ | 0, ioaddr + POINTER); - -    tx_status = inw(ioaddr + DATA_1); - -    dev->stats.tx_errors++; -    if (tx_status & TS_LOSTCAR) dev->stats.tx_carrier_errors++; -    if (tx_status & TS_LATCOL)  dev->stats.tx_window_errors++; -    if (tx_status & TS_16COL) { -	dev->stats.tx_aborted_errors++; -	smc->tx_err++; -    } - -    if (tx_status & TS_SUCCESS) { -	netdev_notice(dev, "Successful packet caused error interrupt?\n"); -    } -    /* re-enable transmit */ -    SMC_SELECT_BANK(0); -    outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR); -    SMC_SELECT_BANK(2); - -    outw(MC_FREEPKT, ioaddr + MMU_CMD); 	/* Free the packet memory. */ - -    /* one less packet waiting for me */ -    smc->packets_waiting--; - -    outw(saved_packet, ioaddr + PNR_ARR); -} - -/*====================================================================*/ - -static void smc_eph_irq(struct net_device *dev) -{ -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    u_short card_stats, ephs; - -    SMC_SELECT_BANK(0); -    ephs = inw(ioaddr + EPH); -    pr_debug("%s: Ethernet protocol handler interrupt, status" -	  " %4.4x.\n", dev->name, ephs); -    /* Could be a counter roll-over warning: update stats. */ -    card_stats = inw(ioaddr + COUNTER); -    /* single collisions */ -    dev->stats.collisions += card_stats & 0xF; -    card_stats >>= 4; -    /* multiple collisions */ -    dev->stats.collisions += card_stats & 0xF; -#if 0 		/* These are for when linux supports these statistics */ -    card_stats >>= 4;			/* deferred */ -    card_stats >>= 4;			/* excess deferred */ -#endif -    /* If we had a transmit error we must re-enable the transmitter. */ -    outw(inw(ioaddr + TCR) | TCR_ENABLE | smc->duplex, ioaddr + TCR); - -    /* Clear a link error interrupt. */ -    SMC_SELECT_BANK(1); -    outw(CTL_AUTO_RELEASE | 0x0000, ioaddr + CONTROL); -    outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE, -	 ioaddr + CONTROL); -    SMC_SELECT_BANK(2); -} - -/*====================================================================*/ - -static irqreturn_t smc_interrupt(int irq, void *dev_id) -{ -    struct net_device *dev = dev_id; -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr; -    u_short saved_bank, saved_pointer, mask, status; -    unsigned int handled = 1; -    char bogus_cnt = INTR_WORK;		/* Work we are willing to do. */ - -    if (!netif_device_present(dev)) -	return IRQ_NONE; - -    ioaddr = dev->base_addr; - -    pr_debug("%s: SMC91c92 interrupt %d at %#x.\n", dev->name, -	  irq, ioaddr); - -    spin_lock(&smc->lock); -    smc->watchdog = 0; -    saved_bank = inw(ioaddr + BANK_SELECT); -    if ((saved_bank & 0xff00) != 0x3300) { -	/* The device does not exist -- the card could be off-line, or -	   maybe it has been ejected. */ -	pr_debug("%s: SMC91c92 interrupt %d for non-existent" -	      "/ejected device.\n", dev->name, irq); -	handled = 0; -	goto irq_done; -    } - -    SMC_SELECT_BANK(2); -    saved_pointer = inw(ioaddr + POINTER); -    mask = inw(ioaddr + INTERRUPT) >> 8; -    /* clear all interrupts */ -    outw(0, ioaddr + INTERRUPT); - -    do { /* read the status flag, and mask it */ -	status = inw(ioaddr + INTERRUPT) & 0xff; -	pr_debug("%s: Status is %#2.2x (mask %#2.2x).\n", dev->name, -	      status, mask); -	if ((status & mask) == 0) { -	    if (bogus_cnt == INTR_WORK) -		handled = 0; -	    break; -	} -	if (status & IM_RCV_INT) { -	    /* Got a packet(s). */ -	    smc_rx(dev); -	} -	if (status & IM_TX_INT) { -	    smc_tx_err(dev); -	    outw(IM_TX_INT, ioaddr + INTERRUPT); -	} -	status &= mask; -	if (status & IM_TX_EMPTY_INT) { -	    outw(IM_TX_EMPTY_INT, ioaddr + INTERRUPT); -	    mask &= ~IM_TX_EMPTY_INT; -	    dev->stats.tx_packets += smc->packets_waiting; -	    smc->packets_waiting = 0; -	} -	if (status & IM_ALLOC_INT) { -	    /* Clear this interrupt so it doesn't happen again */ -	    mask &= ~IM_ALLOC_INT; -	 -	    smc_hardware_send_packet(dev); -	 -	    /* enable xmit interrupts based on this */ -	    mask |= (IM_TX_EMPTY_INT | IM_TX_INT); -	 -	    /* and let the card send more packets to me */ -	    netif_wake_queue(dev); -	} -	if (status & IM_RX_OVRN_INT) { -	    dev->stats.rx_errors++; -	    dev->stats.rx_fifo_errors++; -	    if (smc->duplex) -		smc->rx_ovrn = 1; /* need MC_RESET outside smc_interrupt */ -	    outw(IM_RX_OVRN_INT, ioaddr + INTERRUPT); -	} -	if (status & IM_EPH_INT) -	    smc_eph_irq(dev); -    } while (--bogus_cnt); - -    pr_debug("  Restoring saved registers mask %2.2x bank %4.4x" -	  " pointer %4.4x.\n", mask, saved_bank, saved_pointer); - -    /* restore state register */ -    outw((mask<<8), ioaddr + INTERRUPT); -    outw(saved_pointer, ioaddr + POINTER); -    SMC_SELECT_BANK(saved_bank); - -    pr_debug("%s: Exiting interrupt IRQ%d.\n", dev->name, irq); - -irq_done: - -    if ((smc->manfid == MANFID_OSITECH) && -	(smc->cardid != PRODID_OSITECH_SEVEN)) { -	/* Retrigger interrupt if needed */ -	mask_bits(0x00ff, ioaddr-0x10+OSITECH_RESET_ISR); -	set_bits(0x0300, ioaddr-0x10+OSITECH_RESET_ISR); -    } -    if (smc->manfid == MANFID_MOTOROLA) { -	u_char cor; -	cor = readb(smc->base + MOT_UART + CISREG_COR); -	writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_UART + CISREG_COR); -	writeb(cor, smc->base + MOT_UART + CISREG_COR); -	cor = readb(smc->base + MOT_LAN + CISREG_COR); -	writeb(cor & ~COR_IREQ_ENA, smc->base + MOT_LAN + CISREG_COR); -	writeb(cor, smc->base + MOT_LAN + CISREG_COR); -    } - -    if ((smc->base != NULL) &&  /* Megahertz MFC's */ -	(smc->manfid == MANFID_MEGAHERTZ) && -	(smc->cardid == PRODID_MEGAHERTZ_EM3288)) { - -	u_char tmp; -	tmp = readb(smc->base+MEGAHERTZ_ISR); -	tmp = readb(smc->base+MEGAHERTZ_ISR); - -	/* Retrigger interrupt if needed */ -	writeb(tmp, smc->base + MEGAHERTZ_ISR); -	writeb(tmp, smc->base + MEGAHERTZ_ISR); -    } - -    spin_unlock(&smc->lock); -    return IRQ_RETVAL(handled); -} - -/*====================================================================*/ - -static void smc_rx(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    int rx_status; -    int packet_length;	/* Caution: not frame length, rather words -			   to transfer from the chip. */ - -    /* Assertion: we are in Window 2. */ - -    if (inw(ioaddr + FIFO_PORTS) & FP_RXEMPTY) { -	netdev_err(dev, "smc_rx() with nothing on Rx FIFO\n"); -	return; -    } - -    /*  Reset the read pointer, and read the status and packet length. */ -    outw(PTR_READ | PTR_RCV | PTR_AUTOINC, ioaddr + POINTER); -    rx_status = inw(ioaddr + DATA_1); -    packet_length = inw(ioaddr + DATA_1) & 0x07ff; - -    pr_debug("%s: Receive status %4.4x length %d.\n", -	  dev->name, rx_status, packet_length); - -    if (!(rx_status & RS_ERRORS)) {		 -	/* do stuff to make a new packet */ -	struct sk_buff *skb; -	 -	/* Note: packet_length adds 5 or 6 extra bytes here! */ -	skb = dev_alloc_skb(packet_length+2); -	 -	if (skb == NULL) { -	    pr_debug("%s: Low memory, packet dropped.\n", dev->name); -	    dev->stats.rx_dropped++; -	    outw(MC_RELEASE, ioaddr + MMU_CMD); -	    return; -	} -	 -	packet_length -= (rx_status & RS_ODDFRAME ? 5 : 6); -	skb_reserve(skb, 2); -	insw(ioaddr+DATA_1, skb_put(skb, packet_length), -	     (packet_length+1)>>1); -	skb->protocol = eth_type_trans(skb, dev); -	 -	netif_rx(skb); -	dev->last_rx = jiffies; -	dev->stats.rx_packets++; -	dev->stats.rx_bytes += packet_length; -	if (rx_status & RS_MULTICAST) -	    dev->stats.multicast++; -    } else { -	/* error ... */ -	dev->stats.rx_errors++; -	 -	if (rx_status & RS_ALGNERR)  dev->stats.rx_frame_errors++; -	if (rx_status & (RS_TOOSHORT | RS_TOOLONG)) -	    dev->stats.rx_length_errors++; -	if (rx_status & RS_BADCRC)	dev->stats.rx_crc_errors++; -    } -    /* Let the MMU free the memory of this packet. */ -    outw(MC_RELEASE, ioaddr + MMU_CMD); -} - -/*====================================================================== - -    Set the receive mode. - -    This routine is used by both the protocol level to notify us of -    promiscuous/multicast mode changes, and by the open/reset code to -    initialize the Rx registers.  We always set the multicast list and -    leave the receiver running. - -======================================================================*/ - -static void set_rx_mode(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    struct smc_private *smc = netdev_priv(dev); -    unsigned char multicast_table[8]; -    unsigned long flags; -    u_short rx_cfg_setting; -    int i; - -    memset(multicast_table, 0, sizeof(multicast_table)); - -    if (dev->flags & IFF_PROMISC) { -	rx_cfg_setting = RxStripCRC | RxEnable | RxPromisc | RxAllMulti; -    } else if (dev->flags & IFF_ALLMULTI) -	rx_cfg_setting = RxStripCRC | RxEnable | RxAllMulti; -    else { -	if (!netdev_mc_empty(dev)) { -	    struct netdev_hw_addr *ha; - -	    netdev_for_each_mc_addr(ha, dev) { -		u_int position = ether_crc(6, ha->addr); -		multicast_table[position >> 29] |= 1 << ((position >> 26) & 7); -	    } -	} -	rx_cfg_setting = RxStripCRC | RxEnable; -    } - -    /* Load MC table and Rx setting into the chip without interrupts. */ -    spin_lock_irqsave(&smc->lock, flags); -    SMC_SELECT_BANK(3); -    for (i = 0; i < 8; i++) -	outb(multicast_table[i], ioaddr + MULTICAST0 + i); -    SMC_SELECT_BANK(0); -    outw(rx_cfg_setting, ioaddr + RCR); -    SMC_SELECT_BANK(2); -    spin_unlock_irqrestore(&smc->lock, flags); -} - -/*====================================================================== - -    Senses when a card's config changes. Here, it's coax or TP. - -======================================================================*/ - -static int s9k_config(struct net_device *dev, struct ifmap *map) -{ -    struct smc_private *smc = netdev_priv(dev); -    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { -	if (smc->cfg & CFG_MII_SELECT) -	    return -EOPNOTSUPP; -	else if (map->port > 2) -	    return -EINVAL; -	dev->if_port = map->port; -	netdev_info(dev, "switched to %s port\n", if_names[dev->if_port]); -	smc_reset(dev); -    } -    return 0; -} - -/*====================================================================== - -    Reset the chip, reloading every register that might be corrupted. - -======================================================================*/ - -/* -  Set transceiver type, perhaps to something other than what the user -  specified in dev->if_port. -*/ -static void smc_set_xcvr(struct net_device *dev, int if_port) -{ -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    u_short saved_bank; - -    saved_bank = inw(ioaddr + BANK_SELECT); -    SMC_SELECT_BANK(1); -    if (if_port == 2) { -	outw(smc->cfg | CFG_AUI_SELECT, ioaddr + CONFIG); -	if ((smc->manfid == MANFID_OSITECH) && -	    (smc->cardid != PRODID_OSITECH_SEVEN)) -	    set_bits(OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR); -	smc->media_status = ((dev->if_port == 0) ? 0x0001 : 0x0002); -    } else { -	outw(smc->cfg, ioaddr + CONFIG); -	if ((smc->manfid == MANFID_OSITECH) && -	    (smc->cardid != PRODID_OSITECH_SEVEN)) -	    mask_bits(~OSI_AUI_PWR, ioaddr - 0x10 + OSITECH_AUI_PWR); -	smc->media_status = ((dev->if_port == 0) ? 0x0012 : 0x4001); -    } -    SMC_SELECT_BANK(saved_bank); -} - -static void smc_reset(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    struct smc_private *smc = netdev_priv(dev); -    int i; - -    pr_debug("%s: smc91c92 reset called.\n", dev->name); - -    /* The first interaction must be a write to bring the chip out -       of sleep mode. */ -    SMC_SELECT_BANK(0); -    /* Reset the chip. */ -    outw(RCR_SOFTRESET, ioaddr + RCR); -    udelay(10); - -    /* Clear the transmit and receive configuration registers. */ -    outw(RCR_CLEAR, ioaddr + RCR); -    outw(TCR_CLEAR, ioaddr + TCR); - -    /* Set the Window 1 control, configuration and station addr registers. -       No point in writing the I/O base register ;-> */ -    SMC_SELECT_BANK(1); -    /* Automatically release successfully transmitted packets, -       Accept link errors, counter and Tx error interrupts. */ -    outw(CTL_AUTO_RELEASE | CTL_TE_ENABLE | CTL_CR_ENABLE, -	 ioaddr + CONTROL); -    smc_set_xcvr(dev, dev->if_port); -    if ((smc->manfid == MANFID_OSITECH) && -	(smc->cardid != PRODID_OSITECH_SEVEN)) -	outw((dev->if_port == 2 ? OSI_AUI_PWR : 0) | -	     (inw(ioaddr-0x10+OSITECH_AUI_PWR) & 0xff00), -	     ioaddr - 0x10 + OSITECH_AUI_PWR); - -    /* Fill in the physical address.  The databook is wrong about the order! */ -    for (i = 0; i < 6; i += 2) -	outw((dev->dev_addr[i+1]<<8)+dev->dev_addr[i], -	     ioaddr + ADDR0 + i); - -    /* Reset the MMU */ -    SMC_SELECT_BANK(2); -    outw(MC_RESET, ioaddr + MMU_CMD); -    outw(0, ioaddr + INTERRUPT); - -    /* Re-enable the chip. */ -    SMC_SELECT_BANK(0); -    outw(((smc->cfg & CFG_MII_SELECT) ? 0 : TCR_MONCSN) | -	 TCR_ENABLE | TCR_PAD_EN | smc->duplex, ioaddr + TCR); -    set_rx_mode(dev); - -    if (smc->cfg & CFG_MII_SELECT) { -	SMC_SELECT_BANK(3); - -	/* Reset MII */ -	mdio_write(dev, smc->mii_if.phy_id, 0, 0x8000); - -	/* Advertise 100F, 100H, 10F, 10H */ -	mdio_write(dev, smc->mii_if.phy_id, 4, 0x01e1); - -	/* Restart MII autonegotiation */ -	mdio_write(dev, smc->mii_if.phy_id, 0, 0x0000); -	mdio_write(dev, smc->mii_if.phy_id, 0, 0x1200); -    } - -    /* Enable interrupts. */ -    SMC_SELECT_BANK(2); -    outw((IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT) << 8, -	 ioaddr + INTERRUPT); -} - -/*====================================================================== - -    Media selection timer routine - -======================================================================*/ - -static void media_check(u_long arg) -{ -    struct net_device *dev = (struct net_device *) arg; -    struct smc_private *smc = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    u_short i, media, saved_bank; -    u_short link; -    unsigned long flags; - -    spin_lock_irqsave(&smc->lock, flags); - -    saved_bank = inw(ioaddr + BANK_SELECT); - -    if (!netif_device_present(dev)) -	goto reschedule; - -    SMC_SELECT_BANK(2); - -    /* need MC_RESET to keep the memory consistent. errata? */ -    if (smc->rx_ovrn) { -	outw(MC_RESET, ioaddr + MMU_CMD); -	smc->rx_ovrn = 0; -    } -    i = inw(ioaddr + INTERRUPT); -    SMC_SELECT_BANK(0); -    media = inw(ioaddr + EPH) & EPH_LINK_OK; -    SMC_SELECT_BANK(1); -    media |= (inw(ioaddr + CONFIG) & CFG_AUI_SELECT) ? 2 : 1; - -    SMC_SELECT_BANK(saved_bank); -    spin_unlock_irqrestore(&smc->lock, flags); - -    /* Check for pending interrupt with watchdog flag set: with -       this, we can limp along even if the interrupt is blocked */ -    if (smc->watchdog++ && ((i>>8) & i)) { -	if (!smc->fast_poll) -	    netdev_info(dev, "interrupt(s) dropped!\n"); -	local_irq_save(flags); -	smc_interrupt(dev->irq, dev); -	local_irq_restore(flags); -	smc->fast_poll = HZ; -    } -    if (smc->fast_poll) { -	smc->fast_poll--; -	smc->media.expires = jiffies + HZ/100; -	add_timer(&smc->media); -	return; -    } - -    spin_lock_irqsave(&smc->lock, flags); - -    saved_bank = inw(ioaddr + BANK_SELECT); - -    if (smc->cfg & CFG_MII_SELECT) { -	if (smc->mii_if.phy_id < 0) -	    goto reschedule; - -	SMC_SELECT_BANK(3); -	link = mdio_read(dev, smc->mii_if.phy_id, 1); -	if (!link || (link == 0xffff)) { -	    netdev_info(dev, "MII is missing!\n"); -	    smc->mii_if.phy_id = -1; -	    goto reschedule; -	} - -	link &= 0x0004; -	if (link != smc->link_status) { -	    u_short p = mdio_read(dev, smc->mii_if.phy_id, 5); -	    netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); -	    smc->duplex = (((p & 0x0100) || ((p & 0x1c0) == 0x40)) -			   ? TCR_FDUPLX : 0); -	    if (link) { -		netdev_info(dev, "autonegotiation complete: " -			    "%dbaseT-%cD selected\n", -			    (p & 0x0180) ? 100 : 10, smc->duplex ? 'F' : 'H'); -	    } -	    SMC_SELECT_BANK(0); -	    outw(inw(ioaddr + TCR) | smc->duplex, ioaddr + TCR); -	    smc->link_status = link; -	} -	goto reschedule; -    } - -    /* Ignore collisions unless we've had no rx's recently */ -    if (time_after(jiffies, dev->last_rx + HZ)) { -	if (smc->tx_err || (smc->media_status & EPH_16COL)) -	    media |= EPH_16COL; -    } -    smc->tx_err = 0; - -    if (media != smc->media_status) { -	if ((media & smc->media_status & 1) && -	    ((smc->media_status ^ media) & EPH_LINK_OK)) -	    netdev_info(dev, "%s link beat\n", -			smc->media_status & EPH_LINK_OK ? "lost" : "found"); -	else if ((media & smc->media_status & 2) && -		 ((smc->media_status ^ media) & EPH_16COL)) -	    netdev_info(dev, "coax cable %s\n", -			media & EPH_16COL ? "problem" : "ok"); -	if (dev->if_port == 0) { -	    if (media & 1) { -		if (media & EPH_LINK_OK) -		    netdev_info(dev, "flipped to 10baseT\n"); -		else -		    smc_set_xcvr(dev, 2); -	    } else { -		if (media & EPH_16COL) -		    smc_set_xcvr(dev, 1); -		else -		    netdev_info(dev, "flipped to 10base2\n"); -	    } -	} -	smc->media_status = media; -    } - -reschedule: -    smc->media.expires = jiffies + HZ; -    add_timer(&smc->media); -    SMC_SELECT_BANK(saved_bank); -    spin_unlock_irqrestore(&smc->lock, flags); -} - -static int smc_link_ok(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    struct smc_private *smc = netdev_priv(dev); - -    if (smc->cfg & CFG_MII_SELECT) { -	return mii_link_ok(&smc->mii_if); -    } else { -        SMC_SELECT_BANK(0); -	return inw(ioaddr + EPH) & EPH_LINK_OK; -    } -} - -static int smc_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) -{ -    u16 tmp; -    unsigned int ioaddr = dev->base_addr; - -    ecmd->supported = (SUPPORTED_TP | SUPPORTED_AUI | -	SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full); -		 -    SMC_SELECT_BANK(1); -    tmp = inw(ioaddr + CONFIG); -    ecmd->port = (tmp & CFG_AUI_SELECT) ? PORT_AUI : PORT_TP; -    ecmd->transceiver = XCVR_INTERNAL; -    ecmd->speed = SPEED_10; -    ecmd->phy_address = ioaddr + MGMT; - -    SMC_SELECT_BANK(0); -    tmp = inw(ioaddr + TCR); -    ecmd->duplex = (tmp & TCR_FDUPLX) ? DUPLEX_FULL : DUPLEX_HALF; - -    return 0; -} - -static int smc_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd) -{ -    u16 tmp; -    unsigned int ioaddr = dev->base_addr; - -    if (ecmd->speed != SPEED_10) -    	return -EINVAL; -    if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) -    	return -EINVAL; -    if (ecmd->port != PORT_TP && ecmd->port != PORT_AUI) -	return -EINVAL; -    if (ecmd->transceiver != XCVR_INTERNAL) -    	return -EINVAL; - -    if (ecmd->port == PORT_AUI) -	smc_set_xcvr(dev, 1); -    else -	smc_set_xcvr(dev, 0); - -    SMC_SELECT_BANK(0); -    tmp = inw(ioaddr + TCR); -    if (ecmd->duplex == DUPLEX_FULL) -	tmp |= TCR_FDUPLX; -    else -	tmp &= ~TCR_FDUPLX; -    outw(tmp, ioaddr + TCR); -	 -    return 0; -} - -static int check_if_running(struct net_device *dev) -{ -	if (!netif_running(dev)) -		return -EINVAL; -	return 0; -} - -static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ -	strcpy(info->driver, DRV_NAME); -	strcpy(info->version, DRV_VERSION); -} - -static int smc_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ -	struct smc_private *smc = netdev_priv(dev); -	unsigned int ioaddr = dev->base_addr; -	u16 saved_bank = inw(ioaddr + BANK_SELECT); -	int ret; -	unsigned long flags; - -	spin_lock_irqsave(&smc->lock, flags); -	SMC_SELECT_BANK(3); -	if (smc->cfg & CFG_MII_SELECT) -		ret = mii_ethtool_gset(&smc->mii_if, ecmd); -	else -		ret = smc_netdev_get_ecmd(dev, ecmd); -	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irqrestore(&smc->lock, flags); -	return ret; -} - -static int smc_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ -	struct smc_private *smc = netdev_priv(dev); -	unsigned int ioaddr = dev->base_addr; -	u16 saved_bank = inw(ioaddr + BANK_SELECT); -	int ret; -	unsigned long flags; - -	spin_lock_irqsave(&smc->lock, flags); -	SMC_SELECT_BANK(3); -	if (smc->cfg & CFG_MII_SELECT) -		ret = mii_ethtool_sset(&smc->mii_if, ecmd); -	else -		ret = smc_netdev_set_ecmd(dev, ecmd); -	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irqrestore(&smc->lock, flags); -	return ret; -} - -static u32 smc_get_link(struct net_device *dev) -{ -	struct smc_private *smc = netdev_priv(dev); -	unsigned int ioaddr = dev->base_addr; -	u16 saved_bank = inw(ioaddr + BANK_SELECT); -	u32 ret; -	unsigned long flags; - -	spin_lock_irqsave(&smc->lock, flags); -	SMC_SELECT_BANK(3); -	ret = smc_link_ok(dev); -	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irqrestore(&smc->lock, flags); -	return ret; -} - -static int smc_nway_reset(struct net_device *dev) -{ -	struct smc_private *smc = netdev_priv(dev); -	if (smc->cfg & CFG_MII_SELECT) { -		unsigned int ioaddr = dev->base_addr; -		u16 saved_bank = inw(ioaddr + BANK_SELECT); -		int res; - -		SMC_SELECT_BANK(3); -		res = mii_nway_restart(&smc->mii_if); -		SMC_SELECT_BANK(saved_bank); - -		return res; -	} else -		return -EOPNOTSUPP; -} - -static const struct ethtool_ops ethtool_ops = { -	.begin = check_if_running, -	.get_drvinfo = smc_get_drvinfo, -	.get_settings = smc_get_settings, -	.set_settings = smc_set_settings, -	.get_link = smc_get_link, -	.nway_reset = smc_nway_reset, -}; - -static int smc_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) -{ -	struct smc_private *smc = netdev_priv(dev); -	struct mii_ioctl_data *mii = if_mii(rq); -	int rc = 0; -	u16 saved_bank; -	unsigned int ioaddr = dev->base_addr; -	unsigned long flags; - -	if (!netif_running(dev)) -		return -EINVAL; - -	spin_lock_irqsave(&smc->lock, flags); -	saved_bank = inw(ioaddr + BANK_SELECT); -	SMC_SELECT_BANK(3); -	rc = generic_mii_ioctl(&smc->mii_if, mii, cmd, NULL); -	SMC_SELECT_BANK(saved_bank); -	spin_unlock_irqrestore(&smc->lock, flags); -	return rc; -} - -static struct pcmcia_device_id smc91c92_ids[] = { -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0109, 0x0501), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0140, 0x000a), -	PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3288", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x04cd2988, 0x46a52d63), -	PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "CC/XJEM3336", "DATA/FAX/CELL ETHERNET MODEM", 0xf510db04, 0x0143b773, 0x46a52d63), -	PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "EM1144T", "PCMCIA MODEM", 0xf510db04, 0x856d66c8, 0xbd6c43ef), -	PCMCIA_PFC_DEVICE_PROD_ID123(0, "MEGAHERTZ", "XJEM1144/CCEM1144", "PCMCIA MODEM", 0xf510db04, 0x52d21e1e, 0xbd6c43ef), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Gateway 2000", "XJEM3336", 0xdd9989be, 0x662c394c), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "MEGAHERTZ", "XJEM1144/CCEM1144", 0xf510db04, 0x52d21e1e), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Diamonds Modem+Ethernet", 0xc2f80cd, 0x656947b9), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Ositech", "Trumpcard:Jack of Hearts Modem+Ethernet", 0xc2f80cd, 0xdc9ba5ed), -	PCMCIA_MFC_DEVICE_MANF_CARD(0, 0x016c, 0x0020), -	PCMCIA_DEVICE_MANF_CARD(0x016c, 0x0023), -	PCMCIA_DEVICE_PROD_ID123("BASICS by New Media Corporation", "Ethernet", "SMC91C94", 0x23c78a9d, 0x00b2e941, 0xcef397fb), -	PCMCIA_DEVICE_PROD_ID12("ARGOSY", "Fast Ethernet PCCard", 0x78f308dc, 0xdcea68bc), -	PCMCIA_DEVICE_PROD_ID12("dit Co., Ltd.", "PC Card-10/100BTX", 0xe59365c8, 0x6a2161d1), -	PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L100C", 0x6a26d1cf, 0xc16ce9c5), -	PCMCIA_DEVICE_PROD_ID12("Farallon", "Farallon Enet", 0x58d93fc4, 0x244734e9), -	PCMCIA_DEVICE_PROD_ID12("Megahertz", "CC10BT/2", 0x33234748, 0x3c95b953), -	PCMCIA_DEVICE_PROD_ID12("MELCO/SMC", "LPC-TX", 0xa2cd8e6d, 0x42da662a), -	PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Four of Diamonds Ethernet", 0xc2f80cd, 0xb3466314), -	PCMCIA_DEVICE_PROD_ID12("Ositech", "Trumpcard:Seven of Diamonds Ethernet", 0xc2f80cd, 0x194b650a), -	PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast Ethernet PCCard", 0x281f1c5d, 0xdcea68bc), -	PCMCIA_DEVICE_PROD_ID12("Psion", "10Mb Ethernet", 0x4ef00b21, 0x844be9e9), -	PCMCIA_DEVICE_PROD_ID12("SMC", "EtherEZ Ethernet 8020", 0xc4f8b18b, 0x4a0eeb2d), -	/* These conflict with other cards! */ -	/* PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0100), */ -	/* PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab), */ -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, smc91c92_ids); - -static struct pcmcia_driver smc91c92_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "smc91c92_cs", -	.probe		= smc91c92_probe, -	.remove		= smc91c92_detach, -	.id_table       = smc91c92_ids, -	.suspend	= smc91c92_suspend, -	.resume		= smc91c92_resume, -}; - -static int __init init_smc91c92_cs(void) -{ -	return pcmcia_register_driver(&smc91c92_cs_driver); -} - -static void __exit exit_smc91c92_cs(void) -{ -	pcmcia_unregister_driver(&smc91c92_cs_driver); -} - -module_init(init_smc91c92_cs); -module_exit(exit_smc91c92_cs); diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c deleted file mode 100644 index a46b7fd6c0f..00000000000 --- a/drivers/net/pcmcia/xirc2ps_cs.c +++ /dev/null @@ -1,1813 +0,0 @@ -/* [xirc2ps_cs.c wk 03.11.99] (1.40 1999/11/18 00:06:03) - * Xircom CreditCard Ethernet Adapter IIps driver - * Xircom Realport 10/100 (RE-100) driver  - * - * This driver supports various Xircom CreditCard Ethernet adapters - * including the CE2, CE IIps, RE-10, CEM28, CEM33, CE33, CEM56, - * CE3-100, CE3B, RE-100, REM10BT, and REM56G-100. - * - * 2000-09-24 <psheer@icon.co.za> The Xircom CE3B-100 may not - * autodetect the media properly. In this case use the - * if_port=1 (for 10BaseT) or if_port=4 (for 100BaseT) options - * to force the media type. - *  - * Written originally by Werner Koch based on David Hinds' skeleton of the - * PCMCIA driver. - * - * Copyright (c) 1997,1998 Werner Koch (dd9jn) - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * It is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * - * ALTERNATIVELY, this driver may be distributed under the terms of - * the following license, in which case the provisions of this license - * are required INSTEAD OF the GNU General Public License.  (This clause - * is necessary due to a potential bad interaction between the GPL and - * the restrictions contained in a BSD-style copyright.) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, and the entire permission notice in its entirety, - *    including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - *    products derived from this software without specific prior - *    written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/interrupt.h> -#include <linux/in.h> -#include <linux/delay.h> -#include <linux/ethtool.h> -#include <linux/netdevice.h> -#include <linux/etherdevice.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/ioport.h> -#include <linux/bitops.h> -#include <linux/mii.h> - -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ciscode.h> - -#include <asm/io.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#ifndef MANFID_COMPAQ -  #define MANFID_COMPAQ 	   0x0138 -  #define MANFID_COMPAQ2	   0x0183  /* is this correct? */ -#endif - -#include <pcmcia/ds.h> - -/* Time in jiffies before concluding Tx hung */ -#define TX_TIMEOUT	((400*HZ)/1000) - -/**************** - * Some constants used to access the hardware - */ - -/* Register offsets and value constans */ -#define XIRCREG_CR  0	/* Command register (wr) */ -enum xirc_cr { -    TransmitPacket = 0x01, -    SoftReset = 0x02, -    EnableIntr = 0x04, -    ForceIntr  = 0x08, -    ClearTxFIFO = 0x10, -    ClearRxOvrun = 0x20, -    RestartTx	 = 0x40 -}; -#define XIRCREG_ESR 0	/* Ethernet status register (rd) */ -enum xirc_esr { -    FullPktRcvd = 0x01, /* full packet in receive buffer */ -    PktRejected = 0x04, /* a packet has been rejected */ -    TxPktPend = 0x08,	/* TX Packet Pending */ -    IncorPolarity = 0x10, -    MediaSelect = 0x20	/* set if TP, clear if AUI */ -}; -#define XIRCREG_PR  1	/* Page Register select */ -#define XIRCREG_EDP 4	/* Ethernet Data Port Register */ -#define XIRCREG_ISR 6	/* Ethernet Interrupt Status Register */ -enum xirc_isr { -    TxBufOvr = 0x01,	/* TX Buffer Overflow */ -    PktTxed  = 0x02,	/* Packet Transmitted */ -    MACIntr  = 0x04,	/* MAC Interrupt occurred */ -    TxResGrant = 0x08,	/* Tx Reservation Granted */ -    RxFullPkt = 0x20,	/* Rx Full Packet */ -    RxPktRej  = 0x40,	/* Rx Packet Rejected */ -    ForcedIntr= 0x80	/* Forced Interrupt */ -}; -#define XIRCREG1_IMR0 12 /* Ethernet Interrupt Mask Register (on page 1)*/ -#define XIRCREG1_IMR1 13 -#define XIRCREG0_TSO  8  /* Transmit Space Open Register (on page 0)*/ -#define XIRCREG0_TRS  10 /* Transmit reservation Size Register (page 0)*/ -#define XIRCREG0_DO   12 /* Data Offset Register (page 0) (wr) */ -#define XIRCREG0_RSR  12 /* Receive Status Register (page 0) (rd) */ -enum xirc_rsr { -    PhyPkt = 0x01,	/* set:physical packet, clear: multicast packet */ -    BrdcstPkt = 0x02,	/* set if it is a broadcast packet */ -    PktTooLong = 0x04,	/* set if packet length > 1518 */ -    AlignErr = 0x10,	/* incorrect CRC and last octet not complete */ -    CRCErr = 0x20,	/* incorrect CRC and last octet is complete */ -    PktRxOk = 0x80	/* received ok */ -}; -#define XIRCREG0_PTR 13 /* packets transmitted register (rd) */ -#define XIRCREG0_RBC 14 /* receive byte count regsister (rd) */ -#define XIRCREG1_ECR 14 /* ethernet configurationn register */ -enum xirc_ecr { -    FullDuplex = 0x04,	/* enable full duplex mode */ -    LongTPMode = 0x08,	/* adjust for longer lengths of TP cable */ -    DisablePolCor = 0x10,/* disable auto polarity correction */ -    DisableLinkPulse = 0x20, /* disable link pulse generation */ -    DisableAutoTx = 0x40, /* disable auto-transmit */ -}; -#define XIRCREG2_RBS 8	/* receive buffer start register */ -#define XIRCREG2_LED 10 /* LED Configuration register */ -/* values for the leds:    Bits 2-0 for led 1 - *  0 disabled		   Bits 5-3 for led 2 - *  1 collision - *  2 noncollision - *  3 link_detected - *  4 incor_polarity - *  5 jabber - *  6 auto_assertion - *  7 rx_tx_activity - */ -#define XIRCREG2_MSR 12 /* Mohawk specific register */ - -#define XIRCREG4_GPR0 8 /* General Purpose Register 0 */ -#define XIRCREG4_GPR1 9 /* General Purpose Register 1 */ -#define XIRCREG2_GPR2 13 /* General Purpose Register 2 (page2!)*/ -#define XIRCREG4_BOV 10 /* Bonding Version Register */ -#define XIRCREG4_LMA 12 /* Local Memory Address Register */ -#define XIRCREG4_LMD 14 /* Local Memory Data Port */ -/* MAC register can only by accessed with 8 bit operations */ -#define XIRCREG40_CMD0 8    /* Command Register (wr) */ -enum xirc_cmd { 	    /* Commands */ -    Transmit = 0x01, -    EnableRecv = 0x04, -    DisableRecv = 0x08, -    Abort = 0x10, -    Online = 0x20, -    IntrAck = 0x40, -    Offline = 0x80 -}; -#define XIRCREG5_RHSA0	10  /* Rx Host Start Address */ -#define XIRCREG40_RXST0 9   /* Receive Status Register */ -#define XIRCREG40_TXST0 11  /* Transmit Status Register 0 */ -#define XIRCREG40_TXST1 12  /* Transmit Status Register 10 */ -#define XIRCREG40_RMASK0 13  /* Receive Mask Register */ -#define XIRCREG40_TMASK0 14  /* Transmit Mask Register 0 */ -#define XIRCREG40_TMASK1 15  /* Transmit Mask Register 0 */ -#define XIRCREG42_SWC0	8   /* Software Configuration 0 */ -#define XIRCREG42_SWC1	9   /* Software Configuration 1 */ -#define XIRCREG42_BOC	10  /* Back-Off Configuration */ -#define XIRCREG44_TDR0	8   /* Time Domain Reflectometry 0 */ -#define XIRCREG44_TDR1	9   /* Time Domain Reflectometry 1 */ -#define XIRCREG44_RXBC_LO 10 /* Rx Byte Count 0 (rd) */ -#define XIRCREG44_RXBC_HI 11 /* Rx Byte Count 1 (rd) */ -#define XIRCREG45_REV	 15 /* Revision Register (rd) */ -#define XIRCREG50_IA	8   /* Individual Address (8-13) */ - -static const char *if_names[] = { "Auto", "10BaseT", "10Base2", "AUI", "100BaseT" }; - -/* card types */ -#define XIR_UNKNOWN  0	/* unknown: not supported */ -#define XIR_CE	     1	/* (prodid 1) different hardware: not supported */ -#define XIR_CE2      2	/* (prodid 2) */ -#define XIR_CE3      3	/* (prodid 3) */ -#define XIR_CEM      4	/* (prodid 1) different hardware: not supported */ -#define XIR_CEM2     5	/* (prodid 2) */ -#define XIR_CEM3     6	/* (prodid 3) */ -#define XIR_CEM33    7	/* (prodid 4) */ -#define XIR_CEM56M   8	/* (prodid 5) */ -#define XIR_CEM56    9	/* (prodid 6) */ -#define XIR_CM28    10	/* (prodid 3) modem only: not supported here */ -#define XIR_CM33    11	/* (prodid 4) modem only: not supported here */ -#define XIR_CM56    12	/* (prodid 5) modem only: not supported here */ -#define XIR_CG	    13	/* (prodid 1) GSM modem only: not supported */ -#define XIR_CBE     14	/* (prodid 1) cardbus ethernet: not supported */ -/*====================================================================*/ - -/* Module parameters */ - -MODULE_DESCRIPTION("Xircom PCMCIA ethernet driver"); -MODULE_LICENSE("Dual MPL/GPL"); - -#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0) - -INT_MODULE_PARM(if_port,	0); -INT_MODULE_PARM(full_duplex,	0); -INT_MODULE_PARM(do_sound, 	1); -INT_MODULE_PARM(lockup_hack,	0);  /* anti lockup hack */ - -/*====================================================================*/ - -/* We do not process more than these number of bytes during one - * interrupt. (Of course we receive complete packets, so this is not - * an exact value). - * Something between 2000..22000; first value gives best interrupt latency, - * the second enables the usage of the complete on-chip buffer. We use the - * high value as the initial value. - */ -static unsigned maxrx_bytes = 22000; - -/* MII management prototypes */ -static void mii_idle(unsigned int ioaddr); -static void mii_putbit(unsigned int ioaddr, unsigned data); -static int  mii_getbit(unsigned int ioaddr); -static void mii_wbits(unsigned int ioaddr, unsigned data, int len); -static unsigned mii_rd(unsigned int ioaddr, u_char phyaddr, u_char phyreg); -static void mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg, -		   unsigned data, int len); - -static int has_ce2_string(struct pcmcia_device * link); -static int xirc2ps_config(struct pcmcia_device * link); -static void xirc2ps_release(struct pcmcia_device * link); -static void xirc2ps_detach(struct pcmcia_device *p_dev); - -static irqreturn_t xirc2ps_interrupt(int irq, void *dev_id); - -typedef struct local_info_t { -	struct net_device	*dev; -	struct pcmcia_device	*p_dev; - -    int card_type; -    int probe_port; -    int silicon; /* silicon revision. 0=old CE2, 1=Scipper, 4=Mohawk */ -    int mohawk;  /* a CE3 type card */ -    int dingo;	 /* a CEM56 type card */ -    int new_mii; /* has full 10baseT/100baseT MII */ -    int modem;	 /* is a multi function card (i.e with a modem) */ -    void __iomem *dingo_ccr; /* only used for CEM56 cards */ -    unsigned last_ptr_value; /* last packets transmitted value */ -    const char *manf_str; -    struct work_struct tx_timeout_task; -} local_info_t; - -/**************** - * Some more prototypes - */ -static netdev_tx_t do_start_xmit(struct sk_buff *skb, -				       struct net_device *dev); -static void xirc_tx_timeout(struct net_device *dev); -static void xirc2ps_tx_timeout_task(struct work_struct *work); -static void set_addresses(struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static int set_card_type(struct pcmcia_device *link); -static int do_config(struct net_device *dev, struct ifmap *map); -static int do_open(struct net_device *dev); -static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static const struct ethtool_ops netdev_ethtool_ops; -static void hardreset(struct net_device *dev); -static void do_reset(struct net_device *dev, int full); -static int init_mii(struct net_device *dev); -static void do_powerdown(struct net_device *dev); -static int do_stop(struct net_device *dev); - -/*=============== Helper functions =========================*/ -#define SelectPage(pgnr)   outb((pgnr), ioaddr + XIRCREG_PR) -#define GetByte(reg)	   ((unsigned)inb(ioaddr + (reg))) -#define GetWord(reg)	   ((unsigned)inw(ioaddr + (reg))) -#define PutByte(reg,value) outb((value), ioaddr+(reg)) -#define PutWord(reg,value) outw((value), ioaddr+(reg)) - -/*====== Functions used for debugging =================================*/ -#if 0 /* reading regs may change system status */ -static void -PrintRegisters(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; - -    if (pc_debug > 1) { -	int i, page; - -	printk(KERN_DEBUG pr_fmt("Register  common: ")); -	for (i = 0; i < 8; i++) -	    pr_cont(" %2.2x", GetByte(i)); -	pr_cont("\n"); -	for (page = 0; page <= 8; page++) { -	    printk(KERN_DEBUG pr_fmt("Register page %2x: "), page); -	    SelectPage(page); -	    for (i = 8; i < 16; i++) -		pr_cont(" %2.2x", GetByte(i)); -	    pr_cont("\n"); -	} -	for (page=0x40 ; page <= 0x5f; page++) { -		if (page == 0x43 || (page >= 0x46 && page <= 0x4f) || -		    (page >= 0x51 && page <=0x5e)) -			continue; -	    printk(KERN_DEBUG pr_fmt("Register page %2x: "), page); -	    SelectPage(page); -	    for (i = 8; i < 16; i++) -		pr_cont(" %2.2x", GetByte(i)); -	    pr_cont("\n"); -	} -    } -} -#endif /* 0 */ - -/*============== MII Management functions ===============*/ - -/**************** - * Turn around for read - */ -static void -mii_idle(unsigned int ioaddr) -{ -    PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */ -    udelay(1); -    PutByte(XIRCREG2_GPR2, 0x04|1); /* and drive MDCK high */ -    udelay(1); -} - -/**************** - * Write a bit to MDI/O - */ -static void -mii_putbit(unsigned int ioaddr, unsigned data) -{ -  #if 1 -    if (data) { -	PutByte(XIRCREG2_GPR2, 0x0c|2|0); /* set MDIO */ -	udelay(1); -	PutByte(XIRCREG2_GPR2, 0x0c|2|1); /* and drive MDCK high */ -	udelay(1); -    } else { -	PutByte(XIRCREG2_GPR2, 0x0c|0|0); /* clear MDIO */ -	udelay(1); -	PutByte(XIRCREG2_GPR2, 0x0c|0|1); /* and drive MDCK high */ -	udelay(1); -    } -  #else -    if (data) { -	PutWord(XIRCREG2_GPR2-1, 0x0e0e); -	udelay(1); -	PutWord(XIRCREG2_GPR2-1, 0x0f0f); -	udelay(1); -    } else { -	PutWord(XIRCREG2_GPR2-1, 0x0c0c); -	udelay(1); -	PutWord(XIRCREG2_GPR2-1, 0x0d0d); -	udelay(1); -    } -  #endif -} - -/**************** - * Get a bit from MDI/O - */ -static int -mii_getbit(unsigned int ioaddr) -{ -    unsigned d; - -    PutByte(XIRCREG2_GPR2, 4|0); /* drive MDCK low */ -    udelay(1); -    d = GetByte(XIRCREG2_GPR2); /* read MDIO */ -    PutByte(XIRCREG2_GPR2, 4|1); /* drive MDCK high again */ -    udelay(1); -    return d & 0x20; /* read MDIO */ -} - -static void -mii_wbits(unsigned int ioaddr, unsigned data, int len) -{ -    unsigned m = 1 << (len-1); -    for (; m; m >>= 1) -	mii_putbit(ioaddr, data & m); -} - -static unsigned -mii_rd(unsigned int ioaddr,	u_char phyaddr, u_char phyreg) -{ -    int i; -    unsigned data=0, m; - -    SelectPage(2); -    for (i=0; i < 32; i++)		/* 32 bit preamble */ -	mii_putbit(ioaddr, 1); -    mii_wbits(ioaddr, 0x06, 4); 	/* Start and opcode for read */ -    mii_wbits(ioaddr, phyaddr, 5);	/* PHY address to be accessed */ -    mii_wbits(ioaddr, phyreg, 5);	/* PHY register to read */ -    mii_idle(ioaddr);			/* turn around */ -    mii_getbit(ioaddr); - -    for (m = 1<<15; m; m >>= 1) -	if (mii_getbit(ioaddr)) -	    data |= m; -    mii_idle(ioaddr); -    return data; -} - -static void -mii_wr(unsigned int ioaddr, u_char phyaddr, u_char phyreg, unsigned data, -       int len) -{ -    int i; - -    SelectPage(2); -    for (i=0; i < 32; i++)		/* 32 bit preamble */ -	mii_putbit(ioaddr, 1); -    mii_wbits(ioaddr, 0x05, 4); 	/* Start and opcode for write */ -    mii_wbits(ioaddr, phyaddr, 5);	/* PHY address to be accessed */ -    mii_wbits(ioaddr, phyreg, 5);	/* PHY Register to write */ -    mii_putbit(ioaddr, 1);		/* turn around */ -    mii_putbit(ioaddr, 0); -    mii_wbits(ioaddr, data, len);	/* And write the data */ -    mii_idle(ioaddr); -} - -/*============= Main bulk of functions	=========================*/ - -static const struct net_device_ops netdev_ops = { -	.ndo_open		= do_open, -	.ndo_stop		= do_stop, -	.ndo_start_xmit		= do_start_xmit, -	.ndo_tx_timeout 	= xirc_tx_timeout, -	.ndo_set_config		= do_config, -	.ndo_do_ioctl		= do_ioctl, -	.ndo_set_multicast_list	= set_multicast_list, -	.ndo_change_mtu		= eth_change_mtu, -	.ndo_set_mac_address 	= eth_mac_addr, -	.ndo_validate_addr	= eth_validate_addr, -}; - -static int -xirc2ps_probe(struct pcmcia_device *link) -{ -    struct net_device *dev; -    local_info_t *local; - -    dev_dbg(&link->dev, "attach()\n"); - -    /* Allocate the device structure */ -    dev = alloc_etherdev(sizeof(local_info_t)); -    if (!dev) -	    return -ENOMEM; -    local = netdev_priv(dev); -    local->dev = dev; -    local->p_dev = link; -    link->priv = dev; - -    /* General socket configuration */ -    link->config_index = 1; - -    /* Fill in card specific entries */ -    dev->netdev_ops = &netdev_ops; -    dev->ethtool_ops = &netdev_ethtool_ops; -    dev->watchdog_timeo = TX_TIMEOUT; -    INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task); - -    return xirc2ps_config(link); -} /* xirc2ps_attach */ - -static void -xirc2ps_detach(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; - -    dev_dbg(&link->dev, "detach\n"); - -    unregister_netdev(dev); - -    xirc2ps_release(link); - -    free_netdev(dev); -} /* xirc2ps_detach */ - -/**************** - * Detect the type of the card. s is the buffer with the data of tuple 0x20 - * Returns: 0 := not supported - *		       mediaid=11 and prodid=47 - * Media-Id bits: - *  Ethernet	    0x01 - *  Tokenring	    0x02 - *  Arcnet	    0x04 - *  Wireless	    0x08 - *  Modem	    0x10 - *  GSM only	    0x20 - * Prod-Id bits: - *  Pocket	    0x10 - *  External	    0x20 - *  Creditcard	    0x40 - *  Cardbus	    0x80 - * - */ -static int -set_card_type(struct pcmcia_device *link) -{ -    struct net_device *dev = link->priv; -    local_info_t *local = netdev_priv(dev); -    u8 *buf; -    unsigned int cisrev, mediaid, prodid; -    size_t len; - -    len = pcmcia_get_tuple(link, CISTPL_MANFID, &buf); -    if (len < 5) { -	    dev_err(&link->dev, "invalid CIS -- sorry\n"); -	    return 0; -    } - -    cisrev = buf[2]; -    mediaid = buf[3]; -    prodid = buf[4]; - -    dev_dbg(&link->dev, "cisrev=%02x mediaid=%02x prodid=%02x\n", -	  cisrev, mediaid, prodid); - -    local->mohawk = 0; -    local->dingo = 0; -    local->modem = 0; -    local->card_type = XIR_UNKNOWN; -    if (!(prodid & 0x40)) { -	pr_notice("Oops: Not a creditcard\n"); -	return 0; -    } -    if (!(mediaid & 0x01)) { -	pr_notice("Not an Ethernet card\n"); -	return 0; -    } -    if (mediaid & 0x10) { -	local->modem = 1; -	switch(prodid & 15) { -	  case 1: local->card_type = XIR_CEM   ; break; -	  case 2: local->card_type = XIR_CEM2  ; break; -	  case 3: local->card_type = XIR_CEM3  ; break; -	  case 4: local->card_type = XIR_CEM33 ; break; -	  case 5: local->card_type = XIR_CEM56M; -		  local->mohawk = 1; -		  break; -	  case 6: -	  case 7: /* 7 is the RealPort 10/56 */ -		  local->card_type = XIR_CEM56 ; -		  local->mohawk = 1; -		  local->dingo = 1; -		  break; -	} -    } else { -	switch(prodid & 15) { -	  case 1: local->card_type = has_ce2_string(link)? XIR_CE2 : XIR_CE ; -		  break; -	  case 2: local->card_type = XIR_CE2; break; -	  case 3: local->card_type = XIR_CE3; -		  local->mohawk = 1; -		  break; -	} -    } -    if (local->card_type == XIR_CE || local->card_type == XIR_CEM) { -	pr_notice("Sorry, this is an old CE card\n"); -	return 0; -    } -    if (local->card_type == XIR_UNKNOWN) -	pr_notice("unknown card (mediaid=%02x prodid=%02x)\n", mediaid, prodid); - -    return 1; -} - -/**************** - * There are some CE2 cards out which claim to be a CE card. - * This function looks for a "CE2" in the 3rd version field. - * Returns: true if this is a CE2 - */ -static int -has_ce2_string(struct pcmcia_device * p_dev) -{ -	if (p_dev->prod_id[2] && strstr(p_dev->prod_id[2], "CE2")) -		return 1; -	return 0; -} - -static int -xirc2ps_config_modem(struct pcmcia_device *p_dev, void *priv_data) -{ -	unsigned int ioaddr; - -	if ((p_dev->resource[0]->start & 0xf) == 8) -		return -ENODEV; - -	p_dev->resource[0]->end = 16; -	p_dev->resource[1]->end = 8; -	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; -	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -	p_dev->io_lines = 10; - -	p_dev->resource[1]->start = p_dev->resource[0]->start; -	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { -		p_dev->resource[0]->start = ioaddr; -		if (!pcmcia_request_io(p_dev)) -			return 0; -	} -	return -ENODEV; -} - -static int -xirc2ps_config_check(struct pcmcia_device *p_dev, void *priv_data) -{ -	int *pass = priv_data; -	resource_size_t tmp = p_dev->resource[1]->start; - -	tmp += (*pass ? (p_dev->config_index & 0x20 ? -24 : 8) -		: (p_dev->config_index & 0x20 ?   8 : -24)); - -	if ((p_dev->resource[0]->start & 0xf) == 8) -		return -ENODEV; - -	p_dev->resource[0]->end = 18; -	p_dev->resource[1]->end = 8; -	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; -	p_dev->resource[1]->flags &= ~IO_DATA_PATH_WIDTH; -	p_dev->resource[1]->flags |= IO_DATA_PATH_WIDTH_8; -	p_dev->io_lines = 10; - -	p_dev->resource[1]->start = p_dev->resource[0]->start; -	p_dev->resource[0]->start = tmp; -	return pcmcia_request_io(p_dev); -} - - -static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev, -			     tuple_t *tuple, -			     void *priv) -{ -	struct net_device *dev = priv; -	int i; - -	if (tuple->TupleDataLen != 13) -		return -EINVAL; -	if ((tuple->TupleData[0] != 2) || (tuple->TupleData[1] != 1) || -		(tuple->TupleData[2] != 6)) -		return -EINVAL; -	/* another try	(James Lehmer's CE2 version 4.1)*/ -	for (i = 2; i < 6; i++) -		dev->dev_addr[i] = tuple->TupleData[i+2]; -	return 0; -}; - - -static int -xirc2ps_config(struct pcmcia_device * link) -{ -    struct net_device *dev = link->priv; -    local_info_t *local = netdev_priv(dev); -    unsigned int ioaddr; -    int err; -    u8 *buf; -    size_t len; - -    local->dingo_ccr = NULL; - -    dev_dbg(&link->dev, "config\n"); - -    /* Is this a valid	card */ -    if (link->has_manf_id == 0) { -	pr_notice("manfid not found in CIS\n"); -	goto failure; -    } - -    switch (link->manf_id) { -      case MANFID_XIRCOM: -	local->manf_str = "Xircom"; -	break; -      case MANFID_ACCTON: -	local->manf_str = "Accton"; -	break; -      case MANFID_COMPAQ: -      case MANFID_COMPAQ2: -	local->manf_str = "Compaq"; -	break; -      case MANFID_INTEL: -	local->manf_str = "Intel"; -	break; -      case MANFID_TOSHIBA: -	local->manf_str = "Toshiba"; -	break; -      default: -	pr_notice("Unknown Card Manufacturer ID: 0x%04x\n", -		  (unsigned)link->manf_id); -	goto failure; -    } -    dev_dbg(&link->dev, "found %s card\n", local->manf_str); - -    if (!set_card_type(link)) { -	pr_notice("this card is not supported\n"); -	goto failure; -    } - -    /* get the ethernet address from the CIS */ -    err = pcmcia_get_mac_from_cis(link, dev); - -    /* not found: try to get the node-id from tuple 0x89 */ -    if (err) { -	    len = pcmcia_get_tuple(link, 0x89, &buf); -	    /* data layout looks like tuple 0x22 */ -	    if (buf && len == 8) { -		    if (*buf == CISTPL_FUNCE_LAN_NODE_ID) { -			    int i; -			    for (i = 2; i < 6; i++) -				    dev->dev_addr[i] = buf[i+2]; -		    } else -			    err = -1; -	    } -	    kfree(buf); -    } - -    if (err) -	err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev); - -    if (err) { -	pr_notice("node-id not found in CIS\n"); -	goto failure; -    } - -    if (local->modem) { -	int pass; -	link->config_flags |= CONF_AUTO_SET_IO; - -	if (local->dingo) { -	    /* Take the Modem IO port from the CIS and scan for a free -	     * Ethernet port */ -	    if (!pcmcia_loop_config(link, xirc2ps_config_modem, NULL)) -		    goto port_found; -	} else { -	    /* We do 2 passes here: The first one uses the regular mapping and -	     * the second tries again, thereby considering that the 32 ports are -	     * mirrored every 32 bytes. Actually we use a mirrored port for -	     * the Mako if (on the first pass) the COR bit 5 is set. -	     */ -	    for (pass=0; pass < 2; pass++) -		    if (!pcmcia_loop_config(link, xirc2ps_config_check, -						    &pass)) -			    goto port_found; -	    /* if special option: -	     * try to configure as Ethernet only. -	     * .... */ -	} -	pr_notice("no ports available\n"); -    } else { -	link->io_lines = 10; -	link->resource[0]->end = 16; -	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_16; -	for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { -	    link->resource[0]->start = ioaddr; -	    if (!(err = pcmcia_request_io(link))) -		goto port_found; -	} -	link->resource[0]->start = 0; /* let CS decide */ -	if ((err = pcmcia_request_io(link))) -	    goto config_error; -    } -  port_found: -    if (err) -	 goto config_error; - -    /**************** -     * Now allocate an interrupt line.	Note that this does not -     * actually assign a handler to the interrupt. -     */ -    if ((err=pcmcia_request_irq(link, xirc2ps_interrupt))) -	goto config_error; - -    link->config_flags |= CONF_ENABLE_IRQ; -    if (do_sound) -	    link->config_flags |= CONF_ENABLE_SPKR; - -    if ((err = pcmcia_enable_device(link))) -	goto config_error; - -    if (local->dingo) { -	/* Reset the modem's BAR to the correct value -	 * This is necessary because in the RequestConfiguration call, -	 * the base address of the ethernet port (BasePort1) is written -	 * to the BAR registers of the modem. -	 */ -	err = pcmcia_write_config_byte(link, CISREG_IOBASE_0, (u8) -				link->resource[1]->start & 0xff); -	if (err) -	    goto config_error; - -	err = pcmcia_write_config_byte(link, CISREG_IOBASE_1, -				(link->resource[1]->start >> 8) & 0xff); -	if (err) -	    goto config_error; - -	/* There is no config entry for the Ethernet part which -	 * is at 0x0800. So we allocate a window into the attribute -	 * memory and write direct to the CIS registers -	 */ -	link->resource[2]->flags = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | -					WIN_ENABLE; -	link->resource[2]->start = link->resource[2]->end = 0; -	if ((err = pcmcia_request_window(link, link->resource[2], 0))) -	    goto config_error; - -	local->dingo_ccr = ioremap(link->resource[2]->start, 0x1000) + 0x0800; -	if ((err = pcmcia_map_mem_page(link, link->resource[2], 0))) -	    goto config_error; - -	/* Setup the CCRs; there are no infos in the CIS about the Ethernet -	 * part. -	 */ -	writeb(0x47, local->dingo_ccr + CISREG_COR); -	ioaddr = link->resource[0]->start; -	writeb(ioaddr & 0xff	  , local->dingo_ccr + CISREG_IOBASE_0); -	writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1); - -      #if 0 -	{ -	    u_char tmp; -	    pr_info("ECOR:"); -	    for (i=0; i < 7; i++) { -		tmp = readb(local->dingo_ccr + i*2); -		pr_cont(" %02x", tmp); -	    } -	    pr_cont("\n"); -	    pr_info("DCOR:"); -	    for (i=0; i < 4; i++) { -		tmp = readb(local->dingo_ccr + 0x20 + i*2); -		pr_cont(" %02x", tmp); -	    } -	    pr_cont("\n"); -	    pr_info("SCOR:"); -	    for (i=0; i < 10; i++) { -		tmp = readb(local->dingo_ccr + 0x40 + i*2); -		pr_cont(" %02x", tmp); -	    } -	    pr_cont("\n"); -	} -      #endif - -	writeb(0x01, local->dingo_ccr + 0x20); -	writeb(0x0c, local->dingo_ccr + 0x22); -	writeb(0x00, local->dingo_ccr + 0x24); -	writeb(0x00, local->dingo_ccr + 0x26); -	writeb(0x00, local->dingo_ccr + 0x28); -    } - -    /* The if_port symbol can be set when the module is loaded */ -    local->probe_port=0; -    if (!if_port) { -	local->probe_port = dev->if_port = 1; -    } else if ((if_port >= 1 && if_port <= 2) || -	       (local->mohawk && if_port==4)) -	dev->if_port = if_port; -    else -	pr_notice("invalid if_port requested\n"); - -    /* we can now register the device with the net subsystem */ -    dev->irq = link->irq; -    dev->base_addr = link->resource[0]->start; - -    if (local->dingo) -	do_reset(dev, 1); /* a kludge to make the cem56 work */ - -    SET_NETDEV_DEV(dev, &link->dev); - -    if ((err=register_netdev(dev))) { -	pr_notice("register_netdev() failed\n"); -	goto config_error; -    } - -    /* give some infos about the hardware */ -    netdev_info(dev, "%s: port %#3lx, irq %d, hwaddr %pM\n", -		local->manf_str, (u_long)dev->base_addr, (int)dev->irq, -		dev->dev_addr); - -    return 0; - -  config_error: -    xirc2ps_release(link); -    return -ENODEV; - -  failure: -    return -ENODEV; -} /* xirc2ps_config */ - -static void -xirc2ps_release(struct pcmcia_device *link) -{ -	dev_dbg(&link->dev, "release\n"); - -	if (link->resource[2]->end) { -		struct net_device *dev = link->priv; -		local_info_t *local = netdev_priv(dev); -		if (local->dingo) -			iounmap(local->dingo_ccr - 0x0800); -	} -	pcmcia_disable_device(link); -} /* xirc2ps_release */ - -/*====================================================================*/ - - -static int xirc2ps_suspend(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		netif_device_detach(dev); -		do_powerdown(dev); -	} - -	return 0; -} - -static int xirc2ps_resume(struct pcmcia_device *link) -{ -	struct net_device *dev = link->priv; - -	if (link->open) { -		do_reset(dev,1); -		netif_device_attach(dev); -	} - -	return 0; -} - - -/*====================================================================*/ - -/**************** - * This is the Interrupt service route. - */ -static irqreturn_t -xirc2ps_interrupt(int irq, void *dev_id) -{ -    struct net_device *dev = (struct net_device *)dev_id; -    local_info_t *lp = netdev_priv(dev); -    unsigned int ioaddr; -    u_char saved_page; -    unsigned bytes_rcvd; -    unsigned int_status, eth_status, rx_status, tx_status; -    unsigned rsr, pktlen; -    ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days -				  * is this something to worry about? -				  * -- on a laptop? -				  */ - -    if (!netif_device_present(dev)) -	return IRQ_HANDLED; - -    ioaddr = dev->base_addr; -    if (lp->mohawk) { /* must disable the interrupt */ -	PutByte(XIRCREG_CR, 0); -    } - -    pr_debug("%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr); - -    saved_page = GetByte(XIRCREG_PR); -    /* Read the ISR to see whats the cause for the interrupt. -     * This also clears the interrupt flags on CE2 cards -     */ -    int_status = GetByte(XIRCREG_ISR); -    bytes_rcvd = 0; -  loop_entry: -    if (int_status == 0xff) { /* card may be ejected */ -	pr_debug("%s: interrupt %d for dead card\n", dev->name, irq); -	goto leave; -    } -    eth_status = GetByte(XIRCREG_ESR); - -    SelectPage(0x40); -    rx_status  = GetByte(XIRCREG40_RXST0); -    PutByte(XIRCREG40_RXST0, (~rx_status & 0xff)); -    tx_status = GetByte(XIRCREG40_TXST0); -    tx_status |= GetByte(XIRCREG40_TXST1) << 8; -    PutByte(XIRCREG40_TXST0, 0); -    PutByte(XIRCREG40_TXST1, 0); - -    pr_debug("%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n", -	  dev->name, int_status, eth_status, rx_status, tx_status); - -    /***** receive section ******/ -    SelectPage(0); -    while (eth_status & FullPktRcvd) { -	rsr = GetByte(XIRCREG0_RSR); -	if (bytes_rcvd > maxrx_bytes && (rsr & PktRxOk)) { -	    /* too many bytes received during this int, drop the rest of the -	     * packets */ -	    dev->stats.rx_dropped++; -	    pr_debug("%s: RX drop, too much done\n", dev->name); -	} else if (rsr & PktRxOk) { -	    struct sk_buff *skb; - -	    pktlen = GetWord(XIRCREG0_RBC); -	    bytes_rcvd += pktlen; - -	    pr_debug("rsr=%#02x packet_length=%u\n", rsr, pktlen); - -	    skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */ -	    if (!skb) { -		pr_notice("low memory, packet dropped (size=%u)\n", pktlen); -		dev->stats.rx_dropped++; -	    } else { /* okay get the packet */ -		skb_reserve(skb, 2); -		if (lp->silicon == 0 ) { /* work around a hardware bug */ -		    unsigned rhsa; /* receive start address */ - -		    SelectPage(5); -		    rhsa = GetWord(XIRCREG5_RHSA0); -		    SelectPage(0); -		    rhsa += 3; /* skip control infos */ -		    if (rhsa >= 0x8000) -			rhsa = 0; -		    if (rhsa + pktlen > 0x8000) { -			unsigned i; -			u_char *buf = skb_put(skb, pktlen); -			for (i=0; i < pktlen ; i++, rhsa++) { -			    buf[i] = GetByte(XIRCREG_EDP); -			    if (rhsa == 0x8000) { -				rhsa = 0; -				i--; -			    } -			} -		    } else { -			insw(ioaddr+XIRCREG_EDP, -				skb_put(skb, pktlen), (pktlen+1)>>1); -		    } -		} -	      #if 0 -		else if (lp->mohawk) { -		    /* To use this 32 bit access we should use -		     * a manual optimized loop -		     * Also the words are swapped, we can get more -		     * performance by using 32 bit access and swapping -		     * the words in a register. Will need this for cardbus -		     * -		     * Note: don't forget to change the ALLOC_SKB to .. +3 -		     */ -		    unsigned i; -		    u_long *p = skb_put(skb, pktlen); -		    register u_long a; -		    unsigned int edpreg = ioaddr+XIRCREG_EDP-2; -		    for (i=0; i < len ; i += 4, p++) { -			a = inl(edpreg); -			__asm__("rorl $16,%0\n\t" -				:"=q" (a) -				: "0" (a)); -			*p = a; -		    } -		} -	      #endif -		else { -		    insw(ioaddr+XIRCREG_EDP, skb_put(skb, pktlen), -			    (pktlen+1)>>1); -		} -		skb->protocol = eth_type_trans(skb, dev); -		netif_rx(skb); -		dev->stats.rx_packets++; -		dev->stats.rx_bytes += pktlen; -		if (!(rsr & PhyPkt)) -		    dev->stats.multicast++; -	    } -	} else { /* bad packet */ -	    pr_debug("rsr=%#02x\n", rsr); -	} -	if (rsr & PktTooLong) { -	    dev->stats.rx_frame_errors++; -	    pr_debug("%s: Packet too long\n", dev->name); -	} -	if (rsr & CRCErr) { -	    dev->stats.rx_crc_errors++; -	    pr_debug("%s: CRC error\n", dev->name); -	} -	if (rsr & AlignErr) { -	    dev->stats.rx_fifo_errors++; /* okay ? */ -	    pr_debug("%s: Alignment error\n", dev->name); -	} - -	/* clear the received/dropped/error packet */ -	PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */ - -	/* get the new ethernet status */ -	eth_status = GetByte(XIRCREG_ESR); -    } -    if (rx_status & 0x10) { /* Receive overrun */ -	dev->stats.rx_over_errors++; -	PutByte(XIRCREG_CR, ClearRxOvrun); -	pr_debug("receive overrun cleared\n"); -    } - -    /***** transmit section ******/ -    if (int_status & PktTxed) { -	unsigned n, nn; - -	n = lp->last_ptr_value; -	nn = GetByte(XIRCREG0_PTR); -	lp->last_ptr_value = nn; -	if (nn < n) /* rollover */ -	    dev->stats.tx_packets += 256 - n; -	else if (n == nn) { /* happens sometimes - don't know why */ -	    pr_debug("PTR not changed?\n"); -	} else -	    dev->stats.tx_packets += lp->last_ptr_value - n; -	netif_wake_queue(dev); -    } -    if (tx_status & 0x0002) {	/* Execessive collissions */ -	pr_debug("tx restarted due to execssive collissions\n"); -	PutByte(XIRCREG_CR, RestartTx);  /* restart transmitter process */ -    } -    if (tx_status & 0x0040) -	dev->stats.tx_aborted_errors++; - -    /* recalculate our work chunk so that we limit the duration of this -     * ISR to about 1/10 of a second. -     * Calculate only if we received a reasonable amount of bytes. -     */ -    if (bytes_rcvd > 1000) { -	u_long duration = jiffies - start_ticks; - -	if (duration >= HZ/10) { /* if more than about 1/10 second */ -	    maxrx_bytes = (bytes_rcvd * (HZ/10)) / duration; -	    if (maxrx_bytes < 2000) -		maxrx_bytes = 2000; -	    else if (maxrx_bytes > 22000) -		maxrx_bytes = 22000; -	    pr_debug("set maxrx=%u (rcvd=%u ticks=%lu)\n", -		  maxrx_bytes, bytes_rcvd, duration); -	} else if (!duration && maxrx_bytes < 22000) { -	    /* now much faster */ -	    maxrx_bytes += 2000; -	    if (maxrx_bytes > 22000) -		maxrx_bytes = 22000; -	    pr_debug("set maxrx=%u\n", maxrx_bytes); -	} -    } - -  leave: -    if (lockup_hack) { -	if (int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0) -	    goto loop_entry; -    } -    SelectPage(saved_page); -    PutByte(XIRCREG_CR, EnableIntr);  /* re-enable interrupts */ -    /* Instead of dropping packets during a receive, we could -     * force an interrupt with this command: -     *	  PutByte(XIRCREG_CR, EnableIntr|ForceIntr); -     */ -    return IRQ_HANDLED; -} /* xirc2ps_interrupt */ - -/*====================================================================*/ - -static void -xirc2ps_tx_timeout_task(struct work_struct *work) -{ -	local_info_t *local = -		container_of(work, local_info_t, tx_timeout_task); -	struct net_device *dev = local->dev; -    /* reset the card */ -    do_reset(dev,1); -    dev->trans_start = jiffies; /* prevent tx timeout */ -    netif_wake_queue(dev); -} - -static void -xirc_tx_timeout(struct net_device *dev) -{ -    local_info_t *lp = netdev_priv(dev); -    dev->stats.tx_errors++; -    netdev_notice(dev, "transmit timed out\n"); -    schedule_work(&lp->tx_timeout_task); -} - -static netdev_tx_t -do_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ -    local_info_t *lp = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    int okay; -    unsigned freespace; -    unsigned pktlen = skb->len; - -    pr_debug("do_start_xmit(skb=%p, dev=%p) len=%u\n", -	  skb, dev, pktlen); - - -    /* adjust the packet length to min. required -     * and hope that the buffer is large enough -     * to provide some random data. -     * fixme: For Mohawk we can change this by sending -     * a larger packetlen than we actually have; the chip will -     * pad this in his buffer with random bytes -     */ -    if (pktlen < ETH_ZLEN) -    { -        if (skb_padto(skb, ETH_ZLEN)) -        	return NETDEV_TX_OK; -	pktlen = ETH_ZLEN; -    } - -    netif_stop_queue(dev); -    SelectPage(0); -    PutWord(XIRCREG0_TRS, (u_short)pktlen+2); -    freespace = GetWord(XIRCREG0_TSO); -    okay = freespace & 0x8000; -    freespace &= 0x7fff; -    /* TRS doesn't work - (indeed it is eliminated with sil-rev 1) */ -    okay = pktlen +2 < freespace; -    pr_debug("%s: avail. tx space=%u%s\n", -	  dev->name, freespace, okay ? " (okay)":" (not enough)"); -    if (!okay) { /* not enough space */ -	return NETDEV_TX_BUSY;  /* upper layer may decide to requeue this packet */ -    } -    /* send the packet */ -    PutWord(XIRCREG_EDP, (u_short)pktlen); -    outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1); -    if (pktlen & 1) -	PutByte(XIRCREG_EDP, skb->data[pktlen-1]); - -    if (lp->mohawk) -	PutByte(XIRCREG_CR, TransmitPacket|EnableIntr); - -    dev_kfree_skb (skb); -    dev->stats.tx_bytes += pktlen; -    netif_start_queue(dev); -    return NETDEV_TX_OK; -} - -struct set_address_info { -	int reg_nr; -	int page_nr; -	int mohawk; -	unsigned int ioaddr; -}; - -static void set_address(struct set_address_info *sa_info, char *addr) -{ -	unsigned int ioaddr = sa_info->ioaddr; -	int i; - -	for (i = 0; i < 6; i++) { -		if (sa_info->reg_nr > 15) { -			sa_info->reg_nr = 8; -			sa_info->page_nr++; -			SelectPage(sa_info->page_nr); -		} -		if (sa_info->mohawk) -			PutByte(sa_info->reg_nr++, addr[5 - i]); -		else -			PutByte(sa_info->reg_nr++, addr[i]); -	} -} - -/**************** - * Set all addresses: This first one is the individual address, - * the next 9 addresses are taken from the multicast list and - * the rest is filled with the individual address. - */ -static void set_addresses(struct net_device *dev) -{ -	unsigned int ioaddr = dev->base_addr; -	local_info_t *lp = netdev_priv(dev); -	struct netdev_hw_addr *ha; -	struct set_address_info sa_info; -	int i; - -	/* -	 * Setup the info structure so that by first set_address call it will do -	 * SelectPage with the right page number. Hence these ones here. -	 */ -	sa_info.reg_nr = 15 + 1; -	sa_info.page_nr = 0x50 - 1; -	sa_info.mohawk = lp->mohawk; -	sa_info.ioaddr = ioaddr; - -	set_address(&sa_info, dev->dev_addr); -	i = 0; -	netdev_for_each_mc_addr(ha, dev) { -		if (i++ == 9) -			break; -		set_address(&sa_info, ha->addr); -	} -	while (i++ < 9) -		set_address(&sa_info, dev->dev_addr); -	SelectPage(0); -} - -/**************** - * Set or clear the multicast filter for this adaptor. - * We can filter up to 9 addresses, if more are requested we set - * multicast promiscuous mode. - */ - -static void -set_multicast_list(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    unsigned value; - -    SelectPage(0x42); -    value = GetByte(XIRCREG42_SWC1) & 0xC0; - -    if (dev->flags & IFF_PROMISC) { /* snoop */ -	PutByte(XIRCREG42_SWC1, value | 0x06); /* set MPE and PME */ -    } else if (netdev_mc_count(dev) > 9 || (dev->flags & IFF_ALLMULTI)) { -	PutByte(XIRCREG42_SWC1, value | 0x02); /* set MPE */ -    } else if (!netdev_mc_empty(dev)) { -	/* the chip can filter 9 addresses perfectly */ -	PutByte(XIRCREG42_SWC1, value | 0x01); -	SelectPage(0x40); -	PutByte(XIRCREG40_CMD0, Offline); -	set_addresses(dev); -	SelectPage(0x40); -	PutByte(XIRCREG40_CMD0, EnableRecv | Online); -    } else { /* standard usage */ -	PutByte(XIRCREG42_SWC1, value | 0x00); -    } -    SelectPage(0); -} - -static int -do_config(struct net_device *dev, struct ifmap *map) -{ -    local_info_t *local = netdev_priv(dev); - -    pr_debug("do_config(%p)\n", dev); -    if (map->port != 255 && map->port != dev->if_port) { -	if (map->port > 4) -	    return -EINVAL; -	if (!map->port) { -	    local->probe_port = 1; -	    dev->if_port = 1; -	} else { -	    local->probe_port = 0; -	    dev->if_port = map->port; -	} -	netdev_info(dev, "switching to %s port\n", if_names[dev->if_port]); -	do_reset(dev,1);  /* not the fine way :-) */ -    } -    return 0; -} - -/**************** - * Open the driver - */ -static int -do_open(struct net_device *dev) -{ -    local_info_t *lp = netdev_priv(dev); -    struct pcmcia_device *link = lp->p_dev; - -    dev_dbg(&link->dev, "do_open(%p)\n", dev); - -    /* Check that the PCMCIA card is still here. */ -    /* Physical device present signature. */ -    if (!pcmcia_dev_present(link)) -	return -ENODEV; - -    /* okay */ -    link->open++; - -    netif_start_queue(dev); -    do_reset(dev,1); - -    return 0; -} - -static void netdev_get_drvinfo(struct net_device *dev, -			       struct ethtool_drvinfo *info) -{ -	strcpy(info->driver, "xirc2ps_cs"); -	sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr); -} - -static const struct ethtool_ops netdev_ethtool_ops = { -	.get_drvinfo		= netdev_get_drvinfo, -}; - -static int -do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ -    local_info_t *local = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    struct mii_ioctl_data *data = if_mii(rq); - -    pr_debug("%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", -	  dev->name, rq->ifr_ifrn.ifrn_name, cmd, -	  data->phy_id, data->reg_num, data->val_in, data->val_out); - -    if (!local->mohawk) -	return -EOPNOTSUPP; - -    switch(cmd) { -      case SIOCGMIIPHY:		/* Get the address of the PHY in use. */ -	data->phy_id = 0;	/* we have only this address */ -	/* fall through */ -      case SIOCGMIIREG:		/* Read the specified MII register. */ -	data->val_out = mii_rd(ioaddr, data->phy_id & 0x1f, -			       data->reg_num & 0x1f); -	break; -      case SIOCSMIIREG:		/* Write the specified MII register */ -	mii_wr(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in, -	       16); -	break; -      default: -	return -EOPNOTSUPP; -    } -    return 0; -} - -static void -hardreset(struct net_device *dev) -{ -    local_info_t *local = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; - -    SelectPage(4); -    udelay(1); -    PutByte(XIRCREG4_GPR1, 0);	     /* clear bit 0: power down */ -    msleep(40);				     /* wait 40 msec */ -    if (local->mohawk) -	PutByte(XIRCREG4_GPR1, 1);	 /* set bit 0: power up */ -    else -	PutByte(XIRCREG4_GPR1, 1 | 4);	 /* set bit 0: power up, bit 2: AIC */ -    msleep(20);			     /* wait 20 msec */ -} - -static void -do_reset(struct net_device *dev, int full) -{ -    local_info_t *local = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    unsigned value; - -    pr_debug("%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full); - -    hardreset(dev); -    PutByte(XIRCREG_CR, SoftReset); /* set */ -    msleep(20);			     /* wait 20 msec */ -    PutByte(XIRCREG_CR, 0);	     /* clear */ -    msleep(40);			     /* wait 40 msec */ -    if (local->mohawk) { -	SelectPage(4); -	/* set pin GP1 and GP2 to output  (0x0c) -	 * set GP1 to low to power up the ML6692 (0x00) -	 * set GP2 to high to power up the 10Mhz chip  (0x02) -	 */ -	PutByte(XIRCREG4_GPR0, 0x0e); -    } - -    /* give the circuits some time to power up */ -    msleep(500);			/* about 500ms */ - -    local->last_ptr_value = 0; -    local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4 -				   : (GetByte(XIRCREG4_BOV) & 0x30) >> 4; - -    if (local->probe_port) { -	if (!local->mohawk) { -	    SelectPage(4); -	    PutByte(XIRCREG4_GPR0, 4); -	    local->probe_port = 0; -	} -    } else if (dev->if_port == 2) { /* enable 10Base2 */ -	SelectPage(0x42); -	PutByte(XIRCREG42_SWC1, 0xC0); -    } else { /* enable 10BaseT */ -	SelectPage(0x42); -	PutByte(XIRCREG42_SWC1, 0x80); -    } -    msleep(40);			     /* wait 40 msec to let it complete */ - -  #if 0 -    { -	SelectPage(0); -	value = GetByte(XIRCREG_ESR);	 /* read the ESR */ -	pr_debug("%s: ESR is: %#02x\n", dev->name, value); -    } -  #endif - -    /* setup the ECR */ -    SelectPage(1); -    PutByte(XIRCREG1_IMR0, 0xff); /* allow all ints */ -    PutByte(XIRCREG1_IMR1, 1	); /* and Set TxUnderrunDetect */ -    value = GetByte(XIRCREG1_ECR); -  #if 0 -    if (local->mohawk) -	value |= DisableLinkPulse; -    PutByte(XIRCREG1_ECR, value); -  #endif -    pr_debug("%s: ECR is: %#02x\n", dev->name, value); - -    SelectPage(0x42); -    PutByte(XIRCREG42_SWC0, 0x20); /* disable source insertion */ - -    if (local->silicon != 1) { -	/* set the local memory dividing line. -	 * The comments in the sample code say that this is only -	 * settable with the scipper version 2 which is revision 0. -	 * Always for CE3 cards -	 */ -	SelectPage(2); -	PutWord(XIRCREG2_RBS, 0x2000); -    } - -    if (full) -	set_addresses(dev); - -    /* Hardware workaround: -     * The receive byte pointer after reset is off by 1 so we need -     * to move the offset pointer back to 0. -     */ -    SelectPage(0); -    PutWord(XIRCREG0_DO, 0x2000); /* change offset command, off=0 */ - -    /* setup MAC IMRs and clear status registers */ -    SelectPage(0x40);		     /* Bit 7 ... bit 0 */ -    PutByte(XIRCREG40_RMASK0, 0xff); /* ROK, RAB, rsv, RO, CRC, AE, PTL, MP */ -    PutByte(XIRCREG40_TMASK0, 0xff); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ -    PutByte(XIRCREG40_TMASK1, 0xb0); /* rsv, rsv, PTD, EXT, rsv,rsv,rsv, rsv*/ -    PutByte(XIRCREG40_RXST0,  0x00); /* ROK, RAB, REN, RO, CRC, AE, PTL, MP */ -    PutByte(XIRCREG40_TXST0,  0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ -    PutByte(XIRCREG40_TXST1,  0x00); /* TEN, rsv, PTD, EXT, retry_counter:4  */ - -    if (full && local->mohawk && init_mii(dev)) { -	if (dev->if_port == 4 || local->dingo || local->new_mii) { -	    netdev_info(dev, "MII selected\n"); -	    SelectPage(2); -	    PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08); -	    msleep(20); -	} else { -	    netdev_info(dev, "MII detected; using 10mbs\n"); -	    SelectPage(0x42); -	    if (dev->if_port == 2) /* enable 10Base2 */ -		PutByte(XIRCREG42_SWC1, 0xC0); -	    else  /* enable 10BaseT */ -		PutByte(XIRCREG42_SWC1, 0x80); -	    msleep(40);			/* wait 40 msec to let it complete */ -	} -	if (full_duplex) -	    PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex)); -    } else {  /* No MII */ -	SelectPage(0); -	value = GetByte(XIRCREG_ESR);	 /* read the ESR */ -	dev->if_port = (value & MediaSelect) ? 1 : 2; -    } - -    /* configure the LEDs */ -    SelectPage(2); -    if (dev->if_port == 1 || dev->if_port == 4) /* TP: Link and Activity */ -	PutByte(XIRCREG2_LED, 0x3b); -    else			      /* Coax: Not-Collision and Activity */ -	PutByte(XIRCREG2_LED, 0x3a); - -    if (local->dingo) -	PutByte(0x0b, 0x04); /* 100 Mbit LED */ - -    /* enable receiver and put the mac online */ -    if (full) { -	set_multicast_list(dev); -	SelectPage(0x40); -	PutByte(XIRCREG40_CMD0, EnableRecv | Online); -    } - -    /* setup Ethernet IMR and enable interrupts */ -    SelectPage(1); -    PutByte(XIRCREG1_IMR0, 0xff); -    udelay(1); -    SelectPage(0); -    PutByte(XIRCREG_CR, EnableIntr); -    if (local->modem && !local->dingo) { /* do some magic */ -	if (!(GetByte(0x10) & 0x01)) -	    PutByte(0x10, 0x11); /* unmask master-int bit */ -    } - -    if (full) -	netdev_info(dev, "media %s, silicon revision %d\n", -		    if_names[dev->if_port], local->silicon); -    /* We should switch back to page 0 to avoid a bug in revision 0 -     * where regs with offset below 8 can't be read after an access -     * to the MAC registers */ -    SelectPage(0); -} - -/**************** - * Initialize the Media-Independent-Interface - * Returns: True if we have a good MII - */ -static int -init_mii(struct net_device *dev) -{ -    local_info_t *local = netdev_priv(dev); -    unsigned int ioaddr = dev->base_addr; -    unsigned control, status, linkpartner; -    int i; - -    if (if_port == 4 || if_port == 1) { /* force 100BaseT or 10BaseT */ -	dev->if_port = if_port; -	local->probe_port = 0; -	return 1; -    } - -    status = mii_rd(ioaddr,  0, 1); -    if ((status & 0xff00) != 0x7800) -	return 0; /* No MII */ - -    local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff); -     -    if (local->probe_port) -	control = 0x1000; /* auto neg */ -    else if (dev->if_port == 4) -	control = 0x2000; /* no auto neg, 100mbs mode */ -    else -	control = 0x0000; /* no auto neg, 10mbs mode */ -    mii_wr(ioaddr,  0, 0, control, 16); -    udelay(100); -    control = mii_rd(ioaddr, 0, 0); - -    if (control & 0x0400) { -	netdev_notice(dev, "can't take PHY out of isolation mode\n"); -	local->probe_port = 0; -	return 0; -    } - -    if (local->probe_port) { -	/* according to the DP83840A specs the auto negotiation process -	 * may take up to 3.5 sec, so we use this also for our ML6692 -	 * Fixme: Better to use a timer here! -	 */ -	for (i=0; i < 35; i++) { -	    msleep(100);	 /* wait 100 msec */ -	    status = mii_rd(ioaddr,  0, 1); -	    if ((status & 0x0020) && (status & 0x0004)) -		break; -	} - -	if (!(status & 0x0020)) { -	    netdev_info(dev, "autonegotiation failed; using 10mbs\n"); -	    if (!local->new_mii) { -		control = 0x0000; -		mii_wr(ioaddr,  0, 0, control, 16); -		udelay(100); -		SelectPage(0); -		dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2; -	    } -	} else { -	    linkpartner = mii_rd(ioaddr, 0, 5); -	    netdev_info(dev, "MII link partner: %04x\n", linkpartner); -	    if (linkpartner & 0x0080) { -		dev->if_port = 4; -	    } else -		dev->if_port = 1; -	} -    } - -    return 1; -} - -static void -do_powerdown(struct net_device *dev) -{ - -    unsigned int ioaddr = dev->base_addr; - -    pr_debug("do_powerdown(%p)\n", dev); - -    SelectPage(4); -    PutByte(XIRCREG4_GPR1, 0);	     /* clear bit 0: power down */ -    SelectPage(0); -} - -static int -do_stop(struct net_device *dev) -{ -    unsigned int ioaddr = dev->base_addr; -    local_info_t *lp = netdev_priv(dev); -    struct pcmcia_device *link = lp->p_dev; - -    dev_dbg(&link->dev, "do_stop(%p)\n", dev); - -    if (!link) -	return -ENODEV; - -    netif_stop_queue(dev); - -    SelectPage(0); -    PutByte(XIRCREG_CR, 0);  /* disable interrupts */ -    SelectPage(0x01); -    PutByte(XIRCREG1_IMR0, 0x00); /* forbid all ints */ -    SelectPage(4); -    PutByte(XIRCREG4_GPR1, 0);	/* clear bit 0: power down */ -    SelectPage(0); - -    link->open--; -    return 0; -} - -static struct pcmcia_device_id xirc2ps_ids[] = { -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), -	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), -	PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), -	PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), -	PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), -	PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), -	PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), -	PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), -	PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a), -	PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2), -	PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37), -	PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073), -	PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3), -	PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609), -	PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46), -	PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2), -	PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769), -	PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db), -	PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf), -	/* also matches CFE-10 cards! */ -	/* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */ -	PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids); - - -static struct pcmcia_driver xirc2ps_cs_driver = { -	.owner		= THIS_MODULE, -	.name		= "xirc2ps_cs", -	.probe		= xirc2ps_probe, -	.remove		= xirc2ps_detach, -	.id_table       = xirc2ps_ids, -	.suspend	= xirc2ps_suspend, -	.resume		= xirc2ps_resume, -}; - -static int __init -init_xirc2ps_cs(void) -{ -	return pcmcia_register_driver(&xirc2ps_cs_driver); -} - -static void __exit -exit_xirc2ps_cs(void) -{ -	pcmcia_unregister_driver(&xirc2ps_cs_driver); -} - -module_init(init_xirc2ps_cs); -module_exit(exit_xirc2ps_cs); - -#ifndef MODULE -static int __init setup_xirc2ps_cs(char *str) -{ -	/* if_port, full_duplex, do_sound, lockup_hack -	 */ -	int ints[10] = { -1 }; - -	str = get_options(str, 9, ints); - -#define MAYBE_SET(X,Y) if (ints[0] >= Y && ints[Y] != -1) { X = ints[Y]; } -	MAYBE_SET(if_port, 3); -	MAYBE_SET(full_duplex, 4); -	MAYBE_SET(do_sound, 5); -	MAYBE_SET(lockup_hack, 6); -#undef  MAYBE_SET - -	return 1; -} - -__setup("xirc2ps_cs=", setup_xirc2ps_cs); -#endif  | 
