1ca7a8e85SJeff Kirsher /* 3c509.c: A 3c509 EtherLink3 ethernet driver for linux. */
2ca7a8e85SJeff Kirsher /*
3ca7a8e85SJeff Kirsher Written 1993-2000 by Donald Becker.
4ca7a8e85SJeff Kirsher
5ca7a8e85SJeff Kirsher Copyright 1994-2000 by Donald Becker.
6ca7a8e85SJeff Kirsher Copyright 1993 United States Government as represented by the
7ca7a8e85SJeff Kirsher Director, National Security Agency. This software may be used and
8ca7a8e85SJeff Kirsher distributed according to the terms of the GNU General Public License,
9ca7a8e85SJeff Kirsher incorporated herein by reference.
10ca7a8e85SJeff Kirsher
11ca7a8e85SJeff Kirsher This driver is for the 3Com EtherLinkIII series.
12ca7a8e85SJeff Kirsher
13ca7a8e85SJeff Kirsher The author may be reached as becker@scyld.com, or C/O
14ca7a8e85SJeff Kirsher Scyld Computing Corporation
15ca7a8e85SJeff Kirsher 410 Severn Ave., Suite 210
16ca7a8e85SJeff Kirsher Annapolis MD 21403
17ca7a8e85SJeff Kirsher
18ca7a8e85SJeff Kirsher Known limitations:
19ca7a8e85SJeff Kirsher Because of the way 3c509 ISA detection works it's difficult to predict
20ca7a8e85SJeff Kirsher a priori which of several ISA-mode cards will be detected first.
21ca7a8e85SJeff Kirsher
22ca7a8e85SJeff Kirsher This driver does not use predictive interrupt mode, resulting in higher
23ca7a8e85SJeff Kirsher packet latency but lower overhead. If interrupts are disabled for an
24ca7a8e85SJeff Kirsher unusually long time it could also result in missed packets, but in
25ca7a8e85SJeff Kirsher practice this rarely happens.
26ca7a8e85SJeff Kirsher
27ca7a8e85SJeff Kirsher
28ca7a8e85SJeff Kirsher FIXES:
29ca7a8e85SJeff Kirsher Alan Cox: Removed the 'Unexpected interrupt' bug.
30ca7a8e85SJeff Kirsher Michael Meskes: Upgraded to Donald Becker's version 1.07.
31ca7a8e85SJeff Kirsher Alan Cox: Increased the eeprom delay. Regardless of
32ca7a8e85SJeff Kirsher what the docs say some people definitely
33ca7a8e85SJeff Kirsher get problems with lower (but in card spec)
34ca7a8e85SJeff Kirsher delays
35ca7a8e85SJeff Kirsher v1.10 4/21/97 Fixed module code so that multiple cards may be detected,
36ca7a8e85SJeff Kirsher other cleanups. -djb
37ca7a8e85SJeff Kirsher Andrea Arcangeli: Upgraded to Donald Becker's version 1.12.
38ca7a8e85SJeff Kirsher Rick Payne: Fixed SMP race condition
39ca7a8e85SJeff Kirsher v1.13 9/8/97 Made 'max_interrupt_work' an insmod-settable variable -djb
40ca7a8e85SJeff Kirsher v1.14 10/15/97 Avoided waiting..discard message for fast machines -djb
41ca7a8e85SJeff Kirsher v1.15 1/31/98 Faster recovery for Tx errors. -djb
42ca7a8e85SJeff Kirsher v1.16 2/3/98 Different ID port handling to avoid sound cards. -djb
43ca7a8e85SJeff Kirsher v1.18 12Mar2001 Andrew Morton
44ca7a8e85SJeff Kirsher - Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
45ca7a8e85SJeff Kirsher - Reviewed against 1.18 from scyld.com
46ca7a8e85SJeff Kirsher v1.18a 17Nov2001 Jeff Garzik <jgarzik@pobox.com>
47ca7a8e85SJeff Kirsher - ethtool support
48ca7a8e85SJeff Kirsher v1.18b 1Mar2002 Zwane Mwaikambo <zwane@commfireservices.com>
49ca7a8e85SJeff Kirsher - Power Management support
50ca7a8e85SJeff Kirsher v1.18c 1Mar2002 David Ruggiero <jdr@farfalle.com>
51ca7a8e85SJeff Kirsher - Full duplex support
52ca7a8e85SJeff Kirsher v1.19 16Oct2002 Zwane Mwaikambo <zwane@linuxpower.ca>
53ca7a8e85SJeff Kirsher - Additional ethtool features
54ca7a8e85SJeff Kirsher v1.19a 28Oct2002 Davud Ruggiero <jdr@farfalle.com>
55ca7a8e85SJeff Kirsher - Increase *read_eeprom udelay to workaround oops with 2 cards.
56ca7a8e85SJeff Kirsher v1.19b 08Nov2002 Marc Zyngier <maz@wild-wind.fr.eu.org>
57ca7a8e85SJeff Kirsher - Introduce driver model for EISA cards.
58ca7a8e85SJeff Kirsher v1.20 04Feb2008 Ondrej Zary <linux@rainbow-software.org>
59ca7a8e85SJeff Kirsher - convert to isa_driver and pnp_driver and some cleanups
60ca7a8e85SJeff Kirsher */
61ca7a8e85SJeff Kirsher
62ca7a8e85SJeff Kirsher #define DRV_NAME "3c509"
63ca7a8e85SJeff Kirsher
64ca7a8e85SJeff Kirsher /* A few values that may be tweaked. */
65ca7a8e85SJeff Kirsher
66ca7a8e85SJeff Kirsher /* Time in jiffies before concluding the transmitter is hung. */
67ca7a8e85SJeff Kirsher #define TX_TIMEOUT (400*HZ/1000)
68ca7a8e85SJeff Kirsher
69ca7a8e85SJeff Kirsher #include <linux/module.h>
70ca7a8e85SJeff Kirsher #include <linux/isa.h>
71ca7a8e85SJeff Kirsher #include <linux/pnp.h>
72ca7a8e85SJeff Kirsher #include <linux/string.h>
73ca7a8e85SJeff Kirsher #include <linux/interrupt.h>
74ca7a8e85SJeff Kirsher #include <linux/errno.h>
75ca7a8e85SJeff Kirsher #include <linux/in.h>
76ca7a8e85SJeff Kirsher #include <linux/ioport.h>
77ca7a8e85SJeff Kirsher #include <linux/init.h>
78ca7a8e85SJeff Kirsher #include <linux/netdevice.h>
79ca7a8e85SJeff Kirsher #include <linux/etherdevice.h>
80ca7a8e85SJeff Kirsher #include <linux/pm.h>
81ca7a8e85SJeff Kirsher #include <linux/skbuff.h>
82ca7a8e85SJeff Kirsher #include <linux/delay.h> /* for udelay() */
83ca7a8e85SJeff Kirsher #include <linux/spinlock.h>
84ca7a8e85SJeff Kirsher #include <linux/ethtool.h>
85ca7a8e85SJeff Kirsher #include <linux/device.h>
86ca7a8e85SJeff Kirsher #include <linux/eisa.h>
87ca7a8e85SJeff Kirsher #include <linux/bitops.h>
88ca7a8e85SJeff Kirsher
897c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
90ca7a8e85SJeff Kirsher #include <asm/io.h>
91ca7a8e85SJeff Kirsher #include <asm/irq.h>
92ca7a8e85SJeff Kirsher
93ca7a8e85SJeff Kirsher #ifdef EL3_DEBUG
94ca7a8e85SJeff Kirsher static int el3_debug = EL3_DEBUG;
95ca7a8e85SJeff Kirsher #else
96ca7a8e85SJeff Kirsher static int el3_debug = 2;
97ca7a8e85SJeff Kirsher #endif
98ca7a8e85SJeff Kirsher
99ca7a8e85SJeff Kirsher /* Used to do a global count of all the cards in the system. Must be
100a5e371f6SPaul Gortmaker * a global variable so that the eisa probe routines can increment
101ca7a8e85SJeff Kirsher * it */
102ca7a8e85SJeff Kirsher static int el3_cards = 0;
103ca7a8e85SJeff Kirsher #define EL3_MAX_CARDS 8
104ca7a8e85SJeff Kirsher
105ca7a8e85SJeff Kirsher /* To minimize the size of the driver source I only define operating
106ca7a8e85SJeff Kirsher constants if they are used several times. You'll need the manual
107ca7a8e85SJeff Kirsher anyway if you want to understand driver details. */
108ca7a8e85SJeff Kirsher /* Offsets from base I/O address. */
109ca7a8e85SJeff Kirsher #define EL3_DATA 0x00
110ca7a8e85SJeff Kirsher #define EL3_CMD 0x0e
111ca7a8e85SJeff Kirsher #define EL3_STATUS 0x0e
112ca7a8e85SJeff Kirsher #define EEPROM_READ 0x80
113ca7a8e85SJeff Kirsher
114ca7a8e85SJeff Kirsher #define EL3_IO_EXTENT 16
115ca7a8e85SJeff Kirsher
116ca7a8e85SJeff Kirsher #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
117ca7a8e85SJeff Kirsher
118ca7a8e85SJeff Kirsher
119ca7a8e85SJeff Kirsher /* The top five bits written to EL3_CMD are a command, the lower
120ca7a8e85SJeff Kirsher 11 bits are the parameter, if applicable. */
121ca7a8e85SJeff Kirsher enum c509cmd {
122ca7a8e85SJeff Kirsher TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
123ca7a8e85SJeff Kirsher RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
124ca7a8e85SJeff Kirsher TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
125ca7a8e85SJeff Kirsher FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
126ca7a8e85SJeff Kirsher SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
127ca7a8e85SJeff Kirsher SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
128ca7a8e85SJeff Kirsher StatsDisable = 22<<11, StopCoax = 23<<11, PowerUp = 27<<11,
129ca7a8e85SJeff Kirsher PowerDown = 28<<11, PowerAuto = 29<<11};
130ca7a8e85SJeff Kirsher
131ca7a8e85SJeff Kirsher enum c509status {
132ca7a8e85SJeff Kirsher IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
133ca7a8e85SJeff Kirsher TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
134ca7a8e85SJeff Kirsher IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000, };
135ca7a8e85SJeff Kirsher
136ca7a8e85SJeff Kirsher /* The SetRxFilter command accepts the following classes: */
137ca7a8e85SJeff Kirsher enum RxFilter {
138ca7a8e85SJeff Kirsher RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8 };
139ca7a8e85SJeff Kirsher
140ca7a8e85SJeff Kirsher /* Register window 1 offsets, the window used in normal operation. */
141ca7a8e85SJeff Kirsher #define TX_FIFO 0x00
142ca7a8e85SJeff Kirsher #define RX_FIFO 0x00
143ca7a8e85SJeff Kirsher #define RX_STATUS 0x08
144ca7a8e85SJeff Kirsher #define TX_STATUS 0x0B
145ca7a8e85SJeff Kirsher #define TX_FREE 0x0C /* Remaining free bytes in Tx buffer. */
146ca7a8e85SJeff Kirsher
147ca7a8e85SJeff Kirsher #define WN0_CONF_CTRL 0x04 /* Window 0: Configuration control register */
148ca7a8e85SJeff Kirsher #define WN0_ADDR_CONF 0x06 /* Window 0: Address configuration register */
149ca7a8e85SJeff Kirsher #define WN0_IRQ 0x08 /* Window 0: Set IRQ line in bits 12-15. */
150ca7a8e85SJeff Kirsher #define WN4_MEDIA 0x0A /* Window 4: Various transcvr/media bits. */
151ca7a8e85SJeff Kirsher #define MEDIA_TP 0x00C0 /* Enable link beat and jabber for 10baseT. */
152ca7a8e85SJeff Kirsher #define WN4_NETDIAG 0x06 /* Window 4: Net diagnostic */
153ca7a8e85SJeff Kirsher #define FD_ENABLE 0x8000 /* Enable full-duplex ("external loopback") */
154ca7a8e85SJeff Kirsher
155ca7a8e85SJeff Kirsher /*
156ca7a8e85SJeff Kirsher * Must be a power of two (we use a binary and in the
157ca7a8e85SJeff Kirsher * circular queue)
158ca7a8e85SJeff Kirsher */
159ca7a8e85SJeff Kirsher #define SKB_QUEUE_SIZE 64
160ca7a8e85SJeff Kirsher
161a5e371f6SPaul Gortmaker enum el3_cardtype { EL3_ISA, EL3_PNP, EL3_EISA };
162ca7a8e85SJeff Kirsher
163ca7a8e85SJeff Kirsher struct el3_private {
164ca7a8e85SJeff Kirsher spinlock_t lock;
165ca7a8e85SJeff Kirsher /* skb send-queue */
166ca7a8e85SJeff Kirsher int head, size;
167ca7a8e85SJeff Kirsher struct sk_buff *queue[SKB_QUEUE_SIZE];
168ca7a8e85SJeff Kirsher enum el3_cardtype type;
169ca7a8e85SJeff Kirsher };
170ca7a8e85SJeff Kirsher static int id_port;
171ca7a8e85SJeff Kirsher static int current_tag;
172ca7a8e85SJeff Kirsher static struct net_device *el3_devs[EL3_MAX_CARDS];
173ca7a8e85SJeff Kirsher
174ca7a8e85SJeff Kirsher /* Parameters that may be passed into the module. */
175ca7a8e85SJeff Kirsher static int debug = -1;
176ca7a8e85SJeff Kirsher static int irq[] = {-1, -1, -1, -1, -1, -1, -1, -1};
177ca7a8e85SJeff Kirsher /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
178ca7a8e85SJeff Kirsher static int max_interrupt_work = 10;
179ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
180ca7a8e85SJeff Kirsher static int nopnp;
181ca7a8e85SJeff Kirsher #endif
182ca7a8e85SJeff Kirsher
1832791cf7aSBill Pemberton static int el3_common_init(struct net_device *dev);
184ca7a8e85SJeff Kirsher static void el3_common_remove(struct net_device *dev);
185ca7a8e85SJeff Kirsher static ushort id_read_eeprom(int index);
186ca7a8e85SJeff Kirsher static ushort read_eeprom(int ioaddr, int index);
187ca7a8e85SJeff Kirsher static int el3_open(struct net_device *dev);
188ca7a8e85SJeff Kirsher static netdev_tx_t el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
189ca7a8e85SJeff Kirsher static irqreturn_t el3_interrupt(int irq, void *dev_id);
190ca7a8e85SJeff Kirsher static void update_stats(struct net_device *dev);
191ca7a8e85SJeff Kirsher static struct net_device_stats *el3_get_stats(struct net_device *dev);
192ca7a8e85SJeff Kirsher static int el3_rx(struct net_device *dev);
193ca7a8e85SJeff Kirsher static int el3_close(struct net_device *dev);
194ca7a8e85SJeff Kirsher static void set_multicast_list(struct net_device *dev);
1950290bd29SMichael S. Tsirkin static void el3_tx_timeout (struct net_device *dev, unsigned int txqueue);
196ca7a8e85SJeff Kirsher static void el3_down(struct net_device *dev);
197ca7a8e85SJeff Kirsher static void el3_up(struct net_device *dev);
198ca7a8e85SJeff Kirsher static const struct ethtool_ops ethtool_ops;
199ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
200ca7a8e85SJeff Kirsher static int el3_suspend(struct device *, pm_message_t);
201ca7a8e85SJeff Kirsher static int el3_resume(struct device *);
202ca7a8e85SJeff Kirsher #else
203ca7a8e85SJeff Kirsher #define el3_suspend NULL
204ca7a8e85SJeff Kirsher #define el3_resume NULL
205ca7a8e85SJeff Kirsher #endif
206ca7a8e85SJeff Kirsher
207ca7a8e85SJeff Kirsher
208ca7a8e85SJeff Kirsher /* generic device remove for all device types */
209ca7a8e85SJeff Kirsher static int el3_device_remove (struct device *device);
210ca7a8e85SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
211ca7a8e85SJeff Kirsher static void el3_poll_controller(struct net_device *dev);
212ca7a8e85SJeff Kirsher #endif
213ca7a8e85SJeff Kirsher
214ca7a8e85SJeff Kirsher /* Return 0 on success, 1 on error, 2 when found already detected PnP card */
el3_isa_id_sequence(__be16 * phys_addr)215ca7a8e85SJeff Kirsher static int el3_isa_id_sequence(__be16 *phys_addr)
216ca7a8e85SJeff Kirsher {
217ca7a8e85SJeff Kirsher short lrs_state = 0xff;
218ca7a8e85SJeff Kirsher int i;
219ca7a8e85SJeff Kirsher
220ca7a8e85SJeff Kirsher /* ISA boards are detected by sending the ID sequence to the
221ca7a8e85SJeff Kirsher ID_PORT. We find cards past the first by setting the 'current_tag'
222ca7a8e85SJeff Kirsher on cards as they are found. Cards with their tag set will not
223ca7a8e85SJeff Kirsher respond to subsequent ID sequences. */
224ca7a8e85SJeff Kirsher
225ca7a8e85SJeff Kirsher outb(0x00, id_port);
226ca7a8e85SJeff Kirsher outb(0x00, id_port);
227ca7a8e85SJeff Kirsher for (i = 0; i < 255; i++) {
228ca7a8e85SJeff Kirsher outb(lrs_state, id_port);
229ca7a8e85SJeff Kirsher lrs_state <<= 1;
230ca7a8e85SJeff Kirsher lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
231ca7a8e85SJeff Kirsher }
232ca7a8e85SJeff Kirsher /* For the first probe, clear all board's tag registers. */
233ca7a8e85SJeff Kirsher if (current_tag == 0)
234ca7a8e85SJeff Kirsher outb(0xd0, id_port);
235ca7a8e85SJeff Kirsher else /* Otherwise kill off already-found boards. */
236ca7a8e85SJeff Kirsher outb(0xd8, id_port);
237ca7a8e85SJeff Kirsher if (id_read_eeprom(7) != 0x6d50)
238ca7a8e85SJeff Kirsher return 1;
239ca7a8e85SJeff Kirsher /* Read in EEPROM data, which does contention-select.
240ca7a8e85SJeff Kirsher Only the lowest address board will stay "on-line".
241ca7a8e85SJeff Kirsher 3Com got the byte order backwards. */
242ca7a8e85SJeff Kirsher for (i = 0; i < 3; i++)
243ca7a8e85SJeff Kirsher phys_addr[i] = htons(id_read_eeprom(i));
244ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
245ca7a8e85SJeff Kirsher if (!nopnp) {
246ca7a8e85SJeff Kirsher /* The ISA PnP 3c509 cards respond to the ID sequence too.
247ca7a8e85SJeff Kirsher This check is needed in order not to register them twice. */
248ca7a8e85SJeff Kirsher for (i = 0; i < el3_cards; i++) {
249ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(el3_devs[i]);
250ca7a8e85SJeff Kirsher if (lp->type == EL3_PNP &&
251ae237b3eSdingtianhong ether_addr_equal((u8 *)phys_addr, el3_devs[i]->dev_addr)) {
252ca7a8e85SJeff Kirsher if (el3_debug > 3)
253ca7a8e85SJeff Kirsher pr_debug("3c509 with address %02x %02x %02x %02x %02x %02x was found by ISAPnP\n",
254ca7a8e85SJeff Kirsher phys_addr[0] & 0xff, phys_addr[0] >> 8,
255ca7a8e85SJeff Kirsher phys_addr[1] & 0xff, phys_addr[1] >> 8,
256ca7a8e85SJeff Kirsher phys_addr[2] & 0xff, phys_addr[2] >> 8);
257ca7a8e85SJeff Kirsher /* Set the adaptor tag so that the next card can be found. */
258ca7a8e85SJeff Kirsher outb(0xd0 + ++current_tag, id_port);
259ca7a8e85SJeff Kirsher return 2;
260ca7a8e85SJeff Kirsher }
261ca7a8e85SJeff Kirsher }
262ca7a8e85SJeff Kirsher }
263ca7a8e85SJeff Kirsher #endif /* CONFIG_PNP */
264ca7a8e85SJeff Kirsher return 0;
265ca7a8e85SJeff Kirsher
266ca7a8e85SJeff Kirsher }
267ca7a8e85SJeff Kirsher
el3_dev_fill(struct net_device * dev,__be16 * phys_addr,int ioaddr,int irq,int if_port,enum el3_cardtype type)2681dd06ae8SGreg Kroah-Hartman static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr,
2691dd06ae8SGreg Kroah-Hartman int irq, int if_port, enum el3_cardtype type)
270ca7a8e85SJeff Kirsher {
271ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
272ca7a8e85SJeff Kirsher
27316be9a16SJakub Kicinski eth_hw_addr_set(dev, (u8 *)phys_addr);
274ca7a8e85SJeff Kirsher dev->base_addr = ioaddr;
275ca7a8e85SJeff Kirsher dev->irq = irq;
276ca7a8e85SJeff Kirsher dev->if_port = if_port;
277ca7a8e85SJeff Kirsher lp->type = type;
278ca7a8e85SJeff Kirsher }
279ca7a8e85SJeff Kirsher
el3_isa_match(struct device * pdev,unsigned int ndev)2801dd06ae8SGreg Kroah-Hartman static int el3_isa_match(struct device *pdev, unsigned int ndev)
281ca7a8e85SJeff Kirsher {
282ca7a8e85SJeff Kirsher struct net_device *dev;
283ca7a8e85SJeff Kirsher int ioaddr, isa_irq, if_port, err;
284ca7a8e85SJeff Kirsher unsigned int iobase;
285ca7a8e85SJeff Kirsher __be16 phys_addr[3];
286ca7a8e85SJeff Kirsher
287ca7a8e85SJeff Kirsher while ((err = el3_isa_id_sequence(phys_addr)) == 2)
288ca7a8e85SJeff Kirsher ; /* Skip to next card when PnP card found */
289ca7a8e85SJeff Kirsher if (err == 1)
290ca7a8e85SJeff Kirsher return 0;
291ca7a8e85SJeff Kirsher
292ca7a8e85SJeff Kirsher iobase = id_read_eeprom(8);
293ca7a8e85SJeff Kirsher if_port = iobase >> 14;
294ca7a8e85SJeff Kirsher ioaddr = 0x200 + ((iobase & 0x1f) << 4);
295ca7a8e85SJeff Kirsher if (irq[el3_cards] > 1 && irq[el3_cards] < 16)
296ca7a8e85SJeff Kirsher isa_irq = irq[el3_cards];
297ca7a8e85SJeff Kirsher else
298ca7a8e85SJeff Kirsher isa_irq = id_read_eeprom(9) >> 12;
299ca7a8e85SJeff Kirsher
300ca7a8e85SJeff Kirsher dev = alloc_etherdev(sizeof(struct el3_private));
301ca7a8e85SJeff Kirsher if (!dev)
302ca7a8e85SJeff Kirsher return -ENOMEM;
303ca7a8e85SJeff Kirsher
3043b54912fSMatthew Whitehead SET_NETDEV_DEV(dev, pdev);
305ca7a8e85SJeff Kirsher
306ca7a8e85SJeff Kirsher if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) {
307ca7a8e85SJeff Kirsher free_netdev(dev);
308ca7a8e85SJeff Kirsher return 0;
309ca7a8e85SJeff Kirsher }
310ca7a8e85SJeff Kirsher
311ca7a8e85SJeff Kirsher /* Set the adaptor tag so that the next card can be found. */
312ca7a8e85SJeff Kirsher outb(0xd0 + ++current_tag, id_port);
313ca7a8e85SJeff Kirsher
314ca7a8e85SJeff Kirsher /* Activate the adaptor at the EEPROM location. */
315ca7a8e85SJeff Kirsher outb((ioaddr >> 4) | 0xe0, id_port);
316ca7a8e85SJeff Kirsher
317ca7a8e85SJeff Kirsher EL3WINDOW(0);
318ca7a8e85SJeff Kirsher if (inw(ioaddr) != 0x6d50) {
319ca7a8e85SJeff Kirsher free_netdev(dev);
320ca7a8e85SJeff Kirsher return 0;
321ca7a8e85SJeff Kirsher }
322ca7a8e85SJeff Kirsher
323ca7a8e85SJeff Kirsher /* Free the interrupt so that some other card can use it. */
324ca7a8e85SJeff Kirsher outw(0x0f00, ioaddr + WN0_IRQ);
325ca7a8e85SJeff Kirsher
326ca7a8e85SJeff Kirsher el3_dev_fill(dev, phys_addr, ioaddr, isa_irq, if_port, EL3_ISA);
327ca7a8e85SJeff Kirsher dev_set_drvdata(pdev, dev);
328ca7a8e85SJeff Kirsher if (el3_common_init(dev)) {
329ca7a8e85SJeff Kirsher free_netdev(dev);
330ca7a8e85SJeff Kirsher return 0;
331ca7a8e85SJeff Kirsher }
332ca7a8e85SJeff Kirsher
333ca7a8e85SJeff Kirsher el3_devs[el3_cards++] = dev;
334ca7a8e85SJeff Kirsher return 1;
335ca7a8e85SJeff Kirsher }
336ca7a8e85SJeff Kirsher
el3_isa_remove(struct device * pdev,unsigned int ndev)33730e88d01SUwe Kleine-König static void el3_isa_remove(struct device *pdev,
338ca7a8e85SJeff Kirsher unsigned int ndev)
339ca7a8e85SJeff Kirsher {
340ca7a8e85SJeff Kirsher el3_device_remove(pdev);
341ca7a8e85SJeff Kirsher dev_set_drvdata(pdev, NULL);
342ca7a8e85SJeff Kirsher }
343ca7a8e85SJeff Kirsher
344ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
el3_isa_suspend(struct device * dev,unsigned int n,pm_message_t state)345ca7a8e85SJeff Kirsher static int el3_isa_suspend(struct device *dev, unsigned int n,
346ca7a8e85SJeff Kirsher pm_message_t state)
347ca7a8e85SJeff Kirsher {
348ca7a8e85SJeff Kirsher current_tag = 0;
349ca7a8e85SJeff Kirsher return el3_suspend(dev, state);
350ca7a8e85SJeff Kirsher }
351ca7a8e85SJeff Kirsher
el3_isa_resume(struct device * dev,unsigned int n)352ca7a8e85SJeff Kirsher static int el3_isa_resume(struct device *dev, unsigned int n)
353ca7a8e85SJeff Kirsher {
354ca7a8e85SJeff Kirsher struct net_device *ndev = dev_get_drvdata(dev);
355ca7a8e85SJeff Kirsher int ioaddr = ndev->base_addr, err;
356ca7a8e85SJeff Kirsher __be16 phys_addr[3];
357ca7a8e85SJeff Kirsher
358ca7a8e85SJeff Kirsher while ((err = el3_isa_id_sequence(phys_addr)) == 2)
359ca7a8e85SJeff Kirsher ; /* Skip to next card when PnP card found */
360ca7a8e85SJeff Kirsher if (err == 1)
361ca7a8e85SJeff Kirsher return 0;
362ca7a8e85SJeff Kirsher /* Set the adaptor tag so that the next card can be found. */
363ca7a8e85SJeff Kirsher outb(0xd0 + ++current_tag, id_port);
364ca7a8e85SJeff Kirsher /* Enable the card */
365ca7a8e85SJeff Kirsher outb((ioaddr >> 4) | 0xe0, id_port);
366ca7a8e85SJeff Kirsher EL3WINDOW(0);
367ca7a8e85SJeff Kirsher if (inw(ioaddr) != 0x6d50)
368ca7a8e85SJeff Kirsher return 1;
369ca7a8e85SJeff Kirsher /* Free the interrupt so that some other card can use it. */
370ca7a8e85SJeff Kirsher outw(0x0f00, ioaddr + WN0_IRQ);
371ca7a8e85SJeff Kirsher return el3_resume(dev);
372ca7a8e85SJeff Kirsher }
373ca7a8e85SJeff Kirsher #endif
374ca7a8e85SJeff Kirsher
375ca7a8e85SJeff Kirsher static struct isa_driver el3_isa_driver = {
376ca7a8e85SJeff Kirsher .match = el3_isa_match,
3772791cf7aSBill Pemberton .remove = el3_isa_remove,
378ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
379ca7a8e85SJeff Kirsher .suspend = el3_isa_suspend,
380ca7a8e85SJeff Kirsher .resume = el3_isa_resume,
381ca7a8e85SJeff Kirsher #endif
382ca7a8e85SJeff Kirsher .driver = {
383ca7a8e85SJeff Kirsher .name = "3c509"
384ca7a8e85SJeff Kirsher },
385ca7a8e85SJeff Kirsher };
386ca7a8e85SJeff Kirsher static int isa_registered;
387ca7a8e85SJeff Kirsher
388ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
389d369bcafSArvind Yadav static const struct pnp_device_id el3_pnp_ids[] = {
390ca7a8e85SJeff Kirsher { .id = "TCM5090" }, /* 3Com Etherlink III (TP) */
391ca7a8e85SJeff Kirsher { .id = "TCM5091" }, /* 3Com Etherlink III */
392ca7a8e85SJeff Kirsher { .id = "TCM5094" }, /* 3Com Etherlink III (combo) */
393ca7a8e85SJeff Kirsher { .id = "TCM5095" }, /* 3Com Etherlink III (TPO) */
394ca7a8e85SJeff Kirsher { .id = "TCM5098" }, /* 3Com Etherlink III (TPC) */
395ca7a8e85SJeff Kirsher { .id = "PNP80f7" }, /* 3Com Etherlink III compatible */
396ca7a8e85SJeff Kirsher { .id = "PNP80f8" }, /* 3Com Etherlink III compatible */
397ca7a8e85SJeff Kirsher { .id = "" }
398ca7a8e85SJeff Kirsher };
399ca7a8e85SJeff Kirsher MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
400ca7a8e85SJeff Kirsher
el3_pnp_probe(struct pnp_dev * pdev,const struct pnp_device_id * id)4011dd06ae8SGreg Kroah-Hartman static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
402ca7a8e85SJeff Kirsher {
403ca7a8e85SJeff Kirsher short i;
404ca7a8e85SJeff Kirsher int ioaddr, irq, if_port;
405ca7a8e85SJeff Kirsher __be16 phys_addr[3];
406ca7a8e85SJeff Kirsher struct net_device *dev = NULL;
407ca7a8e85SJeff Kirsher int err;
408ca7a8e85SJeff Kirsher
409ca7a8e85SJeff Kirsher ioaddr = pnp_port_start(pdev, 0);
410ca7a8e85SJeff Kirsher if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-pnp"))
411ca7a8e85SJeff Kirsher return -EBUSY;
412ca7a8e85SJeff Kirsher irq = pnp_irq(pdev, 0);
413ca7a8e85SJeff Kirsher EL3WINDOW(0);
414ca7a8e85SJeff Kirsher for (i = 0; i < 3; i++)
415ca7a8e85SJeff Kirsher phys_addr[i] = htons(read_eeprom(ioaddr, i));
416ca7a8e85SJeff Kirsher if_port = read_eeprom(ioaddr, 8) >> 14;
417ca7a8e85SJeff Kirsher dev = alloc_etherdev(sizeof(struct el3_private));
418ca7a8e85SJeff Kirsher if (!dev) {
419ca7a8e85SJeff Kirsher release_region(ioaddr, EL3_IO_EXTENT);
420ca7a8e85SJeff Kirsher return -ENOMEM;
421ca7a8e85SJeff Kirsher }
422ca7a8e85SJeff Kirsher SET_NETDEV_DEV(dev, &pdev->dev);
423ca7a8e85SJeff Kirsher
424ca7a8e85SJeff Kirsher el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_PNP);
425ca7a8e85SJeff Kirsher pnp_set_drvdata(pdev, dev);
426ca7a8e85SJeff Kirsher err = el3_common_init(dev);
427ca7a8e85SJeff Kirsher
428ca7a8e85SJeff Kirsher if (err) {
429ca7a8e85SJeff Kirsher pnp_set_drvdata(pdev, NULL);
430ca7a8e85SJeff Kirsher free_netdev(dev);
431ca7a8e85SJeff Kirsher return err;
432ca7a8e85SJeff Kirsher }
433ca7a8e85SJeff Kirsher
434ca7a8e85SJeff Kirsher el3_devs[el3_cards++] = dev;
435ca7a8e85SJeff Kirsher return 0;
436ca7a8e85SJeff Kirsher }
437ca7a8e85SJeff Kirsher
el3_pnp_remove(struct pnp_dev * pdev)4382791cf7aSBill Pemberton static void el3_pnp_remove(struct pnp_dev *pdev)
439ca7a8e85SJeff Kirsher {
440ca7a8e85SJeff Kirsher el3_common_remove(pnp_get_drvdata(pdev));
441ca7a8e85SJeff Kirsher pnp_set_drvdata(pdev, NULL);
442ca7a8e85SJeff Kirsher }
443ca7a8e85SJeff Kirsher
444ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
el3_pnp_suspend(struct pnp_dev * pdev,pm_message_t state)445ca7a8e85SJeff Kirsher static int el3_pnp_suspend(struct pnp_dev *pdev, pm_message_t state)
446ca7a8e85SJeff Kirsher {
447ca7a8e85SJeff Kirsher return el3_suspend(&pdev->dev, state);
448ca7a8e85SJeff Kirsher }
449ca7a8e85SJeff Kirsher
el3_pnp_resume(struct pnp_dev * pdev)450ca7a8e85SJeff Kirsher static int el3_pnp_resume(struct pnp_dev *pdev)
451ca7a8e85SJeff Kirsher {
452ca7a8e85SJeff Kirsher return el3_resume(&pdev->dev);
453ca7a8e85SJeff Kirsher }
454ca7a8e85SJeff Kirsher #endif
455ca7a8e85SJeff Kirsher
456ca7a8e85SJeff Kirsher static struct pnp_driver el3_pnp_driver = {
457ca7a8e85SJeff Kirsher .name = "3c509",
458ca7a8e85SJeff Kirsher .id_table = el3_pnp_ids,
459ca7a8e85SJeff Kirsher .probe = el3_pnp_probe,
4602791cf7aSBill Pemberton .remove = el3_pnp_remove,
461ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
462ca7a8e85SJeff Kirsher .suspend = el3_pnp_suspend,
463ca7a8e85SJeff Kirsher .resume = el3_pnp_resume,
464ca7a8e85SJeff Kirsher #endif
465ca7a8e85SJeff Kirsher };
466ca7a8e85SJeff Kirsher static int pnp_registered;
467ca7a8e85SJeff Kirsher #endif /* CONFIG_PNP */
468ca7a8e85SJeff Kirsher
469ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
4704ac5bc34SArvind Yadav static const struct eisa_device_id el3_eisa_ids[] = {
471ca7a8e85SJeff Kirsher { "TCM5090" },
472ca7a8e85SJeff Kirsher { "TCM5091" },
473ca7a8e85SJeff Kirsher { "TCM5092" },
474ca7a8e85SJeff Kirsher { "TCM5093" },
475ca7a8e85SJeff Kirsher { "TCM5094" },
476ca7a8e85SJeff Kirsher { "TCM5095" },
477ca7a8e85SJeff Kirsher { "TCM5098" },
478ca7a8e85SJeff Kirsher { "" }
479ca7a8e85SJeff Kirsher };
480ca7a8e85SJeff Kirsher MODULE_DEVICE_TABLE(eisa, el3_eisa_ids);
481ca7a8e85SJeff Kirsher
482ca7a8e85SJeff Kirsher static int el3_eisa_probe (struct device *device);
483ca7a8e85SJeff Kirsher
484ca7a8e85SJeff Kirsher static struct eisa_driver el3_eisa_driver = {
485ca7a8e85SJeff Kirsher .id_table = el3_eisa_ids,
486ca7a8e85SJeff Kirsher .driver = {
487ca7a8e85SJeff Kirsher .name = "3c579",
488ca7a8e85SJeff Kirsher .probe = el3_eisa_probe,
4892791cf7aSBill Pemberton .remove = el3_device_remove,
490ca7a8e85SJeff Kirsher .suspend = el3_suspend,
491ca7a8e85SJeff Kirsher .resume = el3_resume,
492ca7a8e85SJeff Kirsher }
493ca7a8e85SJeff Kirsher };
494ca7a8e85SJeff Kirsher static int eisa_registered;
495ca7a8e85SJeff Kirsher #endif
496ca7a8e85SJeff Kirsher
497ca7a8e85SJeff Kirsher static const struct net_device_ops netdev_ops = {
498ca7a8e85SJeff Kirsher .ndo_open = el3_open,
499ca7a8e85SJeff Kirsher .ndo_stop = el3_close,
500ca7a8e85SJeff Kirsher .ndo_start_xmit = el3_start_xmit,
501ca7a8e85SJeff Kirsher .ndo_get_stats = el3_get_stats,
502afc4b13dSJiri Pirko .ndo_set_rx_mode = set_multicast_list,
503ca7a8e85SJeff Kirsher .ndo_tx_timeout = el3_tx_timeout,
504ca7a8e85SJeff Kirsher .ndo_set_mac_address = eth_mac_addr,
505ca7a8e85SJeff Kirsher .ndo_validate_addr = eth_validate_addr,
506ca7a8e85SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
507ca7a8e85SJeff Kirsher .ndo_poll_controller = el3_poll_controller,
508ca7a8e85SJeff Kirsher #endif
509ca7a8e85SJeff Kirsher };
510ca7a8e85SJeff Kirsher
el3_common_init(struct net_device * dev)5112791cf7aSBill Pemberton static int el3_common_init(struct net_device *dev)
512ca7a8e85SJeff Kirsher {
513ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
514ca7a8e85SJeff Kirsher int err;
515771edeabSColin Ian King static const char * const if_names[] = {
516771edeabSColin Ian King "10baseT", "AUI", "undefined", "BNC"
517771edeabSColin Ian King };
518ca7a8e85SJeff Kirsher
519ca7a8e85SJeff Kirsher spin_lock_init(&lp->lock);
520ca7a8e85SJeff Kirsher
521ca7a8e85SJeff Kirsher if (dev->mem_start & 0x05) { /* xcvr codes 1/3/4/12 */
522ca7a8e85SJeff Kirsher dev->if_port = (dev->mem_start & 0x0f);
523ca7a8e85SJeff Kirsher } else { /* xcvr codes 0/8 */
524ca7a8e85SJeff Kirsher /* use eeprom value, but save user's full-duplex selection */
525ca7a8e85SJeff Kirsher dev->if_port |= (dev->mem_start & 0x08);
526ca7a8e85SJeff Kirsher }
527ca7a8e85SJeff Kirsher
528ca7a8e85SJeff Kirsher /* The EL3-specific entries in the device structure. */
529ca7a8e85SJeff Kirsher dev->netdev_ops = &netdev_ops;
530ca7a8e85SJeff Kirsher dev->watchdog_timeo = TX_TIMEOUT;
5317ad24ea4SWilfried Klaebe dev->ethtool_ops = ðtool_ops;
532ca7a8e85SJeff Kirsher
533ca7a8e85SJeff Kirsher err = register_netdev(dev);
534ca7a8e85SJeff Kirsher if (err) {
535ca7a8e85SJeff Kirsher pr_err("Failed to register 3c5x9 at %#3.3lx, IRQ %d.\n",
536ca7a8e85SJeff Kirsher dev->base_addr, dev->irq);
537ca7a8e85SJeff Kirsher release_region(dev->base_addr, EL3_IO_EXTENT);
538ca7a8e85SJeff Kirsher return err;
539ca7a8e85SJeff Kirsher }
540ca7a8e85SJeff Kirsher
541ca7a8e85SJeff Kirsher pr_info("%s: 3c5x9 found at %#3.3lx, %s port, address %pM, IRQ %d.\n",
542ca7a8e85SJeff Kirsher dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
543ca7a8e85SJeff Kirsher dev->dev_addr, dev->irq);
544ca7a8e85SJeff Kirsher
545ca7a8e85SJeff Kirsher return 0;
546ca7a8e85SJeff Kirsher
547ca7a8e85SJeff Kirsher }
548ca7a8e85SJeff Kirsher
el3_common_remove(struct net_device * dev)549ca7a8e85SJeff Kirsher static void el3_common_remove (struct net_device *dev)
550ca7a8e85SJeff Kirsher {
551ca7a8e85SJeff Kirsher unregister_netdev (dev);
552ca7a8e85SJeff Kirsher release_region(dev->base_addr, EL3_IO_EXTENT);
553ca7a8e85SJeff Kirsher free_netdev (dev);
554ca7a8e85SJeff Kirsher }
555ca7a8e85SJeff Kirsher
556ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
el3_eisa_probe(struct device * device)557cb4396edSFabian Frederick static int el3_eisa_probe(struct device *device)
558ca7a8e85SJeff Kirsher {
559ca7a8e85SJeff Kirsher short i;
560ca7a8e85SJeff Kirsher int ioaddr, irq, if_port;
561ca7a8e85SJeff Kirsher __be16 phys_addr[3];
562ca7a8e85SJeff Kirsher struct net_device *dev = NULL;
563ca7a8e85SJeff Kirsher struct eisa_device *edev;
564ca7a8e85SJeff Kirsher int err;
565ca7a8e85SJeff Kirsher
566ca7a8e85SJeff Kirsher /* Yeepee, The driver framework is calling us ! */
567ca7a8e85SJeff Kirsher edev = to_eisa_device (device);
568ca7a8e85SJeff Kirsher ioaddr = edev->base_addr;
569ca7a8e85SJeff Kirsher
570ca7a8e85SJeff Kirsher if (!request_region(ioaddr, EL3_IO_EXTENT, "3c579-eisa"))
571ca7a8e85SJeff Kirsher return -EBUSY;
572ca7a8e85SJeff Kirsher
573ca7a8e85SJeff Kirsher /* Change the register set to the configuration window 0. */
574ca7a8e85SJeff Kirsher outw(SelectWindow | 0, ioaddr + 0xC80 + EL3_CMD);
575ca7a8e85SJeff Kirsher
576ca7a8e85SJeff Kirsher irq = inw(ioaddr + WN0_IRQ) >> 12;
577ca7a8e85SJeff Kirsher if_port = inw(ioaddr + 6)>>14;
578ca7a8e85SJeff Kirsher for (i = 0; i < 3; i++)
579ca7a8e85SJeff Kirsher phys_addr[i] = htons(read_eeprom(ioaddr, i));
580ca7a8e85SJeff Kirsher
581ca7a8e85SJeff Kirsher /* Restore the "Product ID" to the EEPROM read register. */
582ca7a8e85SJeff Kirsher read_eeprom(ioaddr, 3);
583ca7a8e85SJeff Kirsher
584ca7a8e85SJeff Kirsher dev = alloc_etherdev(sizeof (struct el3_private));
585ca7a8e85SJeff Kirsher if (dev == NULL) {
586ca7a8e85SJeff Kirsher release_region(ioaddr, EL3_IO_EXTENT);
587ca7a8e85SJeff Kirsher return -ENOMEM;
588ca7a8e85SJeff Kirsher }
589ca7a8e85SJeff Kirsher
5903b54912fSMatthew Whitehead SET_NETDEV_DEV(dev, device);
591ca7a8e85SJeff Kirsher
592ca7a8e85SJeff Kirsher el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA);
593ca7a8e85SJeff Kirsher eisa_set_drvdata (edev, dev);
594ca7a8e85SJeff Kirsher err = el3_common_init(dev);
595ca7a8e85SJeff Kirsher
596ca7a8e85SJeff Kirsher if (err) {
597ca7a8e85SJeff Kirsher eisa_set_drvdata (edev, NULL);
598ca7a8e85SJeff Kirsher free_netdev(dev);
599ca7a8e85SJeff Kirsher return err;
600ca7a8e85SJeff Kirsher }
601ca7a8e85SJeff Kirsher
602ca7a8e85SJeff Kirsher el3_devs[el3_cards++] = dev;
603ca7a8e85SJeff Kirsher return 0;
604ca7a8e85SJeff Kirsher }
605ca7a8e85SJeff Kirsher #endif
606ca7a8e85SJeff Kirsher
607ca7a8e85SJeff Kirsher /* This remove works for all device types.
608ca7a8e85SJeff Kirsher *
609ca7a8e85SJeff Kirsher * The net dev must be stored in the driver data field */
el3_device_remove(struct device * device)6102791cf7aSBill Pemberton static int el3_device_remove(struct device *device)
611ca7a8e85SJeff Kirsher {
612ca7a8e85SJeff Kirsher struct net_device *dev;
613ca7a8e85SJeff Kirsher
614ca7a8e85SJeff Kirsher dev = dev_get_drvdata(device);
615ca7a8e85SJeff Kirsher
616ca7a8e85SJeff Kirsher el3_common_remove (dev);
617ca7a8e85SJeff Kirsher return 0;
618ca7a8e85SJeff Kirsher }
619ca7a8e85SJeff Kirsher
620ca7a8e85SJeff Kirsher /* Read a word from the EEPROM using the regular EEPROM access register.
621ca7a8e85SJeff Kirsher Assume that we are in register window zero.
622ca7a8e85SJeff Kirsher */
read_eeprom(int ioaddr,int index)623ca7a8e85SJeff Kirsher static ushort read_eeprom(int ioaddr, int index)
624ca7a8e85SJeff Kirsher {
625ca7a8e85SJeff Kirsher outw(EEPROM_READ + index, ioaddr + 10);
626ca7a8e85SJeff Kirsher /* Pause for at least 162 us. for the read to take place.
627ca7a8e85SJeff Kirsher Some chips seem to require much longer */
628ca7a8e85SJeff Kirsher mdelay(2);
629ca7a8e85SJeff Kirsher return inw(ioaddr + 12);
630ca7a8e85SJeff Kirsher }
631ca7a8e85SJeff Kirsher
632ca7a8e85SJeff Kirsher /* Read a word from the EEPROM when in the ISA ID probe state. */
id_read_eeprom(int index)633ca7a8e85SJeff Kirsher static ushort id_read_eeprom(int index)
634ca7a8e85SJeff Kirsher {
635ca7a8e85SJeff Kirsher int bit, word = 0;
636ca7a8e85SJeff Kirsher
637ca7a8e85SJeff Kirsher /* Issue read command, and pause for at least 162 us. for it to complete.
638ca7a8e85SJeff Kirsher Assume extra-fast 16Mhz bus. */
639ca7a8e85SJeff Kirsher outb(EEPROM_READ + index, id_port);
640ca7a8e85SJeff Kirsher
641ca7a8e85SJeff Kirsher /* Pause for at least 162 us. for the read to take place. */
642ca7a8e85SJeff Kirsher /* Some chips seem to require much longer */
643ca7a8e85SJeff Kirsher mdelay(4);
644ca7a8e85SJeff Kirsher
645ca7a8e85SJeff Kirsher for (bit = 15; bit >= 0; bit--)
646ca7a8e85SJeff Kirsher word = (word << 1) + (inb(id_port) & 0x01);
647ca7a8e85SJeff Kirsher
648ca7a8e85SJeff Kirsher if (el3_debug > 3)
649ca7a8e85SJeff Kirsher pr_debug(" 3c509 EEPROM word %d %#4.4x.\n", index, word);
650ca7a8e85SJeff Kirsher
651ca7a8e85SJeff Kirsher return word;
652ca7a8e85SJeff Kirsher }
653ca7a8e85SJeff Kirsher
654ca7a8e85SJeff Kirsher
655ca7a8e85SJeff Kirsher static int
el3_open(struct net_device * dev)656ca7a8e85SJeff Kirsher el3_open(struct net_device *dev)
657ca7a8e85SJeff Kirsher {
658ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
659ca7a8e85SJeff Kirsher int i;
660ca7a8e85SJeff Kirsher
661ca7a8e85SJeff Kirsher outw(TxReset, ioaddr + EL3_CMD);
662ca7a8e85SJeff Kirsher outw(RxReset, ioaddr + EL3_CMD);
663ca7a8e85SJeff Kirsher outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD);
664ca7a8e85SJeff Kirsher
665ca7a8e85SJeff Kirsher i = request_irq(dev->irq, el3_interrupt, 0, dev->name, dev);
666ca7a8e85SJeff Kirsher if (i)
667ca7a8e85SJeff Kirsher return i;
668ca7a8e85SJeff Kirsher
669ca7a8e85SJeff Kirsher EL3WINDOW(0);
670ca7a8e85SJeff Kirsher if (el3_debug > 3)
671ca7a8e85SJeff Kirsher pr_debug("%s: Opening, IRQ %d status@%x %4.4x.\n", dev->name,
672ca7a8e85SJeff Kirsher dev->irq, ioaddr + EL3_STATUS, inw(ioaddr + EL3_STATUS));
673ca7a8e85SJeff Kirsher
674ca7a8e85SJeff Kirsher el3_up(dev);
675ca7a8e85SJeff Kirsher
676ca7a8e85SJeff Kirsher if (el3_debug > 3)
677ca7a8e85SJeff Kirsher pr_debug("%s: Opened 3c509 IRQ %d status %4.4x.\n",
678ca7a8e85SJeff Kirsher dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
679ca7a8e85SJeff Kirsher
680ca7a8e85SJeff Kirsher return 0;
681ca7a8e85SJeff Kirsher }
682ca7a8e85SJeff Kirsher
683ca7a8e85SJeff Kirsher static void
el3_tx_timeout(struct net_device * dev,unsigned int txqueue)6840290bd29SMichael S. Tsirkin el3_tx_timeout (struct net_device *dev, unsigned int txqueue)
685ca7a8e85SJeff Kirsher {
686ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
687ca7a8e85SJeff Kirsher
688ca7a8e85SJeff Kirsher /* Transmitter timeout, serious problems. */
689fe3881cfSJoe Perches pr_warn("%s: transmit timed out, Tx_status %2.2x status %4.4x Tx FIFO room %d\n",
690ca7a8e85SJeff Kirsher dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS),
691ca7a8e85SJeff Kirsher inw(ioaddr + TX_FREE));
692ca7a8e85SJeff Kirsher dev->stats.tx_errors++;
693860e9538SFlorian Westphal netif_trans_update(dev); /* prevent tx timeout */
694ca7a8e85SJeff Kirsher /* Issue TX_RESET and TX_START commands. */
695ca7a8e85SJeff Kirsher outw(TxReset, ioaddr + EL3_CMD);
696ca7a8e85SJeff Kirsher outw(TxEnable, ioaddr + EL3_CMD);
697ca7a8e85SJeff Kirsher netif_wake_queue(dev);
698ca7a8e85SJeff Kirsher }
699ca7a8e85SJeff Kirsher
700ca7a8e85SJeff Kirsher
701ca7a8e85SJeff Kirsher static netdev_tx_t
el3_start_xmit(struct sk_buff * skb,struct net_device * dev)702ca7a8e85SJeff Kirsher el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
703ca7a8e85SJeff Kirsher {
704ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
705ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
706ca7a8e85SJeff Kirsher unsigned long flags;
707ca7a8e85SJeff Kirsher
708ca7a8e85SJeff Kirsher netif_stop_queue (dev);
709ca7a8e85SJeff Kirsher
710ca7a8e85SJeff Kirsher dev->stats.tx_bytes += skb->len;
711ca7a8e85SJeff Kirsher
712ca7a8e85SJeff Kirsher if (el3_debug > 4) {
713ca7a8e85SJeff Kirsher pr_debug("%s: el3_start_xmit(length = %u) called, status %4.4x.\n",
714ca7a8e85SJeff Kirsher dev->name, skb->len, inw(ioaddr + EL3_STATUS));
715ca7a8e85SJeff Kirsher }
716ca7a8e85SJeff Kirsher /*
717ca7a8e85SJeff Kirsher * We lock the driver against other processors. Note
718ca7a8e85SJeff Kirsher * we don't need to lock versus the IRQ as we suspended
719ca7a8e85SJeff Kirsher * that. This means that we lose the ability to take
720ca7a8e85SJeff Kirsher * an RX during a TX upload. That sucks a bit with SMP
721ca7a8e85SJeff Kirsher * on an original 3c509 (2K buffer)
722ca7a8e85SJeff Kirsher *
723ca7a8e85SJeff Kirsher * Using disable_irq stops us crapping on other
724ca7a8e85SJeff Kirsher * time sensitive devices.
725ca7a8e85SJeff Kirsher */
726ca7a8e85SJeff Kirsher
727ca7a8e85SJeff Kirsher spin_lock_irqsave(&lp->lock, flags);
728ca7a8e85SJeff Kirsher
729ca7a8e85SJeff Kirsher /* Put out the doubleword header... */
730ca7a8e85SJeff Kirsher outw(skb->len, ioaddr + TX_FIFO);
731ca7a8e85SJeff Kirsher outw(0x00, ioaddr + TX_FIFO);
732ca7a8e85SJeff Kirsher /* ... and the packet rounded to a doubleword. */
733ca7a8e85SJeff Kirsher outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
734ca7a8e85SJeff Kirsher
735ca7a8e85SJeff Kirsher if (inw(ioaddr + TX_FREE) > 1536)
736ca7a8e85SJeff Kirsher netif_start_queue(dev);
737ca7a8e85SJeff Kirsher else
738ca7a8e85SJeff Kirsher /* Interrupt us when the FIFO has room for max-sized packet. */
739ca7a8e85SJeff Kirsher outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
740ca7a8e85SJeff Kirsher
741ca7a8e85SJeff Kirsher spin_unlock_irqrestore(&lp->lock, flags);
742ca7a8e85SJeff Kirsher
7438fa9524dSEric W. Biederman dev_consume_skb_any (skb);
744ca7a8e85SJeff Kirsher
745ca7a8e85SJeff Kirsher /* Clear the Tx status stack. */
746ca7a8e85SJeff Kirsher {
747ca7a8e85SJeff Kirsher short tx_status;
748ca7a8e85SJeff Kirsher int i = 4;
749ca7a8e85SJeff Kirsher
750ca7a8e85SJeff Kirsher while (--i > 0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
751ca7a8e85SJeff Kirsher if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
752ca7a8e85SJeff Kirsher if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
753ca7a8e85SJeff Kirsher if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
754ca7a8e85SJeff Kirsher outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
755ca7a8e85SJeff Kirsher }
756ca7a8e85SJeff Kirsher }
757ca7a8e85SJeff Kirsher return NETDEV_TX_OK;
758ca7a8e85SJeff Kirsher }
759ca7a8e85SJeff Kirsher
760ca7a8e85SJeff Kirsher /* The EL3 interrupt handler. */
761ca7a8e85SJeff Kirsher static irqreturn_t
el3_interrupt(int irq,void * dev_id)762ca7a8e85SJeff Kirsher el3_interrupt(int irq, void *dev_id)
763ca7a8e85SJeff Kirsher {
764ca7a8e85SJeff Kirsher struct net_device *dev = dev_id;
765ca7a8e85SJeff Kirsher struct el3_private *lp;
766ca7a8e85SJeff Kirsher int ioaddr, status;
767ca7a8e85SJeff Kirsher int i = max_interrupt_work;
768ca7a8e85SJeff Kirsher
769ca7a8e85SJeff Kirsher lp = netdev_priv(dev);
770ca7a8e85SJeff Kirsher spin_lock(&lp->lock);
771ca7a8e85SJeff Kirsher
772ca7a8e85SJeff Kirsher ioaddr = dev->base_addr;
773ca7a8e85SJeff Kirsher
774ca7a8e85SJeff Kirsher if (el3_debug > 4) {
775ca7a8e85SJeff Kirsher status = inw(ioaddr + EL3_STATUS);
776ca7a8e85SJeff Kirsher pr_debug("%s: interrupt, status %4.4x.\n", dev->name, status);
777ca7a8e85SJeff Kirsher }
778ca7a8e85SJeff Kirsher
779ca7a8e85SJeff Kirsher while ((status = inw(ioaddr + EL3_STATUS)) &
780ca7a8e85SJeff Kirsher (IntLatch | RxComplete | StatsFull)) {
781ca7a8e85SJeff Kirsher
782ca7a8e85SJeff Kirsher if (status & RxComplete)
783ca7a8e85SJeff Kirsher el3_rx(dev);
784ca7a8e85SJeff Kirsher
785ca7a8e85SJeff Kirsher if (status & TxAvailable) {
786ca7a8e85SJeff Kirsher if (el3_debug > 5)
787ca7a8e85SJeff Kirsher pr_debug(" TX room bit was handled.\n");
788ca7a8e85SJeff Kirsher /* There's room in the FIFO for a full-sized packet. */
789ca7a8e85SJeff Kirsher outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
790ca7a8e85SJeff Kirsher netif_wake_queue (dev);
791ca7a8e85SJeff Kirsher }
792ca7a8e85SJeff Kirsher if (status & (AdapterFailure | RxEarly | StatsFull | TxComplete)) {
793ca7a8e85SJeff Kirsher /* Handle all uncommon interrupts. */
794ca7a8e85SJeff Kirsher if (status & StatsFull) /* Empty statistics. */
795ca7a8e85SJeff Kirsher update_stats(dev);
796ca7a8e85SJeff Kirsher if (status & RxEarly) { /* Rx early is unused. */
797ca7a8e85SJeff Kirsher el3_rx(dev);
798ca7a8e85SJeff Kirsher outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
799ca7a8e85SJeff Kirsher }
800ca7a8e85SJeff Kirsher if (status & TxComplete) { /* Really Tx error. */
801ca7a8e85SJeff Kirsher short tx_status;
802ca7a8e85SJeff Kirsher int i = 4;
803ca7a8e85SJeff Kirsher
804ca7a8e85SJeff Kirsher while (--i>0 && (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
805ca7a8e85SJeff Kirsher if (tx_status & 0x38) dev->stats.tx_aborted_errors++;
806ca7a8e85SJeff Kirsher if (tx_status & 0x30) outw(TxReset, ioaddr + EL3_CMD);
807ca7a8e85SJeff Kirsher if (tx_status & 0x3C) outw(TxEnable, ioaddr + EL3_CMD);
808ca7a8e85SJeff Kirsher outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
809ca7a8e85SJeff Kirsher }
810ca7a8e85SJeff Kirsher }
811ca7a8e85SJeff Kirsher if (status & AdapterFailure) {
812ca7a8e85SJeff Kirsher /* Adapter failure requires Rx reset and reinit. */
813ca7a8e85SJeff Kirsher outw(RxReset, ioaddr + EL3_CMD);
814ca7a8e85SJeff Kirsher /* Set the Rx filter to the current state. */
815ca7a8e85SJeff Kirsher outw(SetRxFilter | RxStation | RxBroadcast
816ca7a8e85SJeff Kirsher | (dev->flags & IFF_ALLMULTI ? RxMulticast : 0)
817ca7a8e85SJeff Kirsher | (dev->flags & IFF_PROMISC ? RxProm : 0),
818ca7a8e85SJeff Kirsher ioaddr + EL3_CMD);
819ca7a8e85SJeff Kirsher outw(RxEnable, ioaddr + EL3_CMD); /* Re-enable the receiver. */
820ca7a8e85SJeff Kirsher outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
821ca7a8e85SJeff Kirsher }
822ca7a8e85SJeff Kirsher }
823ca7a8e85SJeff Kirsher
824ca7a8e85SJeff Kirsher if (--i < 0) {
825ca7a8e85SJeff Kirsher pr_err("%s: Infinite loop in interrupt, status %4.4x.\n",
826ca7a8e85SJeff Kirsher dev->name, status);
827ca7a8e85SJeff Kirsher /* Clear all interrupts. */
828ca7a8e85SJeff Kirsher outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
829ca7a8e85SJeff Kirsher break;
830ca7a8e85SJeff Kirsher }
831ca7a8e85SJeff Kirsher /* Acknowledge the IRQ. */
832ca7a8e85SJeff Kirsher outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD); /* Ack IRQ */
833ca7a8e85SJeff Kirsher }
834ca7a8e85SJeff Kirsher
835ca7a8e85SJeff Kirsher if (el3_debug > 4) {
836ca7a8e85SJeff Kirsher pr_debug("%s: exiting interrupt, status %4.4x.\n", dev->name,
837ca7a8e85SJeff Kirsher inw(ioaddr + EL3_STATUS));
838ca7a8e85SJeff Kirsher }
839ca7a8e85SJeff Kirsher spin_unlock(&lp->lock);
840ca7a8e85SJeff Kirsher return IRQ_HANDLED;
841ca7a8e85SJeff Kirsher }
842ca7a8e85SJeff Kirsher
843ca7a8e85SJeff Kirsher
844ca7a8e85SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
845ca7a8e85SJeff Kirsher /*
846ca7a8e85SJeff Kirsher * Polling receive - used by netconsole and other diagnostic tools
847ca7a8e85SJeff Kirsher * to allow network i/o with interrupts disabled.
848ca7a8e85SJeff Kirsher */
el3_poll_controller(struct net_device * dev)849ca7a8e85SJeff Kirsher static void el3_poll_controller(struct net_device *dev)
850ca7a8e85SJeff Kirsher {
851ca7a8e85SJeff Kirsher disable_irq(dev->irq);
852ca7a8e85SJeff Kirsher el3_interrupt(dev->irq, dev);
853ca7a8e85SJeff Kirsher enable_irq(dev->irq);
854ca7a8e85SJeff Kirsher }
855ca7a8e85SJeff Kirsher #endif
856ca7a8e85SJeff Kirsher
857ca7a8e85SJeff Kirsher static struct net_device_stats *
el3_get_stats(struct net_device * dev)858ca7a8e85SJeff Kirsher el3_get_stats(struct net_device *dev)
859ca7a8e85SJeff Kirsher {
860ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
861ca7a8e85SJeff Kirsher unsigned long flags;
862ca7a8e85SJeff Kirsher
863ca7a8e85SJeff Kirsher /*
864ca7a8e85SJeff Kirsher * This is fast enough not to bother with disable IRQ
865ca7a8e85SJeff Kirsher * stuff.
866ca7a8e85SJeff Kirsher */
867ca7a8e85SJeff Kirsher
868ca7a8e85SJeff Kirsher spin_lock_irqsave(&lp->lock, flags);
869ca7a8e85SJeff Kirsher update_stats(dev);
870ca7a8e85SJeff Kirsher spin_unlock_irqrestore(&lp->lock, flags);
871ca7a8e85SJeff Kirsher return &dev->stats;
872ca7a8e85SJeff Kirsher }
873ca7a8e85SJeff Kirsher
874ca7a8e85SJeff Kirsher /* Update statistics. We change to register window 6, so this should be run
875ca7a8e85SJeff Kirsher single-threaded if the device is active. This is expected to be a rare
876ca7a8e85SJeff Kirsher operation, and it's simpler for the rest of the driver to assume that
877ca7a8e85SJeff Kirsher window 1 is always valid rather than use a special window-state variable.
878ca7a8e85SJeff Kirsher */
update_stats(struct net_device * dev)879ca7a8e85SJeff Kirsher static void update_stats(struct net_device *dev)
880ca7a8e85SJeff Kirsher {
881ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
882ca7a8e85SJeff Kirsher
883ca7a8e85SJeff Kirsher if (el3_debug > 5)
884ca7a8e85SJeff Kirsher pr_debug(" Updating the statistics.\n");
885ca7a8e85SJeff Kirsher /* Turn off statistics updates while reading. */
886ca7a8e85SJeff Kirsher outw(StatsDisable, ioaddr + EL3_CMD);
887ca7a8e85SJeff Kirsher /* Switch to the stats window, and read everything. */
888ca7a8e85SJeff Kirsher EL3WINDOW(6);
889ca7a8e85SJeff Kirsher dev->stats.tx_carrier_errors += inb(ioaddr + 0);
890ca7a8e85SJeff Kirsher dev->stats.tx_heartbeat_errors += inb(ioaddr + 1);
891ca7a8e85SJeff Kirsher /* Multiple collisions. */ inb(ioaddr + 2);
892ca7a8e85SJeff Kirsher dev->stats.collisions += inb(ioaddr + 3);
893ca7a8e85SJeff Kirsher dev->stats.tx_window_errors += inb(ioaddr + 4);
894ca7a8e85SJeff Kirsher dev->stats.rx_fifo_errors += inb(ioaddr + 5);
895ca7a8e85SJeff Kirsher dev->stats.tx_packets += inb(ioaddr + 6);
896ca7a8e85SJeff Kirsher /* Rx packets */ inb(ioaddr + 7);
897ca7a8e85SJeff Kirsher /* Tx deferrals */ inb(ioaddr + 8);
898ca7a8e85SJeff Kirsher inw(ioaddr + 10); /* Total Rx and Tx octets. */
899ca7a8e85SJeff Kirsher inw(ioaddr + 12);
900ca7a8e85SJeff Kirsher
901ca7a8e85SJeff Kirsher /* Back to window 1, and turn statistics back on. */
902ca7a8e85SJeff Kirsher EL3WINDOW(1);
903ca7a8e85SJeff Kirsher outw(StatsEnable, ioaddr + EL3_CMD);
904ca7a8e85SJeff Kirsher }
905ca7a8e85SJeff Kirsher
906ca7a8e85SJeff Kirsher static int
el3_rx(struct net_device * dev)907ca7a8e85SJeff Kirsher el3_rx(struct net_device *dev)
908ca7a8e85SJeff Kirsher {
909ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
910ca7a8e85SJeff Kirsher short rx_status;
911ca7a8e85SJeff Kirsher
912ca7a8e85SJeff Kirsher if (el3_debug > 5)
913ca7a8e85SJeff Kirsher pr_debug(" In rx_packet(), status %4.4x, rx_status %4.4x.\n",
914ca7a8e85SJeff Kirsher inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
915ca7a8e85SJeff Kirsher while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
916ca7a8e85SJeff Kirsher if (rx_status & 0x4000) { /* Error, update stats. */
917ca7a8e85SJeff Kirsher short error = rx_status & 0x3800;
918ca7a8e85SJeff Kirsher
919ca7a8e85SJeff Kirsher outw(RxDiscard, ioaddr + EL3_CMD);
920ca7a8e85SJeff Kirsher dev->stats.rx_errors++;
921ca7a8e85SJeff Kirsher switch (error) {
922ca7a8e85SJeff Kirsher case 0x0000: dev->stats.rx_over_errors++; break;
923ca7a8e85SJeff Kirsher case 0x0800: dev->stats.rx_length_errors++; break;
924ca7a8e85SJeff Kirsher case 0x1000: dev->stats.rx_frame_errors++; break;
925ca7a8e85SJeff Kirsher case 0x1800: dev->stats.rx_length_errors++; break;
926ca7a8e85SJeff Kirsher case 0x2000: dev->stats.rx_frame_errors++; break;
927ca7a8e85SJeff Kirsher case 0x2800: dev->stats.rx_crc_errors++; break;
928ca7a8e85SJeff Kirsher }
929ca7a8e85SJeff Kirsher } else {
930ca7a8e85SJeff Kirsher short pkt_len = rx_status & 0x7ff;
931ca7a8e85SJeff Kirsher struct sk_buff *skb;
932ca7a8e85SJeff Kirsher
9331d266430SPradeep A Dalvi skb = netdev_alloc_skb(dev, pkt_len + 5);
934ca7a8e85SJeff Kirsher if (el3_debug > 4)
935ca7a8e85SJeff Kirsher pr_debug("Receiving packet size %d status %4.4x.\n",
936ca7a8e85SJeff Kirsher pkt_len, rx_status);
937ca7a8e85SJeff Kirsher if (skb != NULL) {
938ca7a8e85SJeff Kirsher skb_reserve(skb, 2); /* Align IP on 16 byte */
939ca7a8e85SJeff Kirsher
940ca7a8e85SJeff Kirsher /* 'skb->data' points to the start of sk_buff data area. */
941ca7a8e85SJeff Kirsher insl(ioaddr + RX_FIFO, skb_put(skb,pkt_len),
942ca7a8e85SJeff Kirsher (pkt_len + 3) >> 2);
943ca7a8e85SJeff Kirsher
944ca7a8e85SJeff Kirsher outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
945ca7a8e85SJeff Kirsher skb->protocol = eth_type_trans(skb,dev);
946ca7a8e85SJeff Kirsher netif_rx(skb);
947ca7a8e85SJeff Kirsher dev->stats.rx_bytes += pkt_len;
948ca7a8e85SJeff Kirsher dev->stats.rx_packets++;
949ca7a8e85SJeff Kirsher continue;
950ca7a8e85SJeff Kirsher }
951ca7a8e85SJeff Kirsher outw(RxDiscard, ioaddr + EL3_CMD);
952ca7a8e85SJeff Kirsher dev->stats.rx_dropped++;
953ca7a8e85SJeff Kirsher if (el3_debug)
954ca7a8e85SJeff Kirsher pr_debug("%s: Couldn't allocate a sk_buff of size %d.\n",
955ca7a8e85SJeff Kirsher dev->name, pkt_len);
956ca7a8e85SJeff Kirsher }
957ca7a8e85SJeff Kirsher inw(ioaddr + EL3_STATUS); /* Delay. */
958ca7a8e85SJeff Kirsher while (inw(ioaddr + EL3_STATUS) & 0x1000)
959ca7a8e85SJeff Kirsher pr_debug(" Waiting for 3c509 to discard packet, status %x.\n",
960ca7a8e85SJeff Kirsher inw(ioaddr + EL3_STATUS) );
961ca7a8e85SJeff Kirsher }
962ca7a8e85SJeff Kirsher
963ca7a8e85SJeff Kirsher return 0;
964ca7a8e85SJeff Kirsher }
965ca7a8e85SJeff Kirsher
966ca7a8e85SJeff Kirsher /*
967ca7a8e85SJeff Kirsher * Set or clear the multicast filter for this adaptor.
968ca7a8e85SJeff Kirsher */
969ca7a8e85SJeff Kirsher static void
set_multicast_list(struct net_device * dev)970ca7a8e85SJeff Kirsher set_multicast_list(struct net_device *dev)
971ca7a8e85SJeff Kirsher {
972ca7a8e85SJeff Kirsher unsigned long flags;
973ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
974ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
975ca7a8e85SJeff Kirsher int mc_count = netdev_mc_count(dev);
976ca7a8e85SJeff Kirsher
977ca7a8e85SJeff Kirsher if (el3_debug > 1) {
978ca7a8e85SJeff Kirsher static int old;
979ca7a8e85SJeff Kirsher if (old != mc_count) {
980ca7a8e85SJeff Kirsher old = mc_count;
981ca7a8e85SJeff Kirsher pr_debug("%s: Setting Rx mode to %d addresses.\n",
982ca7a8e85SJeff Kirsher dev->name, mc_count);
983ca7a8e85SJeff Kirsher }
984ca7a8e85SJeff Kirsher }
985ca7a8e85SJeff Kirsher spin_lock_irqsave(&lp->lock, flags);
986ca7a8e85SJeff Kirsher if (dev->flags&IFF_PROMISC) {
987ca7a8e85SJeff Kirsher outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast | RxProm,
988ca7a8e85SJeff Kirsher ioaddr + EL3_CMD);
989ca7a8e85SJeff Kirsher }
990ca7a8e85SJeff Kirsher else if (mc_count || (dev->flags&IFF_ALLMULTI)) {
991ca7a8e85SJeff Kirsher outw(SetRxFilter | RxStation | RxMulticast | RxBroadcast, ioaddr + EL3_CMD);
992ca7a8e85SJeff Kirsher }
993ca7a8e85SJeff Kirsher else
994ca7a8e85SJeff Kirsher outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
995ca7a8e85SJeff Kirsher spin_unlock_irqrestore(&lp->lock, flags);
996ca7a8e85SJeff Kirsher }
997ca7a8e85SJeff Kirsher
998ca7a8e85SJeff Kirsher static int
el3_close(struct net_device * dev)999ca7a8e85SJeff Kirsher el3_close(struct net_device *dev)
1000ca7a8e85SJeff Kirsher {
1001ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
1002ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
1003ca7a8e85SJeff Kirsher
1004ca7a8e85SJeff Kirsher if (el3_debug > 2)
1005ca7a8e85SJeff Kirsher pr_debug("%s: Shutting down ethercard.\n", dev->name);
1006ca7a8e85SJeff Kirsher
1007ca7a8e85SJeff Kirsher el3_down(dev);
1008ca7a8e85SJeff Kirsher
1009ca7a8e85SJeff Kirsher free_irq(dev->irq, dev);
1010ca7a8e85SJeff Kirsher /* Switching back to window 0 disables the IRQ. */
1011ca7a8e85SJeff Kirsher EL3WINDOW(0);
1012ca7a8e85SJeff Kirsher if (lp->type != EL3_EISA) {
1013ca7a8e85SJeff Kirsher /* But we explicitly zero the IRQ line select anyway. Don't do
1014ca7a8e85SJeff Kirsher * it on EISA cards, it prevents the module from getting an
1015ca7a8e85SJeff Kirsher * IRQ after unload+reload... */
1016ca7a8e85SJeff Kirsher outw(0x0f00, ioaddr + WN0_IRQ);
1017ca7a8e85SJeff Kirsher }
1018ca7a8e85SJeff Kirsher
1019ca7a8e85SJeff Kirsher return 0;
1020ca7a8e85SJeff Kirsher }
1021ca7a8e85SJeff Kirsher
1022ca7a8e85SJeff Kirsher static int
el3_link_ok(struct net_device * dev)1023ca7a8e85SJeff Kirsher el3_link_ok(struct net_device *dev)
1024ca7a8e85SJeff Kirsher {
1025ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
1026ca7a8e85SJeff Kirsher u16 tmp;
1027ca7a8e85SJeff Kirsher
1028ca7a8e85SJeff Kirsher EL3WINDOW(4);
1029ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN4_MEDIA);
1030ca7a8e85SJeff Kirsher EL3WINDOW(1);
1031ca7a8e85SJeff Kirsher return tmp & (1<<11);
1032ca7a8e85SJeff Kirsher }
1033ca7a8e85SJeff Kirsher
1034697dae1eSyuval.shaia@oracle.com static void
el3_netdev_get_ecmd(struct net_device * dev,struct ethtool_link_ksettings * cmd)1035b646cf29SPhilippe Reynes el3_netdev_get_ecmd(struct net_device *dev, struct ethtool_link_ksettings *cmd)
1036ca7a8e85SJeff Kirsher {
1037ca7a8e85SJeff Kirsher u16 tmp;
1038ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
1039b646cf29SPhilippe Reynes u32 supported;
1040ca7a8e85SJeff Kirsher
1041ca7a8e85SJeff Kirsher EL3WINDOW(0);
1042ca7a8e85SJeff Kirsher /* obtain current transceiver via WN4_MEDIA? */
1043ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN0_ADDR_CONF);
1044ca7a8e85SJeff Kirsher switch (tmp >> 14) {
1045ca7a8e85SJeff Kirsher case 0:
1046b646cf29SPhilippe Reynes cmd->base.port = PORT_TP;
1047ca7a8e85SJeff Kirsher break;
1048ca7a8e85SJeff Kirsher case 1:
1049b646cf29SPhilippe Reynes cmd->base.port = PORT_AUI;
1050ca7a8e85SJeff Kirsher break;
1051ca7a8e85SJeff Kirsher case 3:
1052b646cf29SPhilippe Reynes cmd->base.port = PORT_BNC;
1053097c8ff0SGustavo A. R. Silva break;
1054ca7a8e85SJeff Kirsher default:
1055ca7a8e85SJeff Kirsher break;
1056ca7a8e85SJeff Kirsher }
1057ca7a8e85SJeff Kirsher
1058b646cf29SPhilippe Reynes cmd->base.duplex = DUPLEX_HALF;
1059b646cf29SPhilippe Reynes supported = 0;
1060ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN0_CONF_CTRL);
1061ca7a8e85SJeff Kirsher if (tmp & (1<<13))
1062b646cf29SPhilippe Reynes supported |= SUPPORTED_AUI;
1063ca7a8e85SJeff Kirsher if (tmp & (1<<12))
1064b646cf29SPhilippe Reynes supported |= SUPPORTED_BNC;
1065ca7a8e85SJeff Kirsher if (tmp & (1<<9)) {
1066b646cf29SPhilippe Reynes supported |= SUPPORTED_TP | SUPPORTED_10baseT_Half |
1067ca7a8e85SJeff Kirsher SUPPORTED_10baseT_Full; /* hmm... */
1068ca7a8e85SJeff Kirsher EL3WINDOW(4);
1069ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN4_NETDIAG);
1070ca7a8e85SJeff Kirsher if (tmp & FD_ENABLE)
1071b646cf29SPhilippe Reynes cmd->base.duplex = DUPLEX_FULL;
1072ca7a8e85SJeff Kirsher }
1073ca7a8e85SJeff Kirsher
1074b646cf29SPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
1075b646cf29SPhilippe Reynes supported);
1076b646cf29SPhilippe Reynes cmd->base.speed = SPEED_10;
1077ca7a8e85SJeff Kirsher EL3WINDOW(1);
1078ca7a8e85SJeff Kirsher }
1079ca7a8e85SJeff Kirsher
1080ca7a8e85SJeff Kirsher static int
el3_netdev_set_ecmd(struct net_device * dev,const struct ethtool_link_ksettings * cmd)1081b646cf29SPhilippe Reynes el3_netdev_set_ecmd(struct net_device *dev,
1082b646cf29SPhilippe Reynes const struct ethtool_link_ksettings *cmd)
1083ca7a8e85SJeff Kirsher {
1084ca7a8e85SJeff Kirsher u16 tmp;
1085ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
1086ca7a8e85SJeff Kirsher
1087b646cf29SPhilippe Reynes if (cmd->base.speed != SPEED_10)
1088ca7a8e85SJeff Kirsher return -EINVAL;
1089b646cf29SPhilippe Reynes if ((cmd->base.duplex != DUPLEX_HALF) &&
1090b646cf29SPhilippe Reynes (cmd->base.duplex != DUPLEX_FULL))
1091ca7a8e85SJeff Kirsher return -EINVAL;
1092ca7a8e85SJeff Kirsher
1093ca7a8e85SJeff Kirsher /* change XCVR type */
1094ca7a8e85SJeff Kirsher EL3WINDOW(0);
1095ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN0_ADDR_CONF);
1096b646cf29SPhilippe Reynes switch (cmd->base.port) {
1097ca7a8e85SJeff Kirsher case PORT_TP:
1098ca7a8e85SJeff Kirsher tmp &= ~(3<<14);
1099ca7a8e85SJeff Kirsher dev->if_port = 0;
1100ca7a8e85SJeff Kirsher break;
1101ca7a8e85SJeff Kirsher case PORT_AUI:
1102ca7a8e85SJeff Kirsher tmp |= (1<<14);
1103ca7a8e85SJeff Kirsher dev->if_port = 1;
1104ca7a8e85SJeff Kirsher break;
1105ca7a8e85SJeff Kirsher case PORT_BNC:
1106ca7a8e85SJeff Kirsher tmp |= (3<<14);
1107ca7a8e85SJeff Kirsher dev->if_port = 3;
1108ca7a8e85SJeff Kirsher break;
1109ca7a8e85SJeff Kirsher default:
1110ca7a8e85SJeff Kirsher return -EINVAL;
1111ca7a8e85SJeff Kirsher }
1112ca7a8e85SJeff Kirsher
1113ca7a8e85SJeff Kirsher outw(tmp, ioaddr + WN0_ADDR_CONF);
1114ca7a8e85SJeff Kirsher if (dev->if_port == 3) {
1115ca7a8e85SJeff Kirsher /* fire up the DC-DC convertor if BNC gets enabled */
1116ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN0_ADDR_CONF);
1117ca7a8e85SJeff Kirsher if (tmp & (3 << 14)) {
1118ca7a8e85SJeff Kirsher outw(StartCoax, ioaddr + EL3_CMD);
1119ca7a8e85SJeff Kirsher udelay(800);
1120ca7a8e85SJeff Kirsher } else
1121ca7a8e85SJeff Kirsher return -EIO;
1122ca7a8e85SJeff Kirsher }
1123ca7a8e85SJeff Kirsher
1124ca7a8e85SJeff Kirsher EL3WINDOW(4);
1125ca7a8e85SJeff Kirsher tmp = inw(ioaddr + WN4_NETDIAG);
1126b646cf29SPhilippe Reynes if (cmd->base.duplex == DUPLEX_FULL)
1127ca7a8e85SJeff Kirsher tmp |= FD_ENABLE;
1128ca7a8e85SJeff Kirsher else
1129ca7a8e85SJeff Kirsher tmp &= ~FD_ENABLE;
1130ca7a8e85SJeff Kirsher outw(tmp, ioaddr + WN4_NETDIAG);
1131ca7a8e85SJeff Kirsher EL3WINDOW(1);
1132ca7a8e85SJeff Kirsher
1133ca7a8e85SJeff Kirsher return 0;
1134ca7a8e85SJeff Kirsher }
1135ca7a8e85SJeff Kirsher
el3_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)1136ca7a8e85SJeff Kirsher static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
1137ca7a8e85SJeff Kirsher {
1138*f029c781SWolfram Sang strscpy(info->driver, DRV_NAME, sizeof(info->driver));
1139ca7a8e85SJeff Kirsher }
1140ca7a8e85SJeff Kirsher
el3_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)1141b646cf29SPhilippe Reynes static int el3_get_link_ksettings(struct net_device *dev,
1142b646cf29SPhilippe Reynes struct ethtool_link_ksettings *cmd)
1143ca7a8e85SJeff Kirsher {
1144ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
1145ca7a8e85SJeff Kirsher
1146ca7a8e85SJeff Kirsher spin_lock_irq(&lp->lock);
1147697dae1eSyuval.shaia@oracle.com el3_netdev_get_ecmd(dev, cmd);
1148ca7a8e85SJeff Kirsher spin_unlock_irq(&lp->lock);
1149697dae1eSyuval.shaia@oracle.com return 0;
1150ca7a8e85SJeff Kirsher }
1151ca7a8e85SJeff Kirsher
el3_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * cmd)1152b646cf29SPhilippe Reynes static int el3_set_link_ksettings(struct net_device *dev,
1153b646cf29SPhilippe Reynes const struct ethtool_link_ksettings *cmd)
1154ca7a8e85SJeff Kirsher {
1155ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
1156ca7a8e85SJeff Kirsher int ret;
1157ca7a8e85SJeff Kirsher
1158ca7a8e85SJeff Kirsher spin_lock_irq(&lp->lock);
1159b646cf29SPhilippe Reynes ret = el3_netdev_set_ecmd(dev, cmd);
1160ca7a8e85SJeff Kirsher spin_unlock_irq(&lp->lock);
1161ca7a8e85SJeff Kirsher return ret;
1162ca7a8e85SJeff Kirsher }
1163ca7a8e85SJeff Kirsher
el3_get_link(struct net_device * dev)1164ca7a8e85SJeff Kirsher static u32 el3_get_link(struct net_device *dev)
1165ca7a8e85SJeff Kirsher {
1166ca7a8e85SJeff Kirsher struct el3_private *lp = netdev_priv(dev);
1167ca7a8e85SJeff Kirsher u32 ret;
1168ca7a8e85SJeff Kirsher
1169ca7a8e85SJeff Kirsher spin_lock_irq(&lp->lock);
1170ca7a8e85SJeff Kirsher ret = el3_link_ok(dev);
1171ca7a8e85SJeff Kirsher spin_unlock_irq(&lp->lock);
1172ca7a8e85SJeff Kirsher return ret;
1173ca7a8e85SJeff Kirsher }
1174ca7a8e85SJeff Kirsher
el3_get_msglevel(struct net_device * dev)1175ca7a8e85SJeff Kirsher static u32 el3_get_msglevel(struct net_device *dev)
1176ca7a8e85SJeff Kirsher {
1177ca7a8e85SJeff Kirsher return el3_debug;
1178ca7a8e85SJeff Kirsher }
1179ca7a8e85SJeff Kirsher
el3_set_msglevel(struct net_device * dev,u32 v)1180ca7a8e85SJeff Kirsher static void el3_set_msglevel(struct net_device *dev, u32 v)
1181ca7a8e85SJeff Kirsher {
1182ca7a8e85SJeff Kirsher el3_debug = v;
1183ca7a8e85SJeff Kirsher }
1184ca7a8e85SJeff Kirsher
1185ca7a8e85SJeff Kirsher static const struct ethtool_ops ethtool_ops = {
1186ca7a8e85SJeff Kirsher .get_drvinfo = el3_get_drvinfo,
1187ca7a8e85SJeff Kirsher .get_link = el3_get_link,
1188ca7a8e85SJeff Kirsher .get_msglevel = el3_get_msglevel,
1189ca7a8e85SJeff Kirsher .set_msglevel = el3_set_msglevel,
1190b646cf29SPhilippe Reynes .get_link_ksettings = el3_get_link_ksettings,
1191b646cf29SPhilippe Reynes .set_link_ksettings = el3_set_link_ksettings,
1192ca7a8e85SJeff Kirsher };
1193ca7a8e85SJeff Kirsher
1194ca7a8e85SJeff Kirsher static void
el3_down(struct net_device * dev)1195ca7a8e85SJeff Kirsher el3_down(struct net_device *dev)
1196ca7a8e85SJeff Kirsher {
1197ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
1198ca7a8e85SJeff Kirsher
1199ca7a8e85SJeff Kirsher netif_stop_queue(dev);
1200ca7a8e85SJeff Kirsher
1201ca7a8e85SJeff Kirsher /* Turn off statistics ASAP. We update lp->stats below. */
1202ca7a8e85SJeff Kirsher outw(StatsDisable, ioaddr + EL3_CMD);
1203ca7a8e85SJeff Kirsher
1204ca7a8e85SJeff Kirsher /* Disable the receiver and transmitter. */
1205ca7a8e85SJeff Kirsher outw(RxDisable, ioaddr + EL3_CMD);
1206ca7a8e85SJeff Kirsher outw(TxDisable, ioaddr + EL3_CMD);
1207ca7a8e85SJeff Kirsher
1208ca7a8e85SJeff Kirsher if (dev->if_port == 3)
1209ca7a8e85SJeff Kirsher /* Turn off thinnet power. Green! */
1210ca7a8e85SJeff Kirsher outw(StopCoax, ioaddr + EL3_CMD);
1211ca7a8e85SJeff Kirsher else if (dev->if_port == 0) {
1212ca7a8e85SJeff Kirsher /* Disable link beat and jabber, if_port may change here next open(). */
1213ca7a8e85SJeff Kirsher EL3WINDOW(4);
1214ca7a8e85SJeff Kirsher outw(inw(ioaddr + WN4_MEDIA) & ~MEDIA_TP, ioaddr + WN4_MEDIA);
1215ca7a8e85SJeff Kirsher }
1216ca7a8e85SJeff Kirsher
1217ca7a8e85SJeff Kirsher outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
1218ca7a8e85SJeff Kirsher
1219ca7a8e85SJeff Kirsher update_stats(dev);
1220ca7a8e85SJeff Kirsher }
1221ca7a8e85SJeff Kirsher
1222ca7a8e85SJeff Kirsher static void
el3_up(struct net_device * dev)1223ca7a8e85SJeff Kirsher el3_up(struct net_device *dev)
1224ca7a8e85SJeff Kirsher {
1225ca7a8e85SJeff Kirsher int i, sw_info, net_diag;
1226ca7a8e85SJeff Kirsher int ioaddr = dev->base_addr;
1227ca7a8e85SJeff Kirsher
1228ca7a8e85SJeff Kirsher /* Activating the board required and does no harm otherwise */
1229ca7a8e85SJeff Kirsher outw(0x0001, ioaddr + 4);
1230ca7a8e85SJeff Kirsher
1231ca7a8e85SJeff Kirsher /* Set the IRQ line. */
1232ca7a8e85SJeff Kirsher outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ);
1233ca7a8e85SJeff Kirsher
1234ca7a8e85SJeff Kirsher /* Set the station address in window 2 each time opened. */
1235ca7a8e85SJeff Kirsher EL3WINDOW(2);
1236ca7a8e85SJeff Kirsher
1237ca7a8e85SJeff Kirsher for (i = 0; i < 6; i++)
1238ca7a8e85SJeff Kirsher outb(dev->dev_addr[i], ioaddr + i);
1239ca7a8e85SJeff Kirsher
1240ca7a8e85SJeff Kirsher if ((dev->if_port & 0x03) == 3) /* BNC interface */
1241ca7a8e85SJeff Kirsher /* Start the thinnet transceiver. We should really wait 50ms...*/
1242ca7a8e85SJeff Kirsher outw(StartCoax, ioaddr + EL3_CMD);
1243ca7a8e85SJeff Kirsher else if ((dev->if_port & 0x03) == 0) { /* 10baseT interface */
1244ca7a8e85SJeff Kirsher /* Combine secondary sw_info word (the adapter level) and primary
1245ca7a8e85SJeff Kirsher sw_info word (duplex setting plus other useless bits) */
1246ca7a8e85SJeff Kirsher EL3WINDOW(0);
1247ca7a8e85SJeff Kirsher sw_info = (read_eeprom(ioaddr, 0x14) & 0x400f) |
1248ca7a8e85SJeff Kirsher (read_eeprom(ioaddr, 0x0d) & 0xBff0);
1249ca7a8e85SJeff Kirsher
1250ca7a8e85SJeff Kirsher EL3WINDOW(4);
1251ca7a8e85SJeff Kirsher net_diag = inw(ioaddr + WN4_NETDIAG);
1252ca7a8e85SJeff Kirsher net_diag = (net_diag | FD_ENABLE); /* temporarily assume full-duplex will be set */
1253ca7a8e85SJeff Kirsher pr_info("%s: ", dev->name);
1254ca7a8e85SJeff Kirsher switch (dev->if_port & 0x0c) {
1255ca7a8e85SJeff Kirsher case 12:
1256ca7a8e85SJeff Kirsher /* force full-duplex mode if 3c5x9b */
1257ca7a8e85SJeff Kirsher if (sw_info & 0x000f) {
1258ca7a8e85SJeff Kirsher pr_cont("Forcing 3c5x9b full-duplex mode");
1259ca7a8e85SJeff Kirsher break;
1260ca7a8e85SJeff Kirsher }
1261df561f66SGustavo A. R. Silva fallthrough;
1262ca7a8e85SJeff Kirsher case 8:
1263ca7a8e85SJeff Kirsher /* set full-duplex mode based on eeprom config setting */
1264ca7a8e85SJeff Kirsher if ((sw_info & 0x000f) && (sw_info & 0x8000)) {
1265ca7a8e85SJeff Kirsher pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)");
1266ca7a8e85SJeff Kirsher break;
1267ca7a8e85SJeff Kirsher }
1268df561f66SGustavo A. R. Silva fallthrough;
1269ca7a8e85SJeff Kirsher default:
1270ca7a8e85SJeff Kirsher /* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */
1271ca7a8e85SJeff Kirsher pr_cont("Setting 3c5x9/3c5x9B half-duplex mode");
1272ca7a8e85SJeff Kirsher net_diag = (net_diag & ~FD_ENABLE); /* disable full duplex */
1273ca7a8e85SJeff Kirsher }
1274ca7a8e85SJeff Kirsher
1275ca7a8e85SJeff Kirsher outw(net_diag, ioaddr + WN4_NETDIAG);
1276ca7a8e85SJeff Kirsher pr_cont(" if_port: %d, sw_info: %4.4x\n", dev->if_port, sw_info);
1277ca7a8e85SJeff Kirsher if (el3_debug > 3)
1278ca7a8e85SJeff Kirsher pr_debug("%s: 3c5x9 net diag word is now: %4.4x.\n", dev->name, net_diag);
1279ca7a8e85SJeff Kirsher /* Enable link beat and jabber check. */
1280ca7a8e85SJeff Kirsher outw(inw(ioaddr + WN4_MEDIA) | MEDIA_TP, ioaddr + WN4_MEDIA);
1281ca7a8e85SJeff Kirsher }
1282ca7a8e85SJeff Kirsher
1283ca7a8e85SJeff Kirsher /* Switch to the stats window, and clear all stats by reading. */
1284ca7a8e85SJeff Kirsher outw(StatsDisable, ioaddr + EL3_CMD);
1285ca7a8e85SJeff Kirsher EL3WINDOW(6);
1286ca7a8e85SJeff Kirsher for (i = 0; i < 9; i++)
1287ca7a8e85SJeff Kirsher inb(ioaddr + i);
1288ca7a8e85SJeff Kirsher inw(ioaddr + 10);
1289ca7a8e85SJeff Kirsher inw(ioaddr + 12);
1290ca7a8e85SJeff Kirsher
1291ca7a8e85SJeff Kirsher /* Switch to register set 1 for normal use. */
1292ca7a8e85SJeff Kirsher EL3WINDOW(1);
1293ca7a8e85SJeff Kirsher
1294ca7a8e85SJeff Kirsher /* Accept b-case and phys addr only. */
1295ca7a8e85SJeff Kirsher outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
1296ca7a8e85SJeff Kirsher outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
1297ca7a8e85SJeff Kirsher
1298ca7a8e85SJeff Kirsher outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
1299ca7a8e85SJeff Kirsher outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
1300ca7a8e85SJeff Kirsher /* Allow status bits to be seen. */
1301ca7a8e85SJeff Kirsher outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
1302ca7a8e85SJeff Kirsher /* Ack all pending events, and set active indicator mask. */
1303ca7a8e85SJeff Kirsher outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
1304ca7a8e85SJeff Kirsher ioaddr + EL3_CMD);
1305ca7a8e85SJeff Kirsher outw(SetIntrEnb | IntLatch|TxAvailable|TxComplete|RxComplete|StatsFull,
1306ca7a8e85SJeff Kirsher ioaddr + EL3_CMD);
1307ca7a8e85SJeff Kirsher
1308ca7a8e85SJeff Kirsher netif_start_queue(dev);
1309ca7a8e85SJeff Kirsher }
1310ca7a8e85SJeff Kirsher
1311ca7a8e85SJeff Kirsher /* Power Management support functions */
1312ca7a8e85SJeff Kirsher #ifdef CONFIG_PM
1313ca7a8e85SJeff Kirsher
1314ca7a8e85SJeff Kirsher static int
el3_suspend(struct device * pdev,pm_message_t state)1315ca7a8e85SJeff Kirsher el3_suspend(struct device *pdev, pm_message_t state)
1316ca7a8e85SJeff Kirsher {
1317ca7a8e85SJeff Kirsher unsigned long flags;
1318ca7a8e85SJeff Kirsher struct net_device *dev;
1319ca7a8e85SJeff Kirsher struct el3_private *lp;
1320ca7a8e85SJeff Kirsher int ioaddr;
1321ca7a8e85SJeff Kirsher
1322ca7a8e85SJeff Kirsher dev = dev_get_drvdata(pdev);
1323ca7a8e85SJeff Kirsher lp = netdev_priv(dev);
1324ca7a8e85SJeff Kirsher ioaddr = dev->base_addr;
1325ca7a8e85SJeff Kirsher
1326ca7a8e85SJeff Kirsher spin_lock_irqsave(&lp->lock, flags);
1327ca7a8e85SJeff Kirsher
1328ca7a8e85SJeff Kirsher if (netif_running(dev))
1329ca7a8e85SJeff Kirsher netif_device_detach(dev);
1330ca7a8e85SJeff Kirsher
1331ca7a8e85SJeff Kirsher el3_down(dev);
1332ca7a8e85SJeff Kirsher outw(PowerDown, ioaddr + EL3_CMD);
1333ca7a8e85SJeff Kirsher
1334ca7a8e85SJeff Kirsher spin_unlock_irqrestore(&lp->lock, flags);
1335ca7a8e85SJeff Kirsher return 0;
1336ca7a8e85SJeff Kirsher }
1337ca7a8e85SJeff Kirsher
1338ca7a8e85SJeff Kirsher static int
el3_resume(struct device * pdev)1339ca7a8e85SJeff Kirsher el3_resume(struct device *pdev)
1340ca7a8e85SJeff Kirsher {
1341ca7a8e85SJeff Kirsher unsigned long flags;
1342ca7a8e85SJeff Kirsher struct net_device *dev;
1343ca7a8e85SJeff Kirsher struct el3_private *lp;
1344ca7a8e85SJeff Kirsher int ioaddr;
1345ca7a8e85SJeff Kirsher
1346ca7a8e85SJeff Kirsher dev = dev_get_drvdata(pdev);
1347ca7a8e85SJeff Kirsher lp = netdev_priv(dev);
1348ca7a8e85SJeff Kirsher ioaddr = dev->base_addr;
1349ca7a8e85SJeff Kirsher
1350ca7a8e85SJeff Kirsher spin_lock_irqsave(&lp->lock, flags);
1351ca7a8e85SJeff Kirsher
1352ca7a8e85SJeff Kirsher outw(PowerUp, ioaddr + EL3_CMD);
1353ca7a8e85SJeff Kirsher EL3WINDOW(0);
1354ca7a8e85SJeff Kirsher el3_up(dev);
1355ca7a8e85SJeff Kirsher
1356ca7a8e85SJeff Kirsher if (netif_running(dev))
1357ca7a8e85SJeff Kirsher netif_device_attach(dev);
1358ca7a8e85SJeff Kirsher
1359ca7a8e85SJeff Kirsher spin_unlock_irqrestore(&lp->lock, flags);
1360ca7a8e85SJeff Kirsher return 0;
1361ca7a8e85SJeff Kirsher }
1362ca7a8e85SJeff Kirsher
1363ca7a8e85SJeff Kirsher #endif /* CONFIG_PM */
1364ca7a8e85SJeff Kirsher
1365ca7a8e85SJeff Kirsher module_param(debug,int, 0);
1366df298408SDavid Howells module_param_hw_array(irq, int, irq, NULL, 0);
1367ca7a8e85SJeff Kirsher module_param(max_interrupt_work, int, 0);
1368ca7a8e85SJeff Kirsher MODULE_PARM_DESC(debug, "debug level (0-6)");
1369ca7a8e85SJeff Kirsher MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
1370ca7a8e85SJeff Kirsher MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
1371ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1372ca7a8e85SJeff Kirsher module_param(nopnp, int, 0);
1373ca7a8e85SJeff Kirsher MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)");
1374ca7a8e85SJeff Kirsher #endif /* CONFIG_PNP */
1375ca7a8e85SJeff Kirsher MODULE_DESCRIPTION("3Com Etherlink III (3c509, 3c509B, 3c529, 3c579) ethernet driver");
1376ca7a8e85SJeff Kirsher MODULE_LICENSE("GPL");
1377ca7a8e85SJeff Kirsher
el3_init_module(void)1378ca7a8e85SJeff Kirsher static int __init el3_init_module(void)
1379ca7a8e85SJeff Kirsher {
1380ca7a8e85SJeff Kirsher int ret = 0;
1381ca7a8e85SJeff Kirsher
1382ca7a8e85SJeff Kirsher if (debug >= 0)
1383ca7a8e85SJeff Kirsher el3_debug = debug;
1384ca7a8e85SJeff Kirsher
1385ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1386ca7a8e85SJeff Kirsher if (!nopnp) {
1387ca7a8e85SJeff Kirsher ret = pnp_register_driver(&el3_pnp_driver);
1388ca7a8e85SJeff Kirsher if (!ret)
1389ca7a8e85SJeff Kirsher pnp_registered = 1;
1390ca7a8e85SJeff Kirsher }
1391ca7a8e85SJeff Kirsher #endif
1392ca7a8e85SJeff Kirsher /* Select an open I/O location at 0x1*0 to do ISA contention select. */
1393ca7a8e85SJeff Kirsher /* Start with 0x110 to avoid some sound cards.*/
1394ca7a8e85SJeff Kirsher for (id_port = 0x110 ; id_port < 0x200; id_port += 0x10) {
1395ca7a8e85SJeff Kirsher if (!request_region(id_port, 1, "3c509-control"))
1396ca7a8e85SJeff Kirsher continue;
1397ca7a8e85SJeff Kirsher outb(0x00, id_port);
1398ca7a8e85SJeff Kirsher outb(0xff, id_port);
1399ca7a8e85SJeff Kirsher if (inb(id_port) & 0x01)
1400ca7a8e85SJeff Kirsher break;
1401ca7a8e85SJeff Kirsher else
1402ca7a8e85SJeff Kirsher release_region(id_port, 1);
1403ca7a8e85SJeff Kirsher }
1404ca7a8e85SJeff Kirsher if (id_port >= 0x200) {
1405ca7a8e85SJeff Kirsher id_port = 0;
1406ca7a8e85SJeff Kirsher pr_err("No I/O port available for 3c509 activation.\n");
1407ca7a8e85SJeff Kirsher } else {
1408ca7a8e85SJeff Kirsher ret = isa_register_driver(&el3_isa_driver, EL3_MAX_CARDS);
1409ca7a8e85SJeff Kirsher if (!ret)
1410ca7a8e85SJeff Kirsher isa_registered = 1;
1411ca7a8e85SJeff Kirsher }
1412ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
1413ca7a8e85SJeff Kirsher ret = eisa_driver_register(&el3_eisa_driver);
1414ca7a8e85SJeff Kirsher if (!ret)
1415ca7a8e85SJeff Kirsher eisa_registered = 1;
1416ca7a8e85SJeff Kirsher #endif
1417ca7a8e85SJeff Kirsher
1418ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1419ca7a8e85SJeff Kirsher if (pnp_registered)
1420ca7a8e85SJeff Kirsher ret = 0;
1421ca7a8e85SJeff Kirsher #endif
1422ca7a8e85SJeff Kirsher if (isa_registered)
1423ca7a8e85SJeff Kirsher ret = 0;
1424ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
1425ca7a8e85SJeff Kirsher if (eisa_registered)
1426ca7a8e85SJeff Kirsher ret = 0;
1427ca7a8e85SJeff Kirsher #endif
1428ca7a8e85SJeff Kirsher return ret;
1429ca7a8e85SJeff Kirsher }
1430ca7a8e85SJeff Kirsher
el3_cleanup_module(void)1431ca7a8e85SJeff Kirsher static void __exit el3_cleanup_module(void)
1432ca7a8e85SJeff Kirsher {
1433ca7a8e85SJeff Kirsher #ifdef CONFIG_PNP
1434ca7a8e85SJeff Kirsher if (pnp_registered)
1435ca7a8e85SJeff Kirsher pnp_unregister_driver(&el3_pnp_driver);
1436ca7a8e85SJeff Kirsher #endif
1437ca7a8e85SJeff Kirsher if (isa_registered)
1438ca7a8e85SJeff Kirsher isa_unregister_driver(&el3_isa_driver);
1439ca7a8e85SJeff Kirsher if (id_port)
1440ca7a8e85SJeff Kirsher release_region(id_port, 1);
1441ca7a8e85SJeff Kirsher #ifdef CONFIG_EISA
1442ca7a8e85SJeff Kirsher if (eisa_registered)
1443ca7a8e85SJeff Kirsher eisa_driver_unregister(&el3_eisa_driver);
1444ca7a8e85SJeff Kirsher #endif
1445ca7a8e85SJeff Kirsher }
1446ca7a8e85SJeff Kirsher
1447ca7a8e85SJeff Kirsher module_init (el3_init_module);
1448ca7a8e85SJeff Kirsher module_exit (el3_cleanup_module);
1449