11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ne2k-pci.c: A NE2000 clone on PCI bus driver for Linux. */ 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds A Linux device driver for PCI NE2000 clones. 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Authors and other copyright holders: 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1992-2000 by Donald Becker, NE2000 core and various modifications. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1995-1998 by Paul Gortmaker, core modifications and PCI support. 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Copyright 1993 assigned to the United States Government as represented 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds by the Director, National Security Agency. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This software may be used and distributed according to the terms of 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the GNU General Public License (GPL), incorporated herein by reference. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Drivers based on or derived from this code fall under the GPL and must 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retain the authorship, copyright and license notice. This file is not 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds a complete program and may only be used when the entire operating 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds system is licensed under the GPL. 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The author may be reached as becker@scyld.com, or C/O 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Scyld Computing Corporation 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 410 Severn Ave., Suite 210 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Annapolis MD 21403 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Issues remaining: 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds People are making PCI ne2000 clones! Oh the horror, the horror... 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Limited full-duplex support. 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_NAME "ne2k-pci" 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_VERSION "1.03" 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRV_RELDATE "9/22/2003" 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* The user-configurable values. 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds These may be modified when a driver module is loaded.*/ 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MAX_UNITS 8 /* More are supported, limit only on options */ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Used to pass the full-duplex flag, etc. */ 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int full_duplex[MAX_UNITS]; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int options[MAX_UNITS]; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Force a non std. amount of memory. Units are 256 byte pages. */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* #define PACKETBUF_MEMSIZE 0x40 */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ethtool.h> 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h> 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h> 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h> 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "8390.h" 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* These identify the driver base version and may not be removed. */ 648937bb7b44b991c2535ad917e925c2daa2cd6096Stephen Hemmingerstatic const char version[] __devinitconst = 658937bb7b44b991c2535ad917e925c2daa2cd6096Stephen Hemminger KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE 668937bb7b44b991c2535ad917e925c2daa2cd6096Stephen Hemminger " D. Becker/P. Gortmaker\n"; 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if defined(__powerpc__) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define inl_le(addr) le32_to_cpu(inl(addr)) 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define inw_le(addr) le16_to_cpu(inw(addr)) 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PFX DRV_NAME ": " 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Donald Becker / Paul Gortmaker"); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("PCI NE2000 clone driver"); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(options, int, NULL, 0); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(full_duplex, int, NULL, 0); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(debug, "debug level (1-2)"); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(options, "Bit 5: full duplex"); 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)"); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Some defines that people can play with if so inclined. */ 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use 32 bit data-movement operations instead of 16 bit. */ 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define USE_LONGIO 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Do we implement the read before write bugfix ? */ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* #define NE_RW_BUGFIX */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Flags. We rename an existing ei_status field to store flags! */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Thus only the low 8 bits are usable for non-init-time flags. */ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define ne2k_flags reg0 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum { 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ONLY_16BIT_IO=8, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds FORCE_FDX=0x20, /* User override. */ 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds REALTEK_FDX=0x40, HOLTEK_FDX=0x80, 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds STOP_PG_0x60=0x100, 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum ne2k_pci_chipsets { 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_RealTek_RTL_8029 = 0, 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Winbond_89C940, 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Compex_RL2000, 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_KTI_ET32P2, 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_NetVin_NV5000SC, 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Via_86C926, 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_SureCom_NE34, 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Winbond_W89C940F, 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Holtek_HT80232, 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Holtek_HT80229, 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CH_Winbond_89C940_8c4a, 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119b2fd16b4ff2508ac16ae994f4bcd941f97754c00Hormsstatic struct { 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *name; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flags; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} pci_clone_list[] __devinitdata = { 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"RealTek RTL-8029", REALTEK_FDX}, 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Winbond 89C940", 0}, 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Compex RL2000", 0}, 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"KTI ET32P2", 0}, 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"NetVin NV5000SC", 0}, 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Via 86C926", ONLY_16BIT_IO}, 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"SureCom NE34", 0}, 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Winbond W89C940F", 0}, 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX}, 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Holtek HT80229", ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 }, 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {"Winbond W89C940(misprogrammed)", 0}, 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {NULL,} 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 138a3aa18842a5303fc28fcc4d57dbd16618bd830a0Alexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(ne2k_pci_tbl) = { 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x10ec, 0x8029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RealTek_RTL_8029 }, 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x1050, 0x0940, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940 }, 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x11f6, 0x1401, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Compex_RL2000 }, 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x8e2e, 0x3000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_KTI_ET32P2 }, 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x4a14, 0x5000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_NetVin_NV5000SC }, 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x1106, 0x0926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Via_86C926 }, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x10bd, 0x0e34, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_SureCom_NE34 }, 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F }, 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 }, 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 }, 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0x8c4a, 0x1980, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_89C940_8c4a }, 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, } 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, ne2k_pci_tbl); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ---- No user-serviceable parts below ---- */ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NE_BASE (dev->base_addr) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NE_CMD 0x00 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NE_IO_EXTENT 0x20 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NESM_START_PG 0x40 /* First page of TX buffer */ 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_open(struct net_device *dev); 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_close(struct net_device *dev); 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_reset_8390(struct net_device *dev); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ring_page); 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_block_input(struct net_device *dev, int count, 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb, int ring_offset); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_block_output(struct net_device *dev, const int count, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const unsigned char *buf, const int start_page); 1777282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops ne2k_pci_ethtool_ops; 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1796aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* There is no room in the standard 8390 structure for extra info we need, 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds so we build a meta/outer-wrapper structure.. */ 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct ne2k_pci_card { 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pci_dev; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NEx000-clone boards have a Station Address (SA) PROM (SAPROM) in the packet 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buffer memory space. By-the-spec NE2000 clones have 0x57,0x57 in bytes 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x0e,0x0f of the SAPROM, while other supposed NE2000 clones must be 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds detected by their SA prefix. 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Reading the SAPROM from a word-wide card with the 8390 set in byte-wide 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mode results in doubled values, which can be detected and compensated for. 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The probe is also responsible for initializing the card and filling 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds in the 'dev' and 'ei_status' structures. 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2034e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemmingerstatic const struct net_device_ops ne2k_netdev_ops = { 2044e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_open = ne2k_pci_open, 2054e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_stop = ne2k_pci_close, 2064e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_start_xmit = ei_start_xmit, 2074e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_tx_timeout = ei_tx_timeout, 2084e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_get_stats = ei_get_stats, 209afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko .ndo_set_rx_mode = ei_set_multicast_list, 2104e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_validate_addr = eth_validate_addr, 211fe96aaa14f553f0eb7af0e3502563a5400c65257Stephen Hemminger .ndo_set_mac_address = eth_mac_addr, 2124e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_change_mtu = eth_change_mtu, 2134e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger#ifdef CONFIG_NET_POLL_CONTROLLER 2144e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger .ndo_poll_controller = ei_poll, 2154e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger#endif 2164e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger}; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit ne2k_pci_init_one (struct pci_dev *pdev, 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *ent) 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned char SA_prom[32]; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int start_page, stop_page; 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int irq, reg0, chip_idx = ent->driver_data; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static unsigned int fnd_cnt; 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ioaddr; 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int flags = pci_clone_list[chip_idx].flags; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* when built into the kernel, we only print version if device is found */ 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef MODULE 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int printed_version; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!printed_version++) 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(version); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fnd_cnt++; 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = pci_enable_device (pdev); 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return i; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ioaddr = pci_resource_start (pdev, 0); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq = pdev->irq; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { 2479b91cf9daac41eeaaea57ecfe68dc13bb0305fa9Jeff Garzik dev_err(&pdev->dev, "no I/O resource at PCI BAR #0\n"); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (request_region (ioaddr, NE_IO_EXTENT, DRV_NAME) == NULL) { 2529b91cf9daac41eeaaea57ecfe68dc13bb0305fa9Jeff Garzik dev_err(&pdev->dev, "I/O resource 0x%x @ 0x%lx busy\n", 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NE_IO_EXTENT, ioaddr); 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds reg0 = inb(ioaddr); 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (reg0 == 0xFF) 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_res; 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Do a preliminary verification that we have a 8390. */ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int regd; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regd = inb(ioaddr + 0x0d); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xff, ioaddr + 0x0d); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inb(ioaddr + EN0_COUNTER0) != 0) { 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(reg0, ioaddr); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(regd, ioaddr + 0x0d); /* Restore the old values. */ 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_res; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allocate net_device, dev->priv; fill in 8390 specific dev fields. */ 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev = alloc_ei_netdev(); 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev) { 2799b91cf9daac41eeaaea57ecfe68dc13bb0305fa9Jeff Garzik dev_err(&pdev->dev, "cannot allocate ethernet device\n"); 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_res; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2824e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger dev->netdev_ops = &ne2k_netdev_ops; 2834e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SET_NETDEV_DEV(dev, &pdev->dev); 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Reset card. Who knows what dain-bramaged state it was left in. */ 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long reset_start_time = jiffies; 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This looks like a horrible timing loop, but it should never take 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds more than a few cycles. 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((inb(ioaddr + EN0_ISR) & ENISR_RESET) == 0) 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Limit wait: '2' avoids jiffy roll-over. */ 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (jiffies - reset_start_time > 2) { 2989b91cf9daac41eeaaea57ecfe68dc13bb0305fa9Jeff Garzik dev_err(&pdev->dev, 2992e8a538d865de0eb9813c8a0f2284e920299c0ccJeff Garzik "Card failure (no reset ack).\n"); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_netdev; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Read the 16 bytes of station address PROM. 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds We must first initialize registers, similar to NS8390_init(eifdev, 0). 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds We can't reliably read the SAPROM address without this. 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (I learned the hard way!). */ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct {unsigned char value, offset; } program_seq[] = { 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x49, EN0_DCFG}, /* Set word-wide access. */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00, EN0_RCNTLO}, /* Clear the count regs. */ 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00, EN0_RCNTHI}, 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00, EN0_IMR}, /* Mask completion irq. */ 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0xFF, EN0_ISR}, 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {32, EN0_RCNTLO}, 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00, EN0_RCNTHI}, 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {0x00, EN0_RSARHI}, 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds {E8390_RREAD+E8390_START, E8390_CMD}, 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 326ff8ac60948ba819b89e9c87083e8050fc2f89999Denis Cheng for (i = 0; i < ARRAY_SIZE(program_seq); i++) 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(program_seq[i].value, ioaddr + program_seq[i].offset); 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Note: all PCI cards have at least 16 bit access, so we don't have 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to check for 8 bit cards. Most cards permit 32 bit access. */ 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (flags & ONLY_32BIT_IO) { 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 4 ; i++) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT)); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++) 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SA_prom[i] = inb(ioaddr + NE_DATAPORT); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We always set the 8390 registers for word mode. */ 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x49, ioaddr + EN0_DCFG); 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds start_page = NESM_START_PG; 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up the rest of the parameters. */ 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->irq = irq; 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->base_addr = ioaddr; 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pdev, dev); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.name = pci_clone_list[chip_idx].name; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.tx_start_page = start_page; 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.stop_page = stop_page; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.word16 = 1; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.ne2k_flags = flags; 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fnd_cnt < MAX_UNITS) { 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (full_duplex[fnd_cnt] > 0 || (options[fnd_cnt] & FORCE_FDX)) 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.ne2k_flags |= FORCE_FDX; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.rx_start_page = start_page + TX_PAGES; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef PACKETBUF_MEMSIZE 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Allow the packet buffer size to be overridden by know-it-alls. */ 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.reset_8390 = &ne2k_pci_reset_8390; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.block_input = &ne2k_pci_block_input; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.block_output = &ne2k_pci_block_output; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.priv = (unsigned long) pdev; 3724e4fd4e485ad63a9074ff09a9b53ffc7a5c594ecStephen Hemminger 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->ethtool_ops = &ne2k_pci_ethtool_ops; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NS8390_init(dev, 0); 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 376eb457f36929da6d78c1f03cbb9038ef62646d79dJiri Pirko memcpy(dev->dev_addr, SA_prom, dev->addr_len); 377379b026ecc20c4657d37e40ead789f7f28f1a1c1Lubomir Rintel memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); 378379b026ecc20c4657d37e40ead789f7f28f1a1c1Lubomir Rintel 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds i = register_netdev(dev); 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i) 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_out_free_netdev; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 383e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg printk("%s: %s found at %#lx, IRQ %d, %pM.\n", 3840795af5729b18218767fab27c44b1384f72dc9adJoe Perches dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq, 385e174961ca1a0b28f7abf0be47973ad57cb74e5f0Johannes Berg dev->dev_addr); 3860795af5729b18218767fab27c44b1384f72dc9adJoe Perches 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free_netdev: 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev (dev); 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free_res: 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region (ioaddr, NE_IO_EXTENT); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata (pdev, NULL); 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3986aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik/* 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Magic incantation sequence for full duplex on the supported cards. 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int set_realtek_fdx(struct net_device *dev) 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ioaddr = dev->base_addr; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */ 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0xC0, ioaddr + 0x01); /* Enable writes to CONFIG3 */ 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x40, ioaddr + 0x06); /* Enable full duplex */ 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, ioaddr + 0x01); /* Disable writes to CONFIG3 */ 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_PAGE0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 0 */ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int set_holtek_fdx(struct net_device *dev) 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long ioaddr = dev->base_addr; 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_set_fdx(struct net_device *dev) 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4236aa20a2235535605db6d6d2bd850298b2fe7f31eJeff Garzik if (ei_status.ne2k_flags & REALTEK_FDX) 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return set_realtek_fdx(dev); 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (ei_status.ne2k_flags & HOLTEK_FDX) 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return set_holtek_fdx(dev); 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EOPNOTSUPP; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_open(struct net_device *dev) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4331fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner int ret = request_irq(dev->irq, ei_interrupt, IRQF_SHARED, dev->name, dev); 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.ne2k_flags & FORCE_FDX) 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ne2k_pci_set_fdx(dev); 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_open(dev); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_close(struct net_device *dev) 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_close(dev); 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_irq(dev->irq, dev); 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Hard reset the card. This used to pause for the same period that a 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8390 reset command required, but that shouldn't be necessary. */ 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_reset_8390(struct net_device *dev) 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long reset_start_time = jiffies; 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (debug > 1) printk("%s: Resetting the 8390 t=%ld...", 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, jiffies); 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.txing = 0; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing = 0; 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This check _should_not_ be necessary, omit eventually. */ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (jiffies - reset_start_time > 2) { 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: ne2k_pci_reset_8390() did not complete.\n", dev->name); 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Grab the 8390 specific header. Similar to the block_input routine, but 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds we don't need to be concerned with ring wrap as the header will be at 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the start of a page, so we optimize accordingly. */ 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long nic_base = dev->base_addr; 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.dmaing) { 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: DMAing conflict in ne2k_pci_get_8390_hdr " 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "[DMAstat:%d][irqlock:%d].\n", 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, ei_status.dmaing, ei_status.irqlock); 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing |= 0x01; 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, nic_base + EN0_RCNTHI); 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0, nic_base + EN0_RSARLO); /* On page boundary */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ring_page, nic_base + EN0_RSARHI); 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.ne2k_flags & ONLY_16BIT_IO) { 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *(u32*)hdr = le32_to_cpu(inl(NE_BASE + NE_DATAPORT)); 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le16_to_cpus(&hdr->count); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing &= ~0x01; 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Block input and output, similar to the Crynwr packet driver. If you 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds are porting to a new ethercard, look at the packet driver source for hints. 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds The NEx000 doesn't share the on-board packet memory -- you have to put 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds the packet out through the "remote DMA" dataport using outb. */ 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_block_input(struct net_device *dev, int count, 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb, int ring_offset) 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long nic_base = dev->base_addr; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *buf = skb->data; 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.dmaing) { 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: DMAing conflict in ne2k_pci_block_input " 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "[DMAstat:%d][irqlock:%d].\n", 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, ei_status.dmaing, ei_status.irqlock); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing |= 0x01; 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.ne2k_flags & ONLY_32BIT_IO) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = (count + 3) & 0xFFFC; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(count & 0xff, nic_base + EN0_RCNTLO); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(count >> 8, nic_base + EN0_RCNTHI); 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ring_offset & 0xff, nic_base + EN0_RSARLO); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ring_offset >> 8, nic_base + EN0_RSARHI); 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.ne2k_flags & ONLY_16BIT_IO) { 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds insw(NE_BASE + NE_DATAPORT,buf,count>>1); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 0x01) { 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[count-1] = inb(NE_BASE + NE_DATAPORT); 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds insl(NE_BASE + NE_DATAPORT, buf, count>>2); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 3) { 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf += count & ~3; 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 2) { 5483b5e26f7b07f5e537cef705de79174025ecd383cAl Viro __le16 *b = (__le16 *)buf; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5503b5e26f7b07f5e537cef705de79174025ecd383cAl Viro *b++ = cpu_to_le16(inw(NE_BASE + NE_DATAPORT)); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = (char *)b; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 1) 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *buf = inb(NE_BASE + NE_DATAPORT); 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing &= ~0x01; 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_block_output(struct net_device *dev, int count, 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const unsigned char *buf, const int start_page) 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds long nic_base = NE_BASE; 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long dma_start; 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* On little-endian it's always safe to round the count up for 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds word writes. */ 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.ne2k_flags & ONLY_32BIT_IO) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = (count + 3) & 0xFFFC; 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 0x01) 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count++; 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This *shouldn't* happen. If it does, it's the last thing you'll see */ 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.dmaing) { 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("%s: DMAing conflict in ne2k_pci_block_output." 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "[DMAstat:%d][irqlock:%d]\n", 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->name, ei_status.dmaing, ei_status.irqlock); 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing |= 0x01; 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We should already be in page 0, but to be safe... */ 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef NE8390_RW_BUGFIX 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Handle the read-before-write bug the same way as the 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Crynwr packet driver -- the NatSemi method doesn't work. 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Actually this doesn't always work either, but if you have 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds problems with your NEx000 this is better than nothing! */ 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x42, nic_base + EN0_RCNTLO); 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, nic_base + EN0_RCNTHI); 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x42, nic_base + EN0_RSARLO); 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, nic_base + EN0_RSARHI); 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_RREAD+E8390_START, nic_base + NE_CMD); 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ENISR_RDC, nic_base + EN0_ISR); 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Now the normal output. */ 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(count & 0xff, nic_base + EN0_RCNTLO); 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(count >> 8, nic_base + EN0_RCNTHI); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(0x00, nic_base + EN0_RSARLO); 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(start_page, nic_base + EN0_RSARHI); 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD); 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ei_status.ne2k_flags & ONLY_16BIT_IO) { 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outsw(NE_BASE + NE_DATAPORT, buf, count>>1); 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outsl(NE_BASE + NE_DATAPORT, buf, count>>2); 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 3) { 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf += count & ~3; 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (count & 2) { 6133b5e26f7b07f5e537cef705de79174025ecd383cAl Viro __le16 *b = (__le16 *)buf; 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6153b5e26f7b07f5e537cef705de79174025ecd383cAl Viro outw(le16_to_cpu(*b++), NE_BASE + NE_DATAPORT); 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = (char *)b; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dma_start = jiffies; 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ne2k_pci_reset_8390(dev); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NS8390_init(dev,1); 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ei_status.dmaing &= ~0x01; 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void ne2k_pci_get_drvinfo(struct net_device *dev, 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ethtool_drvinfo *info) 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6384cf1653aa90c6320dc8032443b5e322820aa28b1Wang Chen struct ei_device *ei = netdev_priv(dev); 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pci_dev *pci_dev = (struct pci_dev *) ei->priv; 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 64168aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 64268aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 64368aad78c5023b8aa82da99b47f9d8cf40e8ca453Rick Jones strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info)); 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6467282d491ecaee9883233a0e27283c4c79486279aJeff Garzikstatic const struct ethtool_ops ne2k_pci_ethtool_ops = { 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .get_drvinfo = ne2k_pci_get_drvinfo, 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = pci_get_drvdata(pdev); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6545d9428de1a9785f10a4339f80b717be665ba51c7Eric Sesterhenn BUG_ON(!dev); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unregister_netdev(dev); 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds release_region(dev->base_addr, NE_IO_EXTENT); 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_netdev(dev); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_disable_device(pdev); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pdev, NULL); 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = pci_get_drvdata (pdev); 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_device_detach(dev); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_save_state(pdev); 669d58da590451cf6ae75379a2ebf96d3afb8d810d8David Shaohua Li pci_disable_device(pdev); 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_power_state(pdev, pci_choose_state(pdev, state)); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ne2k_pci_resume (struct pci_dev *pdev) 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct net_device *dev = pci_get_drvdata (pdev); 678cad1b9da74f14c5f15b63ffc93c53debe09b3781Jeff Garzik int rc; 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_power_state(pdev, 0); 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_restore_state(pdev); 682cad1b9da74f14c5f15b63ffc93c53debe09b3781Jeff Garzik 683cad1b9da74f14c5f15b63ffc93c53debe09b3781Jeff Garzik rc = pci_enable_device(pdev); 684cad1b9da74f14c5f15b63ffc93c53debe09b3781Jeff Garzik if (rc) 685cad1b9da74f14c5f15b63ffc93c53debe09b3781Jeff Garzik return rc; 686cad1b9da74f14c5f15b63ffc93c53debe09b3781Jeff Garzik 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds NS8390_init(dev, 1); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds netif_device_attach(dev); 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PM */ 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver ne2k_driver = { 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = DRV_NAME, 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = ne2k_pci_init_one, 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = __devexit_p(ne2k_pci_remove_one), 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = ne2k_pci_tbl, 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .suspend = ne2k_pci_suspend, 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .resume = ne2k_pci_resume, 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_PM */ 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init ne2k_pci_init(void) 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* when a module, this is printed whether or not devices are found in probe */ 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(version); 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 715299176206b266f204be859adf9e66efd06628ab2Jeff Garzik return pci_register_driver(&ne2k_driver); 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit ne2k_pci_cleanup(void) 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver (&ne2k_driver); 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(ne2k_pci_init); 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(ne2k_pci_cleanup); 726