xref: /openbmc/linux/drivers/net/ethernet/8390/ne.c (revision 067dee65)
1644570b8SJeff Kirsher // SPDX-License-Identifier: GPL-1.0+
2644570b8SJeff Kirsher /* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */
3644570b8SJeff Kirsher /*
4644570b8SJeff Kirsher     Written 1992-94 by Donald Becker.
5644570b8SJeff Kirsher 
6644570b8SJeff Kirsher     Copyright 1993 United States Government as represented by the
7644570b8SJeff Kirsher     Director, National Security Agency.
8644570b8SJeff Kirsher 
9644570b8SJeff Kirsher     The author may be reached as becker@scyld.com, or C/O
10644570b8SJeff Kirsher     Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403
11644570b8SJeff Kirsher 
12644570b8SJeff Kirsher     This driver should work with many programmed-I/O 8390-based ethernet
13644570b8SJeff Kirsher     boards.  Currently it supports the NE1000, NE2000, many clones,
14644570b8SJeff Kirsher     and some Cabletron products.
15644570b8SJeff Kirsher 
16644570b8SJeff Kirsher     Changelog:
17644570b8SJeff Kirsher 
18644570b8SJeff Kirsher     Paul Gortmaker	: use ENISR_RDC to monitor Tx PIO uploads, made
19644570b8SJeff Kirsher 			  sanity checks and bad clone support optional.
20644570b8SJeff Kirsher     Paul Gortmaker	: new reset code, reset card after probe at boot.
21644570b8SJeff Kirsher     Paul Gortmaker	: multiple card support for module users.
22644570b8SJeff Kirsher     Paul Gortmaker	: Support for PCI ne2k clones, similar to lance.c
23644570b8SJeff Kirsher     Paul Gortmaker	: Allow users with bad cards to avoid full probe.
24644570b8SJeff Kirsher     Paul Gortmaker	: PCI probe changes, more PCI cards supported.
25644570b8SJeff Kirsher     rjohnson@analogic.com : Changed init order so an interrupt will only
26644570b8SJeff Kirsher     occur after memory is allocated for dev->priv. Deallocated memory
27644570b8SJeff Kirsher     last in cleanup_modue()
28644570b8SJeff Kirsher     Richard Guenther    : Added support for ISAPnP cards
29644570b8SJeff Kirsher     Paul Gortmaker	: Discontinued PCI support - use ne2k-pci.c instead.
30644570b8SJeff Kirsher     Hayato Fujiwara	: Add m32r support.
31644570b8SJeff Kirsher 
32644570b8SJeff Kirsher */
33644570b8SJeff Kirsher 
34644570b8SJeff Kirsher /* Routines for the NatSemi-based designs (NE[12]000). */
35644570b8SJeff Kirsher 
36644570b8SJeff Kirsher static const char version1[] =
37644570b8SJeff Kirsher "ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n";
38644570b8SJeff Kirsher static const char version2[] =
39644570b8SJeff Kirsher "Last modified Nov 1, 2000 by Paul Gortmaker\n";
40644570b8SJeff Kirsher 
41644570b8SJeff Kirsher 
42644570b8SJeff Kirsher #include <linux/module.h>
43644570b8SJeff Kirsher #include <linux/kernel.h>
44644570b8SJeff Kirsher #include <linux/errno.h>
45644570b8SJeff Kirsher #include <linux/isapnp.h>
46644570b8SJeff Kirsher #include <linux/init.h>
47644570b8SJeff Kirsher #include <linux/interrupt.h>
48644570b8SJeff Kirsher #include <linux/delay.h>
49644570b8SJeff Kirsher #include <linux/netdevice.h>
50644570b8SJeff Kirsher #include <linux/etherdevice.h>
51644570b8SJeff Kirsher #include <linux/jiffies.h>
52644570b8SJeff Kirsher #include <linux/platform_device.h>
53644570b8SJeff Kirsher #include <net/Space.h>
54644570b8SJeff Kirsher 
55*067dee65SArnd Bergmann #include <asm/io.h>
56644570b8SJeff Kirsher 
57644570b8SJeff Kirsher #include "8390.h"
58644570b8SJeff Kirsher 
59644570b8SJeff Kirsher #define DRV_NAME "ne"
60644570b8SJeff Kirsher 
61644570b8SJeff Kirsher /* Some defines that people can play with if so inclined. */
62644570b8SJeff Kirsher 
63644570b8SJeff Kirsher /* Do we support clones that don't adhere to 14,15 of the SAprom ? */
64644570b8SJeff Kirsher #define SUPPORT_NE_BAD_CLONES
65644570b8SJeff Kirsher /* 0xbad = bad sig or no reset ack */
66644570b8SJeff Kirsher #define BAD 0xbad
67644570b8SJeff Kirsher 
68644570b8SJeff Kirsher #define MAX_NE_CARDS	4	/* Max number of NE cards per module */
69644570b8SJeff Kirsher static struct platform_device *pdev_ne[MAX_NE_CARDS];
70644570b8SJeff Kirsher static int io[MAX_NE_CARDS];
71644570b8SJeff Kirsher static int irq[MAX_NE_CARDS];
72644570b8SJeff Kirsher static int bad[MAX_NE_CARDS];
73644570b8SJeff Kirsher static u32 ne_msg_enable;
74644570b8SJeff Kirsher 
75c45f812fSMatthew Whitehead #ifdef MODULE
76644570b8SJeff Kirsher module_param_hw_array(io, int, ioport, NULL, 0);
77644570b8SJeff Kirsher module_param_hw_array(irq, int, irq, NULL, 0);
78df298408SDavid Howells module_param_array(bad, int, NULL, 0);
79df298408SDavid Howells module_param_named(msg_enable, ne_msg_enable, uint, 0444);
80644570b8SJeff Kirsher MODULE_PARM_DESC(io, "I/O base address(es),required");
81d3757ba4SJoe Perches MODULE_PARM_DESC(irq, "IRQ number(s)");
82644570b8SJeff Kirsher MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures");
83644570b8SJeff Kirsher MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
84644570b8SJeff Kirsher MODULE_DESCRIPTION("NE1000/NE2000 ISA/PnP Ethernet driver");
85c45f812fSMatthew Whitehead MODULE_LICENSE("GPL");
86644570b8SJeff Kirsher #endif /* MODULE */
87644570b8SJeff Kirsher 
88644570b8SJeff Kirsher /* Do we perform extra sanity checks on stuff ? */
89644570b8SJeff Kirsher /* #define NE_SANITY_CHECK */
90644570b8SJeff Kirsher 
91644570b8SJeff Kirsher /* Do we implement the read before write bugfix ? */
92644570b8SJeff Kirsher /* #define NE_RW_BUGFIX */
93644570b8SJeff Kirsher 
94644570b8SJeff Kirsher /* Do we have a non std. amount of memory? (in units of 256 byte pages) */
95644570b8SJeff Kirsher /* #define PACKETBUF_MEMSIZE	0x40 */
96644570b8SJeff Kirsher 
97644570b8SJeff Kirsher /* This is set up so that no ISA autoprobe takes place. We can't guarantee
98644570b8SJeff Kirsher that the ne2k probe is the last 8390 based probe to take place (as it
99644570b8SJeff Kirsher is at boot) and so the probe will get confused by any other 8390 cards.
100644570b8SJeff Kirsher ISA device autoprobes on a running machine are not recommended anyway. */
101644570b8SJeff Kirsher #if !defined(MODULE) && defined(CONFIG_ISA)
102644570b8SJeff Kirsher /* Do we need a portlist for the ISA auto-probe ? */
1038eb97ff5SArnd Bergmann #define NEEDS_PORTLIST
104644570b8SJeff Kirsher #endif
105644570b8SJeff Kirsher 
106644570b8SJeff Kirsher /* A zero-terminated list of I/O addresses to be probed at boot. */
107644570b8SJeff Kirsher #ifdef NEEDS_PORTLIST
108644570b8SJeff Kirsher static unsigned int netcard_portlist[] __initdata = {
109644570b8SJeff Kirsher 	0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
110644570b8SJeff Kirsher };
111644570b8SJeff Kirsher #endif
112644570b8SJeff Kirsher 
113644570b8SJeff Kirsher static struct isapnp_device_id isapnp_clone_list[] __initdata = {
114644570b8SJeff Kirsher 	{	ISAPNP_CARD_ID('A','X','E',0x2011),
115644570b8SJeff Kirsher 		ISAPNP_VENDOR('A','X','E'), ISAPNP_FUNCTION(0x2011),
116644570b8SJeff Kirsher 		(long) "NetGear EA201" },
117644570b8SJeff Kirsher 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
118644570b8SJeff Kirsher 		ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216),
119644570b8SJeff Kirsher 		(long) "NN NE2000" },
120644570b8SJeff Kirsher 	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
121644570b8SJeff Kirsher 		ISAPNP_VENDOR('P','N','P'), ISAPNP_FUNCTION(0x80d6),
122644570b8SJeff Kirsher 		(long) "Generic PNP" },
123644570b8SJeff Kirsher 	{ }	/* terminate list */
124644570b8SJeff Kirsher };
125644570b8SJeff Kirsher 
126644570b8SJeff Kirsher MODULE_DEVICE_TABLE(isapnp, isapnp_clone_list);
127644570b8SJeff Kirsher 
128644570b8SJeff Kirsher #ifdef SUPPORT_NE_BAD_CLONES
129644570b8SJeff Kirsher /* A list of bad clones that we none-the-less recognize. */
130644570b8SJeff Kirsher static struct { const char *name8, *name16; unsigned char SAprefix[4];}
131644570b8SJeff Kirsher bad_clone_list[] __initdata = {
132644570b8SJeff Kirsher     {"DE100", "DE200", {0x00, 0xDE, 0x01,}},
133644570b8SJeff Kirsher     {"DE120", "DE220", {0x00, 0x80, 0xc8,}},
134644570b8SJeff Kirsher     {"DFI1000", "DFI2000", {'D', 'F', 'I',}}, /* Original, eh?  */
135644570b8SJeff Kirsher     {"EtherNext UTP8", "EtherNext UTP16", {0x00, 0x00, 0x79}},
136644570b8SJeff Kirsher     {"NE1000","NE2000-invalid", {0x00, 0x00, 0xd8}}, /* Ancient real NE1000. */
137644570b8SJeff Kirsher     {"NN1000", "NN2000",  {0x08, 0x03, 0x08}}, /* Outlaw no-name clone. */
138644570b8SJeff Kirsher     {"4-DIM8","4-DIM16", {0x00,0x00,0x4d,}},  /* Outlaw 4-Dimension cards. */
139644570b8SJeff Kirsher     {"Con-Intl_8", "Con-Intl_16", {0x00, 0x00, 0x24}}, /* Connect Int'nl */
140644570b8SJeff Kirsher     {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */
141644570b8SJeff Kirsher     {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */
142644570b8SJeff Kirsher     {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */
143644570b8SJeff Kirsher     {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */
144644570b8SJeff Kirsher     {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */
145644570b8SJeff Kirsher #ifdef CONFIG_MACH_TX49XX
146644570b8SJeff Kirsher     {"RBHMA4X00-RTL8019", "RBHMA4X00-RTL8019", {0x00, 0x60, 0x0a}},  /* Toshiba built-in */
147644570b8SJeff Kirsher #endif
148644570b8SJeff Kirsher     {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */
149644570b8SJeff Kirsher     {NULL,}
150644570b8SJeff Kirsher };
151644570b8SJeff Kirsher #endif
152644570b8SJeff Kirsher 
153644570b8SJeff Kirsher /* ---- No user-serviceable parts below ---- */
154644570b8SJeff Kirsher 
155644570b8SJeff Kirsher #define NE_BASE	 (dev->base_addr)
156644570b8SJeff Kirsher #define NE_CMD	 	0x00
157644570b8SJeff Kirsher #define NE_DATAPORT	0x10	/* NatSemi-defined port window offset. */
158644570b8SJeff Kirsher #define NE_RESET	0x1f	/* Issue a read to reset, a write to clear. */
159644570b8SJeff Kirsher #define NE_IO_EXTENT	0x20
160644570b8SJeff Kirsher 
161644570b8SJeff Kirsher #define NE1SM_START_PG	0x20	/* First page of TX buffer */
162644570b8SJeff Kirsher #define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
163644570b8SJeff Kirsher #define NESM_START_PG	0x40	/* First page of TX buffer */
164644570b8SJeff Kirsher #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
165644570b8SJeff Kirsher 
166644570b8SJeff Kirsher #if defined(CONFIG_MACH_TX49XX)
167644570b8SJeff Kirsher #  define DCR_VAL 0x48		/* 8-bit mode */
168e49ac967SGeert Uytterhoeven #elif defined(CONFIG_ATARI)	/* 8-bit mode on Atari, normal on Q40 */
169e49ac967SGeert Uytterhoeven #  define DCR_VAL (MACH_IS_ATARI ? 0x48 : 0x49)
170e49ac967SGeert Uytterhoeven #else
17165eca28dSMichael Schmitz #  define DCR_VAL 0x49
172644570b8SJeff Kirsher #endif
173644570b8SJeff Kirsher 
174644570b8SJeff Kirsher static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
175644570b8SJeff Kirsher static int ne_probe_isapnp(struct net_device *dev);
176644570b8SJeff Kirsher 
177644570b8SJeff Kirsher static void ne_reset_8390(struct net_device *dev);
178644570b8SJeff Kirsher static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
179644570b8SJeff Kirsher 			  int ring_page);
180644570b8SJeff Kirsher static void ne_block_input(struct net_device *dev, int count,
181644570b8SJeff Kirsher 			  struct sk_buff *skb, int ring_offset);
182644570b8SJeff Kirsher static void ne_block_output(struct net_device *dev, const int count,
183644570b8SJeff Kirsher 		const unsigned char *buf, const int start_page);
184644570b8SJeff Kirsher 
185644570b8SJeff Kirsher 
186644570b8SJeff Kirsher /*  Probe for various non-shared-memory ethercards.
187644570b8SJeff Kirsher 
188644570b8SJeff Kirsher    NEx000-clone boards have a Station Address PROM (SAPROM) in the packet
189644570b8SJeff Kirsher    buffer memory space.  NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of
190644570b8SJeff Kirsher    the SAPROM, while other supposed NE2000 clones must be detected by their
191644570b8SJeff Kirsher    SA prefix.
192644570b8SJeff Kirsher 
193644570b8SJeff Kirsher    Reading the SAPROM from a word-wide card with the 8390 set in byte-wide
194644570b8SJeff Kirsher    mode results in doubled values, which can be detected and compensated for.
195644570b8SJeff Kirsher 
196644570b8SJeff Kirsher    The probe is also responsible for initializing the card and filling
197644570b8SJeff Kirsher    in the 'dev' and 'ei_status' structures.
198644570b8SJeff Kirsher 
199644570b8SJeff Kirsher    We use the minimum memory size for some ethercard product lines, iff we can't
200644570b8SJeff Kirsher    distinguish models.  You can increase the packet buffer size by setting
201644570b8SJeff Kirsher    PACKETBUF_MEMSIZE.  Reported Cabletron packet buffer locations are:
202644570b8SJeff Kirsher 	E1010   starts at 0x100 and ends at 0x2000.
203644570b8SJeff Kirsher 	E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory")
204644570b8SJeff Kirsher 	E2010	 starts at 0x100 and ends at 0x4000.
205644570b8SJeff Kirsher 	E2010-x starts at 0x100 and ends at 0xffff.  */
206644570b8SJeff Kirsher 
do_ne_probe(struct net_device * dev)207644570b8SJeff Kirsher static int __init do_ne_probe(struct net_device *dev)
208644570b8SJeff Kirsher {
209644570b8SJeff Kirsher 	unsigned long base_addr = dev->base_addr;
210644570b8SJeff Kirsher #ifdef NEEDS_PORTLIST
211644570b8SJeff Kirsher 	int orig_irq = dev->irq;
212644570b8SJeff Kirsher #endif
213644570b8SJeff Kirsher 
214644570b8SJeff Kirsher 	/* First check any supplied i/o locations. User knows best. <cough> */
215644570b8SJeff Kirsher 	if (base_addr > 0x1ff) {	/* Check a single specified location. */
216644570b8SJeff Kirsher 		int ret = ne_probe1(dev, base_addr);
217644570b8SJeff Kirsher 		if (ret)
218644570b8SJeff Kirsher 			netdev_warn(dev, "ne.c: No NE*000 card found at "
219644570b8SJeff Kirsher 				    "i/o = %#lx\n", base_addr);
220c45f812fSMatthew Whitehead 		return ret;
221644570b8SJeff Kirsher 	}
222644570b8SJeff Kirsher 	else if (base_addr != 0)	/* Don't probe at all. */
223644570b8SJeff Kirsher 		return -ENXIO;
224644570b8SJeff Kirsher 
225644570b8SJeff Kirsher 	/* Then look for any installed ISAPnP clones */
226644570b8SJeff Kirsher 	if (isapnp_present() && (ne_probe_isapnp(dev) == 0))
227644570b8SJeff Kirsher 		return 0;
228644570b8SJeff Kirsher 
229644570b8SJeff Kirsher #ifdef NEEDS_PORTLIST
230644570b8SJeff Kirsher 	/* Last resort. The semi-risky ISA auto-probe. */
231644570b8SJeff Kirsher 	for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
232644570b8SJeff Kirsher 		int ioaddr = netcard_portlist[base_addr];
233644570b8SJeff Kirsher 		dev->irq = orig_irq;
234644570b8SJeff Kirsher 		if (ne_probe1(dev, ioaddr) == 0)
235644570b8SJeff Kirsher 			return 0;
236644570b8SJeff Kirsher 	}
237644570b8SJeff Kirsher #endif
238644570b8SJeff Kirsher 
239644570b8SJeff Kirsher 	return -ENODEV;
240644570b8SJeff Kirsher }
241644570b8SJeff Kirsher 
ne_probe_isapnp(struct net_device * dev)242644570b8SJeff Kirsher static int __init ne_probe_isapnp(struct net_device *dev)
243644570b8SJeff Kirsher {
244644570b8SJeff Kirsher 	int i;
245644570b8SJeff Kirsher 
246644570b8SJeff Kirsher 	for (i = 0; isapnp_clone_list[i].vendor != 0; i++) {
247644570b8SJeff Kirsher 		struct pnp_dev *idev = NULL;
248644570b8SJeff Kirsher 
249644570b8SJeff Kirsher 		while ((idev = pnp_find_dev(NULL,
250644570b8SJeff Kirsher 					    isapnp_clone_list[i].vendor,
251644570b8SJeff Kirsher 					    isapnp_clone_list[i].function,
252644570b8SJeff Kirsher 					    idev))) {
253644570b8SJeff Kirsher 			/* Avoid already found cards from previous calls */
254644570b8SJeff Kirsher 			if (pnp_device_attach(idev) < 0)
255644570b8SJeff Kirsher 				continue;
256644570b8SJeff Kirsher 			if (pnp_activate_dev(idev) < 0) {
257644570b8SJeff Kirsher 			      	pnp_device_detach(idev);
258644570b8SJeff Kirsher 			      	continue;
259644570b8SJeff Kirsher 			}
260644570b8SJeff Kirsher 			/* if no io and irq, search for next */
261644570b8SJeff Kirsher 			if (!pnp_port_valid(idev, 0) || !pnp_irq_valid(idev, 0)) {
262644570b8SJeff Kirsher 				pnp_device_detach(idev);
263644570b8SJeff Kirsher 				continue;
264644570b8SJeff Kirsher 			}
265644570b8SJeff Kirsher 			/* found it */
266644570b8SJeff Kirsher 			dev->base_addr = pnp_port_start(idev, 0);
267644570b8SJeff Kirsher 			dev->irq = pnp_irq(idev, 0);
268644570b8SJeff Kirsher 			netdev_info(dev,
269644570b8SJeff Kirsher 				    "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n",
270c45f812fSMatthew Whitehead 				    (char *) isapnp_clone_list[i].driver_data,
271c45f812fSMatthew Whitehead 				    dev->base_addr, dev->irq);
272644570b8SJeff Kirsher 			if (ne_probe1(dev, dev->base_addr) != 0) {	/* Shouldn't happen. */
273644570b8SJeff Kirsher 				netdev_err(dev,
274644570b8SJeff Kirsher 					   "ne.c: Probe of ISAPnP card at %#lx failed.\n",
275c45f812fSMatthew Whitehead 					   dev->base_addr);
276c45f812fSMatthew Whitehead 				pnp_device_detach(idev);
277c45f812fSMatthew Whitehead 				return -ENXIO;
278644570b8SJeff Kirsher 			}
279644570b8SJeff Kirsher 			ei_status.priv = (unsigned long)idev;
280644570b8SJeff Kirsher 			break;
281644570b8SJeff Kirsher 		}
282644570b8SJeff Kirsher 		if (!idev)
283644570b8SJeff Kirsher 			continue;
284644570b8SJeff Kirsher 		return 0;
285644570b8SJeff Kirsher 	}
286644570b8SJeff Kirsher 
287644570b8SJeff Kirsher 	return -ENODEV;
288644570b8SJeff Kirsher }
289644570b8SJeff Kirsher 
ne_probe1(struct net_device * dev,unsigned long ioaddr)290644570b8SJeff Kirsher static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
291644570b8SJeff Kirsher {
292644570b8SJeff Kirsher 	int i;
293644570b8SJeff Kirsher 	unsigned char SA_prom[32];
294644570b8SJeff Kirsher 	int wordlength = 2;
295644570b8SJeff Kirsher 	const char *name = NULL;
296644570b8SJeff Kirsher 	int start_page, stop_page;
297644570b8SJeff Kirsher 	int neX000, ctron, copam, bad_card;
298644570b8SJeff Kirsher 	int reg0, ret;
299644570b8SJeff Kirsher 	static unsigned version_printed;
300644570b8SJeff Kirsher 	struct ei_device *ei_local = netdev_priv(dev);
301644570b8SJeff Kirsher 
302c45f812fSMatthew Whitehead 	if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
303644570b8SJeff Kirsher 		return -EBUSY;
304644570b8SJeff Kirsher 
305644570b8SJeff Kirsher 	reg0 = inb_p(ioaddr);
306644570b8SJeff Kirsher 	if (reg0 == 0xFF) {
307644570b8SJeff Kirsher 		ret = -ENODEV;
308644570b8SJeff Kirsher 		goto err_out;
309644570b8SJeff Kirsher 	}
310644570b8SJeff Kirsher 
311644570b8SJeff Kirsher 	/* Do a preliminary verification that we have a 8390. */
312644570b8SJeff Kirsher 	{
313644570b8SJeff Kirsher 		int regd;
314644570b8SJeff Kirsher 		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
315644570b8SJeff Kirsher 		regd = inb_p(ioaddr + 0x0d);
316644570b8SJeff Kirsher 		outb_p(0xff, ioaddr + 0x0d);
317644570b8SJeff Kirsher 		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
318644570b8SJeff Kirsher 		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
319644570b8SJeff Kirsher 		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
320644570b8SJeff Kirsher 			outb_p(reg0, ioaddr);
321644570b8SJeff Kirsher 			outb_p(regd, ioaddr + 0x0d);	/* Restore the old values. */
322644570b8SJeff Kirsher 			ret = -ENODEV;
323644570b8SJeff Kirsher 			goto err_out;
324644570b8SJeff Kirsher 		}
325644570b8SJeff Kirsher 	}
326644570b8SJeff Kirsher 
327644570b8SJeff Kirsher 	if ((ne_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
328644570b8SJeff Kirsher 		netdev_info(dev, "%s%s", version1, version2);
329c45f812fSMatthew Whitehead 
330c45f812fSMatthew Whitehead 	netdev_info(dev, "NE*000 ethercard probe at %#3lx:", ioaddr);
331644570b8SJeff Kirsher 
332c45f812fSMatthew Whitehead 	/* A user with a poor card that fails to ack the reset, or that
333644570b8SJeff Kirsher 	   does not have a valid 0x57,0x57 signature can still use this
334644570b8SJeff Kirsher 	   without having to recompile. Specifying an i/o address along
335644570b8SJeff Kirsher 	   with an otherwise unused dev->mem_end value of "0xBAD" will
336644570b8SJeff Kirsher 	   cause the driver to skip these parts of the probe. */
337644570b8SJeff Kirsher 
338644570b8SJeff Kirsher 	bad_card = ((dev->base_addr != 0) && (dev->mem_end == BAD));
339644570b8SJeff Kirsher 
340644570b8SJeff Kirsher 	/* Reset card. Who knows what dain-bramaged state it was left in. */
341644570b8SJeff Kirsher 
342644570b8SJeff Kirsher 	{
343644570b8SJeff Kirsher 		unsigned long reset_start_time = jiffies;
344644570b8SJeff Kirsher 
345644570b8SJeff Kirsher 		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
346644570b8SJeff Kirsher 		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
347644570b8SJeff Kirsher 
348644570b8SJeff Kirsher 		while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
349644570b8SJeff Kirsher 		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
350644570b8SJeff Kirsher 			if (bad_card) {
351644570b8SJeff Kirsher 				pr_cont(" (warning: no reset ack)");
352644570b8SJeff Kirsher 				break;
353c45f812fSMatthew Whitehead 			} else {
354644570b8SJeff Kirsher 				pr_cont(" not found (no reset ack).\n");
355644570b8SJeff Kirsher 				ret = -ENODEV;
356c45f812fSMatthew Whitehead 				goto err_out;
357644570b8SJeff Kirsher 			}
358644570b8SJeff Kirsher 		}
359644570b8SJeff Kirsher 
360644570b8SJeff Kirsher 		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
361644570b8SJeff Kirsher 	}
362644570b8SJeff Kirsher 
363644570b8SJeff Kirsher 	/* Read the 16 bytes of station address PROM.
364644570b8SJeff Kirsher 	   We must first initialize registers, similar to NS8390p_init(eifdev, 0).
365644570b8SJeff Kirsher 	   We can't reliably read the SAPROM address without this.
366644570b8SJeff Kirsher 	   (I learned the hard way!). */
367644570b8SJeff Kirsher 	{
368644570b8SJeff Kirsher 		struct {unsigned char value, offset; } program_seq[] =
369644570b8SJeff Kirsher 		{
370644570b8SJeff Kirsher 			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
371644570b8SJeff Kirsher 			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
372644570b8SJeff Kirsher 			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
373644570b8SJeff Kirsher 			{0x00,	EN0_RCNTHI},
374644570b8SJeff Kirsher 			{0x00,	EN0_IMR},	/* Mask completion irq. */
375644570b8SJeff Kirsher 			{0xFF,	EN0_ISR},
376644570b8SJeff Kirsher 			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
377644570b8SJeff Kirsher 			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
378644570b8SJeff Kirsher 			{32,	EN0_RCNTLO},
379644570b8SJeff Kirsher 			{0x00,	EN0_RCNTHI},
380644570b8SJeff Kirsher 			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
381644570b8SJeff Kirsher 			{0x00,	EN0_RSARHI},
382644570b8SJeff Kirsher 			{E8390_RREAD+E8390_START, E8390_CMD},
383644570b8SJeff Kirsher 		};
384644570b8SJeff Kirsher 
385644570b8SJeff Kirsher 		for (i = 0; i < ARRAY_SIZE(program_seq); i++)
386644570b8SJeff Kirsher 			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
387644570b8SJeff Kirsher 
388644570b8SJeff Kirsher 	}
389644570b8SJeff Kirsher 	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
390644570b8SJeff Kirsher 		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
391644570b8SJeff Kirsher 		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
392644570b8SJeff Kirsher 		if (SA_prom[i] != SA_prom[i+1])
393644570b8SJeff Kirsher 			wordlength = 1;
394644570b8SJeff Kirsher 	}
395644570b8SJeff Kirsher 
396644570b8SJeff Kirsher 	if (wordlength == 2)
397644570b8SJeff Kirsher 	{
398644570b8SJeff Kirsher 		for (i = 0; i < 16; i++)
399644570b8SJeff Kirsher 			SA_prom[i] = SA_prom[i+i];
400644570b8SJeff Kirsher 		/* We must set the 8390 for word mode. */
401644570b8SJeff Kirsher 		outb_p(DCR_VAL, ioaddr + EN0_DCFG);
402644570b8SJeff Kirsher 		start_page = NESM_START_PG;
403644570b8SJeff Kirsher 
404644570b8SJeff Kirsher 		/*
405644570b8SJeff Kirsher 		 * Realtek RTL8019AS datasheet says that the PSTOP register
406644570b8SJeff Kirsher 		 * shouldn't exceed 0x60 in 8-bit mode.
407644570b8SJeff Kirsher 		 * This chip can be identified by reading the signature from
408644570b8SJeff Kirsher 		 * the  remote byte count registers (otherwise write-only)...
409644570b8SJeff Kirsher 		 */
410644570b8SJeff Kirsher 		if ((DCR_VAL & 0x01) == 0 &&		/* 8-bit mode */
411644570b8SJeff Kirsher 		    inb(ioaddr + EN0_RCNTLO) == 0x50 &&
412644570b8SJeff Kirsher 		    inb(ioaddr + EN0_RCNTHI) == 0x70)
413644570b8SJeff Kirsher 			stop_page = 0x60;
414644570b8SJeff Kirsher 		else
415644570b8SJeff Kirsher 			stop_page = NESM_STOP_PG;
416644570b8SJeff Kirsher 	} else {
417644570b8SJeff Kirsher 		start_page = NE1SM_START_PG;
418644570b8SJeff Kirsher 		stop_page  = NE1SM_STOP_PG;
419644570b8SJeff Kirsher 	}
420644570b8SJeff Kirsher 
421644570b8SJeff Kirsher 	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
422644570b8SJeff Kirsher 	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
423644570b8SJeff Kirsher 	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
424644570b8SJeff Kirsher 
425644570b8SJeff Kirsher 	/* Set up the rest of the parameters. */
426644570b8SJeff Kirsher 	if (neX000 || bad_card || copam) {
427644570b8SJeff Kirsher 		name = (wordlength == 2) ? "NE2000" : "NE1000";
428644570b8SJeff Kirsher 	}
429644570b8SJeff Kirsher 	else if (ctron)
430644570b8SJeff Kirsher 	{
431644570b8SJeff Kirsher 		name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
432644570b8SJeff Kirsher 		start_page = 0x01;
433644570b8SJeff Kirsher 		stop_page = (wordlength == 2) ? 0x40 : 0x20;
434644570b8SJeff Kirsher 	}
435644570b8SJeff Kirsher 	else
436644570b8SJeff Kirsher 	{
437644570b8SJeff Kirsher #ifdef SUPPORT_NE_BAD_CLONES
438644570b8SJeff Kirsher 		/* Ack!  Well, there might be a *bad* NE*000 clone there.
439644570b8SJeff Kirsher 		   Check for total bogus addresses. */
440644570b8SJeff Kirsher 		for (i = 0; bad_clone_list[i].name8; i++)
441644570b8SJeff Kirsher 		{
442644570b8SJeff Kirsher 			if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
443644570b8SJeff Kirsher 				SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
444644570b8SJeff Kirsher 				SA_prom[2] == bad_clone_list[i].SAprefix[2])
445644570b8SJeff Kirsher 			{
446644570b8SJeff Kirsher 				if (wordlength == 2)
447644570b8SJeff Kirsher 				{
448644570b8SJeff Kirsher 					name = bad_clone_list[i].name16;
449644570b8SJeff Kirsher 				} else {
450644570b8SJeff Kirsher 					name = bad_clone_list[i].name8;
451644570b8SJeff Kirsher 				}
452644570b8SJeff Kirsher 				break;
453644570b8SJeff Kirsher 			}
454644570b8SJeff Kirsher 		}
455644570b8SJeff Kirsher 		if (bad_clone_list[i].name8 == NULL)
456644570b8SJeff Kirsher 		{
457644570b8SJeff Kirsher 			pr_cont(" not found (invalid signature %2.2x %2.2x).\n",
458644570b8SJeff Kirsher 				SA_prom[14], SA_prom[15]);
459c45f812fSMatthew Whitehead 			ret = -ENXIO;
460644570b8SJeff Kirsher 			goto err_out;
461644570b8SJeff Kirsher 		}
462644570b8SJeff Kirsher #else
463644570b8SJeff Kirsher 		pr_cont(" not found.\n");
464644570b8SJeff Kirsher 		ret = -ENXIO;
465c45f812fSMatthew Whitehead 		goto err_out;
466644570b8SJeff Kirsher #endif
467644570b8SJeff Kirsher 	}
468644570b8SJeff Kirsher 
469644570b8SJeff Kirsher 	if (dev->irq < 2)
470644570b8SJeff Kirsher 	{
471644570b8SJeff Kirsher 		unsigned long cookie = probe_irq_on();
472644570b8SJeff Kirsher 		outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
473644570b8SJeff Kirsher 		outb_p(0x00, ioaddr + EN0_RCNTLO);
474644570b8SJeff Kirsher 		outb_p(0x00, ioaddr + EN0_RCNTHI);
475644570b8SJeff Kirsher 		outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
476644570b8SJeff Kirsher 		mdelay(10);		/* wait 10ms for interrupt to propagate */
477644570b8SJeff Kirsher 		outb_p(0x00, ioaddr + EN0_IMR); 		/* Mask it again. */
478644570b8SJeff Kirsher 		dev->irq = probe_irq_off(cookie);
479644570b8SJeff Kirsher 		if (ne_msg_enable & NETIF_MSG_PROBE)
480644570b8SJeff Kirsher 			pr_cont(" autoirq is %d", dev->irq);
481646fe03bSFinn Thain 	} else if (dev->irq == 2)
482c45f812fSMatthew Whitehead 		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
483644570b8SJeff Kirsher 		   or don't know which one to set. */
484644570b8SJeff Kirsher 		dev->irq = 9;
485644570b8SJeff Kirsher 
486644570b8SJeff Kirsher 	if (! dev->irq) {
487644570b8SJeff Kirsher 		pr_cont(" failed to detect IRQ line.\n");
488644570b8SJeff Kirsher 		ret = -EAGAIN;
489c45f812fSMatthew Whitehead 		goto err_out;
490644570b8SJeff Kirsher 	}
491644570b8SJeff Kirsher 
492644570b8SJeff Kirsher 	/* Snarf the interrupt now.  There's no point in waiting since we cannot
493644570b8SJeff Kirsher 	   share and the board will usually be enabled. */
494644570b8SJeff Kirsher 	ret = request_irq(dev->irq, eip_interrupt, 0, name, dev);
495644570b8SJeff Kirsher 	if (ret) {
496644570b8SJeff Kirsher 		pr_cont(" unable to get IRQ %d (errno=%d).\n", dev->irq, ret);
497644570b8SJeff Kirsher 		goto err_out;
498c45f812fSMatthew Whitehead 	}
499644570b8SJeff Kirsher 
500644570b8SJeff Kirsher 	dev->base_addr = ioaddr;
501644570b8SJeff Kirsher 
502644570b8SJeff Kirsher 	eth_hw_addr_set(dev, SA_prom);
503644570b8SJeff Kirsher 
5048ce218b6SJakub Kicinski 	pr_cont("%pM\n", dev->dev_addr);
505644570b8SJeff Kirsher 
506c45f812fSMatthew Whitehead 	ei_status.name = name;
507644570b8SJeff Kirsher 	ei_status.tx_start_page = start_page;
508644570b8SJeff Kirsher 	ei_status.stop_page = stop_page;
509644570b8SJeff Kirsher 
510644570b8SJeff Kirsher 	/* Use 16-bit mode only if this wasn't overridden by DCR_VAL */
511644570b8SJeff Kirsher 	ei_status.word16 = (wordlength == 2 && (DCR_VAL & 0x01));
512644570b8SJeff Kirsher 
513644570b8SJeff Kirsher 	ei_status.rx_start_page = start_page + TX_PAGES;
514644570b8SJeff Kirsher #ifdef PACKETBUF_MEMSIZE
515644570b8SJeff Kirsher 	 /* Allow the packet buffer size to be overridden by know-it-alls. */
516644570b8SJeff Kirsher 	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
517644570b8SJeff Kirsher #endif
518644570b8SJeff Kirsher 
519644570b8SJeff Kirsher 	ei_status.reset_8390 = &ne_reset_8390;
520644570b8SJeff Kirsher 	ei_status.block_input = &ne_block_input;
521644570b8SJeff Kirsher 	ei_status.block_output = &ne_block_output;
522644570b8SJeff Kirsher 	ei_status.get_8390_hdr = &ne_get_8390_hdr;
523644570b8SJeff Kirsher 	ei_status.priv = 0;
524644570b8SJeff Kirsher 
525644570b8SJeff Kirsher 	dev->netdev_ops = &eip_netdev_ops;
526644570b8SJeff Kirsher 	NS8390p_init(dev, 0);
527644570b8SJeff Kirsher 
528644570b8SJeff Kirsher 	ei_local->msg_enable = ne_msg_enable;
529644570b8SJeff Kirsher 	ret = register_netdev(dev);
530c45f812fSMatthew Whitehead 	if (ret)
531644570b8SJeff Kirsher 		goto out_irq;
532644570b8SJeff Kirsher 	netdev_info(dev, "%s found at %#lx, using IRQ %d.\n",
533644570b8SJeff Kirsher 		    name, ioaddr, dev->irq);
534c45f812fSMatthew Whitehead 	return 0;
535c45f812fSMatthew Whitehead 
536644570b8SJeff Kirsher out_irq:
537644570b8SJeff Kirsher 	free_irq(dev->irq, dev);
538644570b8SJeff Kirsher err_out:
539644570b8SJeff Kirsher 	release_region(ioaddr, NE_IO_EXTENT);
540644570b8SJeff Kirsher 	return ret;
541644570b8SJeff Kirsher }
542644570b8SJeff Kirsher 
543644570b8SJeff Kirsher /* Hard reset the card.  This used to pause for the same period that a
544644570b8SJeff Kirsher    8390 reset command required, but that shouldn't be necessary. */
545644570b8SJeff Kirsher 
ne_reset_8390(struct net_device * dev)546644570b8SJeff Kirsher static void ne_reset_8390(struct net_device *dev)
547644570b8SJeff Kirsher {
548644570b8SJeff Kirsher 	unsigned long reset_start_time = jiffies;
549644570b8SJeff Kirsher 	struct ei_device *ei_local = netdev_priv(dev);
550644570b8SJeff Kirsher 
551c45f812fSMatthew Whitehead 	netif_dbg(ei_local, hw, dev, "resetting the 8390 t=%ld...\n", jiffies);
552644570b8SJeff Kirsher 
553c45f812fSMatthew Whitehead 	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
554644570b8SJeff Kirsher 	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
555644570b8SJeff Kirsher 
556644570b8SJeff Kirsher 	ei_status.txing = 0;
557644570b8SJeff Kirsher 	ei_status.dmaing = 0;
558644570b8SJeff Kirsher 
559644570b8SJeff Kirsher 	/* This check _should_not_ be necessary, omit eventually. */
560644570b8SJeff Kirsher 	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
561644570b8SJeff Kirsher 		if (time_after(jiffies, reset_start_time + 2*HZ/100)) {
562644570b8SJeff Kirsher 			netdev_err(dev, "ne_reset_8390() did not complete.\n");
563644570b8SJeff Kirsher 			break;
564c45f812fSMatthew Whitehead 		}
565644570b8SJeff Kirsher 	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
566644570b8SJeff Kirsher }
567644570b8SJeff Kirsher 
568644570b8SJeff Kirsher /* Grab the 8390 specific header. Similar to the block_input routine, but
569644570b8SJeff Kirsher    we don't need to be concerned with ring wrap as the header will be at
570644570b8SJeff Kirsher    the start of a page, so we optimize accordingly. */
571644570b8SJeff Kirsher 
ne_get_8390_hdr(struct net_device * dev,struct e8390_pkt_hdr * hdr,int ring_page)572644570b8SJeff Kirsher static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
573644570b8SJeff Kirsher {
574644570b8SJeff Kirsher 	int nic_base = dev->base_addr;
575644570b8SJeff Kirsher 
576644570b8SJeff Kirsher 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
577644570b8SJeff Kirsher 
578644570b8SJeff Kirsher 	if (ei_status.dmaing)
579644570b8SJeff Kirsher 	{
580644570b8SJeff Kirsher 		netdev_err(dev, "DMAing conflict in ne_get_8390_hdr "
581644570b8SJeff Kirsher 			   "[DMAstat:%d][irqlock:%d].\n",
582c45f812fSMatthew Whitehead 			   ei_status.dmaing, ei_status.irqlock);
583644570b8SJeff Kirsher 		return;
584c45f812fSMatthew Whitehead 	}
585644570b8SJeff Kirsher 
586644570b8SJeff Kirsher 	ei_status.dmaing |= 0x01;
587644570b8SJeff Kirsher 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
588644570b8SJeff Kirsher 	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
589644570b8SJeff Kirsher 	outb_p(0, nic_base + EN0_RCNTHI);
590644570b8SJeff Kirsher 	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
591644570b8SJeff Kirsher 	outb_p(ring_page, nic_base + EN0_RSARHI);
592644570b8SJeff Kirsher 	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
593644570b8SJeff Kirsher 
594644570b8SJeff Kirsher 	if (ei_status.word16)
595644570b8SJeff Kirsher 		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
596644570b8SJeff Kirsher 	else
597644570b8SJeff Kirsher 		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
598644570b8SJeff Kirsher 
599644570b8SJeff Kirsher 	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
600644570b8SJeff Kirsher 	ei_status.dmaing &= ~0x01;
601644570b8SJeff Kirsher 
602644570b8SJeff Kirsher 	le16_to_cpus(&hdr->count);
603644570b8SJeff Kirsher }
604644570b8SJeff Kirsher 
605644570b8SJeff Kirsher /* Block input and output, similar to the Crynwr packet driver.  If you
606644570b8SJeff Kirsher    are porting to a new ethercard, look at the packet driver source for hints.
607644570b8SJeff Kirsher    The NEx000 doesn't share the on-board packet memory -- you have to put
608644570b8SJeff Kirsher    the packet out through the "remote DMA" dataport using outb. */
609644570b8SJeff Kirsher 
ne_block_input(struct net_device * dev,int count,struct sk_buff * skb,int ring_offset)610644570b8SJeff Kirsher static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
611644570b8SJeff Kirsher {
612644570b8SJeff Kirsher #ifdef NE_SANITY_CHECK
613644570b8SJeff Kirsher 	int xfer_count = count;
614644570b8SJeff Kirsher 	struct ei_device *ei_local = netdev_priv(dev);
615644570b8SJeff Kirsher #endif
616c45f812fSMatthew Whitehead 	int nic_base = dev->base_addr;
617644570b8SJeff Kirsher 	char *buf = skb->data;
618644570b8SJeff Kirsher 
619644570b8SJeff Kirsher 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
620644570b8SJeff Kirsher 	if (ei_status.dmaing)
621644570b8SJeff Kirsher 	{
622644570b8SJeff Kirsher 		netdev_err(dev, "DMAing conflict in ne_block_input "
623644570b8SJeff Kirsher 			   "[DMAstat:%d][irqlock:%d].\n",
624c45f812fSMatthew Whitehead 			   ei_status.dmaing, ei_status.irqlock);
625644570b8SJeff Kirsher 		return;
626c45f812fSMatthew Whitehead 	}
627644570b8SJeff Kirsher 	ei_status.dmaing |= 0x01;
628644570b8SJeff Kirsher 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
629644570b8SJeff Kirsher 	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
630644570b8SJeff Kirsher 	outb_p(count >> 8, nic_base + EN0_RCNTHI);
631644570b8SJeff Kirsher 	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
632644570b8SJeff Kirsher 	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
633644570b8SJeff Kirsher 	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
634644570b8SJeff Kirsher 	if (ei_status.word16)
635644570b8SJeff Kirsher 	{
636644570b8SJeff Kirsher 		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
637644570b8SJeff Kirsher 		if (count & 0x01)
638644570b8SJeff Kirsher 		{
639644570b8SJeff Kirsher 			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
640644570b8SJeff Kirsher #ifdef NE_SANITY_CHECK
641644570b8SJeff Kirsher 			xfer_count++;
642644570b8SJeff Kirsher #endif
643644570b8SJeff Kirsher 		}
644644570b8SJeff Kirsher 	} else {
645644570b8SJeff Kirsher 		insb(NE_BASE + NE_DATAPORT, buf, count);
646644570b8SJeff Kirsher 	}
647644570b8SJeff Kirsher 
648644570b8SJeff Kirsher #ifdef NE_SANITY_CHECK
649644570b8SJeff Kirsher 	/* This was for the ALPHA version only, but enough people have
650644570b8SJeff Kirsher 	   been encountering problems so it is still here.  If you see
651644570b8SJeff Kirsher 	   this message you either 1) have a slightly incompatible clone
652644570b8SJeff Kirsher 	   or 2) have noise/speed problems with your bus. */
653644570b8SJeff Kirsher 
654644570b8SJeff Kirsher 	if (netif_msg_rx_status(ei_local))
655644570b8SJeff Kirsher 	{
656c45f812fSMatthew Whitehead 		/* DMA termination address check... */
657644570b8SJeff Kirsher 		int addr, tries = 20;
658644570b8SJeff Kirsher 		do {
659644570b8SJeff Kirsher 			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
660644570b8SJeff Kirsher 			   -- it's broken for Rx on some cards! */
661644570b8SJeff Kirsher 			int high = inb_p(nic_base + EN0_RSARHI);
662644570b8SJeff Kirsher 			int low = inb_p(nic_base + EN0_RSARLO);
663644570b8SJeff Kirsher 			addr = (high << 8) + low;
664644570b8SJeff Kirsher 			if (((ring_offset + xfer_count) & 0xff) == low)
665644570b8SJeff Kirsher 				break;
666644570b8SJeff Kirsher 		} while (--tries > 0);
667644570b8SJeff Kirsher 	 	if (tries <= 0)
668644570b8SJeff Kirsher 			netdev_warn(dev, "RX transfer address mismatch,"
669644570b8SJeff Kirsher 				    "%#4.4x (expected) vs. %#4.4x (actual).\n",
670c45f812fSMatthew Whitehead 				    ring_offset + xfer_count, addr);
671644570b8SJeff Kirsher 	}
672c45f812fSMatthew Whitehead #endif
673644570b8SJeff Kirsher 	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
674644570b8SJeff Kirsher 	ei_status.dmaing &= ~0x01;
675644570b8SJeff Kirsher }
676644570b8SJeff Kirsher 
ne_block_output(struct net_device * dev,int count,const unsigned char * buf,const int start_page)677644570b8SJeff Kirsher static void ne_block_output(struct net_device *dev, int count,
678644570b8SJeff Kirsher 		const unsigned char *buf, const int start_page)
679644570b8SJeff Kirsher {
680644570b8SJeff Kirsher 	int nic_base = NE_BASE;
681644570b8SJeff Kirsher 	unsigned long dma_start;
682644570b8SJeff Kirsher #ifdef NE_SANITY_CHECK
683644570b8SJeff Kirsher 	int retries = 0;
684644570b8SJeff Kirsher 	struct ei_device *ei_local = netdev_priv(dev);
685644570b8SJeff Kirsher #endif
686c45f812fSMatthew Whitehead 
687644570b8SJeff Kirsher 	/* Round the count up for word writes.  Do we need to do this?
688644570b8SJeff Kirsher 	   What effect will an odd byte count have on the 8390?
689644570b8SJeff Kirsher 	   I should check someday. */
690644570b8SJeff Kirsher 
691644570b8SJeff Kirsher 	if (ei_status.word16 && (count & 0x01))
692644570b8SJeff Kirsher 		count++;
693644570b8SJeff Kirsher 
694644570b8SJeff Kirsher 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
695644570b8SJeff Kirsher 	if (ei_status.dmaing)
696644570b8SJeff Kirsher 	{
697644570b8SJeff Kirsher 		netdev_err(dev, "DMAing conflict in ne_block_output."
698644570b8SJeff Kirsher 			   "[DMAstat:%d][irqlock:%d]\n",
699c45f812fSMatthew Whitehead 			   ei_status.dmaing, ei_status.irqlock);
700644570b8SJeff Kirsher 		return;
701c45f812fSMatthew Whitehead 	}
702644570b8SJeff Kirsher 	ei_status.dmaing |= 0x01;
703644570b8SJeff Kirsher 	/* We should already be in page 0, but to be safe... */
704644570b8SJeff Kirsher 	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
705644570b8SJeff Kirsher 
706644570b8SJeff Kirsher #ifdef NE_SANITY_CHECK
707644570b8SJeff Kirsher retry:
708644570b8SJeff Kirsher #endif
709644570b8SJeff Kirsher 
710644570b8SJeff Kirsher #ifdef NE_RW_BUGFIX
711644570b8SJeff Kirsher 	/* Handle the read-before-write bug the same way as the
712c24672cfSArmin Wolf 	   Crynwr packet driver -- the NatSemi method doesn't work.
713644570b8SJeff Kirsher 	   Actually this doesn't always work either, but if you have
714644570b8SJeff Kirsher 	   problems with your NEx000 this is better than nothing! */
715644570b8SJeff Kirsher 
716644570b8SJeff Kirsher 	outb_p(0x42, nic_base + EN0_RCNTLO);
717644570b8SJeff Kirsher 	outb_p(0x00,   nic_base + EN0_RCNTHI);
718644570b8SJeff Kirsher 	outb_p(0x42, nic_base + EN0_RSARLO);
719644570b8SJeff Kirsher 	outb_p(0x00, nic_base + EN0_RSARHI);
720644570b8SJeff Kirsher 	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
721644570b8SJeff Kirsher 	/* Make certain that the dummy read has occurred. */
722644570b8SJeff Kirsher 	udelay(6);
723644570b8SJeff Kirsher #endif
724644570b8SJeff Kirsher 
725644570b8SJeff Kirsher 	outb_p(ENISR_RDC, nic_base + EN0_ISR);
726644570b8SJeff Kirsher 
727644570b8SJeff Kirsher 	/* Now the normal output. */
728644570b8SJeff Kirsher 	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
729644570b8SJeff Kirsher 	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
730644570b8SJeff Kirsher 	outb_p(0x00, nic_base + EN0_RSARLO);
731644570b8SJeff Kirsher 	outb_p(start_page, nic_base + EN0_RSARHI);
732644570b8SJeff Kirsher 
733644570b8SJeff Kirsher 	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
734644570b8SJeff Kirsher 	if (ei_status.word16) {
735644570b8SJeff Kirsher 		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
736644570b8SJeff Kirsher 	} else {
737644570b8SJeff Kirsher 		outsb(NE_BASE + NE_DATAPORT, buf, count);
738644570b8SJeff Kirsher 	}
739644570b8SJeff Kirsher 
740644570b8SJeff Kirsher 	dma_start = jiffies;
741644570b8SJeff Kirsher 
742644570b8SJeff Kirsher #ifdef NE_SANITY_CHECK
743644570b8SJeff Kirsher 	/* This was for the ALPHA version only, but enough people have
744644570b8SJeff Kirsher 	   been encountering problems so it is still here. */
745644570b8SJeff Kirsher 
746644570b8SJeff Kirsher 	if (netif_msg_tx_queued(ei_local))
747644570b8SJeff Kirsher 	{
748c45f812fSMatthew Whitehead 		/* DMA termination address check... */
749644570b8SJeff Kirsher 		int addr, tries = 20;
750644570b8SJeff Kirsher 		do {
751644570b8SJeff Kirsher 			int high = inb_p(nic_base + EN0_RSARHI);
752644570b8SJeff Kirsher 			int low = inb_p(nic_base + EN0_RSARLO);
753644570b8SJeff Kirsher 			addr = (high << 8) + low;
754644570b8SJeff Kirsher 			if ((start_page << 8) + count == addr)
755644570b8SJeff Kirsher 				break;
756644570b8SJeff Kirsher 		} while (--tries > 0);
757644570b8SJeff Kirsher 
758644570b8SJeff Kirsher 		if (tries <= 0)
759644570b8SJeff Kirsher 		{
760644570b8SJeff Kirsher 			netdev_warn(dev, "Tx packet transfer address mismatch,"
761644570b8SJeff Kirsher 				    "%#4.4x (expected) vs. %#4.4x (actual).\n",
762c45f812fSMatthew Whitehead 				    (start_page << 8) + count, addr);
763644570b8SJeff Kirsher 			if (retries++ == 0)
764c45f812fSMatthew Whitehead 				goto retry;
765644570b8SJeff Kirsher 		}
766644570b8SJeff Kirsher 	}
767644570b8SJeff Kirsher #endif
768644570b8SJeff Kirsher 
769644570b8SJeff Kirsher 	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
770644570b8SJeff Kirsher 		if (time_after(jiffies, dma_start + 2*HZ/100)) {		/* 20ms */
771644570b8SJeff Kirsher 			netdev_warn(dev, "timeout waiting for Tx RDC.\n");
772644570b8SJeff Kirsher 			ne_reset_8390(dev);
773c45f812fSMatthew Whitehead 			NS8390p_init(dev, 1);
774644570b8SJeff Kirsher 			break;
775644570b8SJeff Kirsher 		}
776644570b8SJeff Kirsher 
777644570b8SJeff Kirsher 	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
778644570b8SJeff Kirsher 	ei_status.dmaing &= ~0x01;
779644570b8SJeff Kirsher }
780644570b8SJeff Kirsher 
ne_drv_probe(struct platform_device * pdev)781644570b8SJeff Kirsher static int __init ne_drv_probe(struct platform_device *pdev)
782644570b8SJeff Kirsher {
783644570b8SJeff Kirsher 	struct net_device *dev;
784644570b8SJeff Kirsher 	int err, this_dev = pdev->id;
785644570b8SJeff Kirsher 	struct resource *res;
786644570b8SJeff Kirsher 
787644570b8SJeff Kirsher 	dev = alloc_eip_netdev();
788644570b8SJeff Kirsher 	if (!dev)
789644570b8SJeff Kirsher 		return -ENOMEM;
790644570b8SJeff Kirsher 
791644570b8SJeff Kirsher 	/* ne.c doesn't populate resources in platform_device, but
792644570b8SJeff Kirsher 	 * rbtx4927_ne_init and rbtx4938_ne_init do register devices
793644570b8SJeff Kirsher 	 * with resources.
794644570b8SJeff Kirsher 	 */
795644570b8SJeff Kirsher 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
796644570b8SJeff Kirsher 	if (res) {
797644570b8SJeff Kirsher 		dev->base_addr = res->start;
798644570b8SJeff Kirsher 		dev->irq = platform_get_irq(pdev, 0);
799644570b8SJeff Kirsher 	} else {
800644570b8SJeff Kirsher 		if (this_dev < 0 || this_dev >= MAX_NE_CARDS) {
801644570b8SJeff Kirsher 			free_netdev(dev);
802644570b8SJeff Kirsher 			return -EINVAL;
803644570b8SJeff Kirsher 		}
804644570b8SJeff Kirsher 		dev->base_addr = io[this_dev];
805644570b8SJeff Kirsher 		dev->irq = irq[this_dev];
806644570b8SJeff Kirsher 		dev->mem_end = bad[this_dev];
807644570b8SJeff Kirsher 	}
808644570b8SJeff Kirsher 	SET_NETDEV_DEV(dev, &pdev->dev);
809644570b8SJeff Kirsher 	err = do_ne_probe(dev);
810da9da01dSAlan Cox 	if (err) {
811644570b8SJeff Kirsher 		free_netdev(dev);
812644570b8SJeff Kirsher 		return err;
813644570b8SJeff Kirsher 	}
814644570b8SJeff Kirsher 	platform_set_drvdata(pdev, dev);
815644570b8SJeff Kirsher 
816644570b8SJeff Kirsher 	/* Update with any values found by probing, don't update if
817644570b8SJeff Kirsher 	 * resources were specified.
818644570b8SJeff Kirsher 	 */
819644570b8SJeff Kirsher 	if (!res) {
820644570b8SJeff Kirsher 		io[this_dev] = dev->base_addr;
821644570b8SJeff Kirsher 		irq[this_dev] = dev->irq;
822644570b8SJeff Kirsher 	}
823644570b8SJeff Kirsher 	return 0;
824644570b8SJeff Kirsher }
825644570b8SJeff Kirsher 
ne_drv_remove(struct platform_device * pdev)826644570b8SJeff Kirsher static int ne_drv_remove(struct platform_device *pdev)
827644570b8SJeff Kirsher {
828644570b8SJeff Kirsher 	struct net_device *dev = platform_get_drvdata(pdev);
829644570b8SJeff Kirsher 
830644570b8SJeff Kirsher 	if (dev) {
831644570b8SJeff Kirsher 		struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
832644570b8SJeff Kirsher 		netif_device_detach(dev);
833644570b8SJeff Kirsher 		unregister_netdev(dev);
834644570b8SJeff Kirsher 		if (idev)
835644570b8SJeff Kirsher 			pnp_device_detach(idev);
836644570b8SJeff Kirsher 		/* Careful ne_drv_remove can be called twice, once from
837644570b8SJeff Kirsher 		 * the platform_driver.remove and again when the
838644570b8SJeff Kirsher 		 * platform_device is being removed.
839644570b8SJeff Kirsher 		 */
840644570b8SJeff Kirsher 		ei_status.priv = 0;
841644570b8SJeff Kirsher 		free_irq(dev->irq, dev);
842644570b8SJeff Kirsher 		release_region(dev->base_addr, NE_IO_EXTENT);
843644570b8SJeff Kirsher 		free_netdev(dev);
844644570b8SJeff Kirsher 	}
845644570b8SJeff Kirsher 	return 0;
846644570b8SJeff Kirsher }
847644570b8SJeff Kirsher 
848644570b8SJeff Kirsher /* Remove unused devices or all if true. */
ne_loop_rm_unreg(int all)849644570b8SJeff Kirsher static void ne_loop_rm_unreg(int all)
850644570b8SJeff Kirsher {
851644570b8SJeff Kirsher 	int this_dev;
852644570b8SJeff Kirsher 	struct platform_device *pdev;
853644570b8SJeff Kirsher 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
854644570b8SJeff Kirsher 		pdev = pdev_ne[this_dev];
855644570b8SJeff Kirsher 		/* No network device == unused */
856644570b8SJeff Kirsher 		if (pdev && (!platform_get_drvdata(pdev) || all)) {
857644570b8SJeff Kirsher 			ne_drv_remove(pdev);
858644570b8SJeff Kirsher 			platform_device_unregister(pdev);
859644570b8SJeff Kirsher 			pdev_ne[this_dev] = NULL;
860644570b8SJeff Kirsher 		}
861644570b8SJeff Kirsher 	}
862644570b8SJeff Kirsher }
863644570b8SJeff Kirsher 
864644570b8SJeff Kirsher #ifdef CONFIG_PM
ne_drv_suspend(struct platform_device * pdev,pm_message_t state)865644570b8SJeff Kirsher static int ne_drv_suspend(struct platform_device *pdev, pm_message_t state)
866644570b8SJeff Kirsher {
867644570b8SJeff Kirsher 	struct net_device *dev = platform_get_drvdata(pdev);
868644570b8SJeff Kirsher 
869644570b8SJeff Kirsher 	if (netif_running(dev)) {
870644570b8SJeff Kirsher 		struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
871644570b8SJeff Kirsher 		netif_device_detach(dev);
872644570b8SJeff Kirsher 		if (idev)
873644570b8SJeff Kirsher 			pnp_stop_dev(idev);
874644570b8SJeff Kirsher 	}
875644570b8SJeff Kirsher 	return 0;
876644570b8SJeff Kirsher }
877644570b8SJeff Kirsher 
ne_drv_resume(struct platform_device * pdev)878644570b8SJeff Kirsher static int ne_drv_resume(struct platform_device *pdev)
879644570b8SJeff Kirsher {
880644570b8SJeff Kirsher 	struct net_device *dev = platform_get_drvdata(pdev);
881644570b8SJeff Kirsher 
882644570b8SJeff Kirsher 	if (netif_running(dev)) {
883644570b8SJeff Kirsher 		struct pnp_dev *idev = (struct pnp_dev *)ei_status.priv;
884644570b8SJeff Kirsher 		if (idev)
885644570b8SJeff Kirsher 			pnp_start_dev(idev);
886644570b8SJeff Kirsher 		ne_reset_8390(dev);
887644570b8SJeff Kirsher 		NS8390p_init(dev, 1);
888644570b8SJeff Kirsher 		netif_device_attach(dev);
889644570b8SJeff Kirsher 	}
890644570b8SJeff Kirsher 	return 0;
891644570b8SJeff Kirsher }
892644570b8SJeff Kirsher #else
893644570b8SJeff Kirsher #define ne_drv_suspend NULL
894644570b8SJeff Kirsher #define ne_drv_resume NULL
895644570b8SJeff Kirsher #endif
896644570b8SJeff Kirsher 
897644570b8SJeff Kirsher static struct platform_driver ne_driver = {
898644570b8SJeff Kirsher 	.remove		= ne_drv_remove,
899644570b8SJeff Kirsher 	.suspend	= ne_drv_suspend,
900644570b8SJeff Kirsher 	.resume		= ne_drv_resume,
901644570b8SJeff Kirsher 	.driver		= {
902644570b8SJeff Kirsher 		.name	= DRV_NAME,
903644570b8SJeff Kirsher 	},
904644570b8SJeff Kirsher };
905644570b8SJeff Kirsher 
ne_add_devices(void)906644570b8SJeff Kirsher static void __init ne_add_devices(void)
907644570b8SJeff Kirsher {
908644570b8SJeff Kirsher 	int this_dev;
909644570b8SJeff Kirsher 	struct platform_device *pdev;
910644570b8SJeff Kirsher 
911644570b8SJeff Kirsher 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
912644570b8SJeff Kirsher 		if (pdev_ne[this_dev])
913644570b8SJeff Kirsher 			continue;
914644570b8SJeff Kirsher 		pdev = platform_device_register_simple(
915644570b8SJeff Kirsher 			DRV_NAME, this_dev, NULL, 0);
916644570b8SJeff Kirsher 		if (IS_ERR(pdev))
917644570b8SJeff Kirsher 			continue;
918644570b8SJeff Kirsher 		pdev_ne[this_dev] = pdev;
919644570b8SJeff Kirsher 	}
920644570b8SJeff Kirsher }
921644570b8SJeff Kirsher 
ne_init(void)922644570b8SJeff Kirsher static int __init ne_init(void)
923644570b8SJeff Kirsher {
924a07d8ecfSArnd Bergmann 	int retval;
925644570b8SJeff Kirsher 
926644570b8SJeff Kirsher 	if (IS_MODULE(CONFIG_NE2000))
927d7e203ffSArnd Bergmann 		ne_add_devices();
928d7e203ffSArnd Bergmann 
929644570b8SJeff Kirsher 	retval = platform_driver_probe(&ne_driver, ne_drv_probe);
930d7e203ffSArnd Bergmann 
931644570b8SJeff Kirsher 	if (IS_MODULE(CONFIG_NE2000) && retval) {
932d7e203ffSArnd Bergmann 		if (io[0] == 0)
933d7e203ffSArnd Bergmann 			pr_notice("ne.c: You must supply \"io=0xNNN\""
934644570b8SJeff Kirsher 			       " value(s) for ISA cards.\n");
935c45f812fSMatthew Whitehead 		ne_loop_rm_unreg(1);
936644570b8SJeff Kirsher 		return retval;
937644570b8SJeff Kirsher 	}
938644570b8SJeff Kirsher 
939644570b8SJeff Kirsher 	/* Unregister unused platform_devices. */
940644570b8SJeff Kirsher 	ne_loop_rm_unreg(0);
941644570b8SJeff Kirsher 	return retval;
942644570b8SJeff Kirsher }
943644570b8SJeff Kirsher module_init(ne_init);
944644570b8SJeff Kirsher 
945a07d8ecfSArnd Bergmann #if !defined(MODULE) && defined(CONFIG_NETDEV_LEGACY_INIT)
ne_probe(int unit)946644570b8SJeff Kirsher struct net_device * __init ne_probe(int unit)
947d7e203ffSArnd Bergmann {
948644570b8SJeff Kirsher 	int this_dev;
949644570b8SJeff Kirsher 	struct net_device *dev;
950644570b8SJeff Kirsher 
951644570b8SJeff Kirsher 	/* Find an empty slot, that is no net_device and zero io port. */
952644570b8SJeff Kirsher 	this_dev = 0;
953644570b8SJeff Kirsher 	while ((pdev_ne[this_dev] && platform_get_drvdata(pdev_ne[this_dev])) ||
954644570b8SJeff Kirsher 		io[this_dev]) {
955644570b8SJeff Kirsher 		if (++this_dev == MAX_NE_CARDS)
956644570b8SJeff Kirsher 			return ERR_PTR(-ENOMEM);
957644570b8SJeff Kirsher 	}
958644570b8SJeff Kirsher 
959644570b8SJeff Kirsher 	/* Get irq, io from kernel command line */
960644570b8SJeff Kirsher 	dev = alloc_eip_netdev();
961644570b8SJeff Kirsher 	if (!dev)
962644570b8SJeff Kirsher 		return ERR_PTR(-ENOMEM);
963644570b8SJeff Kirsher 
964644570b8SJeff Kirsher 	sprintf(dev->name, "eth%d", unit);
965644570b8SJeff Kirsher 	netdev_boot_setup_check(dev);
966644570b8SJeff Kirsher 
967644570b8SJeff Kirsher 	io[this_dev] = dev->base_addr;
968644570b8SJeff Kirsher 	irq[this_dev] = dev->irq;
969644570b8SJeff Kirsher 	bad[this_dev] = dev->mem_end;
970644570b8SJeff Kirsher 
971644570b8SJeff Kirsher 	free_netdev(dev);
972644570b8SJeff Kirsher 
973644570b8SJeff Kirsher 	ne_add_devices();
974644570b8SJeff Kirsher 
975644570b8SJeff Kirsher 	/* return the first device found */
976644570b8SJeff Kirsher 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
977644570b8SJeff Kirsher 		if (pdev_ne[this_dev]) {
978644570b8SJeff Kirsher 			dev = platform_get_drvdata(pdev_ne[this_dev]);
979644570b8SJeff Kirsher 			if (dev)
980644570b8SJeff Kirsher 				return dev;
981644570b8SJeff Kirsher 		}
982644570b8SJeff Kirsher 	}
983644570b8SJeff Kirsher 
984644570b8SJeff Kirsher 	return ERR_PTR(-ENODEV);
985644570b8SJeff Kirsher }
986644570b8SJeff Kirsher #endif
987644570b8SJeff Kirsher 
ne_exit(void)9884228c394SArnd Bergmann static void __exit ne_exit(void)
989644570b8SJeff Kirsher {
990644570b8SJeff Kirsher 	platform_driver_unregister(&ne_driver);
991644570b8SJeff Kirsher 	ne_loop_rm_unreg(1);
992644570b8SJeff Kirsher }
993644570b8SJeff Kirsher module_exit(ne_exit);
994644570b8SJeff Kirsher