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

/* 3c574.c: A PCMCIA ethernet driver for the 3com 3c574 "RoadRunner".

	Written 1993-1998 by
	Donald Becker, [email protected], (driver core) and
	David Hinds, [email protected] (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)

#include <linux/module.h>
#include <linux/kernel.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 <linux/uaccess.h>
#include <asm/io.h>

/*====================================================================*/

/* Module parameters */

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();

#define INT_MODULE_PARM(n, v)

/* 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

/* 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
#define EL3_CMD
#define EL3_STATUS

#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 el3_cmds {};

enum elxl_status {};

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

enum Window0 {};
/* These assumes the larger EEPROM. */
enum Win0_EEPROM_cmds {};

/* 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 {};

enum Window3 {};
enum wn3_config {};

enum Window4 {};

#define MEDIA_TP

struct el3_private {};

/* 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 =;

/* 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(struct timer_list *t);
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, unsigned int txqueue);
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 =;

static int tc574_probe(struct pcmcia_device *link)
{}

static void tc574_detach(struct pcmcia_device *link)
{} /* tc574_detach */

static const char *ram_split[] =;

static int tc574_config(struct pcmcia_device *link)
{} /* tc574_config */

static void tc574_release(struct pcmcia_device *link)
{}

static int tc574_suspend(struct pcmcia_device *link)
{}

static int tc574_resume(struct pcmcia_device *link)
{}

static void dump_status(struct net_device *dev)
{}

/*
  Use this for commands that may take time to finish
*/
static void tc574_wait_for_completion(struct net_device *dev, int 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)
{}

/* 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
#define MDIO_DIR_WRITE
#define MDIO_DATA_WRITE0
#define MDIO_DATA_WRITE1
#define MDIO_DATA_READ
#define MDIO_ENB_IN

/* Generate the preamble required for initial synchronization and
   a few older transceivers. */
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)
{}

/* Reset and restore all of the 3c574 registers. */
static void tc574_reset(struct net_device *dev)
{}

static int el3_open(struct net_device *dev)
{}

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

static void pop_tx_status(struct net_device *dev)
{}

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)
{}

/*
    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(struct timer_list *t)
{}

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

/*  Update statistics.
	Surprisingly 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)
{}

static int el3_rx(struct net_device *dev, int worklimit)
{}

/* Provide ioctl() calls to examine the MII xcvr state. */
static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{}

/* 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)
{}

static void set_multicast_list(struct net_device *dev)
{}

static int el3_close(struct net_device *dev)
{}

static const struct pcmcia_device_id tc574_ids[] =;
MODULE_DEVICE_TABLE(pcmcia, tc574_ids);

static struct pcmcia_driver tc574_driver =;
module_pcmcia_driver();