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