11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* lance.c: An AMD LANCE/PCnet ethernet driver for Linux. */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Written/copyright 1993-1998 by Donald Becker. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright 1993 United States Government as represented by the 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Director, National Security Agency. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This software may be used and distributed according to the terms 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds of the GNU General Public License, incorporated herein by reference. 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This driver is for the Allied Telesis AT1500 and HP J2405A, and should work 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds with most other LANCE-based bus-master (NE2100/NE2500) ethercards. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The author may be reached as becker@scyld.com, or C/O 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Scyld Computing Corporation 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410 Severn Ave., Suite 210 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Annapolis MD 21403 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Andrey V. Savochkin: 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - alignment problem with 1.3.* kernel and some minor changes. 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Thomas Bogendoerfer (tsbogend@bigbug.franken.de): 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - added support for Linux/Alpha, but removed most of it, because 226aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik it worked only for the PCI chip. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - added hook for the 32bit lance driver 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - added PCnetPCI II (79C970A) to chip table 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Paul Gortmaker (gpg109@rsphy1.anu.edu.au): 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds - hopefully fix above so Linux/Alpha can use ISA cards too. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8/20/96 Fixed 7990 autoIRQ failure and reversed unneeded alignment -djb 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.12 10/27/97 Module support -djb 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.14 2/3/98 Module support modified, made PCI support optional -djb 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds v1.15 5/27/99 Fixed bug in the cleanup_module(). dev->priv was freed 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds before unregister_netdev() which caused NULL pointer 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reference later in the chain (in rtnetlink_fill_ifinfo()) 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds -- Mika Kuoppala <miku@iki.fi> 346aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the 2.1 version of the old driver - Alan Cox 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Get rid of check_region, check kmalloc return in lance_probe1 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Reworked detection, added support for Racal InterLan EtherBlaster cards 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Vesselin Kostadinov <vesok at yahoo dot com > - 22/4/2004 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45d5b20697ca37d80cc4ec2ba3c5ddf1339dc1d49aAndy Gospodarekstatic const char version[] = "lance.c:v1.16 2006/11/09 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n"; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h> 60d7fe0f241dceade9c8d4af75498765c5ff7f27e6Al Viro#include <linux/mm.h> 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h> 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h> 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0}; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_probe1(struct net_device *dev, int ioaddr, int irq, int options); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init do_lance_probe(struct net_device *dev); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct card { 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char id_offset14; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char id_offset15; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} cards[] = { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { //"normal" 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_offset14 = 0x57, 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_offset15 = 0x57, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { //NI6510EB 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_offset14 = 0x52, 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_offset15 = 0x44, 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { //Racal InterLan EtherBlaster 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_offset14 = 0x52, 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_offset15 = 0x49, 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }, 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NUM_CARDS 3 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef LANCE_DEBUG 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = LANCE_DEBUG; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_debug = 1; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Theory of Operation 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsI. Board Compatibility 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThis device driver is designed for the AMD 79C960, the "PCnet-ISA 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssingle-chip ethernet controller for ISA". This chip is used in a wide 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvariety of boards from vendors such as Allied Telesis, HP, Kingston, 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsand Boca. This driver is also intended to work with older AMD 7990 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdesigns, such as the NE1500 and NE2100, and newer 79C961. For convenience, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsI use the name LANCE to refer to all of the AMD chips, even though it properly 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrefers only to the original 7990. 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsII. Board-specific settings 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe driver is designed to work the boards that use the faster 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbus-master mode, rather than in shared memory mode. (Only older designs 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshave on-board buffer memory needed to support the slower shared memory mode.) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMost ISA boards have jumpered settings for the I/O base, IRQ line, and DMA 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldschannel. This driver probes the likely base addresses: 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{0x300, 0x320, 0x340, 0x360}. 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsAfter the board is found it generates a DMA-timeout interrupt and uses 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsautoIRQ to find the IRQ line. The DMA channel can be set with the low bits 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsof the otherwise-unused dev->mem_start value (aka PARAM1). If unset it is 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsprobed for by enabling each free DMA channel in turn and checking if 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinitialization succeeds. 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe HP-J2405A board is an exception: with this board it is easy to read the 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsEEPROM-set values for the base, IRQ, and DMA. (Of course you must already 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds_know_ the base address -- that field is for writing the EEPROM.) 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIII. Driver operation 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIIIa. Ring buffers 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe LANCE uses ring buffers of Tx and Rx descriptors. Each entry describes 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe base and length of the data buffer, along with status bits. The length 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsof these buffers is set by LANCE_LOG_{RX,TX}_BUFFERS, which is log_2() of 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe buffer length (rather than being directly the buffer length) for 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsimplementation ease. The current values are 2 (Tx) and 4 (Rx), which leads to 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsring sizes of 4 (Tx) and 16 (Rx). Increasing the number of ring entries 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsneedlessly uses extra space and reduces the chance that an upper layer will 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbe able to reorder queued Tx packets based on priority. Decreasing the number 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsof entries makes it more difficult to achieve back-to-back packet transmission 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsand increases the chance that Rx ring will overflow. (Consider the worst case 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsof receiving back-to-back minimum-sized packets.) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe LANCE has the capability to "chain" both Rx and Tx buffers, but this driver 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatically allocates full-sized (slightly oversized -- PKT_BUF_SZ) buffers to 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsavoid the administrative overhead. For the Rx side this avoids dynamically 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsallocating full-sized buffers "just in case", at the expense of a 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmemory-to-memory data copy for each packet received. For most systems this 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsis a good tradeoff: the Rx buffer will always be in low memory, the copy 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsis inexpensive, and it primes the cache for later packet processing. For Tx 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe buffers are only used when needed as low-memory bounce buffers. 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIIIB. 16M memory limitations. 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsFor the ISA bus master mode all structures used directly by the LANCE, 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe initialization block, Rx and Tx rings, and data buffers, must be 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsaccessible from the ISA bus, i.e. in the lower 16M of real memory. 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThis is a problem for current Linux kernels on >16M machines. The network 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdevices are initialized after memory initialization, and the kernel doles out 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmemory from the top of memory downward. The current solution is to have a 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsspecial network initialization routine that's called before memory 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinitialization; this will eventually be generalized for all network devices. 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsAs mentioned before, low-memory "bounce-buffers" are used when needed. 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsIIIC. Synchronization 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe driver runs as two independent, single-threaded flows of control. One 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsis the send-packet routine, which enforces single-threaded use by the 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdev->tbusy flag. The other thread is the interrupt handler, which is single 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthreaded by the hardware and other software. 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe send packet thread has partial control over the Tx ring and 'dev->tbusy' 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsflag. It sets the tbusy flag whenever it's queuing a Tx packet. If the next 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsqueue slot is empty, it clears the tbusy flag when finished otherwise it sets 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe 'lp->tx_full' flag. 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsThe interrupt handler has exclusive control over the Rx ring and records stats 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfrom the Tx ring. (The Tx-done interrupt can't be selectively turned off, so 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldswe can't avoid the interrupt overhead by having the Tx routine reap the Tx 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstats.) After reaping the stats, it marks the queue entry as empty by setting 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsthe 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstx_full and tbusy flags. 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set the number of Tx and Rx buffers, using Log_2(# buffers). 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Reasonable default values are 16 Tx buffers, and 16 Rx buffers. 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds That translates to 4 and 4 (16 == 2^^4). 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This is a compile-time option for efficiency. 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef LANCE_LOG_TX_BUFFERS 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_LOG_TX_BUFFERS 4 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_LOG_RX_BUFFERS 4 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PKT_BUF_SZ 1544 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Offsets from base I/O address. */ 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_DATA 0x10 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_ADDR 0x12 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_RESET 0x14 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_BUS_IF 0x16 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_TOTAL_SIZE 0x18 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 210c63fdf46ad0a7f8fe3c0252a0e763515617e0ea7Eric Dumazet#define TX_TIMEOUT (HZ/5) 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE Rx and Tx ring descriptors. */ 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_rx_head { 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s32 base; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s16 buf_length; /* This length is 2s complement (negative)! */ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s16 msg_length; /* This length is "normal". */ 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_tx_head { 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s32 base; 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s16 length; /* Length is 2s complement (negative)! */ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds s16 misc; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE initialization block, described in databook. */ 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_init_block { 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 mode; /* Pre-set mode (reg. 15) */ 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 phys_addr[6]; /* Physical ethernet address */ 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 filter[2]; /* Multicast filter (unused). */ 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Receive and transmit ring base, along with extra bits. */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 rx_ring; /* Tx and Rx ring base pointers */ 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tx_ring; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct lance_private { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The Tx and Rx ring entries must be aligned on 8-byte boundaries. */ 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_rx_head rx_ring[RX_RING_SIZE]; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_tx_head tx_ring[TX_RING_SIZE]; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_init_block init_block; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *name; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The saved address of a sent-in-place packet/buffer, for skfree(). */ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff* tx_skbuff[TX_RING_SIZE]; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The addresses of receive-in-place skbuffs. */ 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff* rx_skbuff[RX_RING_SIZE]; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long rx_buffs; /* Address of Rx and Tx buffers. */ 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Tx low-memory "bounce buffer" address. */ 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char (*tx_bounce_buffs)[PKT_BUF_SZ]; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cur_rx, cur_tx; /* The next free ring entry */ 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dma; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char chip_version; /* See lance_chip_type. */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spinlock_t devlock; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_MUST_PAD 0x00000001 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_ENABLE_AUTOSELECT 0x00000002 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_MUST_REINIT_RING 0x00000004 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_MUST_UNRESET 0x00000008 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define LANCE_HAS_MISSED_FRAME 0x00000010 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A mapping from the chip ID number to the part number and features. 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds These are from the datasheets -- in real life the '970 version 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reportedly has the same ID as the '965. */ 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct lance_chip_type { 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int id_number; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *name; 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flags; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} chip_table[] = { 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x0000, "LANCE 7990", /* Ancient lance chip. */ 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_MUST_PAD + LANCE_MUST_UNRESET}, 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x0003, "PCnet/ISA 79C960", /* 79C960 PCnet/ISA. */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_HAS_MISSED_FRAME}, 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x2260, "PCnet/ISA+ 79C961", /* 79C961 PCnet/ISA+, Plug-n-Play. */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_HAS_MISSED_FRAME}, 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x2420, "PCnet/PCI 79C970", /* 79C970 or 79C974 PCnet-SCSI, PCI. */ 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_HAS_MISSED_FRAME}, 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds it the PCnet32. */ 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x2430, "PCnet32", /* 79C965 PCnet for VL bus. */ 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_HAS_MISSED_FRAME}, 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x2621, "PCnet/PCI-II 79C970A", /* 79C970A PCInetPCI II. */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_HAS_MISSED_FRAME}, 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x0, "PCnet (unknown)", 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING + 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds LANCE_HAS_MISSED_FRAME}, 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6}; 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers. 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Assume yes until we know the memory size. */ 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned char lance_need_isa_bounce_buffers = 1; 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_open(struct net_device *dev); 3019e24974db6b01ec067c24de09588282b6a1407f0Al Virostatic void lance_init_ring(struct net_device *dev, gfp_t mode); 30261357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t lance_start_xmit(struct sk_buff *skb, 30361357325f377889a1daffa14962d705dc814dd0eStephen Hemminger struct net_device *dev); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_rx(struct net_device *dev); 3057d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt(int irq, void *dev_id); 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int lance_close(struct net_device *dev); 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *lance_get_stats(struct net_device *dev); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list(struct net_device *dev); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_tx_timeout (struct net_device *dev); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3116aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_CARDS 8 /* Max number of interfaces (cards) per module */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device *dev_lance[MAX_CARDS]; 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int io[MAX_CARDS]; 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int dma[MAX_CARDS]; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int irq[MAX_CARDS]; 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(io, int, NULL, 0); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(dma, int, NULL, 0); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(irq, int, NULL, 0); 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(lance_debug, int, 0); 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(io, "LANCE/PCnet I/O base address(es),required"); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)"); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(irq, "LANCE/PCnet IRQ number (ignored for some devices)"); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(lance_debug, "LANCE/PCnet debug level (0-7)"); 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3303805f0e28ca313893b87e881201561d5c1857dd8Andrew Mortonint __init init_module(void) 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int this_dev, found = 0; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) { 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io[this_dev] == 0) { 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (this_dev != 0) /* only complain once */ 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_NOTICE "lance.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n"); 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EPERM; 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_etherdev(0); 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq[this_dev]; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = io[this_dev]; 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = dma[this_dev]; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (do_lance_probe(dev) == 0) { 349b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au> dev_lance[found++] = dev; 350b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au> continue; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (found != 0) 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENXIO; 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 36064916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenkostatic void cleanup_card(struct net_device *dev) 36164916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko{ 362c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 36364916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko if (dev->dma != 4) 36464916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko free_dma(dev->dma); 36564916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko release_region(dev->base_addr, LANCE_TOTAL_SIZE); 36664916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko kfree(lp->tx_bounce_buffs); 36764916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko kfree((void*)lp->rx_buffs); 36864916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko kfree(lp); 36964916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko} 37064916f1ebe93592153c72bcdb189a31e4d40049aDenis Vlasenko 371afc8eb46c0ea2cab8bc28713b2e0614f015a7516Al Virovoid __exit cleanup_module(void) 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int this_dev; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) { 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = dev_lance[this_dev]; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev) { 3786aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik unregister_netdev(dev); 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cleanup_card(dev); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* MODULE */ 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Starting in v2.1.*, the LANCE/PCnet probe is now similar to the other 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds board probes now that kmalloc() can allocate ISA DMA-able regions. 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This also allows the LANCE driver to be used as a module. 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init do_lance_probe(struct net_device *dev) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 39400137dad17707f0d14dbf7e193761220f1c2fe03Hannes Eder unsigned int *port; 39500137dad17707f0d14dbf7e193761220f1c2fe03Hannes Eder int result; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (high_memory <= phys_to_virt(16*1024*1024)) 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_need_isa_bounce_buffers = 0; 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (port = lance_portlist; *port; port++) { 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ioaddr = *port; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = request_region(ioaddr, LANCE_TOTAL_SIZE, 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "lance-probe"); 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (r) { 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Detect the card with minimal I/O reads */ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char offset14 = inb(ioaddr + 14); 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int card; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (card = 0; card < NUM_CARDS; ++card) 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cards[card].id_offset14 == offset14) 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card < NUM_CARDS) {/*yes, the first byte matches*/ 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char offset15 = inb(ioaddr + 15); 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (card = 0; card < NUM_CARDS; ++card) 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((cards[card].id_offset14 == offset14) && 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (cards[card].id_offset15 == offset15)) 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (card < NUM_CARDS) { /*Signature OK*/ 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds result = lance_probe1(dev, ioaddr, 0, 0); 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!result) { 422c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ver = lp->chip_version; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds r->name = chip_table[ver].name; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(ioaddr, LANCE_TOTAL_SIZE); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device * __init lance_probe(int unit) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = alloc_etherdev(0); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENODEV); 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(dev->name, "eth%d", unit); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netdev_boot_setup_check(dev); 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = do_lance_probe(dev); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return dev; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(err); 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 457462540bdb2f08d465a2416764fc628520f82939fStephen Hemmingerstatic const struct net_device_ops lance_netdev_ops = { 458462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_open = lance_open, 459462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_start_xmit = lance_start_xmit, 460462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_stop = lance_close, 461462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_get_stats = lance_get_stats, 462afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = set_multicast_list, 463462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_tx_timeout = lance_tx_timeout, 464462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_change_mtu = eth_change_mtu, 465462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_set_mac_address = eth_mac_addr, 466462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger .ndo_validate_addr = eth_validate_addr, 467462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger}; 468462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int options) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 47200137dad17707f0d14dbf7e193761220f1c2fe03Hannes Eder unsigned long dma_channels; /* Mark spuriously-busy DMA channels */ 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, reset_val, lance_version; 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const char *chipname; 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Flags for specific chips or boards. */ 47600137dad17707f0d14dbf7e193761220f1c2fe03Hannes Eder unsigned char hpJ2405A = 0; /* HP ISA adaptor */ 47700137dad17707f0d14dbf7e193761220f1c2fe03Hannes Eder int hp_builtin = 0; /* HP on-board ethernet. */ 47800137dad17707f0d14dbf7e193761220f1c2fe03Hannes Eder static int did_version; /* Already printed version info. */ 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = -ENOMEM; 481c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro void __iomem *bios; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* First we look for special cases. 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Check for HP's on-board ethernet by looking for 'HP' in the BIOS. 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds There are two HP versions, check the BIOS for the configuration port. 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This method provided by L. Julliard, Laurent_Julliard@grenoble.hp.com. 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 488c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro bios = ioremap(0xf00f0, 0x14); 489c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro if (!bios) 490c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro return -ENOMEM; 491c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro if (readw(bios + 0x12) == 0x5048) { 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const short ioaddr_table[] = { 0x300, 0x320, 0x340, 0x360}; 493c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro int hp_port = (readl(bios + 1) & 1) ? 0x499 : 0x99; 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We can have boards other than the built-in! Verify this is on-board. */ 4958e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches if ((inb(hp_port) & 0xc0) == 0x80 && 4968e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches ioaddr_table[inb(hp_port) & 3] == ioaddr) 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hp_builtin = hp_port; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 499c44fec118b62baad3fc70e2ef3447729a1d9b194Al Viro iounmap(bios); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We also recognize the HP Vectra on-board here, but check below. */ 5018e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches hpJ2405A = (inb(ioaddr) == 0x08 && inb(ioaddr+1) == 0x00 && 5028e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches inb(ioaddr+2) == 0x09); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset the LANCE. */ 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reset_val = inw(ioaddr+LANCE_RESET); /* Reset the LANCE */ 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The Un-Reset needed is only needed for the real NE2100, and will 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds confuse the HP board. */ 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!hpJ2405A) 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(reset_val, ioaddr+LANCE_RESET); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */ 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inw(ioaddr+LANCE_DATA) != 0x0004) 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get the version of the chip. */ 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(88, ioaddr+LANCE_ADDR); 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inw(ioaddr+LANCE_ADDR) != 88) { 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_version = 0; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* Good, it's a newer chip. */ 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int chip_version = inw(ioaddr+LANCE_DATA); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(89, ioaddr+LANCE_ADDR); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip_version |= inw(ioaddr+LANCE_DATA) << 16; 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 2) 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" LANCE chip version is %#x.\n", chip_version); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((chip_version & 0xfff) != 0x003) 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip_version = (chip_version >> 12) & 0xffff; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) { 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lance_version].id_number == chip_version) 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 535b74ca3a896b9ab5f952bc440154758e708c48884Wang Chen /* We can't allocate private data from alloc_etherdev() because it must 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a ISA DMA-able region. */ 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chipname = chip_table[lance_version].name; 5380795af5729b18218767fab27c44b1384f72dc9adJoe Perches printk("%s: %s at %#3x, ", dev->name, chipname, ioaddr); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There is a 16 byte station address PROM at the base address. 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The first six bytes are the station address. */ 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) 5430795af5729b18218767fab27c44b1384f72dc9adJoe Perches dev->dev_addr[i] = inb(ioaddr + i); 544e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk("%pM", dev->dev_addr); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = ioaddr; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Make certain the data structures used by the LANCE are aligned and DMAble. */ 5486aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 549dd00cc486ab1c17049a535413d1751ef3482141cYoann Padioleau lp = kzalloc(sizeof(*lp), GFP_DMA | GFP_KERNEL); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(lp==NULL) 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp); 553c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen dev->ml_priv = lp; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->name = chipname; 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE, 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_DMA | GFP_KERNEL); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lp->rx_buffs) 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_lp; 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_need_isa_bounce_buffers) { 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE, 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_DMA | GFP_KERNEL); 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!lp->tx_bounce_buffs) 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_rx; 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_bounce_buffs = NULL; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->chip_version = lance_version; 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_init(&lp->devlock); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.mode = 0x0003; /* Disable Rx and Tx. */ 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.phys_addr[i] = dev->dev_addr[i]; 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.filter[0] = 0x00000000; 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.filter[1] = 0x00000000; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS; 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0001, ioaddr+LANCE_ADDR); 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inw(ioaddr+LANCE_ADDR); 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0002, ioaddr+LANCE_ADDR); 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inw(ioaddr+LANCE_ADDR); 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA); 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_ADDR); 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inw(ioaddr+LANCE_ADDR); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (irq) { /* Set iff PCI card. */ 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = 4; /* Native bus-master, no DMA channel needed. */ 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq; 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (hp_builtin) { 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const char dma_tbl[4] = {3, 5, 6, 0}; 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const char irq_tbl[4] = {3, 4, 5, 9}; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char port_val = inb(hp_builtin); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = dma_tbl[(port_val >> 4) & 3]; 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq_tbl[(port_val >> 2) & 3]; 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" HP Vectra IRQ %d DMA %d.\n", dev->irq, dev->dma); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (hpJ2405A) { 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const char dma_tbl[4] = {3, 5, 6, 7}; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const char irq_tbl[8] = {3, 4, 5, 9, 10, 11, 12, 15}; 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short reset_val = inw(ioaddr+LANCE_RESET); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = dma_tbl[(reset_val >> 2) & 3]; 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq_tbl[(reset_val >> 4) & 7]; 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" HP J2405A IRQ %d DMA %d.\n", dev->irq, dev->dma); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (lance_version == PCNET_ISAP) { /* The plug-n-play version. */ 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short bus_info; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(8, ioaddr+LANCE_ADDR); 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bus_info = inw(ioaddr+LANCE_BUS_IF); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = bus_info & 0x07; 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = (bus_info >> 4) & 0x0F; 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The DMA channel may be passed in PARAM1. */ 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->mem_start & 0x07) 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = dev->mem_start & 0x07; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->dma == 0) { 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the DMA channel status register, so that we can avoid 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stuck DMA channels in the DMA detection below. */ 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_channels = ((inb(DMA1_STAT_REG) >> 4) & 0x0f) | 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (inb(DMA2_STAT_REG) & 0xf0); 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -ENODEV; 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->irq >= 2) 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" assigned IRQ %d", dev->irq); 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (lance_version != 0) { /* 7990 boards need DMA detection first. */ 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long irq_mask; 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* To auto-IRQ we enable the initialization-done and DMA error 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds interrupts. For ISA boards we get a DMA error, but VLB and PCI 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds boards will work. */ 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_mask = probe_irq_on(); 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an initialization just for the interrupt. */ 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0041, ioaddr+LANCE_DATA); 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(20); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = probe_irq_off(irq_mask); 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->irq) 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", probed IRQ %d", dev->irq); 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", failed to detect IRQ line.\n"); 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_tx; 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Check for the initialization done bit, 0x0100, which means 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds that we don't need a DMA channel. */ 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inw(ioaddr+LANCE_DATA) & 0x0100) 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = 4; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->dma == 4) { 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", no DMA needed.\n"); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (dev->dma) { 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_dma(dev->dma, chipname)) { 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("DMA %d allocation failed.\n", dev->dma); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_tx; 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", assigned DMA %d.\n", dev->dma); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { /* OK, we have to auto-DMA. */ 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 4; i++) { 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static const char dmas[] = { 5, 6, 7, 3 }; 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dma = dmas[i]; 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int boguscnt; 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't enable a permanently busy DMA channel, or the machine 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds will hang. */ 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_bit(dma, &dma_channels)) 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x7f04, ioaddr+LANCE_DATA); /* Clear the memory error bits. */ 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_dma(dma, chipname)) 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 6726aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags=claim_dma_lock(); 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_dma_mode(dma, DMA_MODE_CASCADE); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enable_dma(dma); 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_dma_lock(flags); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an initialization. */ 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0001, ioaddr+LANCE_DATA); 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (boguscnt = 100; boguscnt > 0; --boguscnt) 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inw(ioaddr+LANCE_DATA) & 0x0900) 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inw(ioaddr+LANCE_DATA) & 0x0100) { 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->dma = dma; 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(", DMA %d.\n", dev->dma); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds flags=claim_dma_lock(); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disable_dma(dma); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_dma_lock(flags); 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_dma(dma); 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i == 4) { /* Failure: bail. */ 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("DMA detection failed.\n"); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_tx; 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_version == 0 && dev->irq == 0) { 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We may auto-IRQ now that we have a DMA channel. */ 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an initialization just for the interrupt. */ 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long irq_mask; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_mask = probe_irq_on(); 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0041, ioaddr+LANCE_DATA); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(40); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = probe_irq_off(irq_mask); 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->irq == 0) { 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" Failed to detect the 7990 IRQ line.\n"); 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_dma; 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(" Auto-IRQ detected IRQ%d.\n", dev->irq); 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Turn on auto-select of media (10baseT or BNC) so that the user 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds can watch the LEDs even if the board isn't opened. */ 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0002, ioaddr+LANCE_ADDR); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Don't touch 10base2 power bit. */ 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF); 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 0 && did_version++ == 0) 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(version); 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The LANCE-specific entries in the device structure. */ 729462540bdb2f08d465a2416764fc628520f82939fStephen Hemminger dev->netdev_ops = &lance_netdev_ops; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->watchdog_timeo = TX_TIMEOUT; 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 732b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au> err = register_netdev(dev); 733b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au> if (err) 734b1fc5505e0dbcc3fd7c75bfe6bee39ec50080963<herbert@gondor.apana.org.au> goto out_dma; 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_dma: 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->dma != 4) 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_dma(dev->dma); 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_tx: 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lp->tx_bounce_buffs); 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_rx: 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree((void*)lp->rx_buffs); 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_lp: 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(lp); 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7486aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslance_open(struct net_device *dev) 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 752c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ioaddr = dev->base_addr; 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->irq == 0 || 757a0607fd3a25ba1848a63a0d925e36d914735ab47Joe Perches request_irq(dev->irq, lance_interrupt, 0, lp->name, dev)) { 7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We used to allocate DMA here, but that was silly. 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DMA lines can't be shared! We now permanently allocate them. */ 7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset the LANCE */ 7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inw(ioaddr+LANCE_RESET); 7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The DMA controller is used as a no-operation slave, "cascade mode". */ 7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->dma != 4) { 7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags=claim_dma_lock(); 7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds enable_dma(dev->dma); 7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_dma_mode(dev->dma, DMA_MODE_CASCADE); 7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_dma_lock(flags); 7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Un-Reset the LANCE, needed only for the NE2100. */ 7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lp->chip_version].flags & LANCE_MUST_UNRESET) 7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0, ioaddr+LANCE_RESET); 7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) { 7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */ 7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0002, ioaddr+LANCE_ADDR); 7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Only touch autoselect bit. */ 7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF); 7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 1) 7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n", 7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, dev->irq, dev->dma, 7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (u32) isa_virt_to_bus(lp->tx_ring), 7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (u32) isa_virt_to_bus(lp->rx_ring), 7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (u32) isa_virt_to_bus(&lp->init_block)); 7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev, GFP_KERNEL); 7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Re-initialize the LANCE, and start it when done. */ 7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0001, ioaddr+LANCE_ADDR); 7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw((short) (u32) isa_virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA); 7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0002, ioaddr+LANCE_ADDR); 7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(((u32)isa_virt_to_bus(&lp->init_block)) >> 16, ioaddr+LANCE_DATA); 7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0004, ioaddr+LANCE_ADDR); 8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0915, ioaddr+LANCE_DATA); 8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_ADDR); 8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0001, ioaddr+LANCE_DATA); 8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_start_queue (dev); 8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = 0; 8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (i++ < 100) 8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inw(ioaddr+LANCE_DATA) & 0x0100) 8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 8126aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik /* 8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We used to clear the InitDone bit, 0x0100, here but Mark Stockton 8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * reports that doing so triggers a bug in the '974. 8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0042, ioaddr+LANCE_DATA); 8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 2) 8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: LANCE open after %d ticks, init block %#x csr0 %4.4x.\n", 8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, i, (u32) isa_virt_to_bus(&lp->init_block), inw(ioaddr+LANCE_DATA)); 8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; /* Always succeed */ 8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE has been halted for one reason or another (busmaster memory 8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds arbitration error, Tx FIFO underflow, driver stopped it to reconfigure, 8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds etc.). Modern LANCE variants always reload their ring-buffer 8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds configuration when restarted, so we must reinitialize our ring 8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds context before restarting. As part of this reinitialization, 8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds find all packets still on the Tx ring and pretend that they had been 8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sent (in effect, drop the packets on the floor) - the higher-level 8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds protocols will time out and retransmit. It'd be better to shuffle 8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds these skbs to a temp list and then actually re-Tx them after 8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds restarting the chip, but I'm too lazy to do so right now. dplatt@3do.com 8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8376aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzikstatic void 8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslance_purge_ring(struct net_device *dev) 8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 840c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Free all the skbuffs in the Rx and Tx queues. */ 8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < RX_RING_SIZE; i++) { 8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb = lp->rx_skbuff[i]; 8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_skbuff[i] = NULL; 8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[i].base = 0; /* Not owned by LANCE chip. */ 8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb) 8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(skb); 8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < TX_RING_SIZE; i++) { 8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->tx_skbuff[i]) { 8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_any(lp->tx_skbuff[i]); 8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_skbuff[i] = NULL; 8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize the LANCE Rx and Tx rings. */ 8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 8629e24974db6b01ec067c24de09588282b6a1407f0Al Virolance_init_ring(struct net_device *dev, gfp_t gfp) 8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 864c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx = lp->cur_tx = 0; 8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_rx = lp->dirty_tx = 0; 8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < RX_RING_SIZE; i++) { 8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds void *rx_buff; 8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = alloc_skb(PKT_BUF_SZ, GFP_DMA | gfp); 8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_skbuff[i] = skb; 8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb) { 8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->dev = dev; 878689be43945e9ca7dd704522e55af1b8a73a994d3David S. Miller rx_buff = skb->data; 8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp); 8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rx_buff == NULL) 8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[i].base = 0; 8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[i].base = (u32)isa_virt_to_bus(rx_buff) | 0x80000000; 8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[i].buf_length = -PKT_BUF_SZ; 8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The Tx buffer address is filled in as needed, but we do need to clear 8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the upper ownership bit. */ 8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < TX_RING_SIZE; i++) { 8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_skbuff[i] = NULL; 8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[i].base = 0; 8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.mode = 0x0000; 8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 6; i++) 8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.phys_addr[i] = dev->dev_addr[i]; 8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.filter[0] = 0x00000000; 8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.filter[1] = 0x00000000; 8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.rx_ring = ((u32)isa_virt_to_bus(lp->rx_ring) & 0xffffff) | RX_RING_LEN_BITS; 9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->init_block.tx_ring = ((u32)isa_virt_to_bus(lp->tx_ring) & 0xffffff) | TX_RING_LEN_BITS; 9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void 9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit) 9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 906c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (must_reinit || 9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) { 9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_purge_ring(dev); 9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_init_ring(dev, GFP_ATOMIC); 9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, dev->base_addr + LANCE_ADDR); 9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(csr0_bits, dev->base_addr + LANCE_DATA); 9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void lance_tx_timeout (struct net_device *dev) 9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 920c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = (struct lance_private *) dev->ml_priv; 9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ioaddr = dev->base_addr; 9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw (0, ioaddr + LANCE_ADDR); 9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk ("%s: transmit timed out, status %4.4x, resetting.\n", 9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, inw (ioaddr + LANCE_DATA)); 9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw (0x0004, ioaddr + LANCE_DATA); 9277bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_errors++; 9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version 9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 3) { 9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk (" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx, lp->cur_tx, netif_queue_stopped(dev) ? " (full)" : "", 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx); 9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < RX_RING_SIZE; i++) 9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ", 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, 9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[i].msg_length); 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < TX_RING_SIZE; i++) 9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ", 9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[i].base, -lp->tx_ring[i].length, 9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[i].misc); 9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk ("\n"); 9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_restart (dev, 0x0043, 1); 9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9471ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet dev->trans_start = jiffies; /* prevent tx timeout */ 9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue (dev); 9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 95261357325f377889a1daffa14962d705dc814dd0eStephen Hemmingerstatic netdev_tx_t lance_start_xmit(struct sk_buff *skb, 95361357325f377889a1daffa14962d705dc814dd0eStephen Hemminger struct net_device *dev) 9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 955c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ioaddr = dev->base_addr; 9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry; 9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lp->devlock, flags); 9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 3) { 9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_ADDR); 9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name, 9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inw(ioaddr+LANCE_DATA)); 9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_DATA); 9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Fill in a Tx ring entry */ 9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Mask to ring buffer boundary. */ 9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = lp->cur_tx & TX_RING_MOD_MASK; 9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Caution: the write order is important here, set the base address 9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds with the "ownership" bits last. */ 9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The old LANCE chips doesn't automatically pad buffers to min. size. */ 9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lp->chip_version].flags & LANCE_MUST_PAD) { 9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (skb->len < ETH_ZLEN) { 9805b057c6b1a25d57edf2b4d1e956e50936480a9ffHerbert Xu if (skb_padto(skb, ETH_ZLEN)) 9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].length = -ETH_ZLEN; 9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 9846aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik else 9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].length = -skb->len; 9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].length = -skb->len; 9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].misc = 0x0000; 9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9917bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_bytes += skb->len; 9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If any part of this buffer is >16M we must copy it to a low-memory 9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer. */ 9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((u32)isa_virt_to_bus(skb->data) + skb->len > 0x01000000) { 9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 5) 9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: bouncing a high-memory packet (%#x).\n", 9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, (u32)isa_virt_to_bus(skb->data)); 999d626f62b11e00c16e81e4308ab93d3f13551812aArnaldo Carvalho de Melo skb_copy_from_linear_data(skb, &lp->tx_bounce_buffs[entry], skb->len); 10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].base = 10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((u32)isa_virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000; 10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb(skb); 10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_skbuff[entry] = skb; 10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].base = ((u32)isa_virt_to_bus(skb->data) & 0xffffff) | 0x83000000; 10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_tx++; 10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Trigger an immediate send poll. */ 10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_ADDR); 10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0048, ioaddr+LANCE_DATA); 10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((lp->cur_tx - lp->dirty_tx) >= TX_RING_SIZE) 10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue(dev); 10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lp->devlock, flags); 10186ed106549d17474ca17a16057f4c0ed4eba5a7caPatrick McHardy return NETDEV_TX_OK; 10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The LANCE interrupt handler. */ 10227d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t lance_interrupt(int irq, void *dev_id) 10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = dev_id; 10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct lance_private *lp; 10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int csr0, ioaddr, boguscnt=10; 10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int must_restart; 10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr = dev->base_addr; 1030c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen lp = dev->ml_priv; 10316aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock (&lp->devlock); 10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x00, dev->base_addr + LANCE_ADDR); 10358e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches while ((csr0 = inw(dev->base_addr + LANCE_DATA)) & 0x8600 && 10368e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches --boguscnt >= 0) { 10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Acknowledge all of the current interrupt sources ASAP. */ 10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(csr0 & ~0x004f, dev->base_addr + LANCE_DATA); 10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds must_restart = 0; 10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 5) 10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", 10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0, inw(dev->base_addr + LANCE_DATA)); 10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & 0x0400) /* Rx interrupt */ 10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_rx(dev); 10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & 0x0200) { /* Tx-done interrupt */ 10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int dirty_tx = lp->dirty_tx; 10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (dirty_tx < lp->cur_tx) { 10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = dirty_tx & TX_RING_MOD_MASK; 10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = lp->tx_ring[entry].base; 10556aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status < 0) 10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; /* It still hasn't been Txed */ 10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_ring[entry].base = 0; 10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 0x40000000) { 10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There was an major error, log it. */ 10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err_status = lp->tx_ring[entry].misc; 10647bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_errors++; 10657bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (err_status & 0x0400) 10667bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_aborted_errors++; 10677bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (err_status & 0x0800) 10687bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_carrier_errors++; 10697bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (err_status & 0x1000) 10707bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_window_errors++; 10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err_status & 0x4000) { 10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Ackk! On FIFO errors the Tx unit is turned off! */ 10737bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_fifo_errors++; 10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Remove this verbosity later! */ 10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: Tx FIFO error! Status %4.4x.\n", 10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0); 10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds must_restart = 1; 10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 0x18000000) 10827bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.collisions++; 10837bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_packets++; 10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We must free the original skb if it's not a data-only copy 10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in the bounce buffer. */ 10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->tx_skbuff[entry]) { 10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_kfree_skb_irq(lp->tx_skbuff[entry]); 10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->tx_skbuff[entry] = NULL; 10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx++; 10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef final_version 10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { 10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("out-of-sync dirty pointer, %d vs. %d, full=%s.\n", 10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx, lp->cur_tx, 10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_queue_stopped(dev) ? "yes" : "no"); 11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx += TX_RING_SIZE; 11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* if the ring is no longer full, accept more packets */ 11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (netif_queue_stopped(dev) && 11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) 11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_wake_queue (dev); 11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->dirty_tx = dirty_tx; 11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Log misc errors. */ 11137bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (csr0 & 0x4000) 11147bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.tx_errors++; /* Tx babble. */ 11157bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (csr0 & 0x1000) 11167bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_errors++; /* Missed a Rx frame. */ 11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csr0 & 0x0800) { 11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: Bus master arbitration failure, status %4.4x.\n", 11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, csr0); 11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Restart the chip. */ 11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds must_restart = 1; 11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (must_restart) { 11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* stop the chip to clear the error condition, then restart */ 11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, dev->base_addr + LANCE_ADDR); 11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0004, dev->base_addr + LANCE_DATA); 11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_restart(dev, 0x0002, 0); 11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Clear any other interrupt, and set interrupt enable. */ 11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, dev->base_addr + LANCE_ADDR); 11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x7940, dev->base_addr + LANCE_DATA); 11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 4) 11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: exiting interrupt, csr%d=%#4.4x.\n", 11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, inw(ioaddr + LANCE_ADDR), 11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inw(dev->base_addr + LANCE_DATA)); 11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock (&lp->devlock); 11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return IRQ_HANDLED; 11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslance_rx(struct net_device *dev) 11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1148c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int entry = lp->cur_rx & RX_RING_MOD_MASK; 11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 11516aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If we own the next entry, it's a new packet. Send it up. */ 11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while (lp->rx_ring[entry].base >= 0) { 11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int status = lp->rx_ring[entry].base >> 24; 11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status != 0x03) { /* There was an error. */ 11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* There is a tricky error noted by John Murphy, 11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds <murf@perftech.com> to Russ Nelson: Even with full-sized 11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers it's possible for a jabber packet to use two 11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffers, with only the last correctly noting the error. */ 11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (status & 0x01) /* Only count a general error at the */ 11627bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_errors++; /* end of a packet.*/ 11637bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (status & 0x20) 11647bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_frame_errors++; 11657bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (status & 0x10) 11667bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_over_errors++; 11677bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (status & 0x08) 11687bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_crc_errors++; 11697bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy if (status & 0x04) 11707bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_fifo_errors++; 11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[entry].base &= 0x03ffffff; 11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11736aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik else 11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Malloc up new buffer, compatible with net3. */ 11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short pkt_len = (lp->rx_ring[entry].msg_length & 0xfff)-4; 11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 11786aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(pkt_len<60) 11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: Runt packet!\n",dev->name); 11827bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_errors++; 11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb = dev_alloc_skb(pkt_len+2); 11876aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik if (skb == NULL) 11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: Memory squeeze, deferring packet.\n", dev->name); 11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i < RX_RING_SIZE; i++) 11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lp->rx_ring[(entry+i) & RX_RING_MOD_MASK].base < 0) 11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11946aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik if (i > RX_RING_SIZE -2) 11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 11967bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_dropped++; 11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[entry].base |= 0x80000000; 11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->cur_rx++; 11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 12011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_reserve(skb,2); /* 16 byte align */ 12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb_put(skb,pkt_len); /* Make room */ 12048c7b7faaa630fef7f68d8728cee1cce398cc9697David S. Miller skb_copy_to_linear_data(skb, 12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (unsigned char *)isa_bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)), 12068c7b7faaa630fef7f68d8728cee1cce398cc9697David S. Miller pkt_len); 12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol=eth_type_trans(skb,dev); 12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_rx(skb); 12097bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_packets++; 12107bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_bytes += pkt_len; 12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* The docs say that the buffer length isn't touched, but Andrew Boyd 12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds of QNX reports that some revs of the 79C965 clear it. */ 12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[entry].buf_length = -PKT_BUF_SZ; 12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lp->rx_ring[entry].base |= 0x80000000; 12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds entry = (++lp->cur_rx) & RX_RING_MOD_MASK; 12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We should check that at least two ring entries are free. If not, 12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds we should free one and mark stats->rx_dropped++. */ 12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldslance_close(struct net_device *dev) 12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ioaddr = dev->base_addr; 1230c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_stop_queue (dev); 12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) { 12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(112, ioaddr+LANCE_ADDR); 12367bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); 12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0, ioaddr+LANCE_ADDR); 12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lance_debug > 1) 12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: Shutting down ethercard, status was %2.2x.\n", 12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, inw(ioaddr+LANCE_DATA)); 12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We stop the LANCE here -- it occasionally polls 12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memory if we don't. */ 12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0004, ioaddr+LANCE_DATA); 12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->dma != 4) 12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags=claim_dma_lock(); 12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds disable_dma(dev->dma); 12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_dma_lock(flags); 12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq, dev); 12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_purge_ring(dev); 12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *lance_get_stats(struct net_device *dev) 12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1263c0103606b7e3db191dcbaf988f28fa26aa711230Wang Chen struct lance_private *lp = dev->ml_priv; 12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) { 12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short ioaddr = dev->base_addr; 12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short saved_addr; 12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&lp->devlock, flags); 12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saved_addr = inw(ioaddr+LANCE_ADDR); 12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(112, ioaddr+LANCE_ADDR); 12737bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy dev->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); 12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(saved_addr, ioaddr+LANCE_ADDR); 12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&lp->devlock, flags); 12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12787bfba0b0c15962265950ac0efe6bd4f42414db6dKulikov Vasiliy return &dev->stats; 12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Set or clear the multicast filter for this adaptor. 12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void set_multicast_list(struct net_device *dev) 12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short ioaddr = dev->base_addr; 12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0, ioaddr+LANCE_ADDR); 12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0004, ioaddr+LANCE_DATA); /* Temporarily stop the lance. */ 12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev->flags&IFF_PROMISC) { 12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(15, ioaddr+LANCE_ADDR); 12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x8000, ioaddr+LANCE_DATA); /* Set promiscuous mode */ 12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds short multicast_table[4]; 12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 12974cd24eaf0c6ee7f0242e34ee77ec899f255e66b5Jiri Pirko int num_addrs=netdev_mc_count(dev); 12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(dev->flags&IFF_ALLMULTI) 12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds num_addrs=1; 13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXIT: We don't use the multicast table, but rely on upper-layer filtering. */ 13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(multicast_table, (num_addrs == 0) ? 0 : -1, sizeof(multicast_table)); 13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 4; i++) { 13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(8 + i, ioaddr+LANCE_ADDR); 13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(multicast_table[i], ioaddr+LANCE_DATA); 13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(15, ioaddr+LANCE_ADDR); 13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outw(0x0000, ioaddr+LANCE_DATA); /* Unset promiscuous mode */ 13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lance_restart(dev, 0x0142, 0); /* Resume normal operation */ 13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 13131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1314