linux/drivers/net/ethernet/3com/3c509.c

/* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
/*
	Written 1993-2000 by Donald Becker.

	Copyright 1994-2000 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.

	This driver is for the 3Com EtherLinkIII series.

	The author may be reached as [email protected], or C/O
	Scyld Computing Corporation
	410 Severn Ave., Suite 210
	Annapolis MD 21403

	Known limitations:
	Because of the way 3c509 ISA detection works it's difficult to predict
	a priori which of several ISA-mode cards will be detected first.

	This driver does not use predictive interrupt mode, resulting in higher
	packet latency but lower overhead.  If interrupts are disabled for an
	unusually long time it could also result in missed packets, but in
	practice this rarely happens.


	FIXES:
		Alan Cox:       Removed the 'Unexpected interrupt' bug.
		Michael Meskes:	Upgraded to Donald Becker's version 1.07.
		Alan Cox:	Increased the eeprom delay. Regardless of
				what the docs say some people definitely
				get problems with lower (but in card spec)
				delays
		v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
				other cleanups.  -djb
		Andrea Arcangeli:	Upgraded to Donald Becker's version 1.12.
		Rick Payne:	Fixed SMP race condition
		v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
		v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
		v1.15 1/31/98 Faster recovery for Tx errors. -djb
		v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
		v1.18 12Mar2001 Andrew Morton
			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
			- Reviewed against 1.18 from scyld.com
		v1.18a 17Nov2001 Jeff Garzik <[email protected]>
			- ethtool support
		v1.18b 1Mar2002 Zwane Mwaikambo <[email protected]>
			- Power Management support
		v1.18c 1Mar2002 David Ruggiero <[email protected]>
			- Full duplex support
		v1.19  16Oct2002 Zwane Mwaikambo <[email protected]>
			- Additional ethtool features
		v1.19a 28Oct2002 Davud Ruggiero <[email protected]>
			- Increase *read_eeprom udelay to workaround oops with 2 cards.
		v1.19b 08Nov2002 Marc Zyngier <[email protected]>
			- Introduce driver model for EISA cards.
		v1.20  04Feb2008 Ondrej Zary <[email protected]>
			- convert to isa_driver and pnp_driver and some cleanups
*/

#define DRV_NAME

/* A few values that may be tweaked. */

/* Time in jiffies before concluding the transmitter is hung. */
#define TX_TIMEOUT

#include <linux/module.h>
#include <linux/isa.h>
#include <linux/pnp.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/pm.h>
#include <linux/skbuff.h>
#include <linux/delay.h>	/* for udelay() */
#include <linux/spinlock.h>
#include <linux/ethtool.h>
#include <linux/device.h>
#include <linux/eisa.h>
#include <linux/bitops.h>

#include <linux/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>

#ifdef EL3_DEBUG
static int el3_debug = EL3_DEBUG;
#else
static int el3_debug =;
#endif

/* Used to do a global count of all the cards in the system.  Must be
 * a global variable so that the eisa probe routines can increment
 * it */
static int el3_cards =;
#define EL3_MAX_CARDS

/* To minimize the size of the driver source I only define operating
   constants if they are used several times.  You'll need the manual
   anyway if you want to understand driver details. */
/* Offsets from base I/O address. */
#define EL3_DATA
#define EL3_CMD
#define EL3_STATUS
#define EEPROM_READ

#define EL3_IO_EXTENT

#define EL3WINDOW(win_num)


/* The top five bits written to EL3_CMD are a command, the lower
   11 bits are the parameter, if applicable. */
enum c509cmd {};

enum c509status {};

/* The SetRxFilter command accepts the following classes: */
enum RxFilter {};

/* Register window 1 offsets, the window used in normal operation. */
#define TX_FIFO
#define RX_FIFO
#define RX_STATUS
#define TX_STATUS
#define TX_FREE

#define WN0_CONF_CTRL
#define WN0_ADDR_CONF
#define WN0_IRQ
#define WN4_MEDIA
#define MEDIA_TP
#define WN4_NETDIAG
#define FD_ENABLE

/*
 * Must be a power of two (we use a binary and in the
 * circular queue)
 */
#define SKB_QUEUE_SIZE

enum el3_cardtype {};

struct el3_private {};
static int id_port;
static int current_tag;
static struct net_device *el3_devs[EL3_MAX_CARDS];

/* Parameters that may be passed into the module. */
static int debug =;
static int irq[] =;
/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
static int max_interrupt_work =;
#ifdef CONFIG_PNP
static int nopnp;
#endif

static int el3_common_init(struct net_device *dev);
static void el3_common_remove(struct net_device *dev);
static ushort id_read_eeprom(int index);
static ushort read_eeprom(int ioaddr, int index);
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 set_multicast_list(struct net_device *dev);
static void el3_tx_timeout (struct net_device *dev, unsigned int txqueue);
static void el3_down(struct net_device *dev);
static void el3_up(struct net_device *dev);
static const struct ethtool_ops ethtool_ops;
#ifdef CONFIG_PM
static int el3_suspend(struct device *, pm_message_t);
static int el3_resume(struct device *);
#else
#define el3_suspend
#define el3_resume
#endif


/* generic device remove for all device types */
static int el3_device_remove (struct device *device);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void el3_poll_controller(struct net_device *dev);
#endif

/* Return 0 on success, 1 on error, 2 when found already detected PnP card */
static int el3_isa_id_sequence(__be16 *phys_addr)
{}

static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr,
			 int irq, int if_port, enum el3_cardtype type)
{}

static int el3_isa_match(struct device *pdev, unsigned int ndev)
{}

static void el3_isa_remove(struct device *pdev,
				    unsigned int ndev)
{}

#ifdef CONFIG_PM
static int el3_isa_suspend(struct device *dev, unsigned int n,
			   pm_message_t state)
{}

static int el3_isa_resume(struct device *dev, unsigned int n)
{}
#endif

static struct isa_driver el3_isa_driver =;
static int isa_registered;

#ifdef CONFIG_PNP
static const struct pnp_device_id el3_pnp_ids[] =;
MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);

static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
{}

static void el3_pnp_remove(struct pnp_dev *pdev)
{}

#ifdef CONFIG_PM
static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
{}

static int el3_pnp_resume(struct pnp_dev *pdev)
{}
#endif

static struct pnp_driver el3_pnp_driver =;
static int pnp_registered;
#endif /* CONFIG_PNP */

#ifdef CONFIG_EISA
static const struct eisa_device_id el3_eisa_ids[] =;
MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);

static int el3_eisa_probe (struct device *device);

static struct eisa_driver el3_eisa_driver =;
static int eisa_registered;
#endif

static const struct net_device_ops netdev_ops =;

static int el3_common_init(struct net_device *dev)
{}

static void el3_common_remove (struct net_device *dev)
{}

#ifdef CONFIG_EISA
static int el3_eisa_probe(struct device *device)
{}
#endif

/* This remove works for all device types.
 *
 * The net dev must be stored in the driver data field */
static int el3_device_remove(struct device *device)
{}

/* Read a word from the EEPROM using the regular EEPROM access register.
   Assume that we are in register window zero.
 */
static ushort read_eeprom(int ioaddr, int index)
{}

/* Read a word from the EEPROM when in the ISA ID probe state. */
static ushort id_read_eeprom(int index)
{}


static int
el3_open(struct net_device *dev)
{}

static void
el3_tx_timeout (struct net_device *dev, unsigned int txqueue)
{}


static netdev_tx_t
el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{}

/* The EL3 interrupt handler. */
static irqreturn_t
el3_interrupt(int irq, void *dev_id)
{}


#ifdef CONFIG_NET_POLL_CONTROLLER
/*
 * Polling receive - used by netconsole and other diagnostic tools
 * to allow network i/o with interrupts disabled.
 */
static void el3_poll_controller(struct net_device *dev)
{}
#endif

static struct net_device_stats *
el3_get_stats(struct net_device *dev)
{}

/*  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.
	*/
static void update_stats(struct net_device *dev)
{}

static int
el3_rx(struct net_device *dev)
{}

/*
 *     Set or clear the multicast filter for this adaptor.
 */
static void
set_multicast_list(struct net_device *dev)
{}

static int
el3_close(struct net_device *dev)
{}

static int
el3_link_ok(struct net_device *dev)
{}

static void
el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_link_ksettings *cmd)
{}

static int
el3_netdev_set_ecmd(struct net_device *dev,
		    const struct ethtool_link_ksettings *cmd)
{}

static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{}

static int el3_get_link_ksettings(struct net_device *dev,
				  struct ethtool_link_ksettings *cmd)
{}

static int el3_set_link_ksettings(struct net_device *dev,
				  const struct ethtool_link_ksettings *cmd)
{}

static u32 el3_get_link(struct net_device *dev)
{}

static u32 el3_get_msglevel(struct net_device *dev)
{}

static void el3_set_msglevel(struct net_device *dev, u32 v)
{}

static const struct ethtool_ops ethtool_ops =;

static void
el3_down(struct net_device *dev)
{}

static void
el3_up(struct net_device *dev)
{}

/* Power Management support functions */
#ifdef CONFIG_PM

static int
el3_suspend(struct device *pdev, pm_message_t state)
{}

static int
el3_resume(struct device *pdev)
{}

#endif /* CONFIG_PM */

module_param(debug,int, 0);
module_param_hw_array(irq, int, irq, NULL, 0);
module_param(max_interrupt_work, int, 0);
MODULE_PARM_DESC();
MODULE_PARM_DESC();
MODULE_PARM_DESC();
#ifdef CONFIG_PNP
module_param(nopnp, int, 0);
MODULE_PARM_DESC();
#endif	/* CONFIG_PNP */
MODULE_DESCRIPTION();
MODULE_LICENSE();

static int __init el3_init_module(void)
{}

static void __exit el3_cleanup_module(void)
{}

module_init();
module_exit (el3_cleanup_module);