11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* eepro.c: Intel EtherExpress Pro/10 device driver for Linux. */
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Written 1994, 1995,1996 by Bao C. Ha.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Copyright (C) 1994, 1995,1996 by Bao C. Ha.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	This software may be used and distributed
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	according to the terms of the GNU General Public License,
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	incorporated herein by reference.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	The author may be reached at bao.ha@srs.gov
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	or 418 Hastings Place, Martinez, GA 30907.
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Things remaining to do:
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Better record keeping of errors.
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Eliminate transmit interrupt to reduce overhead.
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Implement "concurrent processing". I won't be doing it!
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Bugs:
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	If you have a problem of not detecting the 82595 during a
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	reboot (warm reset), disable the FLASH memory should fix it.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	This is a compatibility hardware problem.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Versions:
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.13b	basic ethtool support (aris, 09/13/2004)
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.13a   in memory shortage, drop packets also in board
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(Michael Westermann <mw@microdata-pos.de>, 07/30/2002)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.13    irq sharing, rewrote probe function, fixed a nasty bug in
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hardware_send_packet and a major cleanup (aris, 11/08/2001)
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.12d	fixing a problem with single card detected as eight eth devices
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fixing a problem with sudden drop in card performance
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(chris (asdn@go2.pl), 10/29/2001)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.12c	fixing some problems with old cards (aris, 01/08/2001)
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.12b	misc fixes (aris, 06/26/2000)
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.12a   port of version 0.12a of 2.2.x kernels to 2.3.x
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(aris (aris@conectiva.com.br), 05/19/2000)
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.11e   some tweaks about multiple cards support (PdP, jul/aug 1999)
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.11d	added __initdata, __init stuff; call spin_lock_init
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        in eepro_probe1. Replaced "eepro" by dev->name. Augmented
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		the code protected by spin_lock in interrupt routine
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(PdP, 12/12/1998)
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.11c   minor cleanup (PdP, RMC, 09/12/1998)
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.11b   Pascal Dupuis (dupuis@lei.ucl.ac.be): works as a module
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        under 2.1.xx. Debug messages are flagged as KERN_DEBUG to
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		avoid console flooding. Added locking at critical parts. Now
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		the dawn thing is SMP safe.
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.11a   Attempt to get 2.1.xx support up (RMC)
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.11	Brian Candler added support for multiple cards. Tested as
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		a module, no idea if it works when compiled into kernel.
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.10e	Rick Bressler notified me that ifconfig up;ifconfig down fails
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		because the irq is lost somewhere. Fixed that by moving
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		request_irq and free_irq to eepro_open and eepro_close respectively.
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.10d	Ugh! Now Wakeup works. Was seriously broken in my first attempt.
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		I'll need to find a way to specify an ioport other than
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		the default one in the PnP case. PnP definitively sucks.
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		And, yes, this is not the only reason.
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.10c	PnP Wakeup Test for 595FX. uncomment #define PnPWakeup;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to use.
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.10b	Should work now with (some) Pro/10+. At least for
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		me (and my two cards) it does. _No_ guarantee for
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		function with non-Pro/10+ cards! (don't have any)
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(RMC, 9/11/96)
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.10	Added support for the Etherexpress Pro/10+.  The
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		IRQ map was changed significantly from the old
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pro/10.  The new interrupt map was provided by
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Rainer M. Canavan (Canavan@Zeus.cs.bonn.edu).
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(BCH, 9/3/96)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.09	Fixed a race condition in the transmit algorithm,
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		which causes crashes under heavy load with fast
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pentium computers.  The performance should also
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		improve a bit.  The size of RX buffer, and hence
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		TX buffer, can also be changed via lilo or insmod.
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(BCH, 7/31/96)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.08	Implement 32-bit I/O for the 82595TX and 82595FX
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		based lan cards.  Disable full-duplex mode if TPE
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		is not used.  (BCH, 4/8/96)
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.07a	Fix a stat report which counts every packet as a
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		heart-beat failure. (BCH, 6/3/95)
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.07	Modified to support all other 82595-based lan cards.
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		The IRQ vector of the EtherExpress Pro will be set
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		according to the value saved in the EEPROM.  For other
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cards, I will do autoirq_request() to grab the next
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		available interrupt vector. (BCH, 3/17/95)
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.06a,b	Interim released.  Minor changes in the comments and
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		print out format. (BCH, 3/9/95 and 3/14/95)
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.06	First stable release that I am comfortable with. (BCH,
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		3/2/95)
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.05	Complete testing of multicast. (BCH, 2/23/95)
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.04	Adding multicast support. (BCH, 2/14/95)
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	0.03	First widely alpha release for public testing.
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		(BCH, 2/14/95)
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char version[] =
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	"eepro.c: v0.13b 09/13/2004 aris@cathedrallabs.org\n";
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  Sources:
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	This driver wouldn't have been written without the availability
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	of the Crynwr's Lan595 driver source code.  It helps me to
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	familiarize with the 82595 chipset while waiting for the Intel
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	documentation.  I also learned how to detect the 82595 using
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	the packet driver's technique.
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	This driver is written by cutting and pasting the skeleton.c driver
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	provided by Donald Becker.  I also borrowed the EEPROM routine from
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Donald Becker's 82586 driver.
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Datasheet for the Intel 82595 (including the TX and FX version). It
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	provides just enough info that the casual reader might think that it
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	documents the i82595.
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	The User Manual for the 82595.  It provides a lot of the missing
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	information.
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h>
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h>
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h>
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h>
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h>
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ethtool.h>
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h>
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_NAME "eepro"
155d5b20697ca37d80cc4ec2ba3c5ddf1339dc1d49aAndy Gospodarek#define DRV_VERSION "0.13c"
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define compat_dev_kfree_skb( skb, mode ) dev_kfree_skb( (skb) )
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I had reports of looong delays with SLOW_DOWN defined as udelay(2) */
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SLOW_DOWN inb(0x80)
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* udelay(2) */
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define compat_init_data     __initdata
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum iftype { AUI=0, BNC=1, TPE=2 };
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* First, a few definitions that the brave might change. */
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A zero-terminated list of I/O addresses to be probed. */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int eepro_portlist[] compat_init_data =
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0};
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* note: 0x300 is default, the 595FX supports ALL IO Ports
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  from 0x000 to 0x3F0, some of which are reserved in PCs */
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* To try the (not-really PnP Wakeup: */
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PnPWakeup
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* use 0 for production, 1 for verification, >2 for debug */
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef NET_DEBUG
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NET_DEBUG 0
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int net_debug = NET_DEBUG;
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The number of low I/O ports used by the ethercard. */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EEPRO_IO_EXTENT	16
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Different 82595 chips */
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LAN595		0
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LAN595TX	1
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LAN595FX	2
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	LAN595FX_10ISA	3
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Information that need to be kept for each board. */
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct eepro_local {
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned rx_start;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned tx_start; /* start of the transmit chain */
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int tx_last;  /* pointer to last packet in the transmit chain */
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned tx_end;   /* end of the transmit chain (plus 1) */
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int eepro;	/* 1 for the EtherExpress Pro/10,
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   2 for the EtherExpress Pro/10+,
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   3 for the EtherExpress 10 (blue cards),
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   0 for other 82595-based lan cards. */
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int version;	/* a flag to indicate if this is a TX or FX
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   version of the 82595 chip. */
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int stepping;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spinlock_t lock; /* Serializing lock  */
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned rcv_ram;	/* pre-calculated space for rx */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned xmt_ram;	/* pre-calculated space for tx */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char xmt_bar;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char xmt_lower_limit_reg;
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char xmt_upper_limit_reg;
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short xmt_lower_limit;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short xmt_upper_limit;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short rcv_lower_limit;
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short rcv_upper_limit;
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned char eeprom_reg;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short word[8];
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The station (ethernet) address prefix, used for IDing the board. */
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SA_ADDR0 0x00	/* Etherexpress Pro/10 */
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SA_ADDR1 0xaa
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SA_ADDR2 0x00
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define GetBit(x,y) ((x & (1<<y))>>y)
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* EEPROM Word 0: */
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PnP       0  /* Plug 'n Play enable bit */
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_Word1     1  /* Word 1? */
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_BusWidth  2  /* 8/16 bit */
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_FlashAddr 3  /* Flash Address */
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_FlashMask 0x7   /* Mask */
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_AutoIO    6  /* */
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_reserved0 7  /* =0! */
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_Flash     8  /* Flash there? */
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_AutoNeg   9  /* Auto Negotiation enabled? */
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IO0       10 /* IO Address LSB */
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IO0Mask   0x /*...*/
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IO1       15 /* IO MSB */
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* EEPROM Word 1: */
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IntSel    0   /* Interrupt */
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IntMask   0x7
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_LI        3   /* Link Integrity 0= enabled */
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PC        4   /* Polarity Correction 0= enabled */
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_TPE_AUI   5   /* PortSelection 1=TPE */
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_Jabber    6   /* Jabber prevention 0= enabled */
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_AutoPort  7   /* Auto Port Selection 1= Disabled */
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_SMOUT     8   /* SMout Pin Control 0= Input */
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PROM      9   /* Flash EPROM / PROM 0=Flash */
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_reserved1 10  /* .. 12 =0! */
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_AltReady  13  /* Alternate Ready, 0=normal */
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_reserved2 14  /* =0! */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_Duplex    15
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Word2,3,4: */
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IA5       0 /*bit start for individual Addr Byte 5 */
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IA4       8 /*bit start for individual Addr Byte 5 */
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IA3       0 /*bit start for individual Addr Byte 5 */
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IA2       8 /*bit start for individual Addr Byte 5 */
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IA1       0 /*bit start for individual Addr Byte 5 */
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_IA0       8 /*bit start for individual Addr Byte 5 */
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Word 5: */
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_BNC_TPE   0 /* 0=TPE */
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_BootType  1 /* 00=None, 01=IPX, 10=ODI, 11=NDIS */
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_BootTypeMask 0x3
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_NumConn   3  /* Number of Connections 0= One or Two */
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_FlashSock 4  /* Presence of Flash Socket 0= Present */
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PortTPE   5
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PortBNC   6
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PortAUI   7
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_PowerMgt  10 /* 0= disabled */
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_CP        13 /* Concurrent Processing */
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_CPMask    0x7
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Word 6: */
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_Stepping  0 /* Stepping info */
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_StepMask  0x0F
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_BoardID   4 /* Manucaturer Board ID, reserved */
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_BoardMask 0x0FFF
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Word 7: */
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_INT_TO_IRQ 0 /* int to IRQ Mapping  = 0x1EB8 for Pro/10+ */
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_FX_INT2IRQ 0x1EB8 /* the _only_ mapping allowed for FX chips */
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*..*/
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_SIZE 0x40 /* total EEprom Size */
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_Checksum 0xBABA /* initial and final value for adding checksum */
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Card identification via EEprom:   */
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_addr_vendor 0x10  /* Word offset for EISA Vendor ID */
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_addr_id 0x11      /* Word offset for Card ID */
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_addr_SN 0x12      /* Serial Number */
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_addr_CRC_8 0x14   /* CRC over last thee Bytes */
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_vendor_intel0 0x25  /* Vendor ID Intel */
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_vendor_intel1 0xD4
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_id_eepro10p0 0x10   /* ID for eepro/10+ */
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ee_id_eepro10p1 0x31
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
304c63fdf46ad0a7f8fe3c0252a0e763515617e0ea7Eric Dumazet#define TX_TIMEOUT ((4*HZ)/10)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Index to functions, as function prototypes. */
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int	eepro_probe1(struct net_device *dev, int autoprobe);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int	eepro_open(struct net_device *dev);
31061357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t eepro_send_packet(struct sk_buff *skb,
31161357325f377889a1daffa14962d705dc814dd0eStephen Hemminger				     struct net_device *dev);
3127d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t eepro_interrupt(int irq, void *dev_id);
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 	eepro_rx(struct net_device *dev);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 	eepro_transmit_interrupt(struct net_device *dev);
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int	eepro_close(struct net_device *dev);
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void     set_multicast_list(struct net_device *dev);
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void     eepro_tx_timeout (struct net_device *dev);
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int read_eeprom(int ioaddr, int location, struct net_device *dev);
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int	hardware_send_packet(struct net_device *dev, void *buf, short length);
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int	eepro_grab_irq(struct net_device *dev);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			Details of the i82595.
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsYou will need either the datasheet or the user manual to understand what
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsis going on here.  The 82595 is very different from the 82586, 82593.
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe receive algorithm in eepro_rx() is just an implementation of the
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsRCV ring structure that the Intel 82595 imposes at the hardware level.
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe receive buffer is set at 24K, and the transmit buffer is 8K.  I
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsam assuming that the total buffer memory is 32K, which is true for the
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIntel EtherExpress Pro/10.  If it is less than that on a generic card,
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe driver will be broken.
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe transmit algorithm in the hardware_send_packet() is similar to the
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsone in the eepro_rx().  The transmit buffer is a ring linked list.
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsI just queue the next available packet to the end of the list.  In my
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssystem, the 82595 is so fast that the list seems to always contain a
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssingle packet.  In other systems with faster computers and more congested
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsnetwork traffics, the ring linked list should improve performance by
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsallowing up to 8K worth of packets to be queued.
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe sizes of the receive and transmit buffers can now be changed via lilo
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsor insmod.  Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswhere rx-buffer is in KB unit.  Modules uses the parameter mem which is
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsalso in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe receive buffer has to be more than 3K or less than 29K.  Otherwise,
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsit is reset to the default of 24K, and, hence, 8K for the trasnmit
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbuffer (transmit-buffer = 32K - receive-buffer).
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RAM_SIZE        0x8000
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RCV_HEADER      8
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RCV_DEFAULT_RAM 0x6000
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define XMT_HEADER      8
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define XMT_DEFAULT_RAM	(RAM_SIZE - RCV_DEFAULT_RAM)
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define XMT_START_PRO	RCV_DEFAULT_RAM
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define XMT_START_10	0x0000
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RCV_START_PRO	0x0000
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RCV_START_10	XMT_DEFAULT_RAM
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_DONE	0x0008
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RX_OK		0x2000
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RX_ERROR	0x0d81
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	TX_DONE_BIT	0x0080
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	TX_OK		0x2000
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	CHAIN_BIT	0x8000
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_STATUS	0x02
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_CHAIN	0x04
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_COUNT	0x06
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	BANK0_SELECT	0x00
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	BANK1_SELECT	0x40
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	BANK2_SELECT	0x80
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bank 0 registers */
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	COMMAND_REG	0x00	/* Register 0 */
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	MC_SETUP	0x03
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_CMD		0x04
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	DIAGNOSE_CMD	0x07
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_ENABLE_CMD	0x08
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_DISABLE_CMD	0x0a
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	STOP_RCV_CMD	0x0b
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RESET_CMD	0x0e
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	POWER_DOWN_CMD	0x18
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RESUME_XMT_CMD	0x1c
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	SEL_RESET_CMD	0x1e
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	STATUS_REG	0x01	/* Register 1 */
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RX_INT		0x02
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	TX_INT		0x04
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EXEC_STATUS	0x30
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	ID_REG		0x02	/* Register 2	*/
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	R_ROBIN_BITS	0xc0	/* round robin counter */
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	ID_REG_MASK	0x2c
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	ID_REG_SIG	0x24
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	AUTO_ENABLE	0x10
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	INT_MASK_REG	0x03	/* Register 3	*/
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RX_STOP_MASK	0x01
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RX_MASK		0x02
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	TX_MASK		0x04
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EXEC_MASK	0x08
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	ALL_MASK	0x0f
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	IO_32_BIT	0x10
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_BAR		0x04	/* The following are word (16-bit) registers */
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_STOP	0x06
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_BAR_PRO	0x0a
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_BAR_10	0x0b
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	HOST_ADDRESS_REG	0x0c
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	IO_PORT		0x0e
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	IO_PORT_32_BIT	0x0c
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bank 1 registers */
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	REG1	0x01
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	WORD_WIDTH	0x02
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	INT_ENABLE	0x80
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define INT_NO_REG	0x02
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_LOWER_LIMIT_REG	0x08
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_UPPER_LIMIT_REG	0x09
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_LOWER_LIMIT_REG_PRO 0x0a
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_UPPER_LIMIT_REG_PRO 0x0b
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_LOWER_LIMIT_REG_10  0x0b
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_UPPER_LIMIT_REG_10  0x0a
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Bank 2 registers */
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_Chain_Int	0x20	/* Interrupt at the end of the transmit chain */
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	XMT_Chain_ErrStop	0x40 /* Interrupt at the end of the chain even if there are errors */
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	RCV_Discard_BadFrame	0x80 /* Throw bad frames away, and continue to receive others */
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	REG2		0x02
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	PRMSC_Mode	0x01
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	Multi_IA	0x20
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	REG3		0x03
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	TPE_BIT		0x04
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	BNC_BIT		0x20
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	REG13		0x0d
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	FDX		0x00
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	A_N_ENABLE	0x02
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	I_ADD_REG0	0x04
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	I_ADD_REG1	0x05
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	I_ADD_REG2	0x06
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	I_ADD_REG3	0x07
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	I_ADD_REG4	0x08
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	I_ADD_REG5	0x09
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EEPROM_REG_PRO 0x0a
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define	EEPROM_REG_10  0x0b
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EESK 0x01
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EECS 0x02
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EEDI 0x04
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EEDO 0x08
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* do a full reset */
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_reset(ioaddr) outb(RESET_CMD, ioaddr)
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* do a nice reset */
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_sel_reset(ioaddr) 	{ \
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					outb(SEL_RESET_CMD, ioaddr); \
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					SLOW_DOWN; \
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					SLOW_DOWN; \
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* disable all interrupts */
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_dis_int(ioaddr) outb(ALL_MASK, ioaddr + INT_MASK_REG)
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* clear all interrupts */
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_clear_int(ioaddr) outb(ALL_MASK, ioaddr + STATUS_REG)
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable tx/rx */
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_en_int(ioaddr) outb(ALL_MASK & ~(RX_MASK | TX_MASK), \
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							ioaddr + INT_MASK_REG)
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable exec event interrupt */
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_en_intexec(ioaddr) outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG)
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable rx */
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_en_rx(ioaddr) outb(RCV_ENABLE_CMD, ioaddr)
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* disable rx */
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_dis_rx(ioaddr) outb(RCV_DISABLE_CMD, ioaddr)
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* switch bank */
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_sw2bank0(ioaddr) outb(BANK0_SELECT, ioaddr)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_sw2bank1(ioaddr) outb(BANK1_SELECT, ioaddr)
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_sw2bank2(ioaddr) outb(BANK2_SELECT, ioaddr)
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* enable interrupt line */
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_en_intline(ioaddr) outb(inb(ioaddr + REG1) | INT_ENABLE,\
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ioaddr + REG1)
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* disable interrupt line */
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_dis_intline(ioaddr) outb(inb(ioaddr + REG1) & 0x7f, \
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ioaddr + REG1);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* set diagnose flag */
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_diag(ioaddr) outb(DIAGNOSE_CMD, ioaddr)
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ack for rx int */
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_ack_rx(ioaddr) outb (RX_INT, ioaddr + STATUS_REG)
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ack for tx int */
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_ack_tx(ioaddr) outb (TX_INT, ioaddr + STATUS_REG)
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* a complete sel reset */
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eepro_complete_selreset(ioaddr) { \
51409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik						dev->stats.tx_errors++;\
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						eepro_sel_reset(ioaddr);\
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						lp->tx_end = \
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							lp->xmt_lower_limit;\
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						lp->tx_start = lp->tx_end;\
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						lp->tx_last = 0;\
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						dev->trans_start = jiffies;\
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						netif_wake_queue(dev);\
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						eepro_en_rx(ioaddr);\
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Check for a network adaptor of this type, and return '0' if one exists.
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   If dev->base_addr == 0, probe all likely locations.
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   If dev->base_addr == 1, always return failure.
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   If dev->base_addr == 2, allocate space for the device and return success
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   (detachable devices only).
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   */
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init do_eepro_probe(struct net_device *dev)
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int base_addr = dev->base_addr;
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irq = dev->irq;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef PnPWakeup
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* XXXX for multiple cards should this only be run once? */
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Wakeup: */
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define WakeupPort 0x279
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	#define WakeupSeq    {0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x7D, 0xBE,\
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	                      0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,\
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	                      0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,\
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	                      0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x43}
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned short int WS[32]=WakeupSeq;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
550d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik		if (request_region(WakeupPort, 2, "eepro wakeup")) {
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (net_debug>5)
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "Waking UP\n");
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb_p(0,WakeupPort);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb_p(0,WakeupPort);
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			for (i=0; i<32; i++) {
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outb_p(WS[i],WakeupPort);
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (net_debug>5) printk(KERN_DEBUG ": %#x ",WS[i]);
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
560d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
561d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik			release_region(WakeupPort, 2);
562d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik		} else
563d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik			printk(KERN_WARNING "PnP wakeup region busy!\n");
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (base_addr > 0x1ff)		/* Check a single specified location. */
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return eepro_probe1(dev, 0);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (base_addr != 0)	/* Don't probe at all. */
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENXIO;
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; eepro_portlist[i]; i++) {
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->base_addr = eepro_portlist[i];
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->irq = irq;
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (eepro_probe1(dev, 1) == 0)
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return 0;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device * __init eepro_probe(int unit)
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = alloc_etherdev(sizeof(struct eepro_local));
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev)
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENODEV);
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sprintf(dev->name, "eth%d", unit);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netdev_boot_setup_check(dev);
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = do_eepro_probe(dev);
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_netdev(dev);
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(err);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init printEEPROMInfo(struct net_device *dev)
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6074cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen	struct eepro_local *lp = netdev_priv(dev);
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ioaddr = dev->base_addr;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short Word;
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i,j;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	j = ee_Checksum;
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 8; i++)
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		j += lp->word[i];
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for ( ; i < ee_SIZE; i++)
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		j += read_eeprom(ioaddr, i, dev);
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "Checksum: %#x\n",j&0xffff);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Word = lp->word[0];
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "Word0:\n");
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " Plug 'n Pray: %d\n",GetBit(Word,ee_PnP));
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " Buswidth: %d\n",(GetBit(Word,ee_BusWidth)+1)*8 );
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " AutoNegotiation: %d\n",GetBit(Word,ee_AutoNeg));
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " IO Address: %#x\n", (Word>>ee_IO0)<<4);
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug>4)  {
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Word = lp->word[1];
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "Word1:\n");
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG " INT: %d\n", Word & ee_IntMask);
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG " LI: %d\n", GetBit(Word,ee_LI));
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG " PC: %d\n", GetBit(Word,ee_PC));
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG " TPE/AUI: %d\n", GetBit(Word,ee_TPE_AUI));
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG " Jabber: %d\n", GetBit(Word,ee_Jabber));
6354e5b864e7cac67f06f18147b1980cb6b8fb213ecHarvey Harrison		printk(KERN_DEBUG " AutoPort: %d\n", !GetBit(Word,ee_AutoPort));
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG " Duplex: %d\n", GetBit(Word,ee_Duplex));
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Word = lp->word[5];
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "Word5:\n");
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " BNC: %d\n",GetBit(Word,ee_BNC_TPE));
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " NumConnectors: %d\n",GetBit(Word,ee_NumConn));
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " Has ");
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(Word,ee_PortTPE)) printk(KERN_DEBUG "TPE ");
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(Word,ee_PortBNC)) printk(KERN_DEBUG "BNC ");
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(Word,ee_PortAUI)) printk(KERN_DEBUG "AUI ");
647d6dbee861386cd3f4cee62bcf28597e63e251e0cFrans Pop	printk(KERN_DEBUG "port(s)\n");
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Word = lp->word[6];
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "Word6:\n");
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " Stepping: %d\n",Word & ee_StepMask);
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " BoardID: %d\n",Word>>ee_BoardID);
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Word = lp->word[7];
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "Word7:\n");
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " INT to IRQ:\n");
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0, j=0; i<15; i++)
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (GetBit(Word,i)) printk(KERN_DEBUG " INT%d -> IRQ %d;",j++,i);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG "\n");
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* function to recalculate the limits of buffer based on rcv_ram */
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void eepro_recalc (struct net_device *dev)
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *	lp;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp = netdev_priv(dev);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->xmt_ram = RAM_SIZE - lp->rcv_ram;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->eepro == LAN595FX_10ISA) {
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_lower_limit = XMT_START_10;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_upper_limit = (lp->xmt_ram - 2);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->rcv_lower_limit = lp->xmt_ram;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->rcv_upper_limit = (RAM_SIZE - 2);
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->rcv_lower_limit = RCV_START_PRO;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->rcv_upper_limit = (lp->rcv_ram - 2);
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_lower_limit = lp->rcv_ram;
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_upper_limit = (RAM_SIZE - 2);
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* prints boot-time info */
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __init eepro_print_info (struct net_device *dev)
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *	lp = netdev_priv(dev);
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int			i;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const char *		ifmap[] = {"AUI", "10Base2", "10BaseT"};
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	i = inb(dev->base_addr + ID_REG);
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_DEBUG " id: %#x ",i);
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(" io: %#x ", (unsigned)dev->base_addr);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (lp->eepro) {
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case LAN595FX_10ISA:
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("%s: Intel EtherExpress 10 ISA\n at %#x,",
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, (unsigned)dev->base_addr);
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case LAN595FX:
703d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik			printk("%s: Intel EtherExpress Pro/10+ ISA\n at %#x,",
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, (unsigned)dev->base_addr);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case LAN595TX:
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk("%s: Intel EtherExpress Pro/10 ISA at %#x,",
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, (unsigned)dev->base_addr);
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case LAN595:
711d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik			printk("%s: Intel 82595-based lan card at %#x,",
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, (unsigned)dev->base_addr);
7130795af5729b18218767fab27c44b1384f72dc9adJoe Perches			break;
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
716e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg	printk(" %pM", dev->dev_addr);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 3)
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG ", %dK RCV buffer",
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(int)(lp->rcv_ram)/1024);
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->irq > 2)
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]);
724d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	else
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(", %s.\n", ifmap[dev->if_port]);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 3) {
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		i = lp->word[5];
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (i & 0x2000) /* bit 13 of EEPROM word 5 */
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_DEBUG "%s: Concurrent Processing is "
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				"enabled but not used!\n", dev->name);
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check the station address for the manufacturer's code */
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug>3)
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printEEPROMInfo(dev);
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7397282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops eepro_ethtool_ops;
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7418afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemmingerstatic const struct net_device_ops eepro_netdev_ops = {
7428afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger 	.ndo_open               = eepro_open,
7438afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger 	.ndo_stop               = eepro_close,
7448afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger 	.ndo_start_xmit    	= eepro_send_packet,
745afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode	= set_multicast_list,
7468afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger 	.ndo_tx_timeout		= eepro_tx_timeout,
7478afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger	.ndo_change_mtu		= eth_change_mtu,
7488afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger	.ndo_set_mac_address 	= eth_mac_addr,
7498afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger	.ndo_validate_addr	= eth_validate_addr,
7508afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger};
7518afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* This is the real probe routine.  Linux has a history of friendly device
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   probes on the ISA bus.  A good device probe avoids doing writes, and
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   verifies that the correct device exists and functions.  */
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init eepro_probe1(struct net_device *dev, int autoprobe)
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short station_addr[3], id, counter;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ioaddr = dev->base_addr;
762b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>	int err;
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Grab the region so we can find another board if autoIRQ fails. */
765d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	if (!request_region(ioaddr, EEPRO_IO_EXTENT, DRV_NAME)) {
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!autoprobe)
767d6dbee861386cd3f4cee62bcf28597e63e251e0cFrans Pop			printk(KERN_WARNING "EEPRO: io-port 0x%04x in use\n",
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ioaddr);
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EBUSY;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now, we are going to check for the signature of the
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   ID_REG (register 2 of bank 0) */
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	id = inb(ioaddr + ID_REG);
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((id & ID_REG_MASK) != ID_REG_SIG)
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We seem to have the 82595 signature, let's
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   play with its counter (last 2 bits of
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   register 2 of bank 0) to be sure. */
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	counter = id & R_ROBIN_BITS;
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((inb(ioaddr + ID_REG) & R_ROBIN_BITS) != (counter + 0x40))
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto exit;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp = netdev_priv(dev);
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(lp, 0, sizeof(struct eepro_local));
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->xmt_bar = XMT_BAR_PRO;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_PRO;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_PRO;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->eeprom_reg = EEPROM_REG_PRO;
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&lp->lock);
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Now, get the ethernet hardware address from
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   the EEPROM */
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	station_addr[0] = read_eeprom(ioaddr, 2, dev);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* FIXME - find another way to know that we've found
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * an Etherexpress 10
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (station_addr[0] == 0x0000 || station_addr[0] == 0xffff) {
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->eepro = LAN595FX_10ISA;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->eeprom_reg = EEPROM_REG_10;
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->xmt_bar = XMT_BAR_10;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		station_addr[0] = read_eeprom(ioaddr, 2, dev);
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* get all words at once. will be used here and for ethtool */
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < 8; i++) {
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->word[i] = read_eeprom(ioaddr, i, dev);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	station_addr[1] = lp->word[3];
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	station_addr[2] = lp->word[4];
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!lp->eepro) {
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lp->word[7] == ee_FX_INT2IRQ)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->eepro = 2;
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (station_addr[2] == SA_ADDR1)
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->eepro = 1;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Fill in the 'dev' fields. */
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i < 6; i++)
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* RX buffer must be more than 3K and less than 29K */
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->mem_end < 3072 || dev->mem_end > 29696)
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->rcv_ram = RCV_DEFAULT_RAM;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* calculate {xmt,rcv}_{lower,upper}_limit */
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_recalc(dev);
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(lp->word[5], ee_BNC_TPE))
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->if_port = BNC;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->if_port = TPE;
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	if (dev->irq < 2 && lp->eepro != 0) {
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		/* Mask off INT number */
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		int count = lp->word[1] & 7;
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		unsigned irqMask = lp->word[7];
847d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		while (count--)
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			irqMask &= irqMask - 1;
850d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		count = ffs(irqMask);
852d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		if (count)
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			dev->irq = count - 1;
855d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		if (dev->irq < 2) {
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			printk(KERN_ERR " Duh! illegal interrupt vector stored in EEPROM.\n");
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			goto exit;
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		} else if (dev->irq == 2) {
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 			dev->irq = 9;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 		}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	}
863d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
8648afb1cebf5e7fde4a1bddacb559bda8526e64144Stephen Hemminger	dev->netdev_ops		= &eepro_netdev_ops;
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	dev->watchdog_timeo	= TX_TIMEOUT;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->ethtool_ops	= &eepro_ethtool_ops;
867d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* print boot time info */
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_print_info(dev);
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* reset 82595 */
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_reset(ioaddr);
873b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>
874b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>	err = register_netdev(dev);
875b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>	if (err)
876b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>		goto err;
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsexit:
879b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>	err = -ENODEV;
880b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>err:
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 	release_region(dev->base_addr, EEPRO_IO_EXTENT);
882b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au> 	return err;
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Open/initialize the board.  This is called (in the current kernel)
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   sometime after booting when the 'ifconfig' program is run.
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   This routine should set everything up anew at each open, even
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   registers that "should" only need to be set once at boot, so that
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   there is non-reboot way to recover if something goes wrong.
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   */
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
893b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perchesstatic const char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};
894b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perchesstatic const char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int	eepro_grab_irq(struct net_device *dev)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
897b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches	static const int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12, 0 };
898b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches	const int *irqp = irqlist;
899b6bc765067ece933cc3dc7f5e95665a89100b1d5Joe Perches	int temp_reg, ioaddr = dev->base_addr;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable the interrupt line. */
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_en_intline(ioaddr);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* be CAREFUL, BANK 0 now */
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank0(ioaddr);
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear all interrupts */
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_clear_int(ioaddr);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Let EXEC event to interrupt */
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_en_intexec(ioaddr);
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		temp_reg = inb(ioaddr + INT_NO_REG);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9231fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner		if (request_irq (*irqp, NULL, IRQF_SHARED, "bogus", dev) != EBUSY) {
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned long irq_mask;
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Twinkle the interrupt, and check if it's seen */
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			irq_mask = probe_irq_on();
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_diag(ioaddr); /* RESET the 82595 */
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mdelay(20);
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (*irqp == probe_irq_off(irq_mask))  /* It's a good IRQ line */
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* clear all interrupts */
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_clear_int(ioaddr);
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (*++irqp);
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable the physical interrupt line. */
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_dis_intline(ioaddr);
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Mask all the interrupts. */
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_dis_int(ioaddr);
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear all interrupts */
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_clear_int(ioaddr);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev->irq;
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int eepro_open(struct net_device *dev)
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short temp_reg, old8, old9;
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int irqMask;
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i, ioaddr = dev->base_addr;
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 3)
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: entering eepro_open routine.\n", dev->name);
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	irqMask = lp->word[7];
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->eepro == LAN595FX_10ISA) {
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 3;\n");
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (irqMask == ee_FX_INT2IRQ) /* INT to IRQ Mask */
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 2;\n");
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if ((dev->dev_addr[0] == SA_ADDR0 &&
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->dev_addr[1] == SA_ADDR1 &&
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->dev_addr[2] == SA_ADDR2))
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->eepro = 1;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (net_debug > 3) printk(KERN_DEBUG "p->eepro = 1;\n");
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}  /* Yes, an Intel EtherExpress Pro/10 */
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else lp->eepro = 0; /* No, it is a generic 82585 lan card */
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get the interrupt vector for the 82595 */
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->irq < 2 && eepro_grab_irq(dev) == 0) {
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EAGAIN;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
992a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches	if (request_irq(dev->irq , eepro_interrupt, 0, dev->name, dev)) {
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s: unable to get IRQ %d.\n", dev->name, dev->irq);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EAGAIN;
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the 82595. */
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + lp->eeprom_reg);
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->stepping = temp_reg >> 5;	/* Get the stepping number of the 595 */
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 3)
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "The stepping of the 82595 is %d\n", lp->stepping);
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (temp_reg & 0x10) /* Check the TurnOff Enable bit */
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(temp_reg & 0xef, ioaddr + lp->eeprom_reg);
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i < 6; i++)
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i);
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + REG1);    /* Setup Transmit Chaining */
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		| RCV_Discard_BadFrame, ioaddr + REG1);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + REG2); /* Match broadcast */
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(temp_reg | 0x14, ioaddr + REG2);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + REG3);
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the receiving mode */
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank1(ioaddr); /* be CAREFUL, BANK 1 now */
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the interrupt vector */
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + INT_NO_REG);
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA)
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG);
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + INT_NO_REG);
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->eepro == LAN595FX || lp->eepro == LAN595FX_10ISA)
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG);
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG);
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 3)
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "eepro_open: content of INT Reg is %x\n", temp_reg);
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize the RCV and XMT upper and lower limits */
1042d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	outb(lp->rcv_lower_limit >> 8, ioaddr + RCV_LOWER_LIMIT_REG);
1043d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	outb(lp->rcv_upper_limit >> 8, ioaddr + RCV_UPPER_LIMIT_REG);
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(lp->xmt_lower_limit >> 8, ioaddr + lp->xmt_lower_limit_reg);
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(lp->xmt_upper_limit >> 8, ioaddr + lp->xmt_upper_limit_reg);
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Enable the interrupt line. */
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_en_intline(ioaddr);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Switch back to Bank 0 */
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank0(ioaddr);
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Let RX and TX events to interrupt */
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_en_int(ioaddr);
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear all interrupts */
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_clear_int(ioaddr);
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize RCV */
1060d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	outw(lp->rcv_lower_limit, ioaddr + RCV_BAR);
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->rx_start = lp->rcv_lower_limit;
1062d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	outw(lp->rcv_upper_limit | 0xfe, ioaddr + RCV_STOP);
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Initialize XMT */
1065d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	outw(lp->xmt_lower_limit, ioaddr + lp->xmt_bar);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->tx_last = 0;
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Check for the i82595TX and i82595FX */
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	old8 = inb(ioaddr + 8);
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(~old8, ioaddr + 8);
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((temp_reg = inb(ioaddr + 8)) == old8) {
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (net_debug > 3)
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_DEBUG "i82595 detected!\n");
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->version = LAN595;
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->version = LAN595TX;
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(old8, ioaddr + 8);
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		old9 = inb(ioaddr + 9);
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (irqMask==ee_FX_INT2IRQ) {
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (net_debug > 3) {
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "IrqMask: %#x\n",irqMask);
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "i82595FX detected!\n");
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->version = LAN595FX;
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb(old9, ioaddr + 9);
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->if_port != TPE) {	/* Hopefully, this will fix the
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							problem of using Pentiums and
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							pro/10 w/ BNC. */
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				temp_reg = inb(ioaddr + REG13);
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* disable the full duplex mode since it is not
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				applicable with the 10Base2 cable. */
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outb(temp_reg & ~(FDX | A_N_ENABLE), REG13);
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				eepro_sw2bank0(ioaddr); /* be CAREFUL, BANK 0 now */
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else if (net_debug > 3) {
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_DEBUG "temp_reg: %#x  ~old9: %#x\n",temp_reg,((~old9)&0xff));
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_DEBUG "i82595TX detected!\n");
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sel_reset(ioaddr);
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_start_queue(dev);
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 3)
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: exiting eepro_open routine.\n", dev->name);
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* enabling rx */
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_en_rx(ioaddr);
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void eepro_tx_timeout (struct net_device *dev)
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ioaddr = dev->base_addr;
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* if (net_debug > 1) */
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk (KERN_ERR "%s: transmit timed out, %s?\n", dev->name,
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"network cable problem");
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* This is not a duplicate. One message for the console,
112959c51591a0ac7568824f541f57de967e88adaa07Michael Opdenacker	   one for the log file  */
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk (KERN_DEBUG "%s: transmit timed out, %s?\n", dev->name,
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		"network cable problem");
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_complete_selreset(ioaddr);
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
113661357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t eepro_send_packet(struct sk_buff *skb,
113761357325f377889a1daffa14962d705dc814dd0eStephen Hemminger				     struct net_device *dev)
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ioaddr = dev->base_addr;
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short length = skb->len;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG  "%s: entering eepro_send_packet routine.\n", dev->name);
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (length < ETH_ZLEN) {
11485b057c6b1a25d57edf2b4d1e956e50936480a9ffHerbert Xu		if (skb_padto(skb, ETH_ZLEN))
11496ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy			return NETDEV_TX_OK;
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		length = ETH_ZLEN;
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue (dev);
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_dis_int(ioaddr);
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&lp->lock, flags);
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned char *buf = skb->data;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (hardware_send_packet(dev, buf, length))
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* we won't wake queue here because we're out of space */
116209f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.tx_dropped++;
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
11641ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet			dev->stats.tx_bytes+=skb->len;
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			netif_wake_queue(dev);
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_kfree_skb (skb);
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* You might need to clean up and record Tx statistics here. */
117309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik	/* dev->stats.tx_aborted_errors++; */
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: exiting eepro_send_packet routine.\n", dev->name);
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_en_int(ioaddr);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&lp->lock, flags);
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11816ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy	return NETDEV_TX_OK;
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*	The typical workload of the driver:
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Handle the network interface interrupts. */
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
11897d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellseepro_interrupt(int irq, void *dev_id)
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1191c31f28e778ab299a5035ea2bda64f245b8915d7cJeff Garzik	struct net_device *dev = dev_id;
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ioaddr, status, boguscount = 20;
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int handled = 0;
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp = netdev_priv(dev);
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        spin_lock(&lp->lock);
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: entering eepro_interrupt routine.\n", dev->name);
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ioaddr = dev->base_addr;
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (((status = inb(ioaddr + STATUS_REG)) & (RX_INT|TX_INT)) && (boguscount--))
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		handled = 1;
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & RX_INT) {
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (net_debug > 4)
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "%s: packet received interrupt.\n", dev->name);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_dis_int(ioaddr);
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Get the received packets */
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_ack_rx(ioaddr);
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_rx(dev);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_en_int(ioaddr);
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & TX_INT) {
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (net_debug > 4)
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 				printk(KERN_DEBUG "%s: packet transmit interrupt.\n", dev->name);
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_dis_int(ioaddr);
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Process the status of transmitted packets */
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_ack_tx(ioaddr);
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_transmit_interrupt(dev);
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			eepro_en_int(ioaddr);
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: exiting eepro_interrupt routine.\n", dev->name);
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&lp->lock);
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_RETVAL(handled);
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int eepro_close(struct net_device *dev)
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ioaddr = dev->base_addr;
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short temp_reg;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue(dev);
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank1(ioaddr); /* Switch back to Bank 1 */
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable the physical interrupt line. */
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	temp_reg = inb(ioaddr + REG1);
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(temp_reg & 0x7f, ioaddr + REG1);
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank0(ioaddr); /* Switch back to Bank 0 */
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Flush the Tx and disable Rx. */
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(STOP_RCV_CMD, ioaddr);
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->tx_start = lp->tx_end = lp->xmt_lower_limit;
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	lp->tx_last = 0;
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Mask all the interrupts. */
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_dis_int(ioaddr);
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* clear all interrupts */
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_clear_int(ioaddr);
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Reset the 82595 */
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_reset(ioaddr);
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* release the interrupt */
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(dev->irq, dev);
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Update the statistics here. What statistics? */
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set or clear the multicast filter for this adaptor.
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsset_multicast_list(struct net_device *dev)
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short ioaddr = dev->base_addr;
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short mode;
128822bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko	struct netdev_hw_addr *ha;
128906c92ee6384c33dbb6e313c66272181db70abbb0Alexander Beregalov	int mc_count = netdev_mc_count(dev);
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12914cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko	if (dev->flags&(IFF_ALLMULTI|IFF_PROMISC) || mc_count > 63)
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = inb(ioaddr + REG2);
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(mode | PRMSC_Mode, ioaddr + REG2);
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = inb(ioaddr + REG3);
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13014cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko	else if (mc_count == 0)
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = inb(ioaddr + REG2);
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(mode & 0xd6, ioaddr + REG2); /* Turn off Multi-IA and PRMSC_Mode bits */
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = inb(ioaddr + REG3);
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned short status, *eaddrs;
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		int i, boguscount = 0;
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Disable RX and TX interrupts.  Necessary to avoid
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   corruption of the HOST_ADDRESS_REG by interrupt
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		   service routines. */
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_dis_int(ioaddr);
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank2(ioaddr); /* be CAREFUL, BANK 2 now */
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = inb(ioaddr + REG2);
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(mode | Multi_IA, ioaddr + REG2);
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mode = inb(ioaddr + REG3);
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(mode, ioaddr + REG3); /* writing reg. 3 to complete the update */
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank0(ioaddr); /* Return to BANK 0 now */
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(lp->tx_end, ioaddr + HOST_ADDRESS_REG);
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(MC_SETUP, ioaddr + IO_PORT);
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(0, ioaddr + IO_PORT);
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(0, ioaddr + IO_PORT);
13314cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko		outw(6 * (mc_count + 1), ioaddr + IO_PORT);
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
133322bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko		netdev_for_each_mc_addr(ha, dev) {
133422bedad3ce112d5ca1eaf043d4990fa2ed698c87Jiri Pirko			eaddrs = (unsigned short *) ha->addr;
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(*eaddrs++, ioaddr + IO_PORT);
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(*eaddrs++, ioaddr + IO_PORT);
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(*eaddrs++, ioaddr + IO_PORT);
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eaddrs = (unsigned short *) dev->dev_addr;
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(eaddrs[0], ioaddr + IO_PORT);
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(eaddrs[1], ioaddr + IO_PORT);
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(eaddrs[2], ioaddr + IO_PORT);
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(lp->tx_end, ioaddr + lp->xmt_bar);
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(MC_SETUP, ioaddr);
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Update the transmit queue */
13484cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko		i = lp->tx_end + XMT_HEADER + 6 * (mc_count + 1);
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lp->tx_start != lp->tx_end)
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* update the next address and the chain bit in the
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   last packet */
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
13551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(i, ioaddr + IO_PORT);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = inw(ioaddr + IO_PORT);
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->tx_end = i ;
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->tx_start = lp->tx_end = i ;
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Acknowledge that the MC setup is done */
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		do { /* We should be doing this in the eepro_interrupt()! */
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SLOW_DOWN;
13681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			SLOW_DOWN;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (inb(ioaddr + STATUS_REG) & 0x08)
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			{
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				i = inb(ioaddr);
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outb(0x08, ioaddr + STATUS_REG);
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (i & 0x20) { /* command ABORTed */
1375d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik					printk(KERN_NOTICE "%s: multicast setup failed.\n",
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						dev->name);
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else if ((i & 0x0f) == 0x03)	{ /* MC-Done */
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					printk(KERN_DEBUG "%s: set Rx mode to %d address%s.\n",
13804cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko						dev->name, mc_count,
13814cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko						mc_count > 1 ? "es":"");
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					break;
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} while (++boguscount < 100);
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Re-enable RX and TX interrupts */
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_en_int(ioaddr);
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->eepro == LAN595FX_10ISA) {
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_complete_selreset(ioaddr);
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_en_rx(ioaddr);
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The horrible routine to read a word from the serial EEPROM. */
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* IMPORTANT - the 82595 will be set to Bank 0 after the eeprom is read */
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The delay between EEPROM clock transitions. */
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define eeprom_delay() { udelay(40); }
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define EE_READ_CMD (6 << 6)
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1404dac499f912abd5838fa3501efdcd0f23d5f4fc29Hannes Ederstatic int
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsread_eeprom(int ioaddr, int location, struct net_device *dev)
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short retval = 0;
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short ee_addr = ioaddr + lp->eeprom_reg;
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int read_cmd = location | EE_READ_CMD;
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short ctrl_val = EECS ;
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* XXXX - black magic */
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eepro_sw2bank1(ioaddr);
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(0x00, ioaddr + STATUS_REG);
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* XXXX - black magic */
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank2(ioaddr);
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ctrl_val, ee_addr);
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Shift the read command bits out. */
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 8; i >= 0; i--) {
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			: ctrl_val;
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(outval, ee_addr);
14271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(outval | EESK, ee_addr);	/* EEPROM clock tick. */
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eeprom_delay();
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(outval, ee_addr);	/* Finish EEPROM a clock tick. */
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eeprom_delay();
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ctrl_val, ee_addr);
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 16; i > 0; i--) {
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(ctrl_val | EESK, ee_addr);	 eeprom_delay();
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0);
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(ctrl_val, ee_addr);  eeprom_delay();
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Terminate the EEPROM access. */
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ctrl_val &= ~EECS;
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ctrl_val | EESK, ee_addr);
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeprom_delay();
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(ctrl_val, ee_addr);
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eeprom_delay();
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eepro_sw2bank0(ioaddr);
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return retval;
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshardware_send_packet(struct net_device *dev, void *buf, short length)
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short ioaddr = dev->base_addr;
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned status, tx_available, last, end;
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: entering hardware_send_packet routine.\n", dev->name);
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1460022484c17253aea84aa2603068ea065ca59bb5e5Julia Lawall	/* determine how much of the transmit buffer space is available */
1461022484c17253aea84aa2603068ea065ca59bb5e5Julia Lawall	if (lp->tx_end > lp->tx_start)
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tx_available = lp->xmt_ram - (lp->tx_end - lp->tx_start);
1463022484c17253aea84aa2603068ea065ca59bb5e5Julia Lawall	else if (lp->tx_end < lp->tx_start)
1464022484c17253aea84aa2603068ea065ca59bb5e5Julia Lawall		tx_available = lp->tx_start - lp->tx_end;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else tx_available = lp->xmt_ram;
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) >= tx_available) {
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* No space available ??? */
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return 1;
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		last = lp->tx_end;
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (end >= lp->xmt_upper_limit + 2) { /* the transmit buffer is wrapped around */
1476d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik		if ((lp->xmt_upper_limit + 2 - last) <= XMT_HEADER) {
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* Arrrr!!!, must keep the xmt header together,
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				several days were lost to chase this one down. */
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			last = lp->xmt_lower_limit;
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else end = lp->xmt_lower_limit + (end -
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						lp->xmt_upper_limit + 2);
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(last, ioaddr + HOST_ADDRESS_REG);
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(XMT_CMD, ioaddr + IO_PORT);
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(0, ioaddr + IO_PORT);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(end, ioaddr + IO_PORT);
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(length, ioaddr + IO_PORT);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lp->version == LAN595)
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outsw(ioaddr + IO_PORT, buf, (length + 3) >> 1);
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {	/* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unsigned short temp = inb(ioaddr + INT_MASK_REG);
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outsl(ioaddr + IO_PORT_32_BIT, buf, (length + 3) >> 2);
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* A dummy read to flush the DRAM write pipeline */
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = inw(ioaddr + IO_PORT);
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (lp->tx_start == lp->tx_end) {
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(last, ioaddr + lp->xmt_bar);
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb(XMT_CMD, ioaddr);
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			lp->tx_start = last;   /* I don't like to change tx_start here */
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* update the next address and the chain bit in the
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			last packet */
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (lp->tx_end != last) {
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outw(last, ioaddr + IO_PORT);
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			status = inw(ioaddr + IO_PORT);
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Continue the transmit command */
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			outb(RESUME_XMT_CMD, ioaddr);
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->tx_last = last;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->tx_end = end;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (net_debug > 5)
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_DEBUG "%s: exiting hardware_send_packet routine.\n", dev->name);
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldseepro_rx(struct net_device *dev)
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short ioaddr = dev->base_addr;
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short boguscount = 20;
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short rcv_car = lp->rx_start;
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: entering eepro_rx routine.\n", dev->name);
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Set the read pointer to the start of the RCV */
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outw(rcv_car, ioaddr + HOST_ADDRESS_REG);
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rcv_event = inw(ioaddr + IO_PORT);
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (rcv_event == RCV_DONE) {
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcv_status = inw(ioaddr + IO_PORT);
15551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcv_next_frame = inw(ioaddr + IO_PORT);
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcv_size = inw(ioaddr + IO_PORT);
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((rcv_status & (RX_OK | RX_ERROR)) == RX_OK) {
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Malloc up new buffer. */
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			struct sk_buff *skb;
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
156309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.rx_bytes+=rcv_size;
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcv_size &= 0x3fff;
1565c056b734e54e12f38f34a2583a4824e6cecc16c1Pradeep A Dalvi			skb = netdev_alloc_skb(dev, rcv_size + 5);
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (skb == NULL) {
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
156809f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik				dev->stats.rx_dropped++;
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				lp->rx_start = rcv_next_frame;
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_reserve(skb,2);
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (lp->version == LAN595)
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				insw(ioaddr+IO_PORT, skb_put(skb,rcv_size), (rcv_size + 3) >> 1);
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else { /* LAN595TX or LAN595FX, capable of 32-bit I/O processing */
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				unsigned short temp = inb(ioaddr + INT_MASK_REG);
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outb(temp | IO_32_BIT, ioaddr + INT_MASK_REG);
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				insl(ioaddr+IO_PORT_32_BIT, skb_put(skb,rcv_size),
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					(rcv_size + 3) >> 2);
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb->protocol = eth_type_trans(skb,dev);
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			netif_rx(skb);
158909f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.rx_packets++;
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else { /* Not sure will ever reach here,
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			I set the 595 to discard bad received frames */
159409f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.rx_errors++;
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rcv_status & 0x0100)
159709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik				dev->stats.rx_over_errors++;
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (rcv_status & 0x0400)
160009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik				dev->stats.rx_frame_errors++;
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (rcv_status & 0x0800)
160309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik				dev->stats.rx_crc_errors++;
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1605d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik			printk(KERN_DEBUG "%s: event = %#x, status = %#x, next = %#x, size = %#x\n",
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev->name, rcv_event, rcv_status, rcv_next_frame, rcv_size);
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcv_status & 0x1000)
161009f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.rx_length_errors++;
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcv_car = lp->rx_start + RCV_HEADER + rcv_size;
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->rx_start = rcv_next_frame;
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (--boguscount == 0)
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(rcv_next_frame, ioaddr + HOST_ADDRESS_REG);
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcv_event = inw(ioaddr + IO_PORT);
16201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (rcv_car == 0)
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcv_car = lp->rcv_upper_limit | 0xff;
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outw(rcv_car - 1, ioaddr + RCV_STOP);
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (net_debug > 5)
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: exiting eepro_rx routine.\n", dev->name);
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldseepro_transmit_interrupt(struct net_device *dev)
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct eepro_local *lp = netdev_priv(dev);
16351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short ioaddr = dev->base_addr;
1636d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	short boguscount = 25;
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	short xmt_status;
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1639d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	while ((lp->tx_start != lp->tx_end) && boguscount--) {
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xmt_status = inw(ioaddr+IO_PORT);
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(xmt_status & TX_DONE_BIT))
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		xmt_status = inw(ioaddr+IO_PORT);
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		lp->tx_start = inw(ioaddr+IO_PORT);
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_wake_queue (dev);
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (xmt_status & TX_OK)
165309f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.tx_packets++;
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else {
165509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.tx_errors++;
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (xmt_status & 0x0400) {
165709f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik				dev->stats.tx_carrier_errors++;
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "%s: carrier error\n",
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name);
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "%s: XMT status = %#x\n",
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, xmt_status);
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else {
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "%s: XMT status = %#x\n",
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, xmt_status);
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_DEBUG "%s: XMT status = %#x\n",
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name, xmt_status);
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (xmt_status & 0x000f) {
167109f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.collisions += (xmt_status & 0x000f);
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((xmt_status & 0x0040) == 0x0) {
167509f75cd7bf13720738e6a196cc0107ce9a5bd5a0Jeff Garzik			dev->stats.tx_heartbeat_errors++;
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int eepro_ethtool_get_settings(struct net_device *dev,
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					struct ethtool_cmd *cmd)
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16834cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen	struct eepro_local	*lp = netdev_priv(dev);
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1685d61780c0d384939ef31c46b47442854d5def4623Jeff Garzik	cmd->supported = 	SUPPORTED_10baseT_Half |
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				SUPPORTED_10baseT_Full |
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				SUPPORTED_Autoneg;
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd->advertising =	ADVERTISED_10baseT_Half |
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADVERTISED_10baseT_Full |
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ADVERTISED_Autoneg;
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(lp->word[5], ee_PortTPE)) {
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->supported |= SUPPORTED_TP;
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->advertising |= ADVERTISED_TP;
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(lp->word[5], ee_PortBNC)) {
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->supported |= SUPPORTED_BNC;
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->advertising |= ADVERTISED_BNC;
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (GetBit(lp->word[5], ee_PortAUI)) {
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->supported |= SUPPORTED_AUI;
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->advertising |= ADVERTISED_AUI;
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1705707394972093e2056e1e8cc39be19cf9bcb3e7b3David Decotigny	ethtool_cmd_speed_set(cmd, SPEED_10);
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->if_port == TPE && lp->word[1] & ee_Duplex) {
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->duplex = DUPLEX_FULL;
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->duplex = DUPLEX_HALF;
17121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd->port = dev->if_port;
17151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd->phy_address = dev->base_addr;
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cmd->transceiver = XCVR_INTERNAL;
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (lp->word[0] & ee_AutoNeg) {
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd->autoneg = 1;
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void eepro_ethtool_get_drvinfo(struct net_device *dev,
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					struct ethtool_drvinfo *drvinfo)
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
172868aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones	strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
172968aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones	strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
173068aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones	snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),
173168aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones		"ISA 0x%lx", dev->base_addr);
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17347282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops eepro_ethtool_ops = {
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_settings	= eepro_ethtool_get_settings,
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.get_drvinfo 	= eepro_ethtool_get_drvinfo,
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_EEPRO 8
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device *dev_eepro[MAX_EEPRO];
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int io[MAX_EEPRO] = {
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  [0 ... MAX_EEPRO-1] = -1
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int irq[MAX_EEPRO];
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mem[MAX_EEPRO] = {	/* Size of the rx buffer in KB */
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds  [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int autodetect;
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int n_eepro;
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* For linux 2.1.xx */
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Pascal Dupuis and others");
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Intel i82595 ISA EtherExpressPro10/10+ driver");
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1760a1bfcd97414d3e9b3c96f27d9b1a1e76c9543ba6Florin Malitamodule_param_array(io, int, NULL, 0);
1761a1bfcd97414d3e9b3c96f27d9b1a1e76c9543ba6Florin Malitamodule_param_array(irq, int, NULL, 0);
1762a1bfcd97414d3e9b3c96f27d9b1a1e76c9543ba6Florin Malitamodule_param_array(mem, int, NULL, 0);
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(autodetect, int, 0);
1764b595076a180a56d1bb170e6eceda6eb9d76f4cd3Uwe Kleine-KönigMODULE_PARM_DESC(io, "EtherExpress Pro/10 I/O base address(es)");
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(irq, "EtherExpress Pro/10 IRQ number(s)");
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mem, "EtherExpress Pro/10 Rx buffer size(es) in kB (3-29)");
17671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(autodetect, "EtherExpress Pro/10 force board(s) detection (0-1)");
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
176902a3245fcf0911ff92100aa54823dc1c5950fba9Andrew Mortonint __init init_module(void)
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev;
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (io[0] == -1 && autodetect == 0) {
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "eepro_init_module: Probe is very dangerous in ISA boards!\n");
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "eepro_init_module: Please add \"autodetect=1\" to force probe\n");
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (autodetect) {
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* if autodetect is set then we must force detection */
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MAX_EEPRO; i++) {
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			io[i] = 0;
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "eepro_init_module: Auto-detecting boards (May God protect us...)\n");
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1787d513d018e2236930b6163241bbdce64d2c0de49eRoel Kluin	for (i = 0; i < MAX_EEPRO && io[i] != -1; i++) {
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev = alloc_etherdev(sizeof(struct eepro_local));
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!dev)
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->mem_end = mem[i];
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->base_addr = io[i];
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->irq = irq[i];
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (do_eepro_probe(dev) == 0) {
1797b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>			dev_eepro[n_eepro++] = dev;
1798b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au>			continue;
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_netdev(dev);
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (n_eepro)
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_INFO "%s", version);
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return n_eepro ? 0 : -ENODEV;
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1810afc8eb46c0ea2cab8bc28713b2e0614f015a7516Al Virovoid __exit
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscleanup_module(void)
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i=0; i<n_eepro; i++) {
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct net_device *dev = dev_eepro[i];
18171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unregister_netdev(dev);
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_region(dev->base_addr, EEPRO_IO_EXTENT);
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_netdev(dev);
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* MODULE */
1823