1*dc3eb2f4SBagas Sanjaya // SPDX-License-Identifier: GPL-1.0+
2*dc3eb2f4SBagas Sanjaya
3644570b8SJeff Kirsher /*======================================================================
4644570b8SJeff Kirsher
5644570b8SJeff Kirsher A PCMCIA ethernet driver for Asix AX88190-based cards
6644570b8SJeff Kirsher
7644570b8SJeff Kirsher The Asix AX88190 is a NS8390-derived chipset with a few nasty
8644570b8SJeff Kirsher idiosyncracies that make it very inconvenient to support with a
9644570b8SJeff Kirsher standard 8390 driver. This driver is based on pcnet_cs, with the
10644570b8SJeff Kirsher tweaked 8390 code grafted on the end. Much of what I did was to
11644570b8SJeff Kirsher clean up and update a similar driver supplied by Asix, which was
12644570b8SJeff Kirsher adapted by William Lee, william@asix.com.tw.
13644570b8SJeff Kirsher
14644570b8SJeff Kirsher Copyright (C) 2001 David A. Hinds -- dahinds@users.sourceforge.net
15644570b8SJeff Kirsher
16644570b8SJeff Kirsher axnet_cs.c 1.28 2002/06/29 06:27:37
17644570b8SJeff Kirsher
18644570b8SJeff Kirsher The network driver code is based on Donald Becker's NE2000 code:
19644570b8SJeff Kirsher
20644570b8SJeff Kirsher Written 1992,1993 by Donald Becker.
21644570b8SJeff Kirsher Copyright 1993 United States Government as represented by the
22*dc3eb2f4SBagas Sanjaya Director, National Security Agency.
23644570b8SJeff Kirsher Donald Becker may be reached at becker@scyld.com
24644570b8SJeff Kirsher
25644570b8SJeff Kirsher ======================================================================*/
26644570b8SJeff Kirsher
27644570b8SJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28644570b8SJeff Kirsher
29644570b8SJeff Kirsher #include <linux/kernel.h>
30644570b8SJeff Kirsher #include <linux/module.h>
31644570b8SJeff Kirsher #include <linux/ptrace.h>
32644570b8SJeff Kirsher #include <linux/string.h>
33644570b8SJeff Kirsher #include <linux/timer.h>
34644570b8SJeff Kirsher #include <linux/delay.h>
35644570b8SJeff Kirsher #include <linux/spinlock.h>
36644570b8SJeff Kirsher #include <linux/netdevice.h>
37644570b8SJeff Kirsher #include <linux/etherdevice.h>
38644570b8SJeff Kirsher #include <linux/crc32.h>
39644570b8SJeff Kirsher #include <linux/mii.h>
40644570b8SJeff Kirsher #include "8390.h"
41644570b8SJeff Kirsher
42644570b8SJeff Kirsher #include <pcmcia/cistpl.h>
43644570b8SJeff Kirsher #include <pcmcia/ciscode.h>
44644570b8SJeff Kirsher #include <pcmcia/ds.h>
45644570b8SJeff Kirsher #include <pcmcia/cisreg.h>
46644570b8SJeff Kirsher
47644570b8SJeff Kirsher #include <asm/io.h>
48644570b8SJeff Kirsher #include <asm/byteorder.h>
497c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
50644570b8SJeff Kirsher
51644570b8SJeff Kirsher #define AXNET_CMD 0x00
52644570b8SJeff Kirsher #define AXNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
53644570b8SJeff Kirsher #define AXNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
54644570b8SJeff Kirsher #define AXNET_MII_EEP 0x14 /* Offset of MII access port */
55644570b8SJeff Kirsher #define AXNET_TEST 0x15 /* Offset of TEST Register port */
56644570b8SJeff Kirsher #define AXNET_GPIO 0x17 /* Offset of General Purpose Register Port */
57644570b8SJeff Kirsher
58644570b8SJeff Kirsher #define AXNET_START_PG 0x40 /* First page of TX buffer */
59644570b8SJeff Kirsher #define AXNET_STOP_PG 0x80 /* Last page +1 of RX ring */
60644570b8SJeff Kirsher
61644570b8SJeff Kirsher #define AXNET_RDC_TIMEOUT 0x02 /* Max wait in jiffies for Tx RDC */
62644570b8SJeff Kirsher
63644570b8SJeff Kirsher #define IS_AX88190 0x0001
64644570b8SJeff Kirsher #define IS_AX88790 0x0002
65644570b8SJeff Kirsher
66644570b8SJeff Kirsher /*====================================================================*/
67644570b8SJeff Kirsher
68644570b8SJeff Kirsher /* Module parameters */
69644570b8SJeff Kirsher
70644570b8SJeff Kirsher MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
71644570b8SJeff Kirsher MODULE_DESCRIPTION("Asix AX88190 PCMCIA ethernet driver");
72644570b8SJeff Kirsher MODULE_LICENSE("GPL");
73644570b8SJeff Kirsher
74644570b8SJeff Kirsher
75644570b8SJeff Kirsher /*====================================================================*/
76644570b8SJeff Kirsher
77644570b8SJeff Kirsher static int axnet_config(struct pcmcia_device *link);
78644570b8SJeff Kirsher static void axnet_release(struct pcmcia_device *link);
79644570b8SJeff Kirsher static int axnet_open(struct net_device *dev);
80644570b8SJeff Kirsher static int axnet_close(struct net_device *dev);
81644570b8SJeff Kirsher static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
82644570b8SJeff Kirsher static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
83644570b8SJeff Kirsher struct net_device *dev);
84644570b8SJeff Kirsher static struct net_device_stats *get_stats(struct net_device *dev);
85644570b8SJeff Kirsher static void set_multicast_list(struct net_device *dev);
860290bd29SMichael S. Tsirkin static void axnet_tx_timeout(struct net_device *dev, unsigned int txqueue);
87644570b8SJeff Kirsher static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
88c63144e4SKees Cook static void ei_watchdog(struct timer_list *t);
89644570b8SJeff Kirsher static void axnet_reset_8390(struct net_device *dev);
90644570b8SJeff Kirsher
91644570b8SJeff Kirsher static int mdio_read(unsigned int addr, int phy_id, int loc);
92644570b8SJeff Kirsher static void mdio_write(unsigned int addr, int phy_id, int loc, int value);
93644570b8SJeff Kirsher
94644570b8SJeff Kirsher static void get_8390_hdr(struct net_device *,
95644570b8SJeff Kirsher struct e8390_pkt_hdr *, int);
96644570b8SJeff Kirsher static void block_input(struct net_device *dev, int count,
97644570b8SJeff Kirsher struct sk_buff *skb, int ring_offset);
98644570b8SJeff Kirsher static void block_output(struct net_device *dev, int count,
99644570b8SJeff Kirsher const u_char *buf, const int start_page);
100644570b8SJeff Kirsher
101644570b8SJeff Kirsher static void axnet_detach(struct pcmcia_device *p_dev);
102644570b8SJeff Kirsher
103644570b8SJeff Kirsher static void AX88190_init(struct net_device *dev, int startp);
104644570b8SJeff Kirsher static int ax_open(struct net_device *dev);
105644570b8SJeff Kirsher static int ax_close(struct net_device *dev);
106644570b8SJeff Kirsher static irqreturn_t ax_interrupt(int irq, void *dev_id);
107644570b8SJeff Kirsher
108644570b8SJeff Kirsher /*====================================================================*/
109644570b8SJeff Kirsher
110abac0d3fSHimangi Saraogi struct axnet_dev {
111644570b8SJeff Kirsher struct pcmcia_device *p_dev;
112644570b8SJeff Kirsher caddr_t base;
113644570b8SJeff Kirsher struct timer_list watchdog;
114644570b8SJeff Kirsher int stale, fast_poll;
115644570b8SJeff Kirsher u_short link_status;
116644570b8SJeff Kirsher u_char duplex_flag;
117644570b8SJeff Kirsher int phy_id;
118644570b8SJeff Kirsher int flags;
119644570b8SJeff Kirsher int active_low;
120abac0d3fSHimangi Saraogi };
121644570b8SJeff Kirsher
PRIV(struct net_device * dev)122abac0d3fSHimangi Saraogi static inline struct axnet_dev *PRIV(struct net_device *dev)
123644570b8SJeff Kirsher {
124644570b8SJeff Kirsher void *p = (char *)netdev_priv(dev) + sizeof(struct ei_device);
125644570b8SJeff Kirsher return p;
126644570b8SJeff Kirsher }
127644570b8SJeff Kirsher
128644570b8SJeff Kirsher static const struct net_device_ops axnet_netdev_ops = {
129644570b8SJeff Kirsher .ndo_open = axnet_open,
130644570b8SJeff Kirsher .ndo_stop = axnet_close,
131a7605370SArnd Bergmann .ndo_eth_ioctl = axnet_ioctl,
132644570b8SJeff Kirsher .ndo_start_xmit = axnet_start_xmit,
133644570b8SJeff Kirsher .ndo_tx_timeout = axnet_tx_timeout,
134644570b8SJeff Kirsher .ndo_get_stats = get_stats,
135afc4b13dSJiri Pirko .ndo_set_rx_mode = set_multicast_list,
136644570b8SJeff Kirsher .ndo_set_mac_address = eth_mac_addr,
137644570b8SJeff Kirsher .ndo_validate_addr = eth_validate_addr,
138644570b8SJeff Kirsher };
139644570b8SJeff Kirsher
axnet_probe(struct pcmcia_device * link)140644570b8SJeff Kirsher static int axnet_probe(struct pcmcia_device *link)
141644570b8SJeff Kirsher {
142abac0d3fSHimangi Saraogi struct axnet_dev *info;
143644570b8SJeff Kirsher struct net_device *dev;
144644570b8SJeff Kirsher struct ei_device *ei_local;
145644570b8SJeff Kirsher
146644570b8SJeff Kirsher dev_dbg(&link->dev, "axnet_attach()\n");
147644570b8SJeff Kirsher
148abac0d3fSHimangi Saraogi dev = alloc_etherdev(sizeof(struct ei_device) + sizeof(struct axnet_dev));
149644570b8SJeff Kirsher if (!dev)
150644570b8SJeff Kirsher return -ENOMEM;
151644570b8SJeff Kirsher
152644570b8SJeff Kirsher ei_local = netdev_priv(dev);
153644570b8SJeff Kirsher spin_lock_init(&ei_local->page_lock);
154644570b8SJeff Kirsher
155644570b8SJeff Kirsher info = PRIV(dev);
156644570b8SJeff Kirsher info->p_dev = link;
157644570b8SJeff Kirsher link->priv = dev;
158644570b8SJeff Kirsher link->config_flags |= CONF_ENABLE_IRQ;
159644570b8SJeff Kirsher
160644570b8SJeff Kirsher dev->netdev_ops = &axnet_netdev_ops;
161644570b8SJeff Kirsher
162644570b8SJeff Kirsher dev->watchdog_timeo = TX_TIMEOUT;
163644570b8SJeff Kirsher
164644570b8SJeff Kirsher return axnet_config(link);
165644570b8SJeff Kirsher } /* axnet_attach */
166644570b8SJeff Kirsher
axnet_detach(struct pcmcia_device * link)167644570b8SJeff Kirsher static void axnet_detach(struct pcmcia_device *link)
168644570b8SJeff Kirsher {
169644570b8SJeff Kirsher struct net_device *dev = link->priv;
170644570b8SJeff Kirsher
171644570b8SJeff Kirsher dev_dbg(&link->dev, "axnet_detach(0x%p)\n", link);
172644570b8SJeff Kirsher
173644570b8SJeff Kirsher unregister_netdev(dev);
174644570b8SJeff Kirsher
175644570b8SJeff Kirsher axnet_release(link);
176644570b8SJeff Kirsher
177644570b8SJeff Kirsher free_netdev(dev);
178644570b8SJeff Kirsher } /* axnet_detach */
179644570b8SJeff Kirsher
180644570b8SJeff Kirsher /*======================================================================
181644570b8SJeff Kirsher
182644570b8SJeff Kirsher This probes for a card's hardware address by reading the PROM.
183644570b8SJeff Kirsher
184644570b8SJeff Kirsher ======================================================================*/
185644570b8SJeff Kirsher
get_prom(struct pcmcia_device * link)186644570b8SJeff Kirsher static int get_prom(struct pcmcia_device *link)
187644570b8SJeff Kirsher {
188644570b8SJeff Kirsher struct net_device *dev = link->priv;
189644570b8SJeff Kirsher unsigned int ioaddr = dev->base_addr;
1908ce218b6SJakub Kicinski u8 addr[ETH_ALEN];
191644570b8SJeff Kirsher int i, j;
192644570b8SJeff Kirsher
1933396c782SPaul Gortmaker /* This is based on drivers/net/ethernet/8390/ne.c */
194644570b8SJeff Kirsher struct {
195644570b8SJeff Kirsher u_char value, offset;
196644570b8SJeff Kirsher } program_seq[] = {
197644570b8SJeff Kirsher {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
198644570b8SJeff Kirsher {0x01, EN0_DCFG}, /* Set word-wide access. */
199644570b8SJeff Kirsher {0x00, EN0_RCNTLO}, /* Clear the count regs. */
200644570b8SJeff Kirsher {0x00, EN0_RCNTHI},
201644570b8SJeff Kirsher {0x00, EN0_IMR}, /* Mask completion irq. */
202644570b8SJeff Kirsher {0xFF, EN0_ISR},
203644570b8SJeff Kirsher {E8390_RXOFF|0x40, EN0_RXCR}, /* 0x60 Set to monitor */
204644570b8SJeff Kirsher {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
205644570b8SJeff Kirsher {0x10, EN0_RCNTLO},
206644570b8SJeff Kirsher {0x00, EN0_RCNTHI},
207644570b8SJeff Kirsher {0x00, EN0_RSARLO}, /* DMA starting at 0x0400. */
208644570b8SJeff Kirsher {0x04, EN0_RSARHI},
209644570b8SJeff Kirsher {E8390_RREAD+E8390_START, E8390_CMD},
210644570b8SJeff Kirsher };
211644570b8SJeff Kirsher
212644570b8SJeff Kirsher /* Not much of a test, but the alternatives are messy */
213644570b8SJeff Kirsher if (link->config_base != 0x03c0)
214644570b8SJeff Kirsher return 0;
215644570b8SJeff Kirsher
216644570b8SJeff Kirsher axnet_reset_8390(dev);
217644570b8SJeff Kirsher mdelay(10);
218644570b8SJeff Kirsher
219644570b8SJeff Kirsher for (i = 0; i < ARRAY_SIZE(program_seq); i++)
220644570b8SJeff Kirsher outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
221644570b8SJeff Kirsher
222644570b8SJeff Kirsher for (i = 0; i < 6; i += 2) {
223644570b8SJeff Kirsher j = inw(ioaddr + AXNET_DATAPORT);
2248ce218b6SJakub Kicinski addr[i] = j & 0xff;
2258ce218b6SJakub Kicinski addr[i+1] = j >> 8;
226644570b8SJeff Kirsher }
2278ce218b6SJakub Kicinski eth_hw_addr_set(dev, addr);
2288ce218b6SJakub Kicinski
229644570b8SJeff Kirsher return 1;
230644570b8SJeff Kirsher } /* get_prom */
231644570b8SJeff Kirsher
try_io_port(struct pcmcia_device * link)232644570b8SJeff Kirsher static int try_io_port(struct pcmcia_device *link)
233644570b8SJeff Kirsher {
234644570b8SJeff Kirsher int j, ret;
235644570b8SJeff Kirsher link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
236644570b8SJeff Kirsher link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
237644570b8SJeff Kirsher if (link->resource[0]->end == 32) {
238644570b8SJeff Kirsher link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
239644570b8SJeff Kirsher /* for master/slave multifunction cards */
240644570b8SJeff Kirsher if (link->resource[1]->end > 0)
241644570b8SJeff Kirsher link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
242644570b8SJeff Kirsher } else {
243644570b8SJeff Kirsher /* This should be two 16-port windows */
244644570b8SJeff Kirsher link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
245644570b8SJeff Kirsher link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
246644570b8SJeff Kirsher }
247644570b8SJeff Kirsher if (link->resource[0]->start == 0) {
248644570b8SJeff Kirsher for (j = 0; j < 0x400; j += 0x20) {
249644570b8SJeff Kirsher link->resource[0]->start = j ^ 0x300;
250644570b8SJeff Kirsher link->resource[1]->start = (j ^ 0x300) + 0x10;
251644570b8SJeff Kirsher link->io_lines = 16;
252644570b8SJeff Kirsher ret = pcmcia_request_io(link);
253644570b8SJeff Kirsher if (ret == 0)
254644570b8SJeff Kirsher return ret;
255644570b8SJeff Kirsher }
256644570b8SJeff Kirsher return ret;
257644570b8SJeff Kirsher } else {
258644570b8SJeff Kirsher return pcmcia_request_io(link);
259644570b8SJeff Kirsher }
260644570b8SJeff Kirsher }
261644570b8SJeff Kirsher
axnet_configcheck(struct pcmcia_device * p_dev,void * priv_data)262644570b8SJeff Kirsher static int axnet_configcheck(struct pcmcia_device *p_dev, void *priv_data)
263644570b8SJeff Kirsher {
264644570b8SJeff Kirsher if (p_dev->config_index == 0)
265644570b8SJeff Kirsher return -EINVAL;
266644570b8SJeff Kirsher
267644570b8SJeff Kirsher p_dev->config_index = 0x05;
268644570b8SJeff Kirsher if (p_dev->resource[0]->end + p_dev->resource[1]->end < 32)
269644570b8SJeff Kirsher return -ENODEV;
270644570b8SJeff Kirsher
271644570b8SJeff Kirsher return try_io_port(p_dev);
272644570b8SJeff Kirsher }
273644570b8SJeff Kirsher
axnet_config(struct pcmcia_device * link)274644570b8SJeff Kirsher static int axnet_config(struct pcmcia_device *link)
275644570b8SJeff Kirsher {
276644570b8SJeff Kirsher struct net_device *dev = link->priv;
277abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
278644570b8SJeff Kirsher int i, j, j2, ret;
279644570b8SJeff Kirsher
280644570b8SJeff Kirsher dev_dbg(&link->dev, "axnet_config(0x%p)\n", link);
281644570b8SJeff Kirsher
282644570b8SJeff Kirsher /* don't trust the CIS on this; Linksys got it wrong */
283644570b8SJeff Kirsher link->config_regs = 0x63;
284644570b8SJeff Kirsher link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
285644570b8SJeff Kirsher ret = pcmcia_loop_config(link, axnet_configcheck, NULL);
286644570b8SJeff Kirsher if (ret != 0)
287644570b8SJeff Kirsher goto failed;
288644570b8SJeff Kirsher
289644570b8SJeff Kirsher if (!link->irq)
290644570b8SJeff Kirsher goto failed;
291644570b8SJeff Kirsher
292644570b8SJeff Kirsher if (resource_size(link->resource[1]) == 8)
293644570b8SJeff Kirsher link->config_flags |= CONF_ENABLE_SPKR;
294644570b8SJeff Kirsher
295644570b8SJeff Kirsher ret = pcmcia_enable_device(link);
296644570b8SJeff Kirsher if (ret)
297644570b8SJeff Kirsher goto failed;
298644570b8SJeff Kirsher
299644570b8SJeff Kirsher dev->irq = link->irq;
300644570b8SJeff Kirsher dev->base_addr = link->resource[0]->start;
301644570b8SJeff Kirsher
302644570b8SJeff Kirsher if (!get_prom(link)) {
303644570b8SJeff Kirsher pr_notice("this is not an AX88190 card!\n");
304644570b8SJeff Kirsher pr_notice("use pcnet_cs instead.\n");
305644570b8SJeff Kirsher goto failed;
306644570b8SJeff Kirsher }
307644570b8SJeff Kirsher
308644570b8SJeff Kirsher ei_status.name = "AX88190";
309644570b8SJeff Kirsher ei_status.word16 = 1;
310644570b8SJeff Kirsher ei_status.tx_start_page = AXNET_START_PG;
311644570b8SJeff Kirsher ei_status.rx_start_page = AXNET_START_PG + TX_PAGES;
312644570b8SJeff Kirsher ei_status.stop_page = AXNET_STOP_PG;
313644570b8SJeff Kirsher ei_status.reset_8390 = axnet_reset_8390;
314644570b8SJeff Kirsher ei_status.get_8390_hdr = get_8390_hdr;
315644570b8SJeff Kirsher ei_status.block_input = block_input;
316644570b8SJeff Kirsher ei_status.block_output = block_output;
317644570b8SJeff Kirsher
318644570b8SJeff Kirsher if (inb(dev->base_addr + AXNET_TEST) != 0)
319644570b8SJeff Kirsher info->flags |= IS_AX88790;
320644570b8SJeff Kirsher else
321644570b8SJeff Kirsher info->flags |= IS_AX88190;
322644570b8SJeff Kirsher
323644570b8SJeff Kirsher if (info->flags & IS_AX88790)
324644570b8SJeff Kirsher outb(0x10, dev->base_addr + AXNET_GPIO); /* select Internal PHY */
325644570b8SJeff Kirsher
326644570b8SJeff Kirsher info->active_low = 0;
327644570b8SJeff Kirsher
328644570b8SJeff Kirsher for (i = 0; i < 32; i++) {
329644570b8SJeff Kirsher j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
330644570b8SJeff Kirsher j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
331644570b8SJeff Kirsher if (j == j2) continue;
332644570b8SJeff Kirsher if ((j != 0) && (j != 0xffff)) break;
333644570b8SJeff Kirsher }
334644570b8SJeff Kirsher
335644570b8SJeff Kirsher if (i == 32) {
336644570b8SJeff Kirsher /* Maybe PHY is in power down mode. (PPD_SET = 1)
337644570b8SJeff Kirsher Bit 2 of CCSR is active low. */
338644570b8SJeff Kirsher pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
339644570b8SJeff Kirsher for (i = 0; i < 32; i++) {
340644570b8SJeff Kirsher j = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 1);
341644570b8SJeff Kirsher j2 = mdio_read(dev->base_addr + AXNET_MII_EEP, i, 2);
342644570b8SJeff Kirsher if (j == j2) continue;
343644570b8SJeff Kirsher if ((j != 0) && (j != 0xffff)) {
344644570b8SJeff Kirsher info->active_low = 1;
345644570b8SJeff Kirsher break;
346644570b8SJeff Kirsher }
347644570b8SJeff Kirsher }
348644570b8SJeff Kirsher }
349644570b8SJeff Kirsher
350644570b8SJeff Kirsher info->phy_id = (i < 32) ? i : -1;
351644570b8SJeff Kirsher SET_NETDEV_DEV(dev, &link->dev);
352644570b8SJeff Kirsher
353644570b8SJeff Kirsher if (register_netdev(dev) != 0) {
354644570b8SJeff Kirsher pr_notice("register_netdev() failed\n");
355644570b8SJeff Kirsher goto failed;
356644570b8SJeff Kirsher }
357644570b8SJeff Kirsher
358644570b8SJeff Kirsher netdev_info(dev, "Asix AX88%d90: io %#3lx, irq %d, hw_addr %pM\n",
359644570b8SJeff Kirsher ((info->flags & IS_AX88790) ? 7 : 1),
360644570b8SJeff Kirsher dev->base_addr, dev->irq, dev->dev_addr);
361644570b8SJeff Kirsher if (info->phy_id != -1) {
362644570b8SJeff Kirsher netdev_dbg(dev, " MII transceiver at index %d, status %x\n",
363644570b8SJeff Kirsher info->phy_id, j);
364644570b8SJeff Kirsher } else {
365644570b8SJeff Kirsher netdev_notice(dev, " No MII transceivers found!\n");
366644570b8SJeff Kirsher }
367644570b8SJeff Kirsher return 0;
368644570b8SJeff Kirsher
369644570b8SJeff Kirsher failed:
370644570b8SJeff Kirsher axnet_release(link);
371644570b8SJeff Kirsher return -ENODEV;
372644570b8SJeff Kirsher } /* axnet_config */
373644570b8SJeff Kirsher
axnet_release(struct pcmcia_device * link)374644570b8SJeff Kirsher static void axnet_release(struct pcmcia_device *link)
375644570b8SJeff Kirsher {
376644570b8SJeff Kirsher pcmcia_disable_device(link);
377644570b8SJeff Kirsher }
378644570b8SJeff Kirsher
axnet_suspend(struct pcmcia_device * link)379644570b8SJeff Kirsher static int axnet_suspend(struct pcmcia_device *link)
380644570b8SJeff Kirsher {
381644570b8SJeff Kirsher struct net_device *dev = link->priv;
382644570b8SJeff Kirsher
383644570b8SJeff Kirsher if (link->open)
384644570b8SJeff Kirsher netif_device_detach(dev);
385644570b8SJeff Kirsher
386644570b8SJeff Kirsher return 0;
387644570b8SJeff Kirsher }
388644570b8SJeff Kirsher
axnet_resume(struct pcmcia_device * link)389644570b8SJeff Kirsher static int axnet_resume(struct pcmcia_device *link)
390644570b8SJeff Kirsher {
391644570b8SJeff Kirsher struct net_device *dev = link->priv;
392abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
393644570b8SJeff Kirsher
394644570b8SJeff Kirsher if (link->open) {
395644570b8SJeff Kirsher if (info->active_low == 1)
396644570b8SJeff Kirsher pcmcia_write_config_byte(link, CISREG_CCSR, 0x04);
397644570b8SJeff Kirsher
398644570b8SJeff Kirsher axnet_reset_8390(dev);
399644570b8SJeff Kirsher AX88190_init(dev, 1);
400644570b8SJeff Kirsher netif_device_attach(dev);
401644570b8SJeff Kirsher }
402644570b8SJeff Kirsher
403644570b8SJeff Kirsher return 0;
404644570b8SJeff Kirsher }
405644570b8SJeff Kirsher
406644570b8SJeff Kirsher
407644570b8SJeff Kirsher /*======================================================================
408644570b8SJeff Kirsher
409644570b8SJeff Kirsher MII interface support
410644570b8SJeff Kirsher
411644570b8SJeff Kirsher ======================================================================*/
412644570b8SJeff Kirsher
413644570b8SJeff Kirsher #define MDIO_SHIFT_CLK 0x01
414644570b8SJeff Kirsher #define MDIO_DATA_WRITE0 0x00
415644570b8SJeff Kirsher #define MDIO_DATA_WRITE1 0x08
416644570b8SJeff Kirsher #define MDIO_DATA_READ 0x04
417644570b8SJeff Kirsher #define MDIO_MASK 0x0f
418644570b8SJeff Kirsher #define MDIO_ENB_IN 0x02
419644570b8SJeff Kirsher
mdio_sync(unsigned int addr)420644570b8SJeff Kirsher static void mdio_sync(unsigned int addr)
421644570b8SJeff Kirsher {
422644570b8SJeff Kirsher int bits;
423644570b8SJeff Kirsher for (bits = 0; bits < 32; bits++) {
424644570b8SJeff Kirsher outb_p(MDIO_DATA_WRITE1, addr);
425644570b8SJeff Kirsher outb_p(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
426644570b8SJeff Kirsher }
427644570b8SJeff Kirsher }
428644570b8SJeff Kirsher
mdio_read(unsigned int addr,int phy_id,int loc)429644570b8SJeff Kirsher static int mdio_read(unsigned int addr, int phy_id, int loc)
430644570b8SJeff Kirsher {
431644570b8SJeff Kirsher u_int cmd = (0xf6<<10)|(phy_id<<5)|loc;
432644570b8SJeff Kirsher int i, retval = 0;
433644570b8SJeff Kirsher
434644570b8SJeff Kirsher mdio_sync(addr);
435644570b8SJeff Kirsher for (i = 14; i >= 0; i--) {
436644570b8SJeff Kirsher int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
437644570b8SJeff Kirsher outb_p(dat, addr);
438644570b8SJeff Kirsher outb_p(dat | MDIO_SHIFT_CLK, addr);
439644570b8SJeff Kirsher }
440644570b8SJeff Kirsher for (i = 19; i > 0; i--) {
441644570b8SJeff Kirsher outb_p(MDIO_ENB_IN, addr);
442644570b8SJeff Kirsher retval = (retval << 1) | ((inb_p(addr) & MDIO_DATA_READ) != 0);
443644570b8SJeff Kirsher outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
444644570b8SJeff Kirsher }
445644570b8SJeff Kirsher return (retval>>1) & 0xffff;
446644570b8SJeff Kirsher }
447644570b8SJeff Kirsher
mdio_write(unsigned int addr,int phy_id,int loc,int value)448644570b8SJeff Kirsher static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
449644570b8SJeff Kirsher {
450644570b8SJeff Kirsher u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
451644570b8SJeff Kirsher int i;
452644570b8SJeff Kirsher
453644570b8SJeff Kirsher mdio_sync(addr);
454644570b8SJeff Kirsher for (i = 31; i >= 0; i--) {
455644570b8SJeff Kirsher int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
456644570b8SJeff Kirsher outb_p(dat, addr);
457644570b8SJeff Kirsher outb_p(dat | MDIO_SHIFT_CLK, addr);
458644570b8SJeff Kirsher }
459644570b8SJeff Kirsher for (i = 1; i >= 0; i--) {
460644570b8SJeff Kirsher outb_p(MDIO_ENB_IN, addr);
461644570b8SJeff Kirsher outb_p(MDIO_ENB_IN | MDIO_SHIFT_CLK, addr);
462644570b8SJeff Kirsher }
463644570b8SJeff Kirsher }
464644570b8SJeff Kirsher
465644570b8SJeff Kirsher /*====================================================================*/
466644570b8SJeff Kirsher
axnet_open(struct net_device * dev)467644570b8SJeff Kirsher static int axnet_open(struct net_device *dev)
468644570b8SJeff Kirsher {
469644570b8SJeff Kirsher int ret;
470abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
471644570b8SJeff Kirsher struct pcmcia_device *link = info->p_dev;
472644570b8SJeff Kirsher unsigned int nic_base = dev->base_addr;
473644570b8SJeff Kirsher
474644570b8SJeff Kirsher dev_dbg(&link->dev, "axnet_open('%s')\n", dev->name);
475644570b8SJeff Kirsher
476644570b8SJeff Kirsher if (!pcmcia_dev_present(link))
477644570b8SJeff Kirsher return -ENODEV;
478644570b8SJeff Kirsher
479644570b8SJeff Kirsher outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
480644570b8SJeff Kirsher ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, "axnet_cs", dev);
481644570b8SJeff Kirsher if (ret)
482644570b8SJeff Kirsher return ret;
483644570b8SJeff Kirsher
484644570b8SJeff Kirsher link->open++;
485644570b8SJeff Kirsher
486644570b8SJeff Kirsher info->link_status = 0x00;
487c63144e4SKees Cook timer_setup(&info->watchdog, ei_watchdog, 0);
4886753a971SVaishali Thakkar mod_timer(&info->watchdog, jiffies + HZ);
489644570b8SJeff Kirsher
490644570b8SJeff Kirsher return ax_open(dev);
491644570b8SJeff Kirsher } /* axnet_open */
492644570b8SJeff Kirsher
493644570b8SJeff Kirsher /*====================================================================*/
494644570b8SJeff Kirsher
axnet_close(struct net_device * dev)495644570b8SJeff Kirsher static int axnet_close(struct net_device *dev)
496644570b8SJeff Kirsher {
497abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
498644570b8SJeff Kirsher struct pcmcia_device *link = info->p_dev;
499644570b8SJeff Kirsher
500644570b8SJeff Kirsher dev_dbg(&link->dev, "axnet_close('%s')\n", dev->name);
501644570b8SJeff Kirsher
502644570b8SJeff Kirsher ax_close(dev);
503644570b8SJeff Kirsher free_irq(dev->irq, dev);
504644570b8SJeff Kirsher
505644570b8SJeff Kirsher link->open--;
506644570b8SJeff Kirsher netif_stop_queue(dev);
507644570b8SJeff Kirsher del_timer_sync(&info->watchdog);
508644570b8SJeff Kirsher
509644570b8SJeff Kirsher return 0;
510644570b8SJeff Kirsher } /* axnet_close */
511644570b8SJeff Kirsher
512644570b8SJeff Kirsher /*======================================================================
513644570b8SJeff Kirsher
514644570b8SJeff Kirsher Hard reset the card. This used to pause for the same period that
515644570b8SJeff Kirsher a 8390 reset command required, but that shouldn't be necessary.
516644570b8SJeff Kirsher
517644570b8SJeff Kirsher ======================================================================*/
518644570b8SJeff Kirsher
axnet_reset_8390(struct net_device * dev)519644570b8SJeff Kirsher static void axnet_reset_8390(struct net_device *dev)
520644570b8SJeff Kirsher {
521644570b8SJeff Kirsher unsigned int nic_base = dev->base_addr;
522644570b8SJeff Kirsher int i;
523644570b8SJeff Kirsher
524644570b8SJeff Kirsher ei_status.txing = ei_status.dmaing = 0;
525644570b8SJeff Kirsher
526644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
527644570b8SJeff Kirsher
528644570b8SJeff Kirsher outb(inb(nic_base + AXNET_RESET), nic_base + AXNET_RESET);
529644570b8SJeff Kirsher
530644570b8SJeff Kirsher for (i = 0; i < 100; i++) {
531644570b8SJeff Kirsher if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
532644570b8SJeff Kirsher break;
533644570b8SJeff Kirsher udelay(100);
534644570b8SJeff Kirsher }
535644570b8SJeff Kirsher outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
536644570b8SJeff Kirsher
537644570b8SJeff Kirsher if (i == 100)
538644570b8SJeff Kirsher netdev_err(dev, "axnet_reset_8390() did not complete\n");
539644570b8SJeff Kirsher
540644570b8SJeff Kirsher } /* axnet_reset_8390 */
541644570b8SJeff Kirsher
542644570b8SJeff Kirsher /*====================================================================*/
543644570b8SJeff Kirsher
ei_irq_wrapper(int irq,void * dev_id)544644570b8SJeff Kirsher static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
545644570b8SJeff Kirsher {
546644570b8SJeff Kirsher struct net_device *dev = dev_id;
547644570b8SJeff Kirsher PRIV(dev)->stale = 0;
548644570b8SJeff Kirsher return ax_interrupt(irq, dev_id);
549644570b8SJeff Kirsher }
550644570b8SJeff Kirsher
ei_watchdog(struct timer_list * t)551c63144e4SKees Cook static void ei_watchdog(struct timer_list *t)
552644570b8SJeff Kirsher {
553c63144e4SKees Cook struct axnet_dev *info = from_timer(info, t, watchdog);
554c63144e4SKees Cook struct net_device *dev = info->p_dev->priv;
555644570b8SJeff Kirsher unsigned int nic_base = dev->base_addr;
556644570b8SJeff Kirsher unsigned int mii_addr = nic_base + AXNET_MII_EEP;
557644570b8SJeff Kirsher u_short link;
558644570b8SJeff Kirsher
559644570b8SJeff Kirsher if (!netif_device_present(dev)) goto reschedule;
560644570b8SJeff Kirsher
561644570b8SJeff Kirsher /* Check for pending interrupt with expired latency timer: with
562644570b8SJeff Kirsher this, we can limp along even if the interrupt is blocked */
563644570b8SJeff Kirsher if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
564644570b8SJeff Kirsher if (!info->fast_poll)
565644570b8SJeff Kirsher netdev_info(dev, "interrupt(s) dropped!\n");
566644570b8SJeff Kirsher ei_irq_wrapper(dev->irq, dev);
567644570b8SJeff Kirsher info->fast_poll = HZ;
568644570b8SJeff Kirsher }
569644570b8SJeff Kirsher if (info->fast_poll) {
570644570b8SJeff Kirsher info->fast_poll--;
571644570b8SJeff Kirsher info->watchdog.expires = jiffies + 1;
572644570b8SJeff Kirsher add_timer(&info->watchdog);
573644570b8SJeff Kirsher return;
574644570b8SJeff Kirsher }
575644570b8SJeff Kirsher
576644570b8SJeff Kirsher if (info->phy_id < 0)
577644570b8SJeff Kirsher goto reschedule;
578644570b8SJeff Kirsher link = mdio_read(mii_addr, info->phy_id, 1);
579644570b8SJeff Kirsher if (!link || (link == 0xffff)) {
580644570b8SJeff Kirsher netdev_info(dev, "MII is missing!\n");
581644570b8SJeff Kirsher info->phy_id = -1;
582644570b8SJeff Kirsher goto reschedule;
583644570b8SJeff Kirsher }
584644570b8SJeff Kirsher
585644570b8SJeff Kirsher link &= 0x0004;
586644570b8SJeff Kirsher if (link != info->link_status) {
587644570b8SJeff Kirsher u_short p = mdio_read(mii_addr, info->phy_id, 5);
588644570b8SJeff Kirsher netdev_info(dev, "%s link beat\n", link ? "found" : "lost");
589644570b8SJeff Kirsher if (link) {
590644570b8SJeff Kirsher info->duplex_flag = (p & 0x0140) ? 0x80 : 0x00;
591644570b8SJeff Kirsher if (p)
592644570b8SJeff Kirsher netdev_info(dev, "autonegotiation complete: %dbaseT-%cD selected\n",
593644570b8SJeff Kirsher (p & 0x0180) ? 100 : 10, (p & 0x0140) ? 'F' : 'H');
594644570b8SJeff Kirsher else
595644570b8SJeff Kirsher netdev_info(dev, "link partner did not autonegotiate\n");
596644570b8SJeff Kirsher AX88190_init(dev, 1);
597644570b8SJeff Kirsher }
598644570b8SJeff Kirsher info->link_status = link;
599644570b8SJeff Kirsher }
600644570b8SJeff Kirsher
601644570b8SJeff Kirsher reschedule:
602644570b8SJeff Kirsher info->watchdog.expires = jiffies + HZ;
603644570b8SJeff Kirsher add_timer(&info->watchdog);
604644570b8SJeff Kirsher }
605644570b8SJeff Kirsher
606644570b8SJeff Kirsher /*====================================================================*/
607644570b8SJeff Kirsher
axnet_ioctl(struct net_device * dev,struct ifreq * rq,int cmd)608644570b8SJeff Kirsher static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
609644570b8SJeff Kirsher {
610abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
611644570b8SJeff Kirsher struct mii_ioctl_data *data = if_mii(rq);
612644570b8SJeff Kirsher unsigned int mii_addr = dev->base_addr + AXNET_MII_EEP;
613644570b8SJeff Kirsher switch (cmd) {
614644570b8SJeff Kirsher case SIOCGMIIPHY:
615644570b8SJeff Kirsher data->phy_id = info->phy_id;
616df561f66SGustavo A. R. Silva fallthrough;
617644570b8SJeff Kirsher case SIOCGMIIREG: /* Read MII PHY register. */
618644570b8SJeff Kirsher data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
619644570b8SJeff Kirsher return 0;
620644570b8SJeff Kirsher case SIOCSMIIREG: /* Write MII PHY register. */
621644570b8SJeff Kirsher mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
622644570b8SJeff Kirsher return 0;
623644570b8SJeff Kirsher }
624644570b8SJeff Kirsher return -EOPNOTSUPP;
625644570b8SJeff Kirsher }
626644570b8SJeff Kirsher
627644570b8SJeff Kirsher /*====================================================================*/
628644570b8SJeff Kirsher
get_8390_hdr(struct net_device * dev,struct e8390_pkt_hdr * hdr,int ring_page)629644570b8SJeff Kirsher static void get_8390_hdr(struct net_device *dev,
630644570b8SJeff Kirsher struct e8390_pkt_hdr *hdr,
631644570b8SJeff Kirsher int ring_page)
632644570b8SJeff Kirsher {
633644570b8SJeff Kirsher unsigned int nic_base = dev->base_addr;
634644570b8SJeff Kirsher
635644570b8SJeff Kirsher outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
636644570b8SJeff Kirsher outb_p(ring_page, nic_base + EN0_RSARHI);
637644570b8SJeff Kirsher outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
638644570b8SJeff Kirsher
639644570b8SJeff Kirsher insw(nic_base + AXNET_DATAPORT, hdr,
640644570b8SJeff Kirsher sizeof(struct e8390_pkt_hdr)>>1);
641644570b8SJeff Kirsher /* Fix for big endian systems */
642644570b8SJeff Kirsher hdr->count = le16_to_cpu(hdr->count);
643644570b8SJeff Kirsher
644644570b8SJeff Kirsher }
645644570b8SJeff Kirsher
646644570b8SJeff Kirsher /*====================================================================*/
647644570b8SJeff Kirsher
block_input(struct net_device * dev,int count,struct sk_buff * skb,int ring_offset)648644570b8SJeff Kirsher static void block_input(struct net_device *dev, int count,
649644570b8SJeff Kirsher struct sk_buff *skb, int ring_offset)
650644570b8SJeff Kirsher {
651644570b8SJeff Kirsher unsigned int nic_base = dev->base_addr;
652c45f812fSMatthew Whitehead struct ei_device *ei_local = netdev_priv(dev);
653644570b8SJeff Kirsher char *buf = skb->data;
654644570b8SJeff Kirsher
655c45f812fSMatthew Whitehead if ((netif_msg_rx_status(ei_local)) && (count != 4))
656c45f812fSMatthew Whitehead netdev_dbg(dev, "[bi=%d]\n", count+4);
657644570b8SJeff Kirsher outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
658644570b8SJeff Kirsher outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
659644570b8SJeff Kirsher outb_p(E8390_RREAD+E8390_START, nic_base + AXNET_CMD);
660644570b8SJeff Kirsher
661644570b8SJeff Kirsher insw(nic_base + AXNET_DATAPORT,buf,count>>1);
662e7fee115SJoe Perches if (count & 0x01) {
663e7fee115SJoe Perches buf[count-1] = inb(nic_base + AXNET_DATAPORT);
664e7fee115SJoe Perches }
665644570b8SJeff Kirsher }
666644570b8SJeff Kirsher
667644570b8SJeff Kirsher /*====================================================================*/
668644570b8SJeff Kirsher
block_output(struct net_device * dev,int count,const u_char * buf,const int start_page)669644570b8SJeff Kirsher static void block_output(struct net_device *dev, int count,
670644570b8SJeff Kirsher const u_char *buf, const int start_page)
671644570b8SJeff Kirsher {
672644570b8SJeff Kirsher unsigned int nic_base = dev->base_addr;
673644570b8SJeff Kirsher
674644570b8SJeff Kirsher pr_debug("%s: [bo=%d]\n", dev->name, count);
675644570b8SJeff Kirsher
676644570b8SJeff Kirsher /* Round the count up for word writes. Do we need to do this?
677644570b8SJeff Kirsher What effect will an odd byte count have on the 8390?
678644570b8SJeff Kirsher I should check someday. */
679644570b8SJeff Kirsher if (count & 0x01)
680644570b8SJeff Kirsher count++;
681644570b8SJeff Kirsher
682644570b8SJeff Kirsher outb_p(0x00, nic_base + EN0_RSARLO);
683644570b8SJeff Kirsher outb_p(start_page, nic_base + EN0_RSARHI);
684644570b8SJeff Kirsher outb_p(E8390_RWRITE+E8390_START, nic_base + AXNET_CMD);
685644570b8SJeff Kirsher outsw(nic_base + AXNET_DATAPORT, buf, count>>1);
686644570b8SJeff Kirsher }
687644570b8SJeff Kirsher
688644570b8SJeff Kirsher static const struct pcmcia_device_id axnet_ids[] = {
689644570b8SJeff Kirsher PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),
690644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301),
691644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
692644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),
693644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),
694644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
695644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1106),
696644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x8a01, 0xc1ab),
697644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0x021b, 0x0202),
698644570b8SJeff Kirsher PCMCIA_DEVICE_MANF_CARD(0xffff, 0x1090),
699644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("AmbiCom,Inc.", "Fast Ethernet PC Card(AMB8110)", 0x49b020a7, 0x119cc9fc),
700644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID124("Fast Ethernet", "16-bit PC Card", "AX88190", 0xb4be14e3, 0x9a12eb6a, 0xab9be5ef),
701644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("ASIX", "AX88190", 0x0959823b, 0xab9be5ef),
702644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("Billionton", "LNA-100B", 0x552ab682, 0xbc3b87e1),
703644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("CHEETAH ETHERCARD", "EN2228", 0x00fa7bc8, 0x00e990cc),
704644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("CNet", "CNF301", 0xbc477dde, 0x78c5f40b),
705644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXD", 0x5261440f, 0x436768c5),
706644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEtherII PCC-TXD", 0x5261440f, 0x730df72e),
707644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FEther PCC-TXM", 0x5261440f, 0x3abbd061),
708644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("Dynalink", "L100C16", 0x55632fd5, 0x66bc2a90),
709644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("IO DATA", "ETXPCM", 0x547e66dc, 0x233adac2),
710644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V3)", 0x0733cc81, 0x232019a8),
711644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC3-TX", 0x481e0094, 0xf91af609),
712644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA411", 0x9aa79dc3, 0x40fad875),
713644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("PCMCIA", "100BASE", 0x281f1c5d, 0x7c2add04),
714644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEtherCard", 0x281f1c5d, 0x7ef26116),
715644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FEP501", 0x281f1c5d, 0x2e272058),
716644570b8SJeff Kirsher PCMCIA_DEVICE_PROD_ID14("Network Everywhere", "AX88190", 0x820a67b6, 0xab9be5ef),
717644570b8SJeff Kirsher PCMCIA_DEVICE_NULL,
718644570b8SJeff Kirsher };
719644570b8SJeff Kirsher MODULE_DEVICE_TABLE(pcmcia, axnet_ids);
720644570b8SJeff Kirsher
721644570b8SJeff Kirsher static struct pcmcia_driver axnet_cs_driver = {
722644570b8SJeff Kirsher .owner = THIS_MODULE,
723644570b8SJeff Kirsher .name = "axnet_cs",
724644570b8SJeff Kirsher .probe = axnet_probe,
725644570b8SJeff Kirsher .remove = axnet_detach,
726644570b8SJeff Kirsher .id_table = axnet_ids,
727644570b8SJeff Kirsher .suspend = axnet_suspend,
728644570b8SJeff Kirsher .resume = axnet_resume,
729644570b8SJeff Kirsher };
730fdd3f29eSH Hartley Sweeten module_pcmcia_driver(axnet_cs_driver);
731644570b8SJeff Kirsher
732644570b8SJeff Kirsher /*====================================================================*/
733644570b8SJeff Kirsher
734644570b8SJeff Kirsher /* 8390.c: A general NS8390 ethernet driver core for linux. */
735644570b8SJeff Kirsher /*
736644570b8SJeff Kirsher Written 1992-94 by Donald Becker.
737644570b8SJeff Kirsher
738644570b8SJeff Kirsher Copyright 1993 United States Government as represented by the
739644570b8SJeff Kirsher Director, National Security Agency.
740644570b8SJeff Kirsher
741644570b8SJeff Kirsher This software may be used and distributed according to the terms
742644570b8SJeff Kirsher of the GNU General Public License, incorporated herein by reference.
743644570b8SJeff Kirsher
744644570b8SJeff Kirsher The author may be reached as becker@scyld.com, or C/O
745644570b8SJeff Kirsher Scyld Computing Corporation
746644570b8SJeff Kirsher 410 Severn Ave., Suite 210
747644570b8SJeff Kirsher Annapolis MD 21403
748644570b8SJeff Kirsher
749644570b8SJeff Kirsher This is the chip-specific code for many 8390-based ethernet adaptors.
750644570b8SJeff Kirsher This is not a complete driver, it must be combined with board-specific
751644570b8SJeff Kirsher code such as ne.c, wd.c, 3c503.c, etc.
752644570b8SJeff Kirsher
753644570b8SJeff Kirsher Seeing how at least eight drivers use this code, (not counting the
754644570b8SJeff Kirsher PCMCIA ones either) it is easy to break some card by what seems like
755644570b8SJeff Kirsher a simple innocent change. Please contact me or Donald if you think
756644570b8SJeff Kirsher you have found something that needs changing. -- PG
757644570b8SJeff Kirsher
758644570b8SJeff Kirsher Changelog:
759644570b8SJeff Kirsher
760644570b8SJeff Kirsher Paul Gortmaker : remove set_bit lock, other cleanups.
761644570b8SJeff Kirsher Paul Gortmaker : add ei_get_8390_hdr() so we can pass skb's to
762644570b8SJeff Kirsher ei_block_input() for eth_io_copy_and_sum().
763644570b8SJeff Kirsher Paul Gortmaker : exchange static int ei_pingpong for a #define,
764644570b8SJeff Kirsher also add better Tx error handling.
765644570b8SJeff Kirsher Paul Gortmaker : rewrite Rx overrun handling as per NS specs.
766644570b8SJeff Kirsher Alexey Kuznetsov : use the 8390's six bit hash multicast filter.
767644570b8SJeff Kirsher Paul Gortmaker : tweak ANK's above multicast changes a bit.
768644570b8SJeff Kirsher Paul Gortmaker : update packet statistics for v2.1.x
769644570b8SJeff Kirsher Alan Cox : support arbitrary stupid port mappings on the
770644570b8SJeff Kirsher 68K Macintosh. Support >16bit I/O spaces
771644570b8SJeff Kirsher Paul Gortmaker : add kmod support for auto-loading of the 8390
772644570b8SJeff Kirsher module by all drivers that require it.
773644570b8SJeff Kirsher Alan Cox : Spinlocking work, added 'BUG_83C690'
774644570b8SJeff Kirsher Paul Gortmaker : Separate out Tx timeout code from Tx path.
775644570b8SJeff Kirsher
776644570b8SJeff Kirsher Sources:
777644570b8SJeff Kirsher The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
778644570b8SJeff Kirsher
779644570b8SJeff Kirsher */
780644570b8SJeff Kirsher
781644570b8SJeff Kirsher #include <linux/bitops.h>
782644570b8SJeff Kirsher #include <asm/irq.h>
783644570b8SJeff Kirsher #include <linux/fcntl.h>
784644570b8SJeff Kirsher #include <linux/in.h>
785644570b8SJeff Kirsher #include <linux/interrupt.h>
786644570b8SJeff Kirsher
787644570b8SJeff Kirsher #define BUG_83C690
788644570b8SJeff Kirsher
789644570b8SJeff Kirsher /* These are the operational function interfaces to board-specific
790644570b8SJeff Kirsher routines.
791644570b8SJeff Kirsher void reset_8390(struct net_device *dev)
792644570b8SJeff Kirsher Resets the board associated with DEV, including a hardware reset of
793644570b8SJeff Kirsher the 8390. This is only called when there is a transmit timeout, and
794644570b8SJeff Kirsher it is always followed by 8390_init().
795644570b8SJeff Kirsher void block_output(struct net_device *dev, int count, const unsigned char *buf,
796644570b8SJeff Kirsher int start_page)
797644570b8SJeff Kirsher Write the COUNT bytes of BUF to the packet buffer at START_PAGE. The
798644570b8SJeff Kirsher "page" value uses the 8390's 256-byte pages.
799644570b8SJeff Kirsher void get_8390_hdr(struct net_device *dev, struct e8390_hdr *hdr, int ring_page)
800644570b8SJeff Kirsher Read the 4 byte, page aligned 8390 header. *If* there is a
801644570b8SJeff Kirsher subsequent read, it will be of the rest of the packet.
802644570b8SJeff Kirsher void block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
803644570b8SJeff Kirsher Read COUNT bytes from the packet buffer into the skb data area. Start
804644570b8SJeff Kirsher reading from RING_OFFSET, the address as the 8390 sees it. This will always
805644570b8SJeff Kirsher follow the read of the 8390 header.
806644570b8SJeff Kirsher */
807644570b8SJeff Kirsher #define ei_reset_8390 (ei_local->reset_8390)
808644570b8SJeff Kirsher #define ei_block_output (ei_local->block_output)
809644570b8SJeff Kirsher #define ei_block_input (ei_local->block_input)
810644570b8SJeff Kirsher #define ei_get_8390_hdr (ei_local->get_8390_hdr)
811644570b8SJeff Kirsher
812644570b8SJeff Kirsher /* Index to functions. */
813644570b8SJeff Kirsher static void ei_tx_intr(struct net_device *dev);
814644570b8SJeff Kirsher static void ei_tx_err(struct net_device *dev);
815644570b8SJeff Kirsher static void ei_receive(struct net_device *dev);
816644570b8SJeff Kirsher static void ei_rx_overrun(struct net_device *dev);
817644570b8SJeff Kirsher
818644570b8SJeff Kirsher /* Routines generic to NS8390-based boards. */
819644570b8SJeff Kirsher static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
820644570b8SJeff Kirsher int start_page);
821644570b8SJeff Kirsher static void do_set_multicast_list(struct net_device *dev);
822644570b8SJeff Kirsher
823644570b8SJeff Kirsher /*
824644570b8SJeff Kirsher * SMP and the 8390 setup.
825644570b8SJeff Kirsher *
826644570b8SJeff Kirsher * The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
827644570b8SJeff Kirsher * a page register that controls bank and packet buffer access. We guard
828644570b8SJeff Kirsher * this with ei_local->page_lock. Nobody should assume or set the page other
829644570b8SJeff Kirsher * than zero when the lock is not held. Lock holders must restore page 0
830644570b8SJeff Kirsher * before unlocking. Even pure readers must take the lock to protect in
831644570b8SJeff Kirsher * page 0.
832644570b8SJeff Kirsher *
833644570b8SJeff Kirsher * To make life difficult the chip can also be very slow. We therefore can't
834644570b8SJeff Kirsher * just use spinlocks. For the longer lockups we disable the irq the device
835644570b8SJeff Kirsher * sits on and hold the lock. We must hold the lock because there is a dual
836644570b8SJeff Kirsher * processor case other than interrupts (get stats/set multicast list in
837644570b8SJeff Kirsher * parallel with each other and transmit).
838644570b8SJeff Kirsher *
839644570b8SJeff Kirsher * Note: in theory we can just disable the irq on the card _but_ there is
840644570b8SJeff Kirsher * a latency on SMP irq delivery. So we can easily go "disable irq" "sync irqs"
841644570b8SJeff Kirsher * enter lock, take the queued irq. So we waddle instead of flying.
842644570b8SJeff Kirsher *
843644570b8SJeff Kirsher * Finally by special arrangement for the purpose of being generally
844644570b8SJeff Kirsher * annoying the transmit function is called bh atomic. That places
845644570b8SJeff Kirsher * restrictions on the user context callers as disable_irq won't save
846644570b8SJeff Kirsher * them.
847644570b8SJeff Kirsher */
848644570b8SJeff Kirsher
849644570b8SJeff Kirsher /**
850644570b8SJeff Kirsher * ax_open - Open/initialize the board.
851644570b8SJeff Kirsher * @dev: network device to initialize
852644570b8SJeff Kirsher *
853644570b8SJeff Kirsher * This routine goes all-out, setting everything
854644570b8SJeff Kirsher * up anew at each open, even though many of these registers should only
855644570b8SJeff Kirsher * need to be set once at boot.
856644570b8SJeff Kirsher */
ax_open(struct net_device * dev)857644570b8SJeff Kirsher static int ax_open(struct net_device *dev)
858644570b8SJeff Kirsher {
859644570b8SJeff Kirsher unsigned long flags;
860644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
861644570b8SJeff Kirsher
862644570b8SJeff Kirsher /*
863644570b8SJeff Kirsher * Grab the page lock so we own the register set, then call
864644570b8SJeff Kirsher * the init function.
865644570b8SJeff Kirsher */
866644570b8SJeff Kirsher
867644570b8SJeff Kirsher spin_lock_irqsave(&ei_local->page_lock, flags);
868644570b8SJeff Kirsher AX88190_init(dev, 1);
869644570b8SJeff Kirsher /* Set the flag before we drop the lock, That way the IRQ arrives
870644570b8SJeff Kirsher after its set and we get no silly warnings */
871644570b8SJeff Kirsher netif_start_queue(dev);
872644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
873644570b8SJeff Kirsher ei_local->irqlock = 0;
874644570b8SJeff Kirsher return 0;
875644570b8SJeff Kirsher }
876644570b8SJeff Kirsher
877644570b8SJeff Kirsher #define dev_lock(dev) (((struct ei_device *)netdev_priv(dev))->page_lock)
878644570b8SJeff Kirsher
879644570b8SJeff Kirsher /**
880644570b8SJeff Kirsher * ax_close - shut down network device
881644570b8SJeff Kirsher * @dev: network device to close
882644570b8SJeff Kirsher *
883644570b8SJeff Kirsher * Opposite of ax_open(). Only used when "ifconfig <devname> down" is done.
884644570b8SJeff Kirsher */
ax_close(struct net_device * dev)885644570b8SJeff Kirsher static int ax_close(struct net_device *dev)
886644570b8SJeff Kirsher {
887644570b8SJeff Kirsher unsigned long flags;
888644570b8SJeff Kirsher
889644570b8SJeff Kirsher /*
890644570b8SJeff Kirsher * Hold the page lock during close
891644570b8SJeff Kirsher */
892644570b8SJeff Kirsher
893644570b8SJeff Kirsher spin_lock_irqsave(&dev_lock(dev), flags);
894644570b8SJeff Kirsher AX88190_init(dev, 0);
895644570b8SJeff Kirsher spin_unlock_irqrestore(&dev_lock(dev), flags);
896644570b8SJeff Kirsher netif_stop_queue(dev);
897644570b8SJeff Kirsher return 0;
898644570b8SJeff Kirsher }
899644570b8SJeff Kirsher
900644570b8SJeff Kirsher /**
901644570b8SJeff Kirsher * axnet_tx_timeout - handle transmit time out condition
902644570b8SJeff Kirsher * @dev: network device which has apparently fallen asleep
903fd29aeeeSLee Jones * @txqueue: unused
904644570b8SJeff Kirsher *
905644570b8SJeff Kirsher * Called by kernel when device never acknowledges a transmit has
906644570b8SJeff Kirsher * completed (or failed) - i.e. never posted a Tx related interrupt.
907644570b8SJeff Kirsher */
908644570b8SJeff Kirsher
axnet_tx_timeout(struct net_device * dev,unsigned int txqueue)9090290bd29SMichael S. Tsirkin static void axnet_tx_timeout(struct net_device *dev, unsigned int txqueue)
910644570b8SJeff Kirsher {
911644570b8SJeff Kirsher long e8390_base = dev->base_addr;
912644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
913644570b8SJeff Kirsher int txsr, isr, tickssofar = jiffies - dev_trans_start(dev);
914644570b8SJeff Kirsher unsigned long flags;
915644570b8SJeff Kirsher
916644570b8SJeff Kirsher dev->stats.tx_errors++;
917644570b8SJeff Kirsher
918644570b8SJeff Kirsher spin_lock_irqsave(&ei_local->page_lock, flags);
919644570b8SJeff Kirsher txsr = inb(e8390_base+EN0_TSR);
920644570b8SJeff Kirsher isr = inb(e8390_base+EN0_ISR);
921644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
922644570b8SJeff Kirsher
923c45f812fSMatthew Whitehead netdev_dbg(dev, "Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
924644570b8SJeff Kirsher (txsr & ENTSR_ABT) ? "excess collisions." :
925644570b8SJeff Kirsher (isr) ? "lost interrupt?" : "cable problem?",
926644570b8SJeff Kirsher txsr, isr, tickssofar);
927644570b8SJeff Kirsher
928644570b8SJeff Kirsher if (!isr && !dev->stats.tx_packets)
929644570b8SJeff Kirsher {
930644570b8SJeff Kirsher /* The 8390 probably hasn't gotten on the cable yet. */
931644570b8SJeff Kirsher ei_local->interface_num ^= 1; /* Try a different xcvr. */
932644570b8SJeff Kirsher }
933644570b8SJeff Kirsher
934644570b8SJeff Kirsher /* Ugly but a reset can be slow, yet must be protected */
935644570b8SJeff Kirsher
936644570b8SJeff Kirsher spin_lock_irqsave(&ei_local->page_lock, flags);
937644570b8SJeff Kirsher
938644570b8SJeff Kirsher /* Try to restart the card. Perhaps the user has fixed something. */
939644570b8SJeff Kirsher ei_reset_8390(dev);
940644570b8SJeff Kirsher AX88190_init(dev, 1);
941644570b8SJeff Kirsher
942644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
943644570b8SJeff Kirsher netif_wake_queue(dev);
944644570b8SJeff Kirsher }
945644570b8SJeff Kirsher
946644570b8SJeff Kirsher /**
947644570b8SJeff Kirsher * axnet_start_xmit - begin packet transmission
948644570b8SJeff Kirsher * @skb: packet to be sent
949644570b8SJeff Kirsher * @dev: network device to which packet is sent
950644570b8SJeff Kirsher *
951644570b8SJeff Kirsher * Sends a packet to an 8390 network device.
952644570b8SJeff Kirsher */
953644570b8SJeff Kirsher
axnet_start_xmit(struct sk_buff * skb,struct net_device * dev)954644570b8SJeff Kirsher static netdev_tx_t axnet_start_xmit(struct sk_buff *skb,
955644570b8SJeff Kirsher struct net_device *dev)
956644570b8SJeff Kirsher {
957644570b8SJeff Kirsher long e8390_base = dev->base_addr;
958644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
959644570b8SJeff Kirsher int length, send_length, output_page;
960644570b8SJeff Kirsher unsigned long flags;
961644570b8SJeff Kirsher u8 packet[ETH_ZLEN];
962644570b8SJeff Kirsher
963644570b8SJeff Kirsher netif_stop_queue(dev);
964644570b8SJeff Kirsher
965644570b8SJeff Kirsher length = skb->len;
966644570b8SJeff Kirsher
967644570b8SJeff Kirsher /* Mask interrupts from the ethercard.
968644570b8SJeff Kirsher SMP: We have to grab the lock here otherwise the IRQ handler
969644570b8SJeff Kirsher on another CPU can flip window and race the IRQ mask set. We end
970644570b8SJeff Kirsher up trashing the mcast filter not disabling irqs if we don't lock */
971644570b8SJeff Kirsher
972644570b8SJeff Kirsher spin_lock_irqsave(&ei_local->page_lock, flags);
973644570b8SJeff Kirsher outb_p(0x00, e8390_base + EN0_IMR);
974644570b8SJeff Kirsher
975644570b8SJeff Kirsher /*
976644570b8SJeff Kirsher * Slow phase with lock held.
977644570b8SJeff Kirsher */
978644570b8SJeff Kirsher
979644570b8SJeff Kirsher ei_local->irqlock = 1;
980644570b8SJeff Kirsher
981644570b8SJeff Kirsher send_length = max(length, ETH_ZLEN);
982644570b8SJeff Kirsher
983644570b8SJeff Kirsher /*
984644570b8SJeff Kirsher * We have two Tx slots available for use. Find the first free
985644570b8SJeff Kirsher * slot, and then perform some sanity checks. With two Tx bufs,
986644570b8SJeff Kirsher * you get very close to transmitting back-to-back packets. With
987644570b8SJeff Kirsher * only one Tx buf, the transmitter sits idle while you reload the
988644570b8SJeff Kirsher * card, leaving a substantial gap between each transmitted packet.
989644570b8SJeff Kirsher */
990644570b8SJeff Kirsher
991644570b8SJeff Kirsher if (ei_local->tx1 == 0)
992644570b8SJeff Kirsher {
993644570b8SJeff Kirsher output_page = ei_local->tx_start_page;
994644570b8SJeff Kirsher ei_local->tx1 = send_length;
995c45f812fSMatthew Whitehead if ((netif_msg_tx_queued(ei_local)) &&
996c45f812fSMatthew Whitehead ei_local->tx2 > 0)
997c45f812fSMatthew Whitehead netdev_dbg(dev,
998644570b8SJeff Kirsher "idle transmitter tx2=%d, lasttx=%d, txing=%d\n",
999644570b8SJeff Kirsher ei_local->tx2, ei_local->lasttx,
1000644570b8SJeff Kirsher ei_local->txing);
1001644570b8SJeff Kirsher }
1002644570b8SJeff Kirsher else if (ei_local->tx2 == 0)
1003644570b8SJeff Kirsher {
1004644570b8SJeff Kirsher output_page = ei_local->tx_start_page + TX_PAGES/2;
1005644570b8SJeff Kirsher ei_local->tx2 = send_length;
1006c45f812fSMatthew Whitehead if ((netif_msg_tx_queued(ei_local)) &&
1007c45f812fSMatthew Whitehead ei_local->tx1 > 0)
1008c45f812fSMatthew Whitehead netdev_dbg(dev,
1009644570b8SJeff Kirsher "idle transmitter, tx1=%d, lasttx=%d, txing=%d\n",
1010644570b8SJeff Kirsher ei_local->tx1, ei_local->lasttx,
1011644570b8SJeff Kirsher ei_local->txing);
1012644570b8SJeff Kirsher }
1013644570b8SJeff Kirsher else
1014644570b8SJeff Kirsher { /* We should never get here. */
1015c45f812fSMatthew Whitehead netif_dbg(ei_local, tx_err, dev,
1016644570b8SJeff Kirsher "No Tx buffers free! tx1=%d tx2=%d last=%d\n",
1017644570b8SJeff Kirsher ei_local->tx1, ei_local->tx2,
1018644570b8SJeff Kirsher ei_local->lasttx);
1019644570b8SJeff Kirsher ei_local->irqlock = 0;
1020644570b8SJeff Kirsher netif_stop_queue(dev);
1021644570b8SJeff Kirsher outb_p(ENISR_ALL, e8390_base + EN0_IMR);
1022644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
1023644570b8SJeff Kirsher dev->stats.tx_errors++;
1024644570b8SJeff Kirsher return NETDEV_TX_BUSY;
1025644570b8SJeff Kirsher }
1026644570b8SJeff Kirsher
1027644570b8SJeff Kirsher /*
1028644570b8SJeff Kirsher * Okay, now upload the packet and trigger a send if the transmitter
1029644570b8SJeff Kirsher * isn't already sending. If it is busy, the interrupt handler will
1030644570b8SJeff Kirsher * trigger the send later, upon receiving a Tx done interrupt.
1031644570b8SJeff Kirsher */
1032644570b8SJeff Kirsher
1033644570b8SJeff Kirsher if (length == skb->len)
1034644570b8SJeff Kirsher ei_block_output(dev, length, skb->data, output_page);
1035644570b8SJeff Kirsher else {
1036644570b8SJeff Kirsher memset(packet, 0, ETH_ZLEN);
1037644570b8SJeff Kirsher skb_copy_from_linear_data(skb, packet, skb->len);
1038644570b8SJeff Kirsher ei_block_output(dev, length, packet, output_page);
1039644570b8SJeff Kirsher }
1040644570b8SJeff Kirsher
1041644570b8SJeff Kirsher if (! ei_local->txing)
1042644570b8SJeff Kirsher {
1043644570b8SJeff Kirsher ei_local->txing = 1;
1044644570b8SJeff Kirsher NS8390_trigger_send(dev, send_length, output_page);
1045860e9538SFlorian Westphal netif_trans_update(dev);
1046644570b8SJeff Kirsher if (output_page == ei_local->tx_start_page)
1047644570b8SJeff Kirsher {
1048644570b8SJeff Kirsher ei_local->tx1 = -1;
1049644570b8SJeff Kirsher ei_local->lasttx = -1;
1050644570b8SJeff Kirsher }
1051644570b8SJeff Kirsher else
1052644570b8SJeff Kirsher {
1053644570b8SJeff Kirsher ei_local->tx2 = -1;
1054644570b8SJeff Kirsher ei_local->lasttx = -2;
1055644570b8SJeff Kirsher }
1056644570b8SJeff Kirsher }
1057644570b8SJeff Kirsher else ei_local->txqueue++;
1058644570b8SJeff Kirsher
1059644570b8SJeff Kirsher if (ei_local->tx1 && ei_local->tx2)
1060644570b8SJeff Kirsher netif_stop_queue(dev);
1061644570b8SJeff Kirsher else
1062644570b8SJeff Kirsher netif_start_queue(dev);
1063644570b8SJeff Kirsher
1064644570b8SJeff Kirsher /* Turn 8390 interrupts back on. */
1065644570b8SJeff Kirsher ei_local->irqlock = 0;
1066644570b8SJeff Kirsher outb_p(ENISR_ALL, e8390_base + EN0_IMR);
1067644570b8SJeff Kirsher
1068644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
1069644570b8SJeff Kirsher
1070644570b8SJeff Kirsher dev_kfree_skb (skb);
1071644570b8SJeff Kirsher dev->stats.tx_bytes += send_length;
1072644570b8SJeff Kirsher
1073644570b8SJeff Kirsher return NETDEV_TX_OK;
1074644570b8SJeff Kirsher }
1075644570b8SJeff Kirsher
1076644570b8SJeff Kirsher /**
1077644570b8SJeff Kirsher * ax_interrupt - handle the interrupts from an 8390
1078644570b8SJeff Kirsher * @irq: interrupt number
1079644570b8SJeff Kirsher * @dev_id: a pointer to the net_device
1080644570b8SJeff Kirsher *
1081644570b8SJeff Kirsher * Handle the ether interface interrupts. We pull packets from
1082644570b8SJeff Kirsher * the 8390 via the card specific functions and fire them at the networking
1083644570b8SJeff Kirsher * stack. We also handle transmit completions and wake the transmit path if
1084644570b8SJeff Kirsher * necessary. We also update the counters and do other housekeeping as
1085644570b8SJeff Kirsher * needed.
1086644570b8SJeff Kirsher */
1087644570b8SJeff Kirsher
ax_interrupt(int irq,void * dev_id)1088644570b8SJeff Kirsher static irqreturn_t ax_interrupt(int irq, void *dev_id)
1089644570b8SJeff Kirsher {
1090644570b8SJeff Kirsher struct net_device *dev = dev_id;
1091644570b8SJeff Kirsher long e8390_base;
1092644570b8SJeff Kirsher int interrupts, nr_serviced = 0, i;
1093644570b8SJeff Kirsher struct ei_device *ei_local;
1094644570b8SJeff Kirsher int handled = 0;
1095644570b8SJeff Kirsher unsigned long flags;
1096644570b8SJeff Kirsher
1097644570b8SJeff Kirsher e8390_base = dev->base_addr;
1098644570b8SJeff Kirsher ei_local = netdev_priv(dev);
1099644570b8SJeff Kirsher
1100644570b8SJeff Kirsher /*
1101644570b8SJeff Kirsher * Protect the irq test too.
1102644570b8SJeff Kirsher */
1103644570b8SJeff Kirsher
1104644570b8SJeff Kirsher spin_lock_irqsave(&ei_local->page_lock, flags);
1105644570b8SJeff Kirsher
1106644570b8SJeff Kirsher if (ei_local->irqlock) {
1107644570b8SJeff Kirsher #if 1 /* This might just be an interrupt for a PCI device sharing this line */
1108644570b8SJeff Kirsher const char *msg;
1109644570b8SJeff Kirsher /* The "irqlock" check is only for testing. */
1110644570b8SJeff Kirsher if (ei_local->irqlock)
1111644570b8SJeff Kirsher msg = "Interrupted while interrupts are masked!";
1112644570b8SJeff Kirsher else
1113644570b8SJeff Kirsher msg = "Reentering the interrupt handler!";
1114644570b8SJeff Kirsher netdev_info(dev, "%s, isr=%#2x imr=%#2x\n",
1115644570b8SJeff Kirsher msg,
1116644570b8SJeff Kirsher inb_p(e8390_base + EN0_ISR),
1117644570b8SJeff Kirsher inb_p(e8390_base + EN0_IMR));
1118644570b8SJeff Kirsher #endif
1119644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
1120644570b8SJeff Kirsher return IRQ_NONE;
1121644570b8SJeff Kirsher }
1122644570b8SJeff Kirsher
1123c45f812fSMatthew Whitehead netif_dbg(ei_local, intr, dev, "interrupt(isr=%#2.2x)\n",
1124644570b8SJeff Kirsher inb_p(e8390_base + EN0_ISR));
1125644570b8SJeff Kirsher
1126644570b8SJeff Kirsher outb_p(0x00, e8390_base + EN0_ISR);
1127644570b8SJeff Kirsher ei_local->irqlock = 1;
1128644570b8SJeff Kirsher
1129644570b8SJeff Kirsher /* !!Assumption!! -- we stay in page 0. Don't break this. */
1130644570b8SJeff Kirsher while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 &&
1131644570b8SJeff Kirsher ++nr_serviced < MAX_SERVICE)
1132644570b8SJeff Kirsher {
1133644570b8SJeff Kirsher if (!netif_running(dev) || (interrupts == 0xff)) {
1134c45f812fSMatthew Whitehead netif_warn(ei_local, intr, dev,
1135644570b8SJeff Kirsher "interrupt from stopped card\n");
1136644570b8SJeff Kirsher outb_p(interrupts, e8390_base + EN0_ISR);
1137644570b8SJeff Kirsher interrupts = 0;
1138644570b8SJeff Kirsher break;
1139644570b8SJeff Kirsher }
1140644570b8SJeff Kirsher handled = 1;
1141644570b8SJeff Kirsher
1142644570b8SJeff Kirsher /* AX88190 bug fix. */
1143644570b8SJeff Kirsher outb_p(interrupts, e8390_base + EN0_ISR);
1144644570b8SJeff Kirsher for (i = 0; i < 10; i++) {
1145644570b8SJeff Kirsher if (!(inb(e8390_base + EN0_ISR) & interrupts))
1146644570b8SJeff Kirsher break;
1147644570b8SJeff Kirsher outb_p(0, e8390_base + EN0_ISR);
1148644570b8SJeff Kirsher outb_p(interrupts, e8390_base + EN0_ISR);
1149644570b8SJeff Kirsher }
1150644570b8SJeff Kirsher if (interrupts & ENISR_OVER)
1151644570b8SJeff Kirsher ei_rx_overrun(dev);
1152644570b8SJeff Kirsher else if (interrupts & (ENISR_RX+ENISR_RX_ERR))
1153644570b8SJeff Kirsher {
1154644570b8SJeff Kirsher /* Got a good (?) packet. */
1155644570b8SJeff Kirsher ei_receive(dev);
1156644570b8SJeff Kirsher }
1157644570b8SJeff Kirsher /* Push the next to-transmit packet through. */
1158644570b8SJeff Kirsher if (interrupts & ENISR_TX)
1159644570b8SJeff Kirsher ei_tx_intr(dev);
1160644570b8SJeff Kirsher else if (interrupts & ENISR_TX_ERR)
1161644570b8SJeff Kirsher ei_tx_err(dev);
1162644570b8SJeff Kirsher
1163644570b8SJeff Kirsher if (interrupts & ENISR_COUNTERS)
1164644570b8SJeff Kirsher {
1165644570b8SJeff Kirsher dev->stats.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
1166644570b8SJeff Kirsher dev->stats.rx_crc_errors += inb_p(e8390_base + EN0_COUNTER1);
1167644570b8SJeff Kirsher dev->stats.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
1168644570b8SJeff Kirsher }
1169644570b8SJeff Kirsher }
1170644570b8SJeff Kirsher
1171c45f812fSMatthew Whitehead if (interrupts && (netif_msg_intr(ei_local)))
1172644570b8SJeff Kirsher {
1173644570b8SJeff Kirsher handled = 1;
1174644570b8SJeff Kirsher if (nr_serviced >= MAX_SERVICE)
1175644570b8SJeff Kirsher {
1176644570b8SJeff Kirsher /* 0xFF is valid for a card removal */
1177644570b8SJeff Kirsher if (interrupts != 0xFF)
1178c45f812fSMatthew Whitehead netdev_warn(dev,
1179c45f812fSMatthew Whitehead "Too much work at interrupt, status %#2.2x\n",
1180644570b8SJeff Kirsher interrupts);
1181644570b8SJeff Kirsher outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
1182644570b8SJeff Kirsher } else {
1183644570b8SJeff Kirsher netdev_warn(dev, "unknown interrupt %#2x\n",
1184644570b8SJeff Kirsher interrupts);
1185644570b8SJeff Kirsher outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
1186644570b8SJeff Kirsher }
1187644570b8SJeff Kirsher }
1188644570b8SJeff Kirsher
1189644570b8SJeff Kirsher /* Turn 8390 interrupts back on. */
1190644570b8SJeff Kirsher ei_local->irqlock = 0;
1191644570b8SJeff Kirsher outb_p(ENISR_ALL, e8390_base + EN0_IMR);
1192644570b8SJeff Kirsher
1193644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
1194644570b8SJeff Kirsher return IRQ_RETVAL(handled);
1195644570b8SJeff Kirsher }
1196644570b8SJeff Kirsher
1197644570b8SJeff Kirsher /**
1198644570b8SJeff Kirsher * ei_tx_err - handle transmitter error
1199644570b8SJeff Kirsher * @dev: network device which threw the exception
1200644570b8SJeff Kirsher *
1201644570b8SJeff Kirsher * A transmitter error has happened. Most likely excess collisions (which
1202644570b8SJeff Kirsher * is a fairly normal condition). If the error is one where the Tx will
1203644570b8SJeff Kirsher * have been aborted, we try and send another one right away, instead of
1204644570b8SJeff Kirsher * letting the failed packet sit and collect dust in the Tx buffer. This
1205644570b8SJeff Kirsher * is a much better solution as it avoids kernel based Tx timeouts, and
1206644570b8SJeff Kirsher * an unnecessary card reset.
1207644570b8SJeff Kirsher *
1208644570b8SJeff Kirsher * Called with lock held.
1209644570b8SJeff Kirsher */
1210644570b8SJeff Kirsher
ei_tx_err(struct net_device * dev)1211644570b8SJeff Kirsher static void ei_tx_err(struct net_device *dev)
1212644570b8SJeff Kirsher {
1213644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1214644570b8SJeff Kirsher unsigned char txsr = inb_p(e8390_base+EN0_TSR);
1215644570b8SJeff Kirsher unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
1216644570b8SJeff Kirsher
1217644570b8SJeff Kirsher #ifdef VERBOSE_ERROR_DUMP
1218c45f812fSMatthew Whitehead netdev_dbg(dev, "transmitter error (%#2x):", txsr);
1219644570b8SJeff Kirsher if (txsr & ENTSR_ABT)
1220644570b8SJeff Kirsher pr_cont(" excess-collisions");
1221644570b8SJeff Kirsher if (txsr & ENTSR_ND)
1222644570b8SJeff Kirsher pr_cont(" non-deferral");
1223644570b8SJeff Kirsher if (txsr & ENTSR_CRS)
1224644570b8SJeff Kirsher pr_cont(" lost-carrier");
1225644570b8SJeff Kirsher if (txsr & ENTSR_FU)
1226644570b8SJeff Kirsher pr_cont(" FIFO-underrun");
1227644570b8SJeff Kirsher if (txsr & ENTSR_CDH)
1228644570b8SJeff Kirsher pr_cont(" lost-heartbeat");
1229644570b8SJeff Kirsher pr_cont("\n");
1230644570b8SJeff Kirsher #endif
1231644570b8SJeff Kirsher
1232644570b8SJeff Kirsher if (tx_was_aborted)
1233644570b8SJeff Kirsher ei_tx_intr(dev);
1234644570b8SJeff Kirsher else
1235644570b8SJeff Kirsher {
1236644570b8SJeff Kirsher dev->stats.tx_errors++;
1237644570b8SJeff Kirsher if (txsr & ENTSR_CRS) dev->stats.tx_carrier_errors++;
1238644570b8SJeff Kirsher if (txsr & ENTSR_CDH) dev->stats.tx_heartbeat_errors++;
1239644570b8SJeff Kirsher if (txsr & ENTSR_OWC) dev->stats.tx_window_errors++;
1240644570b8SJeff Kirsher }
1241644570b8SJeff Kirsher }
1242644570b8SJeff Kirsher
1243644570b8SJeff Kirsher /**
1244644570b8SJeff Kirsher * ei_tx_intr - transmit interrupt handler
1245644570b8SJeff Kirsher * @dev: network device for which tx intr is handled
1246644570b8SJeff Kirsher *
1247644570b8SJeff Kirsher * We have finished a transmit: check for errors and then trigger the next
1248644570b8SJeff Kirsher * packet to be sent. Called with lock held.
1249644570b8SJeff Kirsher */
1250644570b8SJeff Kirsher
ei_tx_intr(struct net_device * dev)1251644570b8SJeff Kirsher static void ei_tx_intr(struct net_device *dev)
1252644570b8SJeff Kirsher {
1253644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1254644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
1255644570b8SJeff Kirsher int status = inb(e8390_base + EN0_TSR);
1256644570b8SJeff Kirsher
1257644570b8SJeff Kirsher /*
1258644570b8SJeff Kirsher * There are two Tx buffers, see which one finished, and trigger
1259644570b8SJeff Kirsher * the send of another one if it exists.
1260644570b8SJeff Kirsher */
1261644570b8SJeff Kirsher ei_local->txqueue--;
1262644570b8SJeff Kirsher
1263644570b8SJeff Kirsher if (ei_local->tx1 < 0)
1264644570b8SJeff Kirsher {
1265644570b8SJeff Kirsher if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
1266644570b8SJeff Kirsher netdev_err(dev, "%s: bogus last_tx_buffer %d, tx1=%d\n",
1267644570b8SJeff Kirsher ei_local->name, ei_local->lasttx,
1268644570b8SJeff Kirsher ei_local->tx1);
1269644570b8SJeff Kirsher ei_local->tx1 = 0;
1270644570b8SJeff Kirsher if (ei_local->tx2 > 0)
1271644570b8SJeff Kirsher {
1272644570b8SJeff Kirsher ei_local->txing = 1;
1273644570b8SJeff Kirsher NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
1274860e9538SFlorian Westphal netif_trans_update(dev);
1275e7fee115SJoe Perches ei_local->tx2 = -1;
1276644570b8SJeff Kirsher ei_local->lasttx = 2;
1277e7fee115SJoe Perches } else {
1278e7fee115SJoe Perches ei_local->lasttx = 20;
1279e7fee115SJoe Perches ei_local->txing = 0;
1280644570b8SJeff Kirsher }
1281644570b8SJeff Kirsher }
1282644570b8SJeff Kirsher else if (ei_local->tx2 < 0)
1283644570b8SJeff Kirsher {
1284644570b8SJeff Kirsher if (ei_local->lasttx != 2 && ei_local->lasttx != -2)
1285c45f812fSMatthew Whitehead netdev_err(dev, "%s: bogus last_tx_buffer %d, tx2=%d\n",
1286644570b8SJeff Kirsher ei_local->name, ei_local->lasttx,
1287644570b8SJeff Kirsher ei_local->tx2);
1288644570b8SJeff Kirsher ei_local->tx2 = 0;
1289644570b8SJeff Kirsher if (ei_local->tx1 > 0)
1290644570b8SJeff Kirsher {
1291644570b8SJeff Kirsher ei_local->txing = 1;
1292644570b8SJeff Kirsher NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
1293860e9538SFlorian Westphal netif_trans_update(dev);
1294644570b8SJeff Kirsher ei_local->tx1 = -1;
1295644570b8SJeff Kirsher ei_local->lasttx = 1;
1296e7fee115SJoe Perches } else {
1297e7fee115SJoe Perches ei_local->lasttx = 10;
1298e7fee115SJoe Perches ei_local->txing = 0;
1299644570b8SJeff Kirsher }
1300644570b8SJeff Kirsher }
1301644570b8SJeff Kirsher // else
1302644570b8SJeff Kirsher // netdev_warn(dev, "unexpected TX-done interrupt, lasttx=%d\n",
1303644570b8SJeff Kirsher // ei_local->lasttx);
1304644570b8SJeff Kirsher
1305644570b8SJeff Kirsher /* Minimize Tx latency: update the statistics after we restart TXing. */
1306644570b8SJeff Kirsher if (status & ENTSR_COL)
1307644570b8SJeff Kirsher dev->stats.collisions++;
1308644570b8SJeff Kirsher if (status & ENTSR_PTX)
1309644570b8SJeff Kirsher dev->stats.tx_packets++;
1310644570b8SJeff Kirsher else
1311644570b8SJeff Kirsher {
1312644570b8SJeff Kirsher dev->stats.tx_errors++;
1313644570b8SJeff Kirsher if (status & ENTSR_ABT)
1314644570b8SJeff Kirsher {
1315644570b8SJeff Kirsher dev->stats.tx_aborted_errors++;
1316644570b8SJeff Kirsher dev->stats.collisions += 16;
1317644570b8SJeff Kirsher }
1318644570b8SJeff Kirsher if (status & ENTSR_CRS)
1319644570b8SJeff Kirsher dev->stats.tx_carrier_errors++;
1320644570b8SJeff Kirsher if (status & ENTSR_FU)
1321644570b8SJeff Kirsher dev->stats.tx_fifo_errors++;
1322644570b8SJeff Kirsher if (status & ENTSR_CDH)
1323644570b8SJeff Kirsher dev->stats.tx_heartbeat_errors++;
1324644570b8SJeff Kirsher if (status & ENTSR_OWC)
1325644570b8SJeff Kirsher dev->stats.tx_window_errors++;
1326644570b8SJeff Kirsher }
1327644570b8SJeff Kirsher netif_wake_queue(dev);
1328644570b8SJeff Kirsher }
1329644570b8SJeff Kirsher
1330644570b8SJeff Kirsher /**
1331644570b8SJeff Kirsher * ei_receive - receive some packets
1332644570b8SJeff Kirsher * @dev: network device with which receive will be run
1333644570b8SJeff Kirsher *
1334644570b8SJeff Kirsher * We have a good packet(s), get it/them out of the buffers.
1335644570b8SJeff Kirsher * Called with lock held.
1336644570b8SJeff Kirsher */
1337644570b8SJeff Kirsher
ei_receive(struct net_device * dev)1338644570b8SJeff Kirsher static void ei_receive(struct net_device *dev)
1339644570b8SJeff Kirsher {
1340644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1341644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
1342644570b8SJeff Kirsher unsigned char rxing_page, this_frame, next_frame;
1343644570b8SJeff Kirsher unsigned short current_offset;
1344644570b8SJeff Kirsher int rx_pkt_count = 0;
1345644570b8SJeff Kirsher struct e8390_pkt_hdr rx_frame;
1346644570b8SJeff Kirsher
1347644570b8SJeff Kirsher while (++rx_pkt_count < 10)
1348644570b8SJeff Kirsher {
1349644570b8SJeff Kirsher int pkt_len, pkt_stat;
1350644570b8SJeff Kirsher
1351644570b8SJeff Kirsher /* Get the rx page (incoming packet pointer). */
1352644570b8SJeff Kirsher rxing_page = inb_p(e8390_base + EN1_CURPAG -1);
1353644570b8SJeff Kirsher
1354644570b8SJeff Kirsher /* Remove one frame from the ring. Boundary is always a page behind. */
1355644570b8SJeff Kirsher this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
1356644570b8SJeff Kirsher if (this_frame >= ei_local->stop_page)
1357644570b8SJeff Kirsher this_frame = ei_local->rx_start_page;
1358644570b8SJeff Kirsher
1359644570b8SJeff Kirsher /* Someday we'll omit the previous, iff we never get this message.
1360644570b8SJeff Kirsher (There is at least one clone claimed to have a problem.)
1361644570b8SJeff Kirsher
1362644570b8SJeff Kirsher Keep quiet if it looks like a card removal. One problem here
1363644570b8SJeff Kirsher is that some clones crash in roughly the same way.
1364644570b8SJeff Kirsher */
1365c45f812fSMatthew Whitehead if ((netif_msg_rx_err(ei_local)) &&
1366c45f812fSMatthew Whitehead this_frame != ei_local->current_page &&
1367c45f812fSMatthew Whitehead (this_frame != 0x0 || rxing_page != 0xFF))
1368644570b8SJeff Kirsher netdev_err(dev, "mismatched read page pointers %2x vs %2x\n",
1369644570b8SJeff Kirsher this_frame, ei_local->current_page);
1370644570b8SJeff Kirsher
1371644570b8SJeff Kirsher if (this_frame == rxing_page) /* Read all the frames? */
1372644570b8SJeff Kirsher break; /* Done for now */
1373644570b8SJeff Kirsher
1374644570b8SJeff Kirsher current_offset = this_frame << 8;
1375644570b8SJeff Kirsher ei_get_8390_hdr(dev, &rx_frame, this_frame);
1376644570b8SJeff Kirsher
1377644570b8SJeff Kirsher pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
1378644570b8SJeff Kirsher pkt_stat = rx_frame.status;
1379644570b8SJeff Kirsher
1380644570b8SJeff Kirsher next_frame = this_frame + 1 + ((pkt_len+4)>>8);
1381644570b8SJeff Kirsher
1382644570b8SJeff Kirsher if (pkt_len < 60 || pkt_len > 1518)
1383644570b8SJeff Kirsher {
1384c45f812fSMatthew Whitehead netif_err(ei_local, rx_err, dev,
1385644570b8SJeff Kirsher "bogus packet size: %d, status=%#2x nxpg=%#2x\n",
1386644570b8SJeff Kirsher rx_frame.count, rx_frame.status,
1387644570b8SJeff Kirsher rx_frame.next);
1388644570b8SJeff Kirsher dev->stats.rx_errors++;
1389644570b8SJeff Kirsher dev->stats.rx_length_errors++;
1390644570b8SJeff Kirsher }
1391644570b8SJeff Kirsher else if ((pkt_stat & 0x0F) == ENRSR_RXOK)
1392644570b8SJeff Kirsher {
1393644570b8SJeff Kirsher struct sk_buff *skb;
1394644570b8SJeff Kirsher
13951d266430SPradeep A Dalvi skb = netdev_alloc_skb(dev, pkt_len + 2);
1396644570b8SJeff Kirsher if (skb == NULL)
1397644570b8SJeff Kirsher {
1398c45f812fSMatthew Whitehead netif_err(ei_local, rx_err, dev,
1399644570b8SJeff Kirsher "Couldn't allocate a sk_buff of size %d\n",
1400644570b8SJeff Kirsher pkt_len);
1401644570b8SJeff Kirsher dev->stats.rx_dropped++;
1402644570b8SJeff Kirsher break;
1403644570b8SJeff Kirsher }
1404644570b8SJeff Kirsher else
1405644570b8SJeff Kirsher {
1406644570b8SJeff Kirsher skb_reserve(skb,2); /* IP headers on 16 byte boundaries */
1407644570b8SJeff Kirsher skb_put(skb, pkt_len); /* Make room */
1408644570b8SJeff Kirsher ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
1409644570b8SJeff Kirsher skb->protocol=eth_type_trans(skb,dev);
1410644570b8SJeff Kirsher netif_rx(skb);
1411644570b8SJeff Kirsher dev->stats.rx_packets++;
1412644570b8SJeff Kirsher dev->stats.rx_bytes += pkt_len;
1413644570b8SJeff Kirsher if (pkt_stat & ENRSR_PHY)
1414644570b8SJeff Kirsher dev->stats.multicast++;
1415644570b8SJeff Kirsher }
1416644570b8SJeff Kirsher }
1417644570b8SJeff Kirsher else
1418644570b8SJeff Kirsher {
1419c45f812fSMatthew Whitehead netif_err(ei_local, rx_err, dev,
1420644570b8SJeff Kirsher "bogus packet: status=%#2x nxpg=%#2x size=%d\n",
1421644570b8SJeff Kirsher rx_frame.status, rx_frame.next,
1422644570b8SJeff Kirsher rx_frame.count);
1423644570b8SJeff Kirsher dev->stats.rx_errors++;
1424644570b8SJeff Kirsher /* NB: The NIC counts CRC, frame and missed errors. */
1425644570b8SJeff Kirsher if (pkt_stat & ENRSR_FO)
1426644570b8SJeff Kirsher dev->stats.rx_fifo_errors++;
1427644570b8SJeff Kirsher }
1428644570b8SJeff Kirsher next_frame = rx_frame.next;
1429644570b8SJeff Kirsher
1430644570b8SJeff Kirsher /* This _should_ never happen: it's here for avoiding bad clones. */
1431644570b8SJeff Kirsher if (next_frame >= ei_local->stop_page) {
1432644570b8SJeff Kirsher netdev_info(dev, "next frame inconsistency, %#2x\n",
1433644570b8SJeff Kirsher next_frame);
1434644570b8SJeff Kirsher next_frame = ei_local->rx_start_page;
1435644570b8SJeff Kirsher }
1436644570b8SJeff Kirsher ei_local->current_page = next_frame;
1437644570b8SJeff Kirsher outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
1438644570b8SJeff Kirsher }
1439644570b8SJeff Kirsher }
1440644570b8SJeff Kirsher
1441644570b8SJeff Kirsher /**
1442644570b8SJeff Kirsher * ei_rx_overrun - handle receiver overrun
1443644570b8SJeff Kirsher * @dev: network device which threw exception
1444644570b8SJeff Kirsher *
1445644570b8SJeff Kirsher * We have a receiver overrun: we have to kick the 8390 to get it started
1446644570b8SJeff Kirsher * again. Problem is that you have to kick it exactly as NS prescribes in
1447644570b8SJeff Kirsher * the updated datasheets, or "the NIC may act in an unpredictable manner."
1448644570b8SJeff Kirsher * This includes causing "the NIC to defer indefinitely when it is stopped
1449644570b8SJeff Kirsher * on a busy network." Ugh.
1450644570b8SJeff Kirsher * Called with lock held. Don't call this with the interrupts off or your
1451644570b8SJeff Kirsher * computer will hate you - it takes 10ms or so.
1452644570b8SJeff Kirsher */
1453644570b8SJeff Kirsher
ei_rx_overrun(struct net_device * dev)1454644570b8SJeff Kirsher static void ei_rx_overrun(struct net_device *dev)
1455644570b8SJeff Kirsher {
1456abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
1457644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1458644570b8SJeff Kirsher unsigned char was_txing, must_resend = 0;
1459c45f812fSMatthew Whitehead struct ei_device *ei_local = netdev_priv(dev);
1460644570b8SJeff Kirsher
1461644570b8SJeff Kirsher /*
1462644570b8SJeff Kirsher * Record whether a Tx was in progress and then issue the
1463644570b8SJeff Kirsher * stop command.
1464644570b8SJeff Kirsher */
1465644570b8SJeff Kirsher was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
1466644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
1467644570b8SJeff Kirsher
1468c45f812fSMatthew Whitehead netif_dbg(ei_local, rx_err, dev, "Receiver overrun\n");
1469644570b8SJeff Kirsher dev->stats.rx_over_errors++;
1470644570b8SJeff Kirsher
1471644570b8SJeff Kirsher /*
1472644570b8SJeff Kirsher * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
1473644570b8SJeff Kirsher * We wait at least 2ms.
1474644570b8SJeff Kirsher */
1475644570b8SJeff Kirsher
1476644570b8SJeff Kirsher mdelay(2);
1477644570b8SJeff Kirsher
1478644570b8SJeff Kirsher /*
1479644570b8SJeff Kirsher * Reset RBCR[01] back to zero as per magic incantation.
1480644570b8SJeff Kirsher */
1481644570b8SJeff Kirsher outb_p(0x00, e8390_base+EN0_RCNTLO);
1482644570b8SJeff Kirsher outb_p(0x00, e8390_base+EN0_RCNTHI);
1483644570b8SJeff Kirsher
1484644570b8SJeff Kirsher /*
1485644570b8SJeff Kirsher * See if any Tx was interrupted or not. According to NS, this
1486644570b8SJeff Kirsher * step is vital, and skipping it will cause no end of havoc.
1487644570b8SJeff Kirsher */
1488644570b8SJeff Kirsher
1489644570b8SJeff Kirsher if (was_txing)
1490644570b8SJeff Kirsher {
1491644570b8SJeff Kirsher unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
1492644570b8SJeff Kirsher if (!tx_completed)
1493644570b8SJeff Kirsher must_resend = 1;
1494644570b8SJeff Kirsher }
1495644570b8SJeff Kirsher
1496644570b8SJeff Kirsher /*
1497644570b8SJeff Kirsher * Have to enter loopback mode and then restart the NIC before
1498644570b8SJeff Kirsher * you are allowed to slurp packets up off the ring.
1499644570b8SJeff Kirsher */
1500644570b8SJeff Kirsher outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
1501644570b8SJeff Kirsher outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
1502644570b8SJeff Kirsher
1503644570b8SJeff Kirsher /*
1504644570b8SJeff Kirsher * Clear the Rx ring of all the debris, and ack the interrupt.
1505644570b8SJeff Kirsher */
1506644570b8SJeff Kirsher ei_receive(dev);
1507644570b8SJeff Kirsher
1508644570b8SJeff Kirsher /*
1509644570b8SJeff Kirsher * Leave loopback mode, and resend any packet that got stopped.
1510644570b8SJeff Kirsher */
1511644570b8SJeff Kirsher outb_p(E8390_TXCONFIG | info->duplex_flag, e8390_base + EN0_TXCR);
1512644570b8SJeff Kirsher if (must_resend)
1513644570b8SJeff Kirsher outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
1514644570b8SJeff Kirsher }
1515644570b8SJeff Kirsher
1516644570b8SJeff Kirsher /*
1517644570b8SJeff Kirsher * Collect the stats. This is called unlocked and from several contexts.
1518644570b8SJeff Kirsher */
1519644570b8SJeff Kirsher
get_stats(struct net_device * dev)1520644570b8SJeff Kirsher static struct net_device_stats *get_stats(struct net_device *dev)
1521644570b8SJeff Kirsher {
1522644570b8SJeff Kirsher long ioaddr = dev->base_addr;
1523644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
1524644570b8SJeff Kirsher unsigned long flags;
1525644570b8SJeff Kirsher
1526644570b8SJeff Kirsher /* If the card is stopped, just return the present stats. */
1527644570b8SJeff Kirsher if (!netif_running(dev))
1528644570b8SJeff Kirsher return &dev->stats;
1529644570b8SJeff Kirsher
1530644570b8SJeff Kirsher spin_lock_irqsave(&ei_local->page_lock,flags);
1531644570b8SJeff Kirsher /* Read the counter registers, assuming we are in page 0. */
1532644570b8SJeff Kirsher dev->stats.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
1533644570b8SJeff Kirsher dev->stats.rx_crc_errors += inb_p(ioaddr + EN0_COUNTER1);
1534644570b8SJeff Kirsher dev->stats.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
1535644570b8SJeff Kirsher spin_unlock_irqrestore(&ei_local->page_lock, flags);
1536644570b8SJeff Kirsher
1537644570b8SJeff Kirsher return &dev->stats;
1538644570b8SJeff Kirsher }
1539644570b8SJeff Kirsher
1540644570b8SJeff Kirsher /*
1541644570b8SJeff Kirsher * Form the 64 bit 8390 multicast table from the linked list of addresses
1542644570b8SJeff Kirsher * associated with this dev structure.
1543644570b8SJeff Kirsher */
1544644570b8SJeff Kirsher
make_mc_bits(u8 * bits,struct net_device * dev)1545644570b8SJeff Kirsher static inline void make_mc_bits(u8 *bits, struct net_device *dev)
1546644570b8SJeff Kirsher {
1547644570b8SJeff Kirsher struct netdev_hw_addr *ha;
1548644570b8SJeff Kirsher u32 crc;
1549644570b8SJeff Kirsher
1550644570b8SJeff Kirsher netdev_for_each_mc_addr(ha, dev) {
1551644570b8SJeff Kirsher crc = ether_crc(ETH_ALEN, ha->addr);
1552644570b8SJeff Kirsher /*
1553644570b8SJeff Kirsher * The 8390 uses the 6 most significant bits of the
1554644570b8SJeff Kirsher * CRC to index the multicast table.
1555644570b8SJeff Kirsher */
1556644570b8SJeff Kirsher bits[crc>>29] |= (1<<((crc>>26)&7));
1557644570b8SJeff Kirsher }
1558644570b8SJeff Kirsher }
1559644570b8SJeff Kirsher
1560644570b8SJeff Kirsher /**
1561644570b8SJeff Kirsher * do_set_multicast_list - set/clear multicast filter
1562644570b8SJeff Kirsher * @dev: net device for which multicast filter is adjusted
1563644570b8SJeff Kirsher *
1564644570b8SJeff Kirsher * Set or clear the multicast filter for this adaptor.
1565644570b8SJeff Kirsher * Must be called with lock held.
1566644570b8SJeff Kirsher */
1567644570b8SJeff Kirsher
do_set_multicast_list(struct net_device * dev)1568644570b8SJeff Kirsher static void do_set_multicast_list(struct net_device *dev)
1569644570b8SJeff Kirsher {
1570644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1571644570b8SJeff Kirsher int i;
1572644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
1573644570b8SJeff Kirsher
1574644570b8SJeff Kirsher if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) {
1575644570b8SJeff Kirsher memset(ei_local->mcfilter, 0, 8);
1576644570b8SJeff Kirsher if (!netdev_mc_empty(dev))
1577644570b8SJeff Kirsher make_mc_bits(ei_local->mcfilter, dev);
1578644570b8SJeff Kirsher } else {
1579644570b8SJeff Kirsher /* set to accept-all */
1580644570b8SJeff Kirsher memset(ei_local->mcfilter, 0xFF, 8);
1581644570b8SJeff Kirsher }
1582644570b8SJeff Kirsher
1583644570b8SJeff Kirsher outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD);
1584644570b8SJeff Kirsher for(i = 0; i < 8; i++)
1585644570b8SJeff Kirsher {
1586644570b8SJeff Kirsher outb_p(ei_local->mcfilter[i], e8390_base + EN1_MULT_SHIFT(i));
1587644570b8SJeff Kirsher }
1588644570b8SJeff Kirsher outb_p(E8390_NODMA + E8390_PAGE0, e8390_base + E8390_CMD);
1589644570b8SJeff Kirsher
1590644570b8SJeff Kirsher if(dev->flags&IFF_PROMISC)
1591644570b8SJeff Kirsher outb_p(E8390_RXCONFIG | 0x58, e8390_base + EN0_RXCR);
1592644570b8SJeff Kirsher else if (dev->flags & IFF_ALLMULTI || !netdev_mc_empty(dev))
1593644570b8SJeff Kirsher outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR);
1594644570b8SJeff Kirsher else
1595644570b8SJeff Kirsher outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR);
1596644570b8SJeff Kirsher
1597644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
1598644570b8SJeff Kirsher }
1599644570b8SJeff Kirsher
1600644570b8SJeff Kirsher /*
1601644570b8SJeff Kirsher * Called without lock held. This is invoked from user context and may
1602644570b8SJeff Kirsher * be parallel to just about everything else. Its also fairly quick and
1603644570b8SJeff Kirsher * not called too often. Must protect against both bh and irq users
1604644570b8SJeff Kirsher */
1605644570b8SJeff Kirsher
set_multicast_list(struct net_device * dev)1606644570b8SJeff Kirsher static void set_multicast_list(struct net_device *dev)
1607644570b8SJeff Kirsher {
1608644570b8SJeff Kirsher unsigned long flags;
1609644570b8SJeff Kirsher
1610644570b8SJeff Kirsher spin_lock_irqsave(&dev_lock(dev), flags);
1611644570b8SJeff Kirsher do_set_multicast_list(dev);
1612644570b8SJeff Kirsher spin_unlock_irqrestore(&dev_lock(dev), flags);
1613644570b8SJeff Kirsher }
1614644570b8SJeff Kirsher
1615644570b8SJeff Kirsher /* This page of functions should be 8390 generic */
1616644570b8SJeff Kirsher /* Follow National Semi's recommendations for initializing the "NIC". */
1617644570b8SJeff Kirsher
1618644570b8SJeff Kirsher /**
1619644570b8SJeff Kirsher * AX88190_init - initialize 8390 hardware
1620644570b8SJeff Kirsher * @dev: network device to initialize
1621644570b8SJeff Kirsher * @startp: boolean. non-zero value to initiate chip processing
1622644570b8SJeff Kirsher *
1623644570b8SJeff Kirsher * Must be called with lock held.
1624644570b8SJeff Kirsher */
1625644570b8SJeff Kirsher
AX88190_init(struct net_device * dev,int startp)1626644570b8SJeff Kirsher static void AX88190_init(struct net_device *dev, int startp)
1627644570b8SJeff Kirsher {
1628abac0d3fSHimangi Saraogi struct axnet_dev *info = PRIV(dev);
1629644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1630644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev);
1631644570b8SJeff Kirsher int i;
1632644570b8SJeff Kirsher int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
1633644570b8SJeff Kirsher
1634644570b8SJeff Kirsher if(sizeof(struct e8390_pkt_hdr)!=4)
1635644570b8SJeff Kirsher panic("8390.c: header struct mispacked\n");
1636644570b8SJeff Kirsher /* Follow National Semi's recommendations for initing the DP83902. */
1637644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */
1638644570b8SJeff Kirsher outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */
1639644570b8SJeff Kirsher /* Clear the remote byte count registers. */
1640644570b8SJeff Kirsher outb_p(0x00, e8390_base + EN0_RCNTLO);
1641644570b8SJeff Kirsher outb_p(0x00, e8390_base + EN0_RCNTHI);
1642644570b8SJeff Kirsher /* Set to monitor and loopback mode -- this is vital!. */
1643644570b8SJeff Kirsher outb_p(E8390_RXOFF|0x40, e8390_base + EN0_RXCR); /* 0x60 */
1644644570b8SJeff Kirsher outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
1645644570b8SJeff Kirsher /* Set the transmit page and receive ring. */
1646644570b8SJeff Kirsher outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR);
1647644570b8SJeff Kirsher ei_local->tx1 = ei_local->tx2 = 0;
1648644570b8SJeff Kirsher outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG);
1649644570b8SJeff Kirsher outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
1650644570b8SJeff Kirsher ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */
1651644570b8SJeff Kirsher outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG);
1652644570b8SJeff Kirsher /* Clear the pending interrupts and mask. */
1653644570b8SJeff Kirsher outb_p(0xFF, e8390_base + EN0_ISR);
1654644570b8SJeff Kirsher outb_p(0x00, e8390_base + EN0_IMR);
1655644570b8SJeff Kirsher
1656644570b8SJeff Kirsher /* Copy the station address into the DS8390 registers. */
1657644570b8SJeff Kirsher
1658644570b8SJeff Kirsher outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */
1659644570b8SJeff Kirsher for(i = 0; i < 6; i++)
1660644570b8SJeff Kirsher {
1661644570b8SJeff Kirsher outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS_SHIFT(i));
1662644570b8SJeff Kirsher if(inb_p(e8390_base + EN1_PHYS_SHIFT(i))!=dev->dev_addr[i])
1663644570b8SJeff Kirsher netdev_err(dev, "Hw. address read/write mismap %d\n", i);
1664644570b8SJeff Kirsher }
1665644570b8SJeff Kirsher
1666644570b8SJeff Kirsher outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG);
1667644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
1668644570b8SJeff Kirsher
1669644570b8SJeff Kirsher netif_start_queue(dev);
1670644570b8SJeff Kirsher ei_local->tx1 = ei_local->tx2 = 0;
1671644570b8SJeff Kirsher ei_local->txing = 0;
1672644570b8SJeff Kirsher
1673644570b8SJeff Kirsher if (info->flags & IS_AX88790) /* select Internal PHY */
1674644570b8SJeff Kirsher outb(0x10, e8390_base + AXNET_GPIO);
1675644570b8SJeff Kirsher
1676644570b8SJeff Kirsher if (startp)
1677644570b8SJeff Kirsher {
1678644570b8SJeff Kirsher outb_p(0xff, e8390_base + EN0_ISR);
1679644570b8SJeff Kirsher outb_p(ENISR_ALL, e8390_base + EN0_IMR);
1680644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD);
1681644570b8SJeff Kirsher outb_p(E8390_TXCONFIG | info->duplex_flag,
1682644570b8SJeff Kirsher e8390_base + EN0_TXCR); /* xmit on. */
1683644570b8SJeff Kirsher /* 3c503 TechMan says rxconfig only after the NIC is started. */
1684644570b8SJeff Kirsher outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); /* rx on, */
1685644570b8SJeff Kirsher do_set_multicast_list(dev); /* (re)load the mcast table */
1686644570b8SJeff Kirsher }
1687644570b8SJeff Kirsher }
1688644570b8SJeff Kirsher
1689644570b8SJeff Kirsher /* Trigger a transmit start, assuming the length is valid.
1690644570b8SJeff Kirsher Always called with the page lock held */
1691644570b8SJeff Kirsher
NS8390_trigger_send(struct net_device * dev,unsigned int length,int start_page)1692644570b8SJeff Kirsher static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
1693644570b8SJeff Kirsher int start_page)
1694644570b8SJeff Kirsher {
1695644570b8SJeff Kirsher long e8390_base = dev->base_addr;
1696644570b8SJeff Kirsher struct ei_device *ei_local __attribute((unused)) = netdev_priv(dev);
1697644570b8SJeff Kirsher
1698644570b8SJeff Kirsher if (inb_p(e8390_base) & E8390_TRANS)
1699644570b8SJeff Kirsher {
1700644570b8SJeff Kirsher netdev_warn(dev, "trigger_send() called with the transmitter busy\n");
1701644570b8SJeff Kirsher return;
1702644570b8SJeff Kirsher }
1703644570b8SJeff Kirsher outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
1704644570b8SJeff Kirsher outb_p(length >> 8, e8390_base + EN0_TCNTHI);
1705644570b8SJeff Kirsher outb_p(start_page, e8390_base + EN0_TPSR);
1706644570b8SJeff Kirsher outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base+E8390_CMD);
1707644570b8SJeff Kirsher }
1708