blob: c9cd2377ef91f155e080143ee202436fba7bc319 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*======================================================================
2
3 A PCMCIA ethernet driver for NS8390-based cards
4
5 This driver supports the D-Link DE-650 and Linksys EthernetCard
6 cards, the newer D-Link and Linksys combo cards, Accton EN2212
7 cards, the RPTI EP400, and the PreMax PE-200 in non-shared-memory
8 mode, and the IBM Credit Card Adapter, the NE4100, the Thomas
9 Conrad ethernet card, and the Kingston KNE-PCM/x in shared-memory
10 mode. It will also handle the Socket EA card in either mode.
11
12 Copyright (C) 1999 David A. Hinds -- dahinds@users.sourceforge.net
13
14 pcnet_cs.c 1.153 2003/11/09 18:53:09
Jeff Garzik6ed14252006-05-24 00:28:37 -040015
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 The network driver code is based on Donald Becker's NE2000 code:
17
18 Written 1992,1993 by Donald Becker.
19 Copyright 1993 United States Government as represented by the
20 Director, National Security Agency. This software may be used and
21 distributed according to the terms of the GNU General Public License,
22 incorporated herein by reference.
23 Donald Becker may be reached at becker@scyld.com
24
25 Based also on Keith Moore's changes to Don Becker's code, for IBM
26 CCAE support. Drivers merged back together, and shared-memory
27 Socket EA support added, by Ken Raeburn, September 1995.
28
29======================================================================*/
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/init.h>
34#include <linux/ptrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/string.h>
36#include <linux/timer.h>
37#include <linux/delay.h>
38#include <linux/ethtool.h>
39#include <linux/netdevice.h>
Robert P. J. Day9329f4e2007-12-13 16:02:55 -080040#include <linux/log2.h>
Stephen Hemminger23169a42009-03-20 19:36:06 +000041#include <linux/etherdevice.h>
Ben Hutchings0fa0ee052009-09-03 10:41:17 +000042#include <linux/mii.h>
Joe Perches0795af52007-10-03 17:59:30 -070043#include "../8390.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#include <pcmcia/cs.h>
46#include <pcmcia/cistpl.h>
47#include <pcmcia/ciscode.h>
48#include <pcmcia/ds.h>
49#include <pcmcia/cisreg.h>
50
51#include <asm/io.h>
52#include <asm/system.h>
53#include <asm/byteorder.h>
54#include <asm/uaccess.h>
55
56#define PCNET_CMD 0x00
57#define PCNET_DATAPORT 0x10 /* NatSemi-defined port window offset. */
58#define PCNET_RESET 0x1f /* Issue a read to reset, a write to clear. */
59#define PCNET_MISC 0x18 /* For IBM CCAE and Socket EA cards */
60
61#define PCNET_START_PG 0x40 /* First page of TX buffer */
62#define PCNET_STOP_PG 0x80 /* Last page +1 of RX ring */
63
64/* Socket EA cards have a larger packet buffer */
65#define SOCKET_START_PG 0x01
66#define SOCKET_STOP_PG 0xff
67
68#define PCNET_RDC_TIMEOUT (2*HZ/100) /* Max wait in jiffies for Tx RDC */
69
Arjan van de Venf71e1302006-03-03 21:33:57 -050070static const char *if_names[] = { "auto", "10baseT", "10base2"};
Linus Torvalds1da177e2005-04-16 15:20:36 -070071
Linus Torvalds1da177e2005-04-16 15:20:36 -070072
73/*====================================================================*/
74
75/* Module parameters */
76
77MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
78MODULE_DESCRIPTION("NE2000 compatible PCMCIA ethernet driver");
79MODULE_LICENSE("GPL");
80
81#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
82
83INT_MODULE_PARM(if_port, 1); /* Transceiver type */
84INT_MODULE_PARM(use_big_buf, 1); /* use 64K packet buffer? */
85INT_MODULE_PARM(mem_speed, 0); /* shared mem speed, in ns */
86INT_MODULE_PARM(delay_output, 0); /* pause after xmit? */
87INT_MODULE_PARM(delay_time, 4); /* in usec */
88INT_MODULE_PARM(use_shmem, -1); /* use shared memory? */
89INT_MODULE_PARM(full_duplex, 0); /* full duplex? */
90
91/* Ugh! Let the user hardwire the hardware address for queer cards */
92static int hw_addr[6] = { 0, /* ... */ };
93module_param_array(hw_addr, int, NULL, 0);
94
95/*====================================================================*/
96
97static void mii_phy_probe(struct net_device *dev);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +020098static int pcnet_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +020099static void pcnet_release(struct pcmcia_device *link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100static int pcnet_open(struct net_device *dev);
101static int pcnet_close(struct net_device *dev);
102static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
Jeff Garzik7282d492006-09-13 14:30:00 -0400103static const struct ethtool_ops netdev_ethtool_ops;
David Howells7d12e782006-10-05 14:55:46 +0100104static irqreturn_t ei_irq_wrapper(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105static void ei_watchdog(u_long arg);
106static void pcnet_reset_8390(struct net_device *dev);
107static int set_config(struct net_device *dev, struct ifmap *map);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200108static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 int stop_pg, int cm_offset);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200110static int setup_dma_config(struct pcmcia_device *link, int start_pg,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111 int stop_pg);
112
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100113static void pcnet_detach(struct pcmcia_device *p_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115/*====================================================================*/
116
117typedef struct hw_info_t {
118 u_int offset;
119 u_char a0, a1, a2;
120 u_int flags;
121} hw_info_t;
122
123#define DELAY_OUTPUT 0x01
124#define HAS_MISC_REG 0x02
125#define USE_BIG_BUF 0x04
126#define HAS_IBM_MISC 0x08
127#define IS_DL10019 0x10
128#define IS_DL10022 0x20
129#define HAS_MII 0x40
130#define USE_SHMEM 0x80 /* autodetected */
131
132#define AM79C9XX_HOME_PHY 0x00006B90 /* HomePNA PHY */
133#define AM79C9XX_ETH_PHY 0x00006B70 /* 10baseT PHY */
134#define MII_PHYID_REV_MASK 0xfffffff0
135#define MII_PHYID_REG1 0x02
136#define MII_PHYID_REG2 0x03
137
138static hw_info_t hw_info[] = {
Jeff Garzik6ed14252006-05-24 00:28:37 -0400139 { /* Accton EN2212 */ 0x0ff0, 0x00, 0x00, 0xe8, DELAY_OUTPUT },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 { /* Allied Telesis LA-PCM */ 0x0ff0, 0x00, 0x00, 0xf4, 0 },
141 { /* APEX MultiCard */ 0x03f4, 0x00, 0x20, 0xe5, 0 },
142 { /* ASANTE FriendlyNet */ 0x4910, 0x00, 0x00, 0x94,
143 DELAY_OUTPUT | HAS_IBM_MISC },
144 { /* Danpex EN-6200P2 */ 0x0110, 0x00, 0x40, 0xc7, 0 },
145 { /* DataTrek NetCard */ 0x0ff0, 0x00, 0x20, 0xe8, 0 },
146 { /* Dayna CommuniCard E */ 0x0110, 0x00, 0x80, 0x19, 0 },
147 { /* D-Link DE-650 */ 0x0040, 0x00, 0x80, 0xc8, 0 },
148 { /* EP-210 Ethernet */ 0x0110, 0x00, 0x40, 0x33, 0 },
149 { /* EP4000 Ethernet */ 0x01c0, 0x00, 0x00, 0xb4, 0 },
150 { /* Epson EEN10B */ 0x0ff0, 0x00, 0x00, 0x48,
151 HAS_MISC_REG | HAS_IBM_MISC },
152 { /* ELECOM Laneed LD-CDWA */ 0xb8, 0x08, 0x00, 0x42, 0 },
153 { /* Hypertec Ethernet */ 0x01c0, 0x00, 0x40, 0x4c, 0 },
154 { /* IBM CCAE */ 0x0ff0, 0x08, 0x00, 0x5a,
155 HAS_MISC_REG | HAS_IBM_MISC },
156 { /* IBM CCAE */ 0x0ff0, 0x00, 0x04, 0xac,
157 HAS_MISC_REG | HAS_IBM_MISC },
158 { /* IBM CCAE */ 0x0ff0, 0x00, 0x06, 0x29,
159 HAS_MISC_REG | HAS_IBM_MISC },
160 { /* IBM FME */ 0x0374, 0x08, 0x00, 0x5a,
161 HAS_MISC_REG | HAS_IBM_MISC },
162 { /* IBM FME */ 0x0374, 0x00, 0x04, 0xac,
163 HAS_MISC_REG | HAS_IBM_MISC },
164 { /* Kansai KLA-PCM/T */ 0x0ff0, 0x00, 0x60, 0x87,
165 HAS_MISC_REG | HAS_IBM_MISC },
166 { /* NSC DP83903 */ 0x0374, 0x08, 0x00, 0x17,
167 HAS_MISC_REG | HAS_IBM_MISC },
168 { /* NSC DP83903 */ 0x0374, 0x00, 0xc0, 0xa8,
169 HAS_MISC_REG | HAS_IBM_MISC },
170 { /* NSC DP83903 */ 0x0374, 0x00, 0xa0, 0xb0,
171 HAS_MISC_REG | HAS_IBM_MISC },
172 { /* NSC DP83903 */ 0x0198, 0x00, 0x20, 0xe0,
173 HAS_MISC_REG | HAS_IBM_MISC },
174 { /* I-O DATA PCLA/T */ 0x0ff0, 0x00, 0xa0, 0xb0, 0 },
175 { /* Katron PE-520 */ 0x0110, 0x00, 0x40, 0xf6, 0 },
176 { /* Kingston KNE-PCM/x */ 0x0ff0, 0x00, 0xc0, 0xf0,
177 HAS_MISC_REG | HAS_IBM_MISC },
178 { /* Kingston KNE-PCM/x */ 0x0ff0, 0xe2, 0x0c, 0x0f,
179 HAS_MISC_REG | HAS_IBM_MISC },
180 { /* Kingston KNE-PC2 */ 0x0180, 0x00, 0xc0, 0xf0, 0 },
181 { /* Maxtech PCN2000 */ 0x5000, 0x00, 0x00, 0xe8, 0 },
182 { /* NDC Instant-Link */ 0x003a, 0x00, 0x80, 0xc6, 0 },
183 { /* NE2000 Compatible */ 0x0ff0, 0x00, 0xa0, 0x0c, 0 },
184 { /* Network General Sniffer */ 0x0ff0, 0x00, 0x00, 0x65,
185 HAS_MISC_REG | HAS_IBM_MISC },
Jeff Garzik6ed14252006-05-24 00:28:37 -0400186 { /* Panasonic VEL211 */ 0x0ff0, 0x00, 0x80, 0x45,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700187 HAS_MISC_REG | HAS_IBM_MISC },
188 { /* PreMax PE-200 */ 0x07f0, 0x00, 0x20, 0xe0, 0 },
189 { /* RPTI EP400 */ 0x0110, 0x00, 0x40, 0x95, 0 },
190 { /* SCM Ethernet */ 0x0ff0, 0x00, 0x20, 0xcb, 0 },
191 { /* Socket EA */ 0x4000, 0x00, 0xc0, 0x1b,
192 DELAY_OUTPUT | HAS_MISC_REG | USE_BIG_BUF },
193 { /* Socket LP-E CF+ */ 0x01c0, 0x00, 0xc0, 0x1b, 0 },
194 { /* SuperSocket RE450T */ 0x0110, 0x00, 0xe0, 0x98, 0 },
195 { /* Volktek NPL-402CT */ 0x0060, 0x00, 0x40, 0x05, 0 },
196 { /* NEC PC-9801N-J12 */ 0x0ff0, 0x00, 0x00, 0x4c, 0 },
197 { /* PCMCIA Technology OEM */ 0x01c8, 0x00, 0xa0, 0x0c, 0 }
198};
199
Denis Chengff8ac602007-09-02 18:30:18 +0800200#define NR_INFO ARRAY_SIZE(hw_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
202static hw_info_t default_info = { 0, 0, 0, 0, 0 };
203static hw_info_t dl10019_info = { 0, 0, 0, 0, IS_DL10019|HAS_MII };
204static hw_info_t dl10022_info = { 0, 0, 0, 0, IS_DL10022|HAS_MII };
205
206typedef struct pcnet_dev_t {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100207 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 u_int flags;
209 void __iomem *base;
210 struct timer_list watchdog;
211 int stale, fast_poll;
212 u_char phy_id;
213 u_char eth_phy, pna_phy;
214 u_short link_status;
215 u_long mii_reset;
216} pcnet_dev_t;
217
218static inline pcnet_dev_t *PRIV(struct net_device *dev)
219{
220 char *p = netdev_priv(dev);
221 return (pcnet_dev_t *)(p + sizeof(struct ei_device));
222}
223
Stephen Hemminger23169a42009-03-20 19:36:06 +0000224static const struct net_device_ops pcnet_netdev_ops = {
225 .ndo_open = pcnet_open,
226 .ndo_stop = pcnet_close,
227 .ndo_set_config = set_config,
228 .ndo_start_xmit = ei_start_xmit,
229 .ndo_get_stats = ei_get_stats,
230 .ndo_do_ioctl = ei_ioctl,
231 .ndo_set_multicast_list = ei_set_multicast_list,
232 .ndo_tx_timeout = ei_tx_timeout,
233 .ndo_change_mtu = eth_change_mtu,
234 .ndo_set_mac_address = eth_mac_addr,
235 .ndo_validate_addr = eth_validate_addr,
236#ifdef CONFIG_NET_POLL_CONTROLLER
237 .ndo_poll_controller = ei_poll,
238#endif
239};
240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241/*======================================================================
242
243 pcnet_attach() creates an "instance" of the driver, allocating
244 local data structures for one device. The device is registered
245 with Card Services.
246
247======================================================================*/
248
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200249static int pcnet_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250{
251 pcnet_dev_t *info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 struct net_device *dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200254 dev_dbg(&link->dev, "pcnet_attach()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255
256 /* Create new ethernet device */
257 dev = __alloc_ei_netdev(sizeof(pcnet_dev_t));
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100258 if (!dev) return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 info = PRIV(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200260 info->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 link->priv = dev;
262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 link->conf.Attributes = CONF_ENABLE_IRQ;
264 link->conf.IntType = INT_MEMORY_AND_IO;
265
Stephen Hemminger23169a42009-03-20 19:36:06 +0000266 dev->netdev_ops = &pcnet_netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200268 return pcnet_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269} /* pcnet_attach */
270
271/*======================================================================
272
273 This deletes a driver "instance". The device is de-registered
274 with Card Services. If it has been released, all local data
275 structures are freed. Otherwise, the structures will be freed
276 when the device is released.
277
278======================================================================*/
279
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200280static void pcnet_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100282 struct net_device *dev = link->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200284 dev_dbg(&link->dev, "pcnet_detach\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Dominik Brodowskic7c2fa02010-03-20 19:39:26 +0100286 unregister_netdev(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100288 pcnet_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100290 free_netdev(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291} /* pcnet_detach */
292
293/*======================================================================
294
295 This probes for a card's hardware address, for card types that
296 encode this information in their CIS.
297
298======================================================================*/
299
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200300static hw_info_t *get_hwinfo(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301{
302 struct net_device *dev = link->priv;
303 win_req_t req;
304 memreq_t mem;
305 u_char __iomem *base, *virt;
306 int i, j;
307
308 /* Allocate a small memory window */
309 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
310 req.Base = 0; req.Size = 0;
311 req.AccessSpeed = 0;
Dominik Brodowski6838b032009-11-03 01:31:52 +0100312 i = pcmcia_request_window(link, &req, &link->win);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200313 if (i != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315
316 virt = ioremap(req.Base, req.Size);
317 mem.Page = 0;
318 for (i = 0; i < NR_INFO; i++) {
319 mem.CardOffset = hw_info[i].offset & ~(req.Size-1);
Magnus Damm868575d2006-12-13 19:46:43 +0900320 pcmcia_map_mem_page(link, link->win, &mem);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321 base = &virt[hw_info[i].offset & (req.Size-1)];
322 if ((readb(base+0) == hw_info[i].a0) &&
323 (readb(base+2) == hw_info[i].a1) &&
Jaswinder Singh Rajput03b88a62009-09-12 09:08:49 +0000324 (readb(base+4) == hw_info[i].a2)) {
325 for (j = 0; j < 6; j++)
326 dev->dev_addr[j] = readb(base + (j<<1));
327 break;
328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 }
Jeff Garzik6ed14252006-05-24 00:28:37 -0400330
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 iounmap(virt);
Magnus Dammf5560da2006-12-13 19:46:38 +0900332 j = pcmcia_release_window(link, link->win);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 return (i < NR_INFO) ? hw_info+i : NULL;
334} /* get_hwinfo */
335
336/*======================================================================
337
338 This probes for a card's hardware address by reading the PROM.
339 It checks the address against a list of known types, then falls
340 back to a simple NE2000 clone signature check.
341
342======================================================================*/
343
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200344static hw_info_t *get_prom(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
346 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800347 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 u_char prom[32];
349 int i, j;
350
351 /* This is lifted straight from drivers/net/ne.c */
352 struct {
353 u_char value, offset;
354 } program_seq[] = {
355 {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
356 {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */
357 {0x00, EN0_RCNTLO}, /* Clear the count regs. */
358 {0x00, EN0_RCNTHI},
359 {0x00, EN0_IMR}, /* Mask completion irq. */
360 {0xFF, EN0_ISR},
361 {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */
362 {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */
363 {32, EN0_RCNTLO},
364 {0x00, EN0_RCNTHI},
365 {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */
366 {0x00, EN0_RSARHI},
367 {E8390_RREAD+E8390_START, E8390_CMD},
368 };
369
370 pcnet_reset_8390(dev);
371 mdelay(10);
372
Denis Chengff8ac602007-09-02 18:30:18 +0800373 for (i = 0; i < ARRAY_SIZE(program_seq); i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
375
376 for (i = 0; i < 32; i++)
377 prom[i] = inb(ioaddr + PCNET_DATAPORT);
378 for (i = 0; i < NR_INFO; i++) {
379 if ((prom[0] == hw_info[i].a0) &&
380 (prom[2] == hw_info[i].a1) &&
381 (prom[4] == hw_info[i].a2))
382 break;
383 }
384 if ((i < NR_INFO) || ((prom[28] == 0x57) && (prom[30] == 0x57))) {
385 for (j = 0; j < 6; j++)
386 dev->dev_addr[j] = prom[j<<1];
387 return (i < NR_INFO) ? hw_info+i : &default_info;
388 }
389 return NULL;
390} /* get_prom */
391
392/*======================================================================
393
394 For DL10019 based cards, like the Linksys EtherFast
395
396======================================================================*/
397
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200398static hw_info_t *get_dl10019(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399{
400 struct net_device *dev = link->priv;
401 int i;
402 u_char sum;
403
404 for (sum = 0, i = 0x14; i < 0x1c; i++)
405 sum += inb_p(dev->base_addr + i);
406 if (sum != 0xff)
407 return NULL;
408 for (i = 0; i < 6; i++)
409 dev->dev_addr[i] = inb_p(dev->base_addr + 0x14 + i);
410 i = inb(dev->base_addr + 0x1f);
411 return ((i == 0x91)||(i == 0x99)) ? &dl10022_info : &dl10019_info;
412}
413
414/*======================================================================
415
416 For Asix AX88190 based cards
417
418======================================================================*/
419
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200420static hw_info_t *get_ax88190(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421{
422 struct net_device *dev = link->priv;
Olof Johansson906da802008-02-04 22:27:35 -0800423 unsigned int ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 int i, j;
425
426 /* Not much of a test, but the alternatives are messy */
427 if (link->conf.ConfigBase != 0x03c0)
428 return NULL;
429
430 outb_p(0x01, ioaddr + EN0_DCFG); /* Set word-wide access. */
431 outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0400. */
432 outb_p(0x04, ioaddr + EN0_RSARHI);
433 outb_p(E8390_RREAD+E8390_START, ioaddr + E8390_CMD);
434
435 for (i = 0; i < 6; i += 2) {
436 j = inw(ioaddr + PCNET_DATAPORT);
437 dev->dev_addr[i] = j & 0xff;
438 dev->dev_addr[i+1] = j >> 8;
439 }
440 printk(KERN_NOTICE "pcnet_cs: this is an AX88190 card!\n");
441 printk(KERN_NOTICE "pcnet_cs: use axnet_cs instead.\n");
442 return NULL;
443}
444
445/*======================================================================
446
447 This should be totally unnecessary... but when we can't figure
448 out the hardware address any other way, we'll let the user hard
449 wire it when the module is initialized.
450
451======================================================================*/
452
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200453static hw_info_t *get_hwired(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 struct net_device *dev = link->priv;
456 int i;
457
458 for (i = 0; i < 6; i++)
459 if (hw_addr[i] != 0) break;
460 if (i == 6)
461 return NULL;
462
463 for (i = 0; i < 6; i++)
464 dev->dev_addr[i] = hw_addr[i];
465
466 return &default_info;
467} /* get_hwired */
468
469/*======================================================================
470
471 pcnet_config() is scheduled to run after a CARD_INSERTION event
472 is received, to configure the PCMCIA socket, and to make the
473 ethernet device available to the system.
474
475======================================================================*/
476
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200477static int try_io_port(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478{
479 int j, ret;
480 if (link->io.NumPorts1 == 32) {
481 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
482 if (link->io.NumPorts2 > 0) {
483 /* for master/slave multifunction cards */
484 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 }
486 } else {
487 /* This should be two 16-port windows */
488 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
489 link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
490 }
491 if (link->io.BasePort1 == 0) {
492 link->io.IOAddrLines = 16;
493 for (j = 0; j < 0x400; j += 0x20) {
494 link->io.BasePort1 = j ^ 0x300;
495 link->io.BasePort2 = (j ^ 0x300) + 0x10;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200496 ret = pcmcia_request_io(link, &link->io);
Dominik Brodowski4c89e882008-08-03 10:07:45 +0200497 if (ret == 0)
498 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 }
500 return ret;
501 } else {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200502 return pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
504}
505
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200506static int pcnet_confcheck(struct pcmcia_device *p_dev,
507 cistpl_cftable_entry_t *cfg,
Dominik Brodowski8e2fc392008-08-02 15:30:31 +0200508 cistpl_cftable_entry_t *dflt,
Dominik Brodowskiad913c12008-08-02 16:12:00 +0200509 unsigned int vcc,
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200510 void *priv_data)
511{
512 int *has_shmem = priv_data;
513 int i;
514 cistpl_io_t *io = &cfg->io;
515
516 if (cfg->index == 0 || cfg->io.nwin == 0)
517 return -EINVAL;
518
Dominik Brodowskib54bf942008-08-02 14:28:43 +0200519 /* For multifunction cards, by convention, we configure the
520 network function with window 0, and serial with window 1 */
521 if (io->nwin > 1) {
522 i = (io->win[1].len > io->win[0].len);
523 p_dev->io.BasePort2 = io->win[1-i].base;
524 p_dev->io.NumPorts2 = io->win[1-i].len;
525 } else {
526 i = p_dev->io.NumPorts2 = 0;
527 }
528
529 *has_shmem = ((cfg->mem.nwin == 1) &&
530 (cfg->mem.win[0].len >= 0x4000));
531 p_dev->io.BasePort1 = io->win[i].base;
532 p_dev->io.NumPorts1 = io->win[i].len;
533 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
534 if (p_dev->io.NumPorts1 + p_dev->io.NumPorts2 >= 32)
535 return try_io_port(p_dev);
536
537 return 0;
538}
539
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200540static int pcnet_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 struct net_device *dev = link->priv;
543 pcnet_dev_t *info = PRIV(dev);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200544 int ret, start_pg, stop_pg, cm_offset;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400545 int has_shmem = 0;
Richard Knutsson9ab98982008-02-04 22:27:42 -0800546 hw_info_t *local_hw_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200548 dev_dbg(&link->dev, "pcnet_config\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200550 ret = pcmcia_loop_config(link, pcnet_confcheck, &has_shmem);
551 if (ret)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Dominik Brodowskieb141202010-03-07 12:21:16 +0100554 if (!link->irq)
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200555 goto failed;
Jeff Garzik6ed14252006-05-24 00:28:37 -0400556
Dominik Brodowski9a017a92010-07-24 15:58:54 +0200557 if (resource_size(link->resource[1]) == 8) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 link->conf.Attributes |= CONF_ENABLE_SPKR;
559 link->conf.Status = CCSR_AUDIO_ENA;
560 }
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400561 if ((link->manf_id == MANFID_IBM) &&
562 (link->card_id == PRODID_IBM_HOME_AND_AWAY))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 link->conf.ConfigIndex |= 0x10;
Jeff Garzik6ed14252006-05-24 00:28:37 -0400564
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200565 ret = pcmcia_request_configuration(link, &link->conf);
566 if (ret)
567 goto failed;
Dominik Brodowskieb141202010-03-07 12:21:16 +0100568 dev->irq = link->irq;
Dominik Brodowski9a017a92010-07-24 15:58:54 +0200569 dev->base_addr = link->resource[0]->start;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 if (info->flags & HAS_MISC_REG) {
571 if ((if_port == 1) || (if_port == 2))
572 dev->if_port = if_port;
573 else
574 printk(KERN_NOTICE "pcnet_cs: invalid if_port requested\n");
575 } else {
576 dev->if_port = 0;
577 }
578
Joe Perches8e95a202009-12-03 07:58:21 +0000579 if ((link->conf.ConfigBase == 0x03c0) &&
580 (link->manf_id == 0x149) && (link->card_id == 0xc1ab)) {
Komuro61da96b2008-02-18 22:06:19 +0900581 printk(KERN_INFO "pcnet_cs: this is an AX88190 card!\n");
582 printk(KERN_INFO "pcnet_cs: use axnet_cs instead.\n");
583 goto failed;
584 }
585
Richard Knutsson9ab98982008-02-04 22:27:42 -0800586 local_hw_info = get_hwinfo(link);
587 if (local_hw_info == NULL)
588 local_hw_info = get_prom(link);
589 if (local_hw_info == NULL)
590 local_hw_info = get_dl10019(link);
591 if (local_hw_info == NULL)
592 local_hw_info = get_ax88190(link);
593 if (local_hw_info == NULL)
594 local_hw_info = get_hwired(link);
Jeff Garzik6ed14252006-05-24 00:28:37 -0400595
Richard Knutsson9ab98982008-02-04 22:27:42 -0800596 if (local_hw_info == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 printk(KERN_NOTICE "pcnet_cs: unable to read hardware net"
598 " address for io base %#3lx\n", dev->base_addr);
599 goto failed;
600 }
601
Richard Knutsson9ab98982008-02-04 22:27:42 -0800602 info->flags = local_hw_info->flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700603 /* Check for user overrides */
604 info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400605 if ((link->manf_id == MANFID_SOCKET) &&
606 ((link->card_id == PRODID_SOCKET_LPE) ||
607 (link->card_id == PRODID_SOCKET_LPE_CF) ||
608 (link->card_id == PRODID_SOCKET_EIO)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 info->flags &= ~USE_BIG_BUF;
610 if (!use_big_buf)
611 info->flags &= ~USE_BIG_BUF;
Jeff Garzik6ed14252006-05-24 00:28:37 -0400612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (info->flags & USE_BIG_BUF) {
614 start_pg = SOCKET_START_PG;
615 stop_pg = SOCKET_STOP_PG;
616 cm_offset = 0x10000;
617 } else {
618 start_pg = PCNET_START_PG;
619 stop_pg = PCNET_STOP_PG;
620 cm_offset = 0;
621 }
622
623 /* has_shmem is ignored if use_shmem != -1 */
624 if ((use_shmem == 0) || (!has_shmem && (use_shmem == -1)) ||
625 (setup_shmem_window(link, start_pg, stop_pg, cm_offset) != 0))
626 setup_dma_config(link, start_pg, stop_pg);
627
628 ei_status.name = "NE2000";
629 ei_status.word16 = 1;
630 ei_status.reset_8390 = &pcnet_reset_8390;
631
632 SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
633
Stephen Hemminger23169a42009-03-20 19:36:06 +0000634 if (info->flags & (IS_DL10019|IS_DL10022))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 mii_phy_probe(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Dominik Brodowskidd2e5a12009-11-03 10:27:34 +0100637 SET_NETDEV_DEV(dev, &link->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if (register_netdev(dev) != 0) {
640 printk(KERN_NOTICE "pcnet_cs: register_netdev() failed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 goto failed;
642 }
643
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 if (info->flags & (IS_DL10019|IS_DL10022)) {
645 u_char id = inb(dev->base_addr + 0x1a);
646 printk(KERN_INFO "%s: NE2000 (DL100%d rev %02x): ",
647 dev->name, ((info->flags & IS_DL10022) ? 22 : 19), id);
648 if (info->pna_phy)
649 printk("PNA, ");
650 } else {
651 printk(KERN_INFO "%s: NE2000 Compatible: ", dev->name);
652 }
653 printk("io %#3lx, irq %d,", dev->base_addr, dev->irq);
654 if (info->flags & USE_SHMEM)
655 printk (" mem %#5lx,", dev->mem_start);
656 if (info->flags & HAS_MISC_REG)
657 printk(" %s xcvr,", if_names[dev->if_port]);
Johannes Berge1749612008-10-27 15:59:26 -0700658 printk(" hw_addr %pM\n", dev->dev_addr);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200659 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661failed:
662 pcnet_release(link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200663 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664} /* pcnet_config */
665
666/*======================================================================
667
668 After a card is removed, pcnet_release() will unregister the net
669 device, and release the PCMCIA configuration. If the device is
670 still open, this will be postponed until it is closed.
671
672======================================================================*/
673
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200674static void pcnet_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675{
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +0100676 pcnet_dev_t *info = PRIV(link->priv);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200678 dev_dbg(&link->dev, "pcnet_release\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +0100680 if (info->flags & USE_SHMEM)
681 iounmap(info->base);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200683 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684}
685
686/*======================================================================
687
688 The card status event handler. Mostly, this schedules other
689 stuff to run after an event is received. A CARD_REMOVAL event
690 also sets some flags to discourage the net drivers from trying
691 to talk to the card any more.
692
693======================================================================*/
694
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200695static int pcnet_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100696{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100697 struct net_device *dev = link->priv;
698
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100699 if (link->open)
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100700 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100701
702 return 0;
703}
704
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200705static int pcnet_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100706{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100707 struct net_device *dev = link->priv;
708
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100709 if (link->open) {
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100710 pcnet_reset_8390(dev);
711 NS8390_init(dev, 1);
712 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100713 }
714
715 return 0;
716}
717
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719/*======================================================================
720
721 MII interface support for DL10019 and DL10022 based cards
722
723 On the DL10019, the MII IO direction bit is 0x10; on the DL10022
724 it is 0x20. Setting both bits seems to work on both card types.
725
726======================================================================*/
727
728#define DLINK_GPIO 0x1c
729#define DLINK_DIAG 0x1d
730#define DLINK_EEPROM 0x1e
731
732#define MDIO_SHIFT_CLK 0x80
733#define MDIO_DATA_OUT 0x40
734#define MDIO_DIR_WRITE 0x30
735#define MDIO_DATA_WRITE0 (MDIO_DIR_WRITE)
736#define MDIO_DATA_WRITE1 (MDIO_DIR_WRITE | MDIO_DATA_OUT)
737#define MDIO_DATA_READ 0x10
738#define MDIO_MASK 0x0f
739
Olof Johansson906da802008-02-04 22:27:35 -0800740static void mdio_sync(unsigned int addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741{
742 int bits, mask = inb(addr) & MDIO_MASK;
743 for (bits = 0; bits < 32; bits++) {
744 outb(mask | MDIO_DATA_WRITE1, addr);
745 outb(mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);
746 }
747}
748
Olof Johansson906da802008-02-04 22:27:35 -0800749static int mdio_read(unsigned int addr, int phy_id, int loc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
751 u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
752 int i, retval = 0, mask = inb(addr) & MDIO_MASK;
753
754 mdio_sync(addr);
755 for (i = 13; i >= 0; i--) {
756 int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
757 outb(mask | dat, addr);
758 outb(mask | dat | MDIO_SHIFT_CLK, addr);
759 }
760 for (i = 19; i > 0; i--) {
761 outb(mask, addr);
762 retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
763 outb(mask | MDIO_SHIFT_CLK, addr);
764 }
765 return (retval>>1) & 0xffff;
766}
767
Olof Johansson906da802008-02-04 22:27:35 -0800768static void mdio_write(unsigned int addr, int phy_id, int loc, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769{
770 u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
771 int i, mask = inb(addr) & MDIO_MASK;
772
773 mdio_sync(addr);
774 for (i = 31; i >= 0; i--) {
775 int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
776 outb(mask | dat, addr);
777 outb(mask | dat | MDIO_SHIFT_CLK, addr);
778 }
779 for (i = 1; i >= 0; i--) {
780 outb(mask, addr);
781 outb(mask | MDIO_SHIFT_CLK, addr);
782 }
783}
784
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785/*======================================================================
786
787 EEPROM access routines for DL10019 and DL10022 based cards
788
789======================================================================*/
790
791#define EE_EEP 0x40
792#define EE_ASIC 0x10
793#define EE_CS 0x08
794#define EE_CK 0x04
795#define EE_DO 0x02
796#define EE_DI 0x01
797#define EE_ADOT 0x01 /* DataOut for ASIC */
798#define EE_READ_CMD 0x06
799
800#define DL19FDUPLX 0x0400 /* DL10019 Full duplex mode */
801
Olof Johansson906da802008-02-04 22:27:35 -0800802static int read_eeprom(unsigned int ioaddr, int location)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803{
804 int i, retval = 0;
Olof Johansson906da802008-02-04 22:27:35 -0800805 unsigned int ee_addr = ioaddr + DLINK_EEPROM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 int read_cmd = location | (EE_READ_CMD << 8);
807
808 outb(0, ee_addr);
809 outb(EE_EEP|EE_CS, ee_addr);
810
811 /* Shift the read command bits out. */
812 for (i = 10; i >= 0; i--) {
813 short dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
814 outb_p(EE_EEP|EE_CS|dataval, ee_addr);
815 outb_p(EE_EEP|EE_CS|dataval|EE_CK, ee_addr);
816 }
817 outb(EE_EEP|EE_CS, ee_addr);
818
819 for (i = 16; i > 0; i--) {
820 outb_p(EE_EEP|EE_CS | EE_CK, ee_addr);
821 retval = (retval << 1) | ((inb(ee_addr) & EE_DI) ? 1 : 0);
822 outb_p(EE_EEP|EE_CS, ee_addr);
823 }
824
825 /* Terminate the EEPROM access. */
826 outb(0, ee_addr);
827 return retval;
828}
829
830/*
831 The internal ASIC registers can be changed by EEPROM READ access
832 with EE_ASIC bit set.
833 In ASIC mode, EE_ADOT is used to output the data to the ASIC.
834*/
835
Olof Johansson906da802008-02-04 22:27:35 -0800836static void write_asic(unsigned int ioaddr, int location, short asic_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837{
838 int i;
Olof Johansson906da802008-02-04 22:27:35 -0800839 unsigned int ee_addr = ioaddr + DLINK_EEPROM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 short dataval;
841 int read_cmd = location | (EE_READ_CMD << 8);
842
843 asic_data |= read_eeprom(ioaddr, location);
844
845 outb(0, ee_addr);
846 outb(EE_ASIC|EE_CS|EE_DI, ee_addr);
847
848 read_cmd = read_cmd >> 1;
849
850 /* Shift the read command bits out. */
851 for (i = 9; i >= 0; i--) {
852 dataval = (read_cmd & (1 << i)) ? EE_DO : 0;
853 outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
854 outb_p(EE_ASIC|EE_CS|EE_DI|dataval|EE_CK, ee_addr);
855 outb_p(EE_ASIC|EE_CS|EE_DI|dataval, ee_addr);
856 }
857 // sync
858 outb(EE_ASIC|EE_CS, ee_addr);
859 outb(EE_ASIC|EE_CS|EE_CK, ee_addr);
860 outb(EE_ASIC|EE_CS, ee_addr);
861
862 for (i = 15; i >= 0; i--) {
863 dataval = (asic_data & (1 << i)) ? EE_ADOT : 0;
864 outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
865 outb_p(EE_ASIC|EE_CS|dataval|EE_CK, ee_addr);
866 outb_p(EE_ASIC|EE_CS|dataval, ee_addr);
867 }
868
869 /* Terminate the ASIC access. */
870 outb(EE_ASIC|EE_DI, ee_addr);
871 outb(EE_ASIC|EE_DI| EE_CK, ee_addr);
872 outb(EE_ASIC|EE_DI, ee_addr);
873
874 outb(0, ee_addr);
875}
876
877/*====================================================================*/
878
879static void set_misc_reg(struct net_device *dev)
880{
Olof Johansson906da802008-02-04 22:27:35 -0800881 unsigned int nic_base = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 pcnet_dev_t *info = PRIV(dev);
883 u_char tmp;
Jeff Garzik6ed14252006-05-24 00:28:37 -0400884
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 if (info->flags & HAS_MISC_REG) {
886 tmp = inb_p(nic_base + PCNET_MISC) & ~3;
887 if (dev->if_port == 2)
888 tmp |= 1;
889 if (info->flags & USE_BIG_BUF)
890 tmp |= 2;
891 if (info->flags & HAS_IBM_MISC)
892 tmp |= 8;
893 outb_p(tmp, nic_base + PCNET_MISC);
894 }
895 if (info->flags & IS_DL10022) {
896 if (info->flags & HAS_MII) {
Komurofcf194d2006-07-23 10:20:55 +0900897 /* Advertise 100F, 100H, 10F, 10H */
898 mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 /* Restart MII autonegotiation */
900 mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
901 mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
902 info->mii_reset = jiffies;
903 } else {
904 outb(full_duplex ? 4 : 0, nic_base + DLINK_DIAG);
905 }
Komurod89a64b2005-10-28 16:09:54 -0400906 } else if (info->flags & IS_DL10019) {
907 /* Advertise 100F, 100H, 10F, 10H */
908 mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 4, 0x01e1);
909 /* Restart MII autonegotiation */
910 mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x0000);
911 mdio_write(nic_base + DLINK_GPIO, info->eth_phy, 0, 0x1200);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 }
913}
914
915/*====================================================================*/
916
917static void mii_phy_probe(struct net_device *dev)
918{
919 pcnet_dev_t *info = PRIV(dev);
Olof Johansson906da802008-02-04 22:27:35 -0800920 unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 int i;
922 u_int tmp, phyid;
923
924 for (i = 31; i >= 0; i--) {
925 tmp = mdio_read(mii_addr, i, 1);
926 if ((tmp == 0) || (tmp == 0xffff))
927 continue;
928 tmp = mdio_read(mii_addr, i, MII_PHYID_REG1);
929 phyid = tmp << 16;
930 phyid |= mdio_read(mii_addr, i, MII_PHYID_REG2);
931 phyid &= MII_PHYID_REV_MASK;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200932 pr_debug("%s: MII at %d is 0x%08x\n", dev->name, i, phyid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 if (phyid == AM79C9XX_HOME_PHY) {
934 info->pna_phy = i;
935 } else if (phyid != AM79C9XX_ETH_PHY) {
936 info->eth_phy = i;
937 }
938 }
939}
940
941static int pcnet_open(struct net_device *dev)
942{
Yoichi Yuasa59b34c12007-06-05 22:55:06 +0900943 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 pcnet_dev_t *info = PRIV(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200945 struct pcmcia_device *link = info->p_dev;
Komuro54299ef2008-06-07 21:37:56 +0900946 unsigned int nic_base = dev->base_addr;
Dominik Brodowskifd238232006-03-05 10:45:09 +0100947
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200948 dev_dbg(&link->dev, "pcnet_open('%s')\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
Dominik Brodowski9940ec32006-03-05 11:04:33 +0100950 if (!pcmcia_dev_present(link))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 return -ENODEV;
952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 set_misc_reg(dev);
Komuro54299ef2008-06-07 21:37:56 +0900954
955 outb_p(0xFF, nic_base + EN0_ISR); /* Clear bogus intr. */
Dominik Brodowskiac8b4222010-07-21 22:38:13 +0200956 ret = request_irq(dev->irq, ei_irq_wrapper, IRQF_SHARED, dev->name, dev);
Yoichi Yuasa59b34c12007-06-05 22:55:06 +0900957 if (ret)
958 return ret;
959
960 link->open++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
962 info->phy_id = info->eth_phy;
963 info->link_status = 0x00;
964 init_timer(&info->watchdog);
965 info->watchdog.function = &ei_watchdog;
966 info->watchdog.data = (u_long)dev;
967 info->watchdog.expires = jiffies + HZ;
968 add_timer(&info->watchdog);
969
970 return ei_open(dev);
971} /* pcnet_open */
972
973/*====================================================================*/
974
975static int pcnet_close(struct net_device *dev)
976{
977 pcnet_dev_t *info = PRIV(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200978 struct pcmcia_device *link = info->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Dominik Brodowskidd0fab52009-10-24 15:51:05 +0200980 dev_dbg(&link->dev, "pcnet_close('%s')\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981
982 ei_close(dev);
983 free_irq(dev->irq, dev);
Jeff Garzik6ed14252006-05-24 00:28:37 -0400984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 link->open--;
986 netif_stop_queue(dev);
987 del_timer_sync(&info->watchdog);
988
989 return 0;
990} /* pcnet_close */
991
992/*======================================================================
993
994 Hard reset the card. This used to pause for the same period that
995 a 8390 reset command required, but that shouldn't be necessary.
996
997======================================================================*/
998
999static void pcnet_reset_8390(struct net_device *dev)
1000{
Olof Johansson906da802008-02-04 22:27:35 -08001001 unsigned int nic_base = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 int i;
1003
1004 ei_status.txing = ei_status.dmaing = 0;
1005
1006 outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, nic_base + E8390_CMD);
1007
1008 outb(inb(nic_base + PCNET_RESET), nic_base + PCNET_RESET);
1009
1010 for (i = 0; i < 100; i++) {
1011 if ((inb_p(nic_base+EN0_ISR) & ENISR_RESET) != 0)
1012 break;
1013 udelay(100);
1014 }
1015 outb_p(ENISR_RESET, nic_base + EN0_ISR); /* Ack intr. */
Jeff Garzik6ed14252006-05-24 00:28:37 -04001016
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 if (i == 100)
1018 printk(KERN_ERR "%s: pcnet_reset_8390() did not complete.\n",
1019 dev->name);
1020 set_misc_reg(dev);
Jeff Garzik6ed14252006-05-24 00:28:37 -04001021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022} /* pcnet_reset_8390 */
1023
1024/*====================================================================*/
1025
1026static int set_config(struct net_device *dev, struct ifmap *map)
1027{
1028 pcnet_dev_t *info = PRIV(dev);
1029 if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
1030 if (!(info->flags & HAS_MISC_REG))
1031 return -EOPNOTSUPP;
1032 else if ((map->port < 1) || (map->port > 2))
1033 return -EINVAL;
1034 dev->if_port = map->port;
1035 printk(KERN_INFO "%s: switched to %s port\n",
1036 dev->name, if_names[dev->if_port]);
1037 NS8390_init(dev, 1);
1038 }
1039 return 0;
1040}
1041
1042/*====================================================================*/
1043
David Howells7d12e782006-10-05 14:55:46 +01001044static irqreturn_t ei_irq_wrapper(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045{
1046 struct net_device *dev = dev_id;
Andreas Mohr93ad4fb2005-04-11 16:47:43 -07001047 pcnet_dev_t *info;
David Howells7d12e782006-10-05 14:55:46 +01001048 irqreturn_t ret = ei_interrupt(irq, dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Andreas Mohr93ad4fb2005-04-11 16:47:43 -07001050 if (ret == IRQ_HANDLED) {
1051 info = PRIV(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 info->stale = 0;
Andreas Mohr93ad4fb2005-04-11 16:47:43 -07001053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 return ret;
1055}
1056
1057static void ei_watchdog(u_long arg)
1058{
1059 struct net_device *dev = (struct net_device *)arg;
1060 pcnet_dev_t *info = PRIV(dev);
Olof Johansson906da802008-02-04 22:27:35 -08001061 unsigned int nic_base = dev->base_addr;
1062 unsigned int mii_addr = nic_base + DLINK_GPIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 u_short link;
1064
1065 if (!netif_device_present(dev)) goto reschedule;
1066
1067 /* Check for pending interrupt with expired latency timer: with
1068 this, we can limp along even if the interrupt is blocked */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) {
1070 if (!info->fast_poll)
1071 printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
David Howells7d12e782006-10-05 14:55:46 +01001072 ei_irq_wrapper(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 info->fast_poll = HZ;
1074 }
1075 if (info->fast_poll) {
1076 info->fast_poll--;
1077 info->watchdog.expires = jiffies + 1;
1078 add_timer(&info->watchdog);
1079 return;
1080 }
1081
1082 if (!(info->flags & HAS_MII))
1083 goto reschedule;
1084
1085 mdio_read(mii_addr, info->phy_id, 1);
1086 link = mdio_read(mii_addr, info->phy_id, 1);
1087 if (!link || (link == 0xffff)) {
1088 if (info->eth_phy) {
1089 info->phy_id = info->eth_phy = 0;
1090 } else {
1091 printk(KERN_INFO "%s: MII is missing!\n", dev->name);
1092 info->flags &= ~HAS_MII;
1093 }
1094 goto reschedule;
1095 }
1096
1097 link &= 0x0004;
1098 if (link != info->link_status) {
1099 u_short p = mdio_read(mii_addr, info->phy_id, 5);
1100 printk(KERN_INFO "%s: %s link beat\n", dev->name,
1101 (link) ? "found" : "lost");
1102 if (link && (info->flags & IS_DL10022)) {
1103 /* Disable collision detection on full duplex links */
1104 outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG);
1105 } else if (link && (info->flags & IS_DL10019)) {
1106 /* Disable collision detection on full duplex links */
1107 write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0);
1108 }
1109 if (link) {
1110 if (info->phy_id == info->eth_phy) {
1111 if (p)
1112 printk(KERN_INFO "%s: autonegotiation complete: "
1113 "%sbaseT-%cD selected\n", dev->name,
1114 ((p & 0x0180) ? "100" : "10"),
1115 ((p & 0x0140) ? 'F' : 'H'));
1116 else
1117 printk(KERN_INFO "%s: link partner did not "
1118 "autonegotiate\n", dev->name);
1119 }
1120 NS8390_init(dev, 1);
1121 }
1122 info->link_status = link;
1123 }
1124 if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) {
1125 link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004;
1126 if (((info->phy_id == info->pna_phy) && link) ||
1127 ((info->phy_id != info->pna_phy) && !link)) {
1128 /* isolate this MII and try flipping to the other one */
1129 mdio_write(mii_addr, info->phy_id, 0, 0x0400);
1130 info->phy_id ^= info->pna_phy ^ info->eth_phy;
1131 printk(KERN_INFO "%s: switched to %s transceiver\n", dev->name,
1132 (info->phy_id == info->eth_phy) ? "ethernet" : "PNA");
1133 mdio_write(mii_addr, info->phy_id, 0,
1134 (info->phy_id == info->eth_phy) ? 0x1000 : 0);
1135 info->link_status = 0;
1136 info->mii_reset = jiffies;
1137 }
1138 }
1139
1140reschedule:
1141 info->watchdog.expires = jiffies + HZ;
1142 add_timer(&info->watchdog);
1143}
1144
1145/*====================================================================*/
1146
1147static void netdev_get_drvinfo(struct net_device *dev,
1148 struct ethtool_drvinfo *info)
1149{
1150 strcpy(info->driver, "pcnet_cs");
1151}
1152
Jeff Garzik7282d492006-09-13 14:30:00 -04001153static const struct ethtool_ops netdev_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 .get_drvinfo = netdev_get_drvinfo,
1155};
1156
1157/*====================================================================*/
1158
1159
1160static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
1161{
1162 pcnet_dev_t *info = PRIV(dev);
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001163 struct mii_ioctl_data *data = if_mii(rq);
Olof Johansson906da802008-02-04 22:27:35 -08001164 unsigned int mii_addr = dev->base_addr + DLINK_GPIO;
Stephen Hemminger23169a42009-03-20 19:36:06 +00001165
1166 if (!(info->flags & (IS_DL10019|IS_DL10022)))
1167 return -EINVAL;
1168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 switch (cmd) {
1170 case SIOCGMIIPHY:
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001171 data->phy_id = info->phy_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 case SIOCGMIIREG: /* Read MII PHY register. */
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001173 data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 return 0;
1175 case SIOCSMIIREG: /* Write MII PHY register. */
Ben Hutchings0fa0ee052009-09-03 10:41:17 +00001176 mdio_write(mii_addr, data->phy_id, data->reg_num & 0x1f, data->val_in);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 return 0;
1178 }
1179 return -EOPNOTSUPP;
1180}
1181
1182/*====================================================================*/
1183
1184static void dma_get_8390_hdr(struct net_device *dev,
1185 struct e8390_pkt_hdr *hdr,
1186 int ring_page)
1187{
Olof Johansson906da802008-02-04 22:27:35 -08001188 unsigned int nic_base = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189
1190 if (ei_status.dmaing) {
1191 printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
1192 "[DMAstat:%1x][irqlock:%1x]\n",
1193 dev->name, ei_status.dmaing, ei_status.irqlock);
1194 return;
1195 }
Jeff Garzik6ed14252006-05-24 00:28:37 -04001196
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 ei_status.dmaing |= 0x01;
1198 outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
1199 outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
1200 outb_p(0, nic_base + EN0_RCNTHI);
1201 outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */
1202 outb_p(ring_page, nic_base + EN0_RSARHI);
1203 outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
1204
1205 insw(nic_base + PCNET_DATAPORT, hdr,
1206 sizeof(struct e8390_pkt_hdr)>>1);
1207 /* Fix for big endian systems */
1208 hdr->count = le16_to_cpu(hdr->count);
1209
1210 outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
1211 ei_status.dmaing &= ~0x01;
1212}
1213
1214/*====================================================================*/
1215
1216static void dma_block_input(struct net_device *dev, int count,
1217 struct sk_buff *skb, int ring_offset)
1218{
Olof Johansson906da802008-02-04 22:27:35 -08001219 unsigned int nic_base = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 int xfer_count = count;
1221 char *buf = skb->data;
1222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 if ((ei_debug > 4) && (count != 4))
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001224 pr_debug("%s: [bi=%d]\n", dev->name, count+4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 if (ei_status.dmaing) {
1226 printk(KERN_NOTICE "%s: DMAing conflict in dma_block_input."
1227 "[DMAstat:%1x][irqlock:%1x]\n",
1228 dev->name, ei_status.dmaing, ei_status.irqlock);
1229 return;
1230 }
1231 ei_status.dmaing |= 0x01;
1232 outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + PCNET_CMD);
1233 outb_p(count & 0xff, nic_base + EN0_RCNTLO);
1234 outb_p(count >> 8, nic_base + EN0_RCNTHI);
1235 outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
1236 outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
1237 outb_p(E8390_RREAD+E8390_START, nic_base + PCNET_CMD);
1238
1239 insw(nic_base + PCNET_DATAPORT,buf,count>>1);
1240 if (count & 0x01)
1241 buf[count-1] = inb(nic_base + PCNET_DATAPORT), xfer_count++;
1242
Andreas Mohr93ad4fb2005-04-11 16:47:43 -07001243 /* This was for the ALPHA version only, but enough people have been
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 encountering problems that it is still here. */
1245#ifdef PCMCIA_DEBUG
1246 if (ei_debug > 4) { /* DMA termination address check... */
1247 int addr, tries = 20;
1248 do {
1249 /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
1250 -- it's broken for Rx on some cards! */
1251 int high = inb_p(nic_base + EN0_RSARHI);
1252 int low = inb_p(nic_base + EN0_RSARLO);
1253 addr = (high << 8) + low;
1254 if (((ring_offset + xfer_count) & 0xff) == (addr & 0xff))
1255 break;
1256 } while (--tries > 0);
1257 if (tries <= 0)
1258 printk(KERN_NOTICE "%s: RX transfer address mismatch,"
1259 "%#4.4x (expected) vs. %#4.4x (actual).\n",
1260 dev->name, ring_offset + xfer_count, addr);
1261 }
1262#endif
1263 outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
1264 ei_status.dmaing &= ~0x01;
1265} /* dma_block_input */
1266
1267/*====================================================================*/
1268
1269static void dma_block_output(struct net_device *dev, int count,
1270 const u_char *buf, const int start_page)
1271{
Olof Johansson906da802008-02-04 22:27:35 -08001272 unsigned int nic_base = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 pcnet_dev_t *info = PRIV(dev);
1274#ifdef PCMCIA_DEBUG
1275 int retries = 0;
1276#endif
1277 u_long dma_start;
1278
1279#ifdef PCMCIA_DEBUG
1280 if (ei_debug > 4)
1281 printk(KERN_DEBUG "%s: [bo=%d]\n", dev->name, count);
1282#endif
1283
1284 /* Round the count up for word writes. Do we need to do this?
1285 What effect will an odd byte count have on the 8390?
1286 I should check someday. */
1287 if (count & 0x01)
1288 count++;
1289 if (ei_status.dmaing) {
1290 printk(KERN_NOTICE "%s: DMAing conflict in dma_block_output."
1291 "[DMAstat:%1x][irqlock:%1x]\n",
1292 dev->name, ei_status.dmaing, ei_status.irqlock);
1293 return;
1294 }
1295 ei_status.dmaing |= 0x01;
1296 /* We should already be in page 0, but to be safe... */
1297 outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base+PCNET_CMD);
1298
1299#ifdef PCMCIA_DEBUG
1300 retry:
1301#endif
1302
1303 outb_p(ENISR_RDC, nic_base + EN0_ISR);
1304
1305 /* Now the normal output. */
1306 outb_p(count & 0xff, nic_base + EN0_RCNTLO);
1307 outb_p(count >> 8, nic_base + EN0_RCNTHI);
1308 outb_p(0x00, nic_base + EN0_RSARLO);
1309 outb_p(start_page, nic_base + EN0_RSARHI);
1310
1311 outb_p(E8390_RWRITE+E8390_START, nic_base + PCNET_CMD);
1312 outsw(nic_base + PCNET_DATAPORT, buf, count>>1);
1313
1314 dma_start = jiffies;
1315
1316#ifdef PCMCIA_DEBUG
Andreas Mohr93ad4fb2005-04-11 16:47:43 -07001317 /* This was for the ALPHA version only, but enough people have been
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 encountering problems that it is still here. */
1319 if (ei_debug > 4) { /* DMA termination address check... */
1320 int addr, tries = 20;
1321 do {
1322 int high = inb_p(nic_base + EN0_RSARHI);
1323 int low = inb_p(nic_base + EN0_RSARLO);
1324 addr = (high << 8) + low;
1325 if ((start_page << 8) + count == addr)
1326 break;
1327 } while (--tries > 0);
1328 if (tries <= 0) {
1329 printk(KERN_NOTICE "%s: Tx packet transfer address mismatch,"
1330 "%#4.4x (expected) vs. %#4.4x (actual).\n",
1331 dev->name, (start_page << 8) + count, addr);
1332 if (retries++ == 0)
1333 goto retry;
1334 }
1335 }
1336#endif
1337
1338 while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
1339 if (time_after(jiffies, dma_start + PCNET_RDC_TIMEOUT)) {
1340 printk(KERN_NOTICE "%s: timeout waiting for Tx RDC.\n",
1341 dev->name);
1342 pcnet_reset_8390(dev);
1343 NS8390_init(dev, 1);
1344 break;
1345 }
1346
1347 outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
1348 if (info->flags & DELAY_OUTPUT)
1349 udelay((long)delay_time);
1350 ei_status.dmaing &= ~0x01;
1351}
1352
1353/*====================================================================*/
1354
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001355static int setup_dma_config(struct pcmcia_device *link, int start_pg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 int stop_pg)
1357{
1358 struct net_device *dev = link->priv;
1359
1360 ei_status.tx_start_page = start_pg;
1361 ei_status.rx_start_page = start_pg + TX_PAGES;
1362 ei_status.stop_page = stop_pg;
1363
1364 /* set up block i/o functions */
1365 ei_status.get_8390_hdr = &dma_get_8390_hdr;
1366 ei_status.block_input = &dma_block_input;
1367 ei_status.block_output = &dma_block_output;
1368
1369 return 0;
1370}
1371
1372/*====================================================================*/
1373
1374static void copyin(void *dest, void __iomem *src, int c)
1375{
1376 u_short *d = dest;
1377 u_short __iomem *s = src;
1378 int odd;
1379
1380 if (c <= 0)
1381 return;
1382 odd = (c & 1); c >>= 1;
1383
1384 if (c) {
1385 do { *d++ = __raw_readw(s++); } while (--c);
1386 }
1387 /* get last byte by fetching a word and masking */
1388 if (odd)
1389 *((u_char *)d) = readw(s) & 0xff;
1390}
1391
1392static void copyout(void __iomem *dest, const void *src, int c)
1393{
1394 u_short __iomem *d = dest;
1395 const u_short *s = src;
1396 int odd;
1397
1398 if (c <= 0)
1399 return;
1400 odd = (c & 1); c >>= 1;
1401
1402 if (c) {
1403 do { __raw_writew(*s++, d++); } while (--c);
1404 }
1405 /* copy last byte doing a read-modify-write */
1406 if (odd)
1407 writew((readw(d) & 0xff00) | *(u_char *)s, d);
1408}
1409
1410/*====================================================================*/
1411
1412static void shmem_get_8390_hdr(struct net_device *dev,
1413 struct e8390_pkt_hdr *hdr,
1414 int ring_page)
1415{
1416 void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
1417 + (ring_page << 8)
1418 - (ei_status.rx_start_page << 8);
Jeff Garzik6ed14252006-05-24 00:28:37 -04001419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 copyin(hdr, xfer_start, sizeof(struct e8390_pkt_hdr));
1421 /* Fix for big endian systems */
1422 hdr->count = le16_to_cpu(hdr->count);
1423}
1424
1425/*====================================================================*/
1426
1427static void shmem_block_input(struct net_device *dev, int count,
1428 struct sk_buff *skb, int ring_offset)
1429{
Al Viro99417762005-04-03 09:15:52 +01001430 void __iomem *base = ei_status.mem;
1431 unsigned long offset = (TX_PAGES<<8) + ring_offset
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 - (ei_status.rx_start_page << 8);
1433 char *buf = skb->data;
Jeff Garzik6ed14252006-05-24 00:28:37 -04001434
Al Viro99417762005-04-03 09:15:52 +01001435 if (offset + count > ei_status.priv) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 /* We must wrap the input move. */
Al Viro99417762005-04-03 09:15:52 +01001437 int semi_count = ei_status.priv - offset;
1438 copyin(buf, base + offset, semi_count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 buf += semi_count;
Al Viro99417762005-04-03 09:15:52 +01001440 offset = TX_PAGES<<8;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 count -= semi_count;
1442 }
Al Viro99417762005-04-03 09:15:52 +01001443 copyin(buf, base + offset, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444}
1445
1446/*====================================================================*/
1447
1448static void shmem_block_output(struct net_device *dev, int count,
1449 const u_char *buf, const int start_page)
1450{
1451 void __iomem *shmem = ei_status.mem + (start_page << 8);
1452 shmem -= ei_status.tx_start_page << 8;
1453 copyout(shmem, buf, count);
1454}
1455
1456/*====================================================================*/
1457
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001458static int setup_shmem_window(struct pcmcia_device *link, int start_pg,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 int stop_pg, int cm_offset)
1460{
1461 struct net_device *dev = link->priv;
1462 pcnet_dev_t *info = PRIV(dev);
1463 win_req_t req;
1464 memreq_t mem;
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001465 int i, window_size, offset, ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 window_size = (stop_pg - start_pg) << 8;
1468 if (window_size > 32 * 1024)
1469 window_size = 32 * 1024;
1470
1471 /* Make sure it's a power of two. */
Robert P. J. Day9329f4e2007-12-13 16:02:55 -08001472 window_size = roundup_pow_of_two(window_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473
1474 /* Allocate a memory window */
1475 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
1476 req.Attributes |= WIN_USE_WAIT;
1477 req.Base = 0; req.Size = window_size;
1478 req.AccessSpeed = mem_speed;
Dominik Brodowski6838b032009-11-03 01:31:52 +01001479 ret = pcmcia_request_window(link, &req, &link->win);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001480 if (ret)
1481 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483 mem.CardOffset = (start_pg << 8) + cm_offset;
1484 offset = mem.CardOffset % window_size;
1485 mem.CardOffset -= offset;
1486 mem.Page = 0;
Magnus Damm868575d2006-12-13 19:46:43 +09001487 ret = pcmcia_map_mem_page(link, link->win, &mem);
Dominik Brodowskidd0fab52009-10-24 15:51:05 +02001488 if (ret)
1489 goto failed;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
1491 /* Try scribbling on the buffer */
1492 info->base = ioremap(req.Base, window_size);
1493 for (i = 0; i < (TX_PAGES<<8); i += 2)
1494 __raw_writew((i>>1), info->base+offset+i);
1495 udelay(100);
1496 for (i = 0; i < (TX_PAGES<<8); i += 2)
1497 if (__raw_readw(info->base+offset+i) != (i>>1)) break;
1498 pcnet_reset_8390(dev);
1499 if (i != (TX_PAGES<<8)) {
1500 iounmap(info->base);
Magnus Dammf5560da2006-12-13 19:46:38 +09001501 pcmcia_release_window(link, link->win);
Magnus Damm0bdf9b32006-12-13 19:46:53 +09001502 info->base = NULL; link->win = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 goto failed;
1504 }
Jeff Garzik6ed14252006-05-24 00:28:37 -04001505
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 ei_status.mem = info->base + offset;
Al Viro99417762005-04-03 09:15:52 +01001507 ei_status.priv = req.Size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 dev->mem_start = (u_long)ei_status.mem;
Al Viro99417762005-04-03 09:15:52 +01001509 dev->mem_end = dev->mem_start + req.Size;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
1511 ei_status.tx_start_page = start_pg;
1512 ei_status.rx_start_page = start_pg + TX_PAGES;
1513 ei_status.stop_page = start_pg + ((req.Size - offset) >> 8);
1514
1515 /* set up block i/o functions */
1516 ei_status.get_8390_hdr = &shmem_get_8390_hdr;
1517 ei_status.block_input = &shmem_block_input;
1518 ei_status.block_output = &shmem_block_output;
1519
1520 info->flags |= USE_SHMEM;
1521 return 0;
1522
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523failed:
1524 return 1;
1525}
1526
1527/*====================================================================*/
1528
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001529static struct pcmcia_device_id pcnet_ids[] = {
1530 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0057, 0x0021),
1531 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0104, 0x000a),
1532 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0xea15),
1533 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0x3341),
1534 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0143, 0xc0ab),
1535 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x021b, 0x0101),
1536 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x08a1, 0xc0ab),
Komurod277ad02005-07-28 01:07:24 -07001537 PCMCIA_PFC_DEVICE_PROD_ID12(0, "AnyCom", "Fast Ethernet + 56K COMBO", 0x578ba6e7, 0xb0ac62c4),
Ken Kawasaki1546a712010-03-27 10:55:37 +00001538 PCMCIA_PFC_DEVICE_PROD_ID12(0, "ATKK", "LM33-PCM-T", 0xba9eb7e2, 0x077c174e),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001539 PCMCIA_PFC_DEVICE_PROD_ID12(0, "D-Link", "DME336T", 0x1a424a1c, 0xb23897ff),
1540 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Grey Cell", "GCS3000", 0x2a151fac, 0x48b932ae),
1541 PCMCIA_PFC_DEVICE_PROD_ID12(0, "Linksys", "EtherFast 10&100 + 56K PC Card (PCMLM56)", 0x0733cc81, 0xb3765033),
1542 PCMCIA_PFC_DEVICE_PROD_ID12(0, "LINKSYS", "PCMLM336", 0xf7cb0b07, 0x7a821b58),
Komuro40738f32007-05-27 08:57:58 +09001543 PCMCIA_PFC_DEVICE_PROD_ID12(0, "MICRO RESEARCH", "COMBO-L/M-336", 0xb2ced065, 0x3ced0555),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001544 PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
1545 PCMCIA_PFC_DEVICE_PROD_ID12(0, "PCMCIAs", "LanModem", 0xdcfe12d3, 0xc67c648f),
1546 PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away 28.8 PC Card ", 0xb569a6e5, 0x5bd4ff2c),
1547 PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "Home and Away Credit Card Adapter", 0xb569a6e5, 0x4bdf15c3),
1548 PCMCIA_MFC_DEVICE_PROD_ID12(0, "IBM", "w95 Home and Away Credit Card ", 0xb569a6e5, 0xae911c15),
1549 PCMCIA_MFC_DEVICE_PROD_ID123(0, "APEX DATA", "MULTICARD", "ETHERNET-MODEM", 0x11c2da09, 0x7289dc5d, 0xaad95e1f),
1550 PCMCIA_MFC_DEVICE_PROD_ID2(0, "FAX/Modem/Ethernet Combo Card ", 0x1ed59302),
1551 PCMCIA_DEVICE_MANF_CARD(0x0057, 0x1004),
1552 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x000d),
1553 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0075),
1554 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0145),
1555 PCMCIA_DEVICE_MANF_CARD(0x0149, 0x0230),
1556 PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
Komuro61da96b2008-02-18 22:06:19 +09001557 PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001558 PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
1559 PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
1560 PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
1561 PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001562 PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
1563 PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0307),
1564 PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030a),
1565 PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1103),
1566 PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1121),
1567 PCMCIA_DEVICE_PROD_ID12("2408LAN", "Ethernet", 0x352fff7f, 0x00b2e941),
Marcin Juszkiewicz654e0222007-07-10 11:40:28 +02001568 PCMCIA_DEVICE_PROD_ID1234("Socket", "CF 10/100 Ethernet Card", "Revision B", "05/11/06", 0xb38bcc2e, 0x4de88352, 0xeaca6c8d, 0x7e57c22e),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001569 PCMCIA_DEVICE_PROD_ID123("Cardwell", "PCMCIA", "ETHERNET", 0x9533672e, 0x281f1c5d, 0x3ff7175b),
1570 PCMCIA_DEVICE_PROD_ID123("CNet ", "CN30BC", "ETHERNET", 0x9fe55d3d, 0x85601198, 0x3ff7175b),
1571 PCMCIA_DEVICE_PROD_ID123("Digital", "Ethernet", "Adapter", 0x9999ab35, 0x00b2e941, 0x4b0d829e),
1572 PCMCIA_DEVICE_PROD_ID123("Edimax Technology Inc.", "PCMCIA", "Ethernet Card", 0x738a0019, 0x281f1c5d, 0x5e9d92c0),
1573 PCMCIA_DEVICE_PROD_ID123("EFA ", "EFA207", "ETHERNET", 0x3d294be4, 0xeb9aab6c, 0x3ff7175b),
1574 PCMCIA_DEVICE_PROD_ID123("I-O DATA", "PCLA", "ETHERNET", 0x1d55d7ec, 0xe4c64d34, 0x3ff7175b),
1575 PCMCIA_DEVICE_PROD_ID123("IO DATA", "PCLATE", "ETHERNET", 0x547e66dc, 0x6b260753, 0x3ff7175b),
1576 PCMCIA_DEVICE_PROD_ID123("KingMax Technology Inc.", "EN10-T2", "PCMCIA Ethernet Card", 0x932b7189, 0x699e4436, 0x6f6652e0),
1577 PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2216", 0x281f1c5d, 0xd4cd2f20, 0xb87add82),
1578 PCMCIA_DEVICE_PROD_ID123("PCMCIA", "PCMCIA-ETHERNET-CARD", "UE2620", 0x281f1c5d, 0xd4cd2f20, 0x7d3d83a8),
1579 PCMCIA_DEVICE_PROD_ID1("2412LAN", 0x67f236ab),
1580 PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2212", 0xdfc6b5b2, 0xcb112a11),
1581 PCMCIA_DEVICE_PROD_ID12("ACCTON", "EN2216-PCMCIA-ETHERNET", 0xdfc6b5b2, 0x5542bfff),
1582 PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA100-PCM-T V2 100/10M LAN PC Card", 0xbb7fbdd7, 0xcd91cc68),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001583 PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA100-PCM V2", 0x36634a66, 0xc6d05997),
Jun Komuro9c7046c2005-06-27 16:28:30 -07001584 PCMCIA_DEVICE_PROD_ID12("Allied Telesis, K.K.", "CentreCOM LA-PCM_V2", 0xbb7fBdd7, 0x28e299f8),
1585 PCMCIA_DEVICE_PROD_ID12("Allied Telesis K.K.", "LA-PCM V3", 0x36634a66, 0x62241d96),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001586 PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8010", 0x5070a7f9, 0x82f96e96),
1587 PCMCIA_DEVICE_PROD_ID12("AmbiCom", "AMB8610", 0x5070a7f9, 0x86741224),
1588 PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002", 0x93b15570, 0x75ec3efb),
1589 PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8002T", 0x93b15570, 0x461c5247),
1590 PCMCIA_DEVICE_PROD_ID12("AmbiCom Inc", "AMB8010", 0x93b15570, 0x82f96e96),
1591 PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet", 0x578ba6e7, 0x0a9888c1),
1592 PCMCIA_DEVICE_PROD_ID12("AnyCom", "ECO Ethernet 10/100", 0x578ba6e7, 0x939fedbd),
1593 PCMCIA_DEVICE_PROD_ID12("AROWANA", "PCMCIA Ethernet LAN Card", 0x313adbc8, 0x08d9f190),
1594 PCMCIA_DEVICE_PROD_ID12("ASANTE", "FriendlyNet PC Card", 0x3a7ade0f, 0x41c64504),
1595 PCMCIA_DEVICE_PROD_ID12("Billionton", "LNT-10TB", 0x552ab682, 0xeeb1ba6a),
1596 PCMCIA_DEVICE_PROD_ID12("CF", "10Base-Ethernet", 0x44ebf863, 0x93ae4d79),
1597 PCMCIA_DEVICE_PROD_ID12("CNet", "CN40BC Ethernet", 0xbc477dde, 0xfba775a7),
1598 PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "BASEline PCMCIA 10 MBit Ethernetadapter", 0xfa2e424d, 0xe9190d8a),
1599 PCMCIA_DEVICE_PROD_ID12("COMPU-SHACK", "FASTline PCMCIA 10/100 Fast-Ethernet", 0xfa2e424d, 0x3953d9b9),
1600 PCMCIA_DEVICE_PROD_ID12("CONTEC", "C-NET(PC)C-10L", 0x21cab552, 0xf6f90722),
1601 PCMCIA_DEVICE_PROD_ID12("corega", "FEther PCC-TXF", 0x0a21501a, 0xa51564a2),
1602 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-T", 0x5261440f, 0xfa9d85bd),
Dominik Brodowski654272982006-04-04 10:17:52 +02001603 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega EtherII PCC-TD", 0x5261440f, 0xc49bd73d),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001604 PCMCIA_DEVICE_PROD_ID12("Corega K.K.", "corega EtherII PCC-TD", 0xd4fdcbd8, 0xc49bd73d),
1605 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-T", 0x5261440f, 0x6705fcaa),
Komuro2dcc9ff2008-08-30 12:13:33 +09001606 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega Ether PCC-TD", 0x5261440f, 0x47d5ca83),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001607 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "corega FastEther PCC-TX", 0x5261440f, 0x485e85d9),
1608 PCMCIA_DEVICE_PROD_ID12("Corega,K.K.", "Ethernet LAN Card", 0x110d26d9, 0x9fd2f0a2),
1609 PCMCIA_DEVICE_PROD_ID12("corega,K.K.", "Ethernet LAN Card", 0x9791a90e, 0x9fd2f0a2),
Komuro77aab8b2006-12-17 19:23:17 +09001610 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "(CG-LAPCCTXD)", 0x5261440f, 0x73ec0d88),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001611 PCMCIA_DEVICE_PROD_ID12("CouplerlessPCMCIA", "100BASE", 0xee5af0ad, 0x7c2add04),
1612 PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-010", 0x77008979, 0x9d8d445d),
1613 PCMCIA_DEVICE_PROD_ID12("CyQ've", "ELA-110E 10/100M LAN Card", 0x77008979, 0xfd184814),
1614 PCMCIA_DEVICE_PROD_ID12("DataTrek.", "NetCard ", 0x5cd66d9d, 0x84697ce0),
1615 PCMCIA_DEVICE_PROD_ID12("Dayna Communications, Inc.", "CommuniCard E", 0x0c629325, 0xb4e7dbaf),
1616 PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100", 0x697403d8, 0xe160b995),
1617 PCMCIA_DEVICE_PROD_ID12("Digicom", "Palladio LAN 10/100 Dongless", 0x697403d8, 0xa6d3b233),
1618 PCMCIA_DEVICE_PROD_ID12("DIGITAL", "DEPCM-XX", 0x69616cb3, 0xe600e76e),
1619 PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-650", 0x1a424a1c, 0xf28c8398),
1620 PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660", 0x1a424a1c, 0xd9a1d05b),
Komurod277ad02005-07-28 01:07:24 -07001621 PCMCIA_DEVICE_PROD_ID12("D-Link", "DE-660+", 0x1a424a1c, 0x50dcd0ec),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001622 PCMCIA_DEVICE_PROD_ID12("D-Link", "DFE-650", 0x1a424a1c, 0x0f0073f9),
1623 PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 PC Card", 0x725b842d, 0xf1efee84),
1624 PCMCIA_DEVICE_PROD_ID12("Dual Speed", "10/100 Port Attached PC Card", 0x725b842d, 0x2db1f8e9),
1625 PCMCIA_DEVICE_PROD_ID12("Dynalink", "L10BC", 0x55632fd5, 0xdc65f2b1),
1626 PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10BC", 0x6a26d1cf, 0xdc65f2b1),
1627 PCMCIA_DEVICE_PROD_ID12("DYNALINK", "L10C", 0x6a26d1cf, 0xc4f84efb),
1628 PCMCIA_DEVICE_PROD_ID12("E-CARD", "E-CARD", 0x6701da11, 0x6701da11),
1629 PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet 10BaseT card", 0x53c864c6, 0xedd059f6),
1630 PCMCIA_DEVICE_PROD_ID12("EIGER Labs Inc.", "Ethernet Combo card", 0x53c864c6, 0x929c486c),
1631 PCMCIA_DEVICE_PROD_ID12("Ethernet", "Adapter", 0x00b2e941, 0x4b0d829e),
1632 PCMCIA_DEVICE_PROD_ID12("Ethernet Adapter", "E2000 PCMCIA Ethernet", 0x96767301, 0x71fbbc61),
1633 PCMCIA_DEVICE_PROD_ID12("Ethernet PCMCIA adapter", "EP-210", 0x8dd86181, 0xf2b52517),
1634 PCMCIA_DEVICE_PROD_ID12("Fast Ethernet", "Adapter", 0xb4be14e3, 0x4b0d829e),
1635 PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2000", 0x2a151fac, 0xf00555cb),
1636 PCMCIA_DEVICE_PROD_ID12("Grey Cell", "GCS2220", 0x2a151fac, 0xc1b7e327),
1637 PCMCIA_DEVICE_PROD_ID12("GVC", "NIC-2000p", 0x76e171bd, 0x6eb1c947),
1638 PCMCIA_DEVICE_PROD_ID12("IBM Corp.", "Ethernet", 0xe3736c88, 0x00b2e941),
1639 PCMCIA_DEVICE_PROD_ID12("IC-CARD", "IC-CARD", 0x60cb09a6, 0x60cb09a6),
Komurod277ad02005-07-28 01:07:24 -07001640 PCMCIA_DEVICE_PROD_ID12("IC-CARD+", "IC-CARD+", 0x93693494, 0x93693494),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001641 PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCETTX", 0x547e66dc, 0x6fc5459b),
1642 PCMCIA_DEVICE_PROD_ID12("iPort", "10/100 Ethernet Card", 0x56c538d2, 0x11b0ffc0),
1643 PCMCIA_DEVICE_PROD_ID12("KANSAI ELECTRIC CO.,LTD", "KLA-PCM/T", 0xb18dc3b4, 0xcc51a956),
1644 PCMCIA_DEVICE_PROD_ID12("KCI", "PE520 PCMCIA Ethernet Adapter", 0xa89b87d3, 0x1eb88e64),
1645 PCMCIA_DEVICE_PROD_ID12("KINGMAX", "EN10T2T", 0x7bcb459a, 0xa5c81fa5),
1646 PCMCIA_DEVICE_PROD_ID12("Kingston", "KNE-PC2", 0x1128e633, 0xce2a89b3),
1647 PCMCIA_DEVICE_PROD_ID12("Kingston Technology Corp.", "EtheRx PC Card Ethernet Adapter", 0x313c7be3, 0x0afb54a2),
1648 PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-10/100CD", 0x1b7827b2, 0xcda71d1c),
1649 PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDF", 0x1b7827b2, 0xfec71e40),
1650 PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDL/T", 0x1b7827b2, 0x79fba4f7),
Jun Komuro9c7046c2005-06-27 16:28:30 -07001651 PCMCIA_DEVICE_PROD_ID12("Laneed", "LD-CDS", 0x1b7827b2, 0x931afaab),
Komurodad8c732007-09-30 10:28:14 +09001652 PCMCIA_DEVICE_PROD_ID12("LEMEL", "LM-N89TX PRO", 0xbbefb52f, 0xd2897a97),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001653 PCMCIA_DEVICE_PROD_ID12("Linksys", "Combo PCMCIA EthernetCard (EC2T)", 0x0733cc81, 0x32ee8c78),
1654 PCMCIA_DEVICE_PROD_ID12("LINKSYS", "E-CARD", 0xf7cb0b07, 0x6701da11),
1655 PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 Integrated PC Card (PCM100)", 0x0733cc81, 0x453c3f9d),
1656 PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100)", 0x0733cc81, 0x66c5a389),
1657 PCMCIA_DEVICE_PROD_ID12("Linksys", "EtherFast 10/100 PC Card (PCMPC100 V2)", 0x0733cc81, 0x3a3b28e9),
Komurod277ad02005-07-28 01:07:24 -07001658 PCMCIA_DEVICE_PROD_ID12("Linksys", "HomeLink Phoneline + 10/100 Network PC Card (PCM100H1)", 0x733cc81, 0x7a3e5c3a),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001659 PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TX", 0x88fcdeda, 0x6d772737),
Komuroc96a34e2006-03-03 21:21:13 -05001660 PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN100TE", 0x88fcdeda, 0x0e714bee),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001661 PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN20T", 0x88fcdeda, 0x81090922),
Komuro77aab8b2006-12-17 19:23:17 +09001662 PCMCIA_DEVICE_PROD_ID12("Logitec", "LPM-LN10TE", 0x88fcdeda, 0xc1e2521c),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001663 PCMCIA_DEVICE_PROD_ID12("LONGSHINE", "PCMCIA Ethernet Card", 0xf866b0b0, 0x6f6652e0),
1664 PCMCIA_DEVICE_PROD_ID12("MACNICA", "ME1-JEIDA", 0x20841b68, 0xaf8a3578),
1665 PCMCIA_DEVICE_PROD_ID12("Macsense", "MPC-10", 0xd830297f, 0xd265c307),
1666 PCMCIA_DEVICE_PROD_ID12("Matsushita Electric Industrial Co.,LTD.", "CF-VEL211", 0x44445376, 0x8ded41d4),
1667 PCMCIA_DEVICE_PROD_ID12("MAXTECH", "PCN2000", 0x78d64bc0, 0xca0ca4b8),
1668 PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-T", 0x481e0094, 0xa2eb0cf3),
1669 PCMCIA_DEVICE_PROD_ID12("MELCO", "LPC2-TX", 0x481e0094, 0x41a6916c),
1670 PCMCIA_DEVICE_PROD_ID12("Microcom C.E.", "Travel Card LAN 10/100", 0x4b91cec7, 0xe70220d6),
1671 PCMCIA_DEVICE_PROD_ID12("Microdyne", "NE4200", 0x2e6da59b, 0x0478e472),
1672 PCMCIA_DEVICE_PROD_ID12("MIDORI ELEC.", "LT-PCMT", 0x648d55c1, 0xbde526c7),
1673 PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover 4100", 0x36e1191f, 0x60c229b9),
1674 PCMCIA_DEVICE_PROD_ID12("National Semiconductor", "InfoMover NE4100", 0x36e1191f, 0xa6617ec8),
1675 PCMCIA_DEVICE_PROD_ID12("NEC", "PC-9801N-J12", 0x18df0ba0, 0xbc912d76),
1676 PCMCIA_DEVICE_PROD_ID12("NETGEAR", "FA410TX", 0x9aa79dc3, 0x60e5bc0e),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001677 PCMCIA_DEVICE_PROD_ID12("Network Everywhere", "Fast Ethernet 10/100 PC Card", 0x820a67b6, 0x31ed1a5f),
Jun Komuro9c7046c2005-06-27 16:28:30 -07001678 PCMCIA_DEVICE_PROD_ID12("NextCom K.K.", "Next Hawk", 0xaedaec74, 0xad050ef1),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001679 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100Mbps Ethernet Card", 0x281f1c5d, 0x6e41773b),
1680 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet", 0x281f1c5d, 0x00b2e941),
1681 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET", 0x281f1c5d, 0x3ff7175b),
1682 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet 10BaseT Card", 0x281f1c5d, 0x4de2f6c8),
1683 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Card", 0x281f1c5d, 0x5e9d92c0),
1684 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Ethernet Combo card", 0x281f1c5d, 0x929c486c),
1685 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "ETHERNET V1.0", 0x281f1c5d, 0x4d8817c8),
1686 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FastEthernet", 0x281f1c5d, 0xfe871eeb),
1687 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "Fast-Ethernet", 0x281f1c5d, 0x45f1f3b4),
1688 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "FAST ETHERNET CARD", 0x281f1c5d, 0xec5dbca7),
1689 PCMCIA_DEVICE_PROD_ID12("PCMCIA LAN", "Ethernet", 0x7500e246, 0x00b2e941),
1690 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "LNT-10TN", 0x281f1c5d, 0xe707f641),
1691 PCMCIA_DEVICE_PROD_ID12("PCMCIAs", "ComboCard", 0xdcfe12d3, 0xcd8906cc),
1692 PCMCIA_DEVICE_PROD_ID12("PCMCIA", "UE2212", 0x281f1c5d, 0xbf17199b),
1693 PCMCIA_DEVICE_PROD_ID12("PCMCIA", " Ethernet NE2000 Compatible", 0x281f1c5d, 0x42d5d7e1),
1694 PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10baseT 3.3V", 0xebf91155, 0x30074c80),
1695 PCMCIA_DEVICE_PROD_ID12("PRETEC", "Ethernet CompactLAN 10BaseT 3.3V", 0xebf91155, 0x7f5a4f50),
1696 PCMCIA_DEVICE_PROD_ID12("Psion Dacom", "Gold Card Ethernet", 0xf5f025c2, 0x3a30e110),
1697 PCMCIA_DEVICE_PROD_ID12("=RELIA==", "Ethernet", 0xcdd0644a, 0x00b2e941),
Ken Kawasaki4c3dd302009-07-04 14:17:10 +00001698 PCMCIA_DEVICE_PROD_ID12("RIOS Systems Co.", "PC CARD3 ETHERNET", 0x7dd33481, 0x10b41826),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001699 PCMCIA_DEVICE_PROD_ID12("RP", "1625B Ethernet NE2000 Compatible", 0xe3e66e22, 0xb96150df),
1700 PCMCIA_DEVICE_PROD_ID12("RPTI", "EP400 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4a7e2ae0),
1701 PCMCIA_DEVICE_PROD_ID12("RPTI", "EP401 Ethernet NE2000 Compatible", 0xdc6f88fd, 0x4bcbd7fd),
1702 PCMCIA_DEVICE_PROD_ID12("RPTI LTD.", "EP400", 0xc53ac515, 0x81e39388),
1703 PCMCIA_DEVICE_PROD_ID12("SCM", "Ethernet Combo card", 0xbdc3b102, 0x929c486c),
1704 PCMCIA_DEVICE_PROD_ID12("Seiko Epson Corp.", "Ethernet", 0x09928730, 0x00b2e941),
1705 PCMCIA_DEVICE_PROD_ID12("SMC", "EZCard-10-PCMCIA", 0xc4f8b18b, 0xfb21d265),
1706 PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision D", 0xc70a4760, 0x2ade483e),
1707 PCMCIA_DEVICE_PROD_ID12("Socket Communications Inc", "Socket EA PCMCIA LAN Adapter Revision E", 0xc70a4760, 0x5dd978a8),
1708 PCMCIA_DEVICE_PROD_ID12("TDK", "LAK-CD031 for PCMCIA", 0x1eae9475, 0x0ed386fa),
1709 PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE450T", 0x466b05f0, 0x8b74bc4f),
Jun Komuro9c7046c2005-06-27 16:28:30 -07001710 PCMCIA_DEVICE_PROD_ID12("Telecom Device K.K.", "SuperSocket RE550T", 0x466b05f0, 0x33c8db2a),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001711 PCMCIA_DEVICE_PROD_ID13("Hypertec", "EP401", 0x8787bec7, 0xf6e4a31e),
1712 PCMCIA_DEVICE_PROD_ID13("KingMax Technology Inc.", "Ethernet Card", 0x932b7189, 0x5e9d92c0),
1713 PCMCIA_DEVICE_PROD_ID13("LONGSHINE", "EP401", 0xf866b0b0, 0xf6e4a31e),
1714 PCMCIA_DEVICE_PROD_ID13("Xircom", "CFE-10", 0x2e3ee845, 0x22a49f89),
1715 PCMCIA_DEVICE_PROD_ID1("CyQ've 10 Base-T LAN CARD", 0x94faf360),
1716 PCMCIA_DEVICE_PROD_ID1("EP-210 PCMCIA LAN CARD.", 0x8850b4de),
1717 PCMCIA_DEVICE_PROD_ID1("ETHER-C16", 0x06a8514f),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001718 PCMCIA_DEVICE_PROD_ID1("NE2000 Compatible", 0x75b8ad5a),
1719 PCMCIA_DEVICE_PROD_ID2("EN-6200P2", 0xa996d078),
1720 /* too generic! */
1721 /* PCMCIA_DEVICE_PROD_ID12("PCMCIA", "10/100 Ethernet Card", 0x281f1c5d, 0x11b0ffc0), */
Ken Kawasaki531afd62009-09-15 02:42:25 -07001722 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "EN2218-LAN/MODEM", 0x281f1c5d, 0x570f348e, "cis/PCMLM28.cis"),
1723 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "PCMCIA", "UE2218-LAN/MODEM", 0x281f1c5d, 0x6fdcacee, "cis/PCMLM28.cis"),
1724 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"),
1725 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"),
1726 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"),
Ken Kawasaki8b1d9202010-06-12 00:17:28 +00001727 PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "TOSHIBA", "Modem/LAN Card", 0xb4585a1a, 0x53f922f8, "cis/PCMLM28.cis"),
Ken Kawasakibf6fda62009-10-05 00:40:03 -07001728 PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"),
1729 PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"),
1730 PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"),
Ken Kawasaki1546a712010-03-27 10:55:37 +00001731 PCMCIA_DEVICE_CIS_PROD_ID12("Allied Telesis,K.K", "Ethernet LAN Card", 0x2ad62f3c, 0x9fd2f0a2, "cis/LA-PCM.cis"),
Ken Kawasakiabe88062010-01-06 20:37:58 -08001732 PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "cis/PE520.cis"),
Ken Kawasakibf6fda62009-10-05 00:40:03 -07001733 PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
Ken Kawasaki63ca2d742009-10-17 15:39:20 +00001734 PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
Ken Kawasakibf6fda62009-10-05 00:40:03 -07001735 PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
Komuro7a1fd332007-12-17 22:22:31 +09001736 PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
Jeff Garzik6ed14252006-05-24 00:28:37 -04001737 PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
Marcin Juszkiewiczcf393eb2006-05-23 11:15:57 +02001738 0xb4be14e3, 0x43ac239b, 0x0877b627),
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001739 PCMCIA_DEVICE_NULL
1740};
1741MODULE_DEVICE_TABLE(pcmcia, pcnet_ids);
Ben Hutchings84899922009-11-07 12:04:09 +00001742MODULE_FIRMWARE("cis/PCMLM28.cis");
1743MODULE_FIRMWARE("cis/DP83903.cis");
1744MODULE_FIRMWARE("cis/LA-PCM.cis");
Ken Kawasakiabe88062010-01-06 20:37:58 -08001745MODULE_FIRMWARE("cis/PE520.cis");
Ben Hutchings84899922009-11-07 12:04:09 +00001746MODULE_FIRMWARE("cis/NE2K.cis");
1747MODULE_FIRMWARE("cis/PE-200.cis");
1748MODULE_FIRMWARE("cis/tamarack.cis");
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001749
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750static struct pcmcia_driver pcnet_driver = {
1751 .drv = {
1752 .name = "pcnet_cs",
1753 },
Dominik Brodowskif8cfa612005-11-14 21:25:51 +01001754 .probe = pcnet_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +01001755 .remove = pcnet_detach,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 .owner = THIS_MODULE,
Dominik Brodowskice8a0032005-06-27 16:28:30 -07001757 .id_table = pcnet_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +01001758 .suspend = pcnet_suspend,
1759 .resume = pcnet_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760};
1761
1762static int __init init_pcnet_cs(void)
1763{
1764 return pcmcia_register_driver(&pcnet_driver);
1765}
1766
1767static void __exit exit_pcnet_cs(void)
1768{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 pcmcia_unregister_driver(&pcnet_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770}
1771
1772module_init(init_pcnet_cs);
1773module_exit(exit_pcnet_cs);