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