blob: e3731fd156067f34ca41a0e5a5a677da229b965f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*======================================================================
2 fmvj18x_cs.c 2.8 2002/03/23
3
4 A fmvj18x (and its compatibles) PCMCIA client driver
5
6 Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp
7
8 TDK LAK-CD021 and CONTEC C-NET(PC)C support added by
9 Nobuhiro Katayama, kata-n@po.iijnet.or.jp
10
11 The PCMCIA client code is based on code written by David Hinds.
12 Network code is based on the "FMV-18x driver" by Yutaka TAMIYA
13 but is actually largely Donald Becker's AT1700 driver, which
14 carries the following attribution:
15
16 Written 1993-94 by Donald Becker.
17
18 Copyright 1993 United States Government as represented by the
19 Director, National Security Agency.
20
21 This software may be used and distributed according to the terms
22 of the GNU General Public License, incorporated herein by reference.
23
24 The author may be reached as becker@scyld.com, or C/O
25 Scyld Computing Corporation
26 410 Severn Ave., Suite 210
27 Annapolis MD 21403
28
29======================================================================*/
30
31#define DRV_NAME "fmvj18x_cs"
Andy Gospodarekd5b20692006-09-11 17:39:18 -040032#define DRV_VERSION "2.9"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/init.h>
37#include <linux/ptrace.h>
38#include <linux/slab.h>
39#include <linux/string.h>
40#include <linux/timer.h>
41#include <linux/interrupt.h>
42#include <linux/in.h>
43#include <linux/delay.h>
44#include <linux/ethtool.h>
45#include <linux/netdevice.h>
46#include <linux/etherdevice.h>
47#include <linux/skbuff.h>
48#include <linux/if_arp.h>
49#include <linux/ioport.h>
50#include <linux/crc32.h>
51
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <pcmcia/cs_types.h>
53#include <pcmcia/cs.h>
54#include <pcmcia/cistpl.h>
55#include <pcmcia/ciscode.h>
56#include <pcmcia/ds.h>
57
58#include <asm/uaccess.h>
59#include <asm/io.h>
60#include <asm/system.h>
61
62/*====================================================================*/
63
64/* Module parameters */
65
66MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
67MODULE_LICENSE("GPL");
68
69#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
70
71/* SRAM configuration */
72/* 0:4KB*2 TX buffer else:8KB*2 TX buffer */
73INT_MODULE_PARM(sram_config, 0);
74
75#ifdef PCMCIA_DEBUG
76INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
77#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
78static char *version = DRV_NAME ".c " DRV_VERSION " 2002/03/23";
79#else
80#define DEBUG(n, args...)
81#endif
82
83/*====================================================================*/
84/*
85 PCMCIA event handlers
86 */
Dominik Brodowski15b99ac2006-03-31 17:26:06 +020087static int fmvj18x_config(struct pcmcia_device *link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +020088static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
89static int fmvj18x_setup_mfc(struct pcmcia_device *link);
90static void fmvj18x_release(struct pcmcia_device *link);
Dominik Brodowskicc3b4862005-11-14 21:23:14 +010091static void fmvj18x_detach(struct pcmcia_device *p_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93/*
94 LAN controller(MBH86960A) specific routines
95 */
96static int fjn_config(struct net_device *dev, struct ifmap *map);
97static int fjn_open(struct net_device *dev);
98static int fjn_close(struct net_device *dev);
99static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
David Howells7d12e782006-10-05 14:55:46 +0100100static irqreturn_t fjn_interrupt(int irq, void *dev_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101static void fjn_rx(struct net_device *dev);
102static void fjn_reset(struct net_device *dev);
103static struct net_device_stats *fjn_get_stats(struct net_device *dev);
104static void set_rx_mode(struct net_device *dev);
105static void fjn_tx_timeout(struct net_device *dev);
Jeff Garzik7282d492006-09-13 14:30:00 -0400106static const struct ethtool_ops netdev_ethtool_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108/*
109 card type
110 */
111typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
112 XXX10304
113} cardtype_t;
114
115/*
116 driver specific data structure
117*/
118typedef struct local_info_t {
Dominik Brodowskifd238232006-03-05 10:45:09 +0100119 struct pcmcia_device *p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 dev_node_t node;
121 struct net_device_stats stats;
122 long open_time;
123 uint tx_started:1;
124 uint tx_queue;
125 u_short tx_queue_len;
126 cardtype_t cardtype;
127 u_short sent;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128} local_info_t;
129
Komuroab808822005-12-01 02:37:17 -0500130#define MC_FILTERBREAK 64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
132/*====================================================================*/
133/*
134 ioport offset from the base address
135 */
136#define TX_STATUS 0 /* transmit status register */
137#define RX_STATUS 1 /* receive status register */
138#define TX_INTR 2 /* transmit interrupt mask register */
139#define RX_INTR 3 /* receive interrupt mask register */
140#define TX_MODE 4 /* transmit mode register */
141#define RX_MODE 5 /* receive mode register */
142#define CONFIG_0 6 /* configuration register 0 */
143#define CONFIG_1 7 /* configuration register 1 */
144
145#define NODE_ID 8 /* node ID register (bank 0) */
146#define MAR_ADR 8 /* multicast address registers (bank 1) */
147
148#define DATAPORT 8 /* buffer mem port registers (bank 2) */
149#define TX_START 10 /* transmit start register */
150#define COL_CTRL 11 /* 16 collision control register */
151#define BMPR12 12 /* reserved */
152#define BMPR13 13 /* reserved */
153#define RX_SKIP 14 /* skip received packet register */
154
155#define LAN_CTRL 16 /* LAN card control register */
156
157#define MAC_ID 0x1a /* hardware address */
158#define UNGERMANN_MAC_ID 0x18 /* UNGERMANN-BASS hardware address */
159
160/*
161 control bits
162 */
163#define ENA_TMT_OK 0x80
164#define ENA_TMT_REC 0x20
165#define ENA_COL 0x04
166#define ENA_16_COL 0x02
167#define ENA_TBUS_ERR 0x01
168
169#define ENA_PKT_RDY 0x80
170#define ENA_BUS_ERR 0x40
171#define ENA_LEN_ERR 0x08
172#define ENA_ALG_ERR 0x04
173#define ENA_CRC_ERR 0x02
174#define ENA_OVR_FLO 0x01
175
176/* flags */
177#define F_TMT_RDY 0x80 /* can accept new packet */
178#define F_NET_BSY 0x40 /* carrier is detected */
179#define F_TMT_OK 0x20 /* send packet successfully */
180#define F_SRT_PKT 0x10 /* short packet error */
181#define F_COL_ERR 0x04 /* collision error */
182#define F_16_COL 0x02 /* 16 collision error */
183#define F_TBUS_ERR 0x01 /* bus read error */
184
185#define F_PKT_RDY 0x80 /* packet(s) in buffer */
186#define F_BUS_ERR 0x40 /* bus read error */
187#define F_LEN_ERR 0x08 /* short packet */
188#define F_ALG_ERR 0x04 /* frame error */
189#define F_CRC_ERR 0x02 /* CRC error */
190#define F_OVR_FLO 0x01 /* overflow error */
191
192#define F_BUF_EMP 0x40 /* receive buffer is empty */
193
194#define F_SKP_PKT 0x05 /* drop packet in buffer */
195
196/* default bitmaps */
197#define D_TX_INTR ( ENA_TMT_OK )
198#define D_RX_INTR ( ENA_PKT_RDY | ENA_LEN_ERR \
199 | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO )
200#define TX_STAT_M ( F_TMT_RDY )
201#define RX_STAT_M ( F_PKT_RDY | F_LEN_ERR \
202 | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO )
203
204/* commands */
205#define D_TX_MODE 0x06 /* no tests, detect carrier */
206#define ID_MATCHED 0x02 /* (RX_MODE) */
207#define RECV_ALL 0x03 /* (RX_MODE) */
208#define CONFIG0_DFL 0x5a /* 16bit bus, 4K x 2 Tx queues */
209#define CONFIG0_DFL_1 0x5e /* 16bit bus, 8K x 2 Tx queues */
210#define CONFIG0_RST 0xda /* Data Link Controller off (CONFIG_0) */
211#define CONFIG0_RST_1 0xde /* Data Link Controller off (CONFIG_0) */
212#define BANK_0 0xa0 /* bank 0 (CONFIG_1) */
213#define BANK_1 0xa4 /* bank 1 (CONFIG_1) */
214#define BANK_2 0xa8 /* bank 2 (CONFIG_1) */
215#define CHIP_OFF 0x80 /* contrl chip power off (CONFIG_1) */
216#define DO_TX 0x80 /* do transmit packet */
217#define SEND_PKT 0x81 /* send a packet */
218#define AUTO_MODE 0x07 /* Auto skip packet on 16 col detected */
219#define MANU_MODE 0x03 /* Stop and skip packet on 16 col */
220#define TDK_AUTO_MODE 0x47 /* Auto skip packet on 16 col detected */
221#define TDK_MANU_MODE 0x43 /* Stop and skip packet on 16 col */
222#define INTR_OFF 0x0d /* LAN controller ignores interrupts */
223#define INTR_ON 0x1d /* LAN controller will catch interrupts */
224
225#define TX_TIMEOUT ((400*HZ)/1000)
226
227#define BANK_0U 0x20 /* bank 0 (CONFIG_1) */
228#define BANK_1U 0x24 /* bank 1 (CONFIG_1) */
229#define BANK_2U 0x28 /* bank 2 (CONFIG_1) */
230
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200231static int fmvj18x_probe(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232{
233 local_info_t *lp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 struct net_device *dev;
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100235
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 DEBUG(0, "fmvj18x_attach()\n");
237
238 /* Make up a FMVJ18x specific data structure */
239 dev = alloc_etherdev(sizeof(local_info_t));
240 if (!dev)
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100241 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 lp = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 link->priv = dev;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200244 lp->p_dev = link;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
246 /* The io structure describes IO port mapping */
247 link->io.NumPorts1 = 32;
248 link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
249 link->io.IOAddrLines = 5;
250
251 /* Interrupt setup */
252 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
253 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
254 link->irq.Handler = &fjn_interrupt;
255 link->irq.Instance = dev;
Dominik Brodowskif8cfa612005-11-14 21:25:51 +0100256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 /* General socket configuration */
258 link->conf.Attributes = CONF_ENABLE_IRQ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 link->conf.IntType = INT_MEMORY_AND_IO;
260
261 /* The FMVJ18x specific entries in the device structure. */
262 SET_MODULE_OWNER(dev);
263 dev->hard_start_xmit = &fjn_start_xmit;
264 dev->set_config = &fjn_config;
265 dev->get_stats = &fjn_get_stats;
266 dev->set_multicast_list = &set_rx_mode;
267 dev->open = &fjn_open;
268 dev->stop = &fjn_close;
269#ifdef HAVE_TX_TIMEOUT
270 dev->tx_timeout = fjn_tx_timeout;
271 dev->watchdog_timeo = TX_TIMEOUT;
272#endif
273 SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200275 return fmvj18x_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276} /* fmvj18x_attach */
277
278/*====================================================================*/
279
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200280static void fmvj18x_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281{
282 struct net_device *dev = link->priv;
Dominik Brodowskib4635812005-11-14 21:25:35 +0100283
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285
Dominik Brodowskifd238232006-03-05 10:45:09 +0100286 if (link->dev_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 unregister_netdev(dev);
288
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100289 fmvj18x_release(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 free_netdev(dev);
292} /* fmvj18x_detach */
293
294/*====================================================================*/
295
296#define CS_CHECK(fn, ret) \
297do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
298
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200299static int mfc_try_io_port(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300{
301 int i, ret;
Arjan van de Venf71e1302006-03-03 21:33:57 -0500302 static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
304 for (i = 0; i < 5; i++) {
305 link->io.BasePort2 = serial_base[i];
306 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
307 if (link->io.BasePort2 == 0) {
308 link->io.NumPorts2 = 0;
309 printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
310 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200311 ret = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 if (ret == CS_SUCCESS) return ret;
313 }
314 return ret;
315}
316
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200317static int ungermann_try_io_port(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
319 int ret;
320 kio_addr_t ioaddr;
321 /*
322 Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
323 0x380,0x3c0 only for ioport.
324 */
325 for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
326 link->io.BasePort1 = ioaddr;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200327 ret = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 if (ret == CS_SUCCESS) {
329 /* calculate ConfigIndex value */
330 link->conf.ConfigIndex =
331 ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
332 return ret;
333 }
334 }
335 return ret; /* RequestIO failed */
336}
337
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200338static int fmvj18x_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340 struct net_device *dev = link->priv;
341 local_info_t *lp = netdev_priv(dev);
342 tuple_t tuple;
343 cisparse_t parse;
344 u_short buf[32];
345 int i, last_fn, last_ret, ret;
346 kio_addr_t ioaddr;
347 cardtype_t cardtype;
348 char *card_name = "unknown";
349 u_char *node_id;
350
351 DEBUG(0, "fmvj18x_config(0x%p)\n", link);
352
353 /*
354 This reads the card's CONFIG tuple to find its configuration
355 registers.
356 */
357 tuple.DesiredTuple = CISTPL_CONFIG;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200358 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 tuple.TupleData = (u_char *)buf;
360 tuple.TupleDataMax = 64;
361 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200362 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
363 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365 link->conf.ConfigBase = parse.config.base;
366 link->conf.Present = parse.config.rmask[0];
367
368 tuple.DesiredTuple = CISTPL_FUNCE;
369 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200370 if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
372 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200373 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
374 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
375 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 link->conf.ConfigIndex = parse.cftable_entry.index;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400377 switch (link->manf_id) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 case MANFID_TDK:
379 cardtype = TDK;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400380 if (link->card_id == PRODID_TDK_GN3410
381 || link->card_id == PRODID_TDK_NP9610
382 || link->card_id == PRODID_TDK_MN3200) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383 /* MultiFunction Card */
384 link->conf.ConfigBase = 0x800;
385 link->conf.ConfigIndex = 0x47;
386 link->io.NumPorts2 = 8;
387 }
388 break;
389 case MANFID_CONTEC:
390 cardtype = CONTEC;
391 break;
392 case MANFID_FUJITSU:
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400393 if (link->card_id == PRODID_FUJITSU_MBH10302)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
395 but these are MBH10304 based card. */
396 cardtype = MBH10304;
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400397 else if (link->card_id == PRODID_FUJITSU_MBH10304)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 cardtype = MBH10304;
399 else
400 cardtype = LA501;
401 break;
402 default:
403 cardtype = MBH10304;
404 }
405 } else {
406 /* old type card */
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400407 switch (link->manf_id) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 case MANFID_FUJITSU:
Dominik Brodowskiefd50582006-10-25 21:28:53 -0400409 if (link->card_id == PRODID_FUJITSU_MBH10304) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 cardtype = XXX10304; /* MBH10304 with buggy CIS */
411 link->conf.ConfigIndex = 0x20;
412 } else {
413 cardtype = MBH10302; /* NextCom NC5310, etc. */
414 link->conf.ConfigIndex = 1;
415 }
416 break;
417 case MANFID_UNGERMANN:
418 cardtype = UNGERMANN;
419 break;
420 default:
421 cardtype = MBH10302;
422 link->conf.ConfigIndex = 1;
423 }
424 }
425
426 if (link->io.NumPorts2 != 0) {
427 link->irq.Attributes =
428 IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
429 ret = mfc_try_io_port(link);
430 if (ret != CS_SUCCESS) goto cs_failed;
431 } else if (cardtype == UNGERMANN) {
432 ret = ungermann_try_io_port(link);
433 if (ret != CS_SUCCESS) goto cs_failed;
434 } else {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200435 CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200437 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
438 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 dev->irq = link->irq.AssignedIRQ;
440 dev->base_addr = link->io.BasePort1;
441
442 if (link->io.BasePort2 != 0)
443 fmvj18x_setup_mfc(link);
444
445 ioaddr = dev->base_addr;
446
447 /* Reset controller */
448 if (sram_config == 0)
449 outb(CONFIG0_RST, ioaddr + CONFIG_0);
450 else
451 outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
452
453 /* Power On chip and select bank 0 */
454 if (cardtype == MBH10302)
455 outb(BANK_0, ioaddr + CONFIG_1);
456 else
457 outb(BANK_0U, ioaddr + CONFIG_1);
458
459 /* Set hardware address */
460 switch (cardtype) {
461 case MBH10304:
462 case TDK:
463 case LA501:
464 case CONTEC:
465 tuple.DesiredTuple = CISTPL_FUNCE;
466 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200467 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200469 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 if (cardtype == MBH10304) {
471 /* MBH10304's CIS_FUNCE is corrupted */
472 node_id = &(tuple.TupleData[5]);
473 card_name = "FMV-J182";
474 } else {
475 while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200476 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
477 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 }
479 node_id = &(tuple.TupleData[2]);
480 if( cardtype == TDK ) {
481 card_name = "TDK LAK-CD021";
482 } else if( cardtype == LA501 ) {
483 card_name = "LA501";
484 } else {
485 card_name = "C-NET(PC)C";
486 }
487 }
488 /* Read MACID from CIS */
489 for (i = 0; i < 6; i++)
490 dev->dev_addr[i] = node_id[i];
491 break;
492 case UNGERMANN:
493 /* Read MACID from register */
494 for (i = 0; i < 6; i++)
495 dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
496 card_name = "Access/CARD";
497 break;
498 case XXX10304:
499 /* Read MACID from Buggy CIS */
500 if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) {
501 printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
502 goto failed;
503 }
504 for (i = 0 ; i < 6; i++) {
505 dev->dev_addr[i] = tuple.TupleData[i];
506 }
507 card_name = "FMV-J182";
508 break;
509 case MBH10302:
510 default:
511 /* Read MACID from register */
512 for (i = 0; i < 6; i++)
513 dev->dev_addr[i] = inb(ioaddr + MAC_ID + i);
514 card_name = "FMV-J181";
515 break;
516 }
517
518 lp->cardtype = cardtype;
Dominik Brodowskifd238232006-03-05 10:45:09 +0100519 link->dev_node = &lp->node;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200520 SET_NETDEV_DEV(dev, &handle_to_dev(link));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
522 if (register_netdev(dev) != 0) {
523 printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
Dominik Brodowskifd238232006-03-05 10:45:09 +0100524 link->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 goto failed;
526 }
527
528 strcpy(lp->node.dev_name, dev->name);
529
530 /* print current configuration */
531 printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ",
532 dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
533 dev->base_addr, dev->irq);
534 for (i = 0; i < 6; i++)
535 printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
536
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200537 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539cs_failed:
540 /* All Card Services errors end up here */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200541 cs_error(link, last_fn, last_ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542failed:
543 fmvj18x_release(link);
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200544 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545} /* fmvj18x_config */
546/*====================================================================*/
547
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200548static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
550 win_req_t req;
551 memreq_t mem;
552 u_char __iomem *base;
553 int i, j;
554
555 /* Allocate a small memory window */
556 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
557 req.Base = 0; req.Size = 0;
558 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200559 i = pcmcia_request_window(&link, &req, &link->win);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200561 cs_error(link, RequestWindow, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 return -1;
563 }
564
565 base = ioremap(req.Base, req.Size);
566 mem.Page = 0;
567 mem.CardOffset = 0;
568 pcmcia_map_mem_page(link->win, &mem);
569
570 /*
571 * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
572 * 22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
573 * 'xx' is garbage.
574 * 'yy' is MAC address.
575 */
576 for (i = 0; i < 0x200; i++) {
577 if (readb(base+i*2) == 0x22) {
578 if (readb(base+(i-1)*2) == 0xff
579 && readb(base+(i+5)*2) == 0x04
580 && readb(base+(i+6)*2) == 0x06
581 && readb(base+(i+13)*2) == 0xff)
582 break;
583 }
584 }
585
586 if (i != 0x200) {
587 for (j = 0 ; j < 6; j++,i++) {
588 node_id[j] = readb(base+(i+7)*2);
589 }
590 }
591
592 iounmap(base);
593 j = pcmcia_release_window(link->win);
594 if (j != CS_SUCCESS)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200595 cs_error(link, ReleaseWindow, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 return (i != 0x200) ? 0 : -1;
597
598} /* fmvj18x_get_hwinfo */
599/*====================================================================*/
600
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200601static int fmvj18x_setup_mfc(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 win_req_t req;
604 memreq_t mem;
605 u_char __iomem *base;
606 int i, j;
607 struct net_device *dev = link->priv;
608 kio_addr_t ioaddr;
609
610 /* Allocate a small memory window */
611 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
612 req.Base = 0; req.Size = 0;
613 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200614 i = pcmcia_request_window(&link, &req, &link->win);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200616 cs_error(link, RequestWindow, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 return -1;
618 }
619
620 base = ioremap(req.Base, req.Size);
621 mem.Page = 0;
622 mem.CardOffset = 0;
623 pcmcia_map_mem_page(link->win, &mem);
624
625 ioaddr = dev->base_addr;
626 writeb(0x47, base+0x800); /* Config Option Register of LAN */
627 writeb(0x0, base+0x802); /* Config and Status Register */
628
629 writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */
630 writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */
631
632 writeb(0x45, base+0x820); /* Config Option Register of Modem */
633 writeb(0x8, base+0x822); /* Config and Status Register */
634
635 iounmap(base);
636 j = pcmcia_release_window(link->win);
637 if (j != CS_SUCCESS)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200638 cs_error(link, ReleaseWindow, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 return 0;
640
641}
642/*====================================================================*/
643
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200644static void fmvj18x_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645{
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +0100646 DEBUG(0, "fmvj18x_release(0x%p)\n", link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200647 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700648}
649
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200650static int fmvj18x_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100651{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100652 struct net_device *dev = link->priv;
653
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100654 if (link->open)
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100655 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100656
657 return 0;
658}
659
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200660static int fmvj18x_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100661{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100662 struct net_device *dev = link->priv;
663
Dominik Brodowskie2d40962006-03-02 00:09:29 +0100664 if (link->open) {
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100665 fjn_reset(dev);
666 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100667 }
668
669 return 0;
670}
671
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672/*====================================================================*/
673
Dominik Brodowskicda4de82005-06-27 16:28:22 -0700674static struct pcmcia_device_id fmvj18x_ids[] = {
675 PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
676 PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
677 PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
678 PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
679 PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
680 PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
681 PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
682 PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
683 PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0 ", 0x8cef4d3a, 0x075fc7b6),
684 PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0 ", 0x8cef4d3a, 0xbccf43e6),
685 PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
686 PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
687 PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
688 PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
689 PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304 ES", 0x2599f454),
690 PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
691 PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
692 PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
Jun Komurof4d75102005-06-27 16:28:44 -0700693 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
694 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
Dominik Brodowskicda4de82005-06-27 16:28:22 -0700695 PCMCIA_DEVICE_NULL,
696};
697MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
698
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699static struct pcmcia_driver fmvj18x_cs_driver = {
700 .owner = THIS_MODULE,
701 .drv = {
702 .name = "fmvj18x_cs",
703 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200704 .probe = fmvj18x_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100705 .remove = fmvj18x_detach,
Dominik Brodowskicda4de82005-06-27 16:28:22 -0700706 .id_table = fmvj18x_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100707 .suspend = fmvj18x_suspend,
708 .resume = fmvj18x_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709};
710
711static int __init init_fmvj18x_cs(void)
712{
713 return pcmcia_register_driver(&fmvj18x_cs_driver);
714}
715
716static void __exit exit_fmvj18x_cs(void)
717{
718 pcmcia_unregister_driver(&fmvj18x_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719}
720
721module_init(init_fmvj18x_cs);
722module_exit(exit_fmvj18x_cs);
723
724/*====================================================================*/
725
David Howells7d12e782006-10-05 14:55:46 +0100726static irqreturn_t fjn_interrupt(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727{
728 struct net_device *dev = dev_id;
729 local_info_t *lp = netdev_priv(dev);
730 kio_addr_t ioaddr;
731 unsigned short tx_stat, rx_stat;
732
733 if (lp == NULL) {
734 printk(KERN_NOTICE "fjn_interrupt(): irq %d for "
735 "unknown device.\n", irq);
736 return IRQ_NONE;
737 }
738 ioaddr = dev->base_addr;
739
740 /* avoid multiple interrupts */
741 outw(0x0000, ioaddr + TX_INTR);
742
743 /* wait for a while */
744 udelay(1);
745
746 /* get status */
747 tx_stat = inb(ioaddr + TX_STATUS);
748 rx_stat = inb(ioaddr + RX_STATUS);
749
750 /* clear status */
751 outb(tx_stat, ioaddr + TX_STATUS);
752 outb(rx_stat, ioaddr + RX_STATUS);
753
754 DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
755 DEBUG(4, " tx_status %02x.\n", tx_stat);
756
757 if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
758 /* there is packet(s) in rx buffer */
759 fjn_rx(dev);
760 }
761 if (tx_stat & F_TMT_RDY) {
762 lp->stats.tx_packets += lp->sent ;
763 lp->sent = 0 ;
764 if (lp->tx_queue) {
765 outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
766 lp->sent = lp->tx_queue ;
767 lp->tx_queue = 0;
768 lp->tx_queue_len = 0;
769 dev->trans_start = jiffies;
770 } else {
771 lp->tx_started = 0;
772 }
773 netif_wake_queue(dev);
774 }
775 DEBUG(4, "%s: exiting interrupt,\n", dev->name);
776 DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
777
778 outb(D_TX_INTR, ioaddr + TX_INTR);
779 outb(D_RX_INTR, ioaddr + RX_INTR);
780 return IRQ_HANDLED;
781
782} /* fjn_interrupt */
783
784/*====================================================================*/
785
786static void fjn_tx_timeout(struct net_device *dev)
787{
788 struct local_info_t *lp = netdev_priv(dev);
789 kio_addr_t ioaddr = dev->base_addr;
790
791 printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
792 dev->name, htons(inw(ioaddr + TX_STATUS)),
793 inb(ioaddr + TX_STATUS) & F_TMT_RDY
794 ? "IRQ conflict" : "network cable problem");
795 printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
796 "%04x %04x %04x %04x %04x.\n",
797 dev->name, htons(inw(ioaddr + 0)),
798 htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
799 htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
800 htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
801 htons(inw(ioaddr +14)));
802 lp->stats.tx_errors++;
803 /* ToDo: We should try to restart the adaptor... */
804 local_irq_disable();
805 fjn_reset(dev);
806
807 lp->tx_started = 0;
808 lp->tx_queue = 0;
809 lp->tx_queue_len = 0;
810 lp->sent = 0;
811 lp->open_time = jiffies;
812 local_irq_enable();
813 netif_wake_queue(dev);
814}
815
816static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
817{
818 struct local_info_t *lp = netdev_priv(dev);
819 kio_addr_t ioaddr = dev->base_addr;
820 short length = skb->len;
821
822 if (length < ETH_ZLEN)
823 {
Herbert Xu5b057c62006-06-23 02:06:41 -0700824 if (skb_padto(skb, ETH_ZLEN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 return 0;
826 length = ETH_ZLEN;
827 }
828
829 netif_stop_queue(dev);
830
831 {
832 unsigned char *buf = skb->data;
833
834 if (length > ETH_FRAME_LEN) {
835 printk(KERN_NOTICE "%s: Attempting to send a large packet"
836 " (%d bytes).\n", dev->name, length);
837 return 1;
838 }
839
840 DEBUG(4, "%s: Transmitting a packet of length %lu.\n",
841 dev->name, (unsigned long)skb->len);
842 lp->stats.tx_bytes += skb->len;
843
844 /* Disable both interrupts. */
845 outw(0x0000, ioaddr + TX_INTR);
846
847 /* wait for a while */
848 udelay(1);
849
850 outw(length, ioaddr + DATAPORT);
851 outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
852
853 lp->tx_queue++;
854 lp->tx_queue_len += ((length+3) & ~1);
855
856 if (lp->tx_started == 0) {
857 /* If the Tx is idle, always trigger a transmit. */
858 outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
859 lp->sent = lp->tx_queue ;
860 lp->tx_queue = 0;
861 lp->tx_queue_len = 0;
862 dev->trans_start = jiffies;
863 lp->tx_started = 1;
864 netif_start_queue(dev);
865 } else {
866 if( sram_config == 0 ) {
867 if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
868 /* Yes, there is room for one more packet. */
869 netif_start_queue(dev);
870 } else {
871 if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
872 lp->tx_queue < 127 )
873 /* Yes, there is room for one more packet. */
874 netif_start_queue(dev);
875 }
876 }
877
878 /* Re-enable interrupts */
879 outb(D_TX_INTR, ioaddr + TX_INTR);
880 outb(D_RX_INTR, ioaddr + RX_INTR);
881 }
882 dev_kfree_skb (skb);
883
884 return 0;
885} /* fjn_start_xmit */
886
887/*====================================================================*/
888
889static void fjn_reset(struct net_device *dev)
890{
891 struct local_info_t *lp = netdev_priv(dev);
892 kio_addr_t ioaddr = dev->base_addr;
893 int i;
894
895 DEBUG(4, "fjn_reset(%s) called.\n",dev->name);
896
897 /* Reset controller */
898 if( sram_config == 0 )
899 outb(CONFIG0_RST, ioaddr + CONFIG_0);
900 else
901 outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
902
903 /* Power On chip and select bank 0 */
904 if (lp->cardtype == MBH10302)
905 outb(BANK_0, ioaddr + CONFIG_1);
906 else
907 outb(BANK_0U, ioaddr + CONFIG_1);
908
909 /* Set Tx modes */
910 outb(D_TX_MODE, ioaddr + TX_MODE);
911 /* set Rx modes */
912 outb(ID_MATCHED, ioaddr + RX_MODE);
913
914 /* Set hardware address */
915 for (i = 0; i < 6; i++)
916 outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
917
Komuroab808822005-12-01 02:37:17 -0500918 /* (re)initialize the multicast table */
919 set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
921 /* Switch to bank 2 (runtime mode) */
922 if (lp->cardtype == MBH10302)
923 outb(BANK_2, ioaddr + CONFIG_1);
924 else
925 outb(BANK_2U, ioaddr + CONFIG_1);
926
927 /* set 16col ctrl bits */
928 if( lp->cardtype == TDK || lp->cardtype == CONTEC)
929 outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
930 else
931 outb(AUTO_MODE, ioaddr + COL_CTRL);
932
933 /* clear Reserved Regs */
934 outb(0x00, ioaddr + BMPR12);
935 outb(0x00, ioaddr + BMPR13);
936
937 /* reset Skip packet reg. */
938 outb(0x01, ioaddr + RX_SKIP);
939
940 /* Enable Tx and Rx */
941 if( sram_config == 0 )
942 outb(CONFIG0_DFL, ioaddr + CONFIG_0);
943 else
944 outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
945
946 /* Init receive pointer ? */
947 inw(ioaddr + DATAPORT);
948 inw(ioaddr + DATAPORT);
949
950 /* Clear all status */
951 outb(0xff, ioaddr + TX_STATUS);
952 outb(0xff, ioaddr + RX_STATUS);
953
954 if (lp->cardtype == MBH10302)
955 outb(INTR_OFF, ioaddr + LAN_CTRL);
956
957 /* Turn on Rx interrupts */
958 outb(D_TX_INTR, ioaddr + TX_INTR);
959 outb(D_RX_INTR, ioaddr + RX_INTR);
960
961 /* Turn on interrupts from LAN card controller */
962 if (lp->cardtype == MBH10302)
963 outb(INTR_ON, ioaddr + LAN_CTRL);
964} /* fjn_reset */
965
966/*====================================================================*/
967
968static void fjn_rx(struct net_device *dev)
969{
970 struct local_info_t *lp = netdev_priv(dev);
971 kio_addr_t ioaddr = dev->base_addr;
972 int boguscount = 10; /* 5 -> 10: by agy 19940922 */
973
974 DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n",
975 dev->name, inb(ioaddr + RX_STATUS));
976
977 while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
978 u_short status = inw(ioaddr + DATAPORT);
979
980 DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n",
981 dev->name, inb(ioaddr + RX_MODE), status);
982#ifndef final_version
983 if (status == 0) {
984 outb(F_SKP_PKT, ioaddr + RX_SKIP);
985 break;
986 }
987#endif
988 if ((status & 0xF0) != 0x20) { /* There was an error. */
989 lp->stats.rx_errors++;
990 if (status & F_LEN_ERR) lp->stats.rx_length_errors++;
991 if (status & F_ALG_ERR) lp->stats.rx_frame_errors++;
992 if (status & F_CRC_ERR) lp->stats.rx_crc_errors++;
993 if (status & F_OVR_FLO) lp->stats.rx_over_errors++;
994 } else {
995 u_short pkt_len = inw(ioaddr + DATAPORT);
996 /* Malloc up new buffer. */
997 struct sk_buff *skb;
998
999 if (pkt_len > 1550) {
1000 printk(KERN_NOTICE "%s: The FMV-18x claimed a very "
1001 "large packet, size %d.\n", dev->name, pkt_len);
1002 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1003 lp->stats.rx_errors++;
1004 break;
1005 }
1006 skb = dev_alloc_skb(pkt_len+2);
1007 if (skb == NULL) {
1008 printk(KERN_NOTICE "%s: Memory squeeze, dropping "
1009 "packet (len %d).\n", dev->name, pkt_len);
1010 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1011 lp->stats.rx_dropped++;
1012 break;
1013 }
1014 skb->dev = dev;
1015
1016 skb_reserve(skb, 2);
1017 insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
1018 (pkt_len + 1) >> 1);
1019 skb->protocol = eth_type_trans(skb, dev);
1020
1021#ifdef PCMCIA_DEBUG
1022 if (pc_debug > 5) {
1023 int i;
1024 printk(KERN_DEBUG "%s: Rxed packet of length %d: ",
1025 dev->name, pkt_len);
1026 for (i = 0; i < 14; i++)
1027 printk(" %02x", skb->data[i]);
1028 printk(".\n");
1029 }
1030#endif
1031
1032 netif_rx(skb);
1033 dev->last_rx = jiffies;
1034 lp->stats.rx_packets++;
1035 lp->stats.rx_bytes += pkt_len;
1036 }
1037 if (--boguscount <= 0)
1038 break;
1039 }
1040
1041 /* If any worth-while packets have been received, dev_rint()
1042 has done a netif_wake_queue() for us and will work on them
1043 when we get to the bottom-half routine. */
1044/*
1045 if (lp->cardtype != TDK) {
1046 int i;
1047 for (i = 0; i < 20; i++) {
1048 if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
1049 break;
1050 (void)inw(ioaddr + DATAPORT); /+ dummy status read +/
1051 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1052 }
1053
1054 if (i > 0)
1055 DEBUG(5, "%s: Exint Rx packet with mode %02x after "
1056 "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
1057 }
1058*/
1059
1060 return;
1061} /* fjn_rx */
1062
1063/*====================================================================*/
1064
1065static void netdev_get_drvinfo(struct net_device *dev,
1066 struct ethtool_drvinfo *info)
1067{
1068 strcpy(info->driver, DRV_NAME);
1069 strcpy(info->version, DRV_VERSION);
1070 sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);
1071}
1072
1073#ifdef PCMCIA_DEBUG
1074static u32 netdev_get_msglevel(struct net_device *dev)
1075{
1076 return pc_debug;
1077}
1078
1079static void netdev_set_msglevel(struct net_device *dev, u32 level)
1080{
1081 pc_debug = level;
1082}
1083#endif /* PCMCIA_DEBUG */
1084
Jeff Garzik7282d492006-09-13 14:30:00 -04001085static const struct ethtool_ops netdev_ethtool_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 .get_drvinfo = netdev_get_drvinfo,
1087#ifdef PCMCIA_DEBUG
1088 .get_msglevel = netdev_get_msglevel,
1089 .set_msglevel = netdev_set_msglevel,
1090#endif /* PCMCIA_DEBUG */
1091};
1092
1093static int fjn_config(struct net_device *dev, struct ifmap *map){
1094 return 0;
1095}
1096
1097static int fjn_open(struct net_device *dev)
1098{
1099 struct local_info_t *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001100 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101
1102 DEBUG(4, "fjn_open('%s').\n", dev->name);
1103
Dominik Brodowski9940ec32006-03-05 11:04:33 +01001104 if (!pcmcia_dev_present(link))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 return -ENODEV;
1106
1107 link->open++;
1108
1109 fjn_reset(dev);
1110
1111 lp->tx_started = 0;
1112 lp->tx_queue = 0;
1113 lp->tx_queue_len = 0;
1114 lp->open_time = jiffies;
1115 netif_start_queue(dev);
1116
1117 return 0;
1118} /* fjn_open */
1119
1120/*====================================================================*/
1121
1122static int fjn_close(struct net_device *dev)
1123{
1124 struct local_info_t *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001125 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 kio_addr_t ioaddr = dev->base_addr;
1127
1128 DEBUG(4, "fjn_close('%s').\n", dev->name);
1129
1130 lp->open_time = 0;
1131 netif_stop_queue(dev);
1132
1133 /* Set configuration register 0 to disable Tx and Rx. */
1134 if( sram_config == 0 )
1135 outb(CONFIG0_RST ,ioaddr + CONFIG_0);
1136 else
1137 outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
1138
1139 /* Update the statistics -- ToDo. */
1140
1141 /* Power-down the chip. Green, green, green! */
1142 outb(CHIP_OFF ,ioaddr + CONFIG_1);
1143
1144 /* Set the ethernet adaptor disable IRQ */
1145 if (lp->cardtype == MBH10302)
1146 outb(INTR_OFF, ioaddr + LAN_CTRL);
1147
1148 link->open--;
1149
1150 return 0;
1151} /* fjn_close */
1152
1153/*====================================================================*/
1154
1155static struct net_device_stats *fjn_get_stats(struct net_device *dev)
1156{
1157 local_info_t *lp = netdev_priv(dev);
1158 return &lp->stats;
1159} /* fjn_get_stats */
1160
1161/*====================================================================*/
1162
1163/*
1164 Set the multicast/promiscuous mode for this adaptor.
1165*/
1166
1167static void set_rx_mode(struct net_device *dev)
1168{
1169 kio_addr_t ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 u_char mc_filter[8]; /* Multicast hash filter */
1171 u_long flags;
1172 int i;
1173
Komuroab808822005-12-01 02:37:17 -05001174 int saved_bank;
Komurod9a8a0a2005-08-06 12:01:43 +09001175 int saved_config_0 = inb(ioaddr + CONFIG_0);
1176
1177 local_irq_save(flags);
1178
1179 /* Disable Tx and Rx */
1180 if (sram_config == 0)
1181 outb(CONFIG0_RST, ioaddr + CONFIG_0);
1182 else
1183 outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
1184
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 if (dev->flags & IFF_PROMISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 memset(mc_filter, 0xff, sizeof(mc_filter));
1187 outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
1188 } else if (dev->mc_count > MC_FILTERBREAK
1189 || (dev->flags & IFF_ALLMULTI)) {
1190 /* Too many to filter perfectly -- accept all multicasts. */
1191 memset(mc_filter, 0xff, sizeof(mc_filter));
1192 outb(2, ioaddr + RX_MODE); /* Use normal mode. */
1193 } else if (dev->mc_count == 0) {
1194 memset(mc_filter, 0x00, sizeof(mc_filter));
1195 outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */
1196 } else {
1197 struct dev_mc_list *mclist;
1198 int i;
1199
1200 memset(mc_filter, 0, sizeof(mc_filter));
1201 for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
1202 i++, mclist = mclist->next) {
1203 unsigned int bit =
Komurod9a8a0a2005-08-06 12:01:43 +09001204 ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
1205 mc_filter[bit >> 3] |= (1 << (bit & 7));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 }
Komurod9a8a0a2005-08-06 12:01:43 +09001207 outb(2, ioaddr + RX_MODE); /* Use normal mode. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209
Komuroab808822005-12-01 02:37:17 -05001210 /* Switch to bank 1 and set the multicast table. */
1211 saved_bank = inb(ioaddr + CONFIG_1);
1212 outb(0xe4, ioaddr + CONFIG_1);
1213
1214 for (i = 0; i < 8; i++)
1215 outb(mc_filter[i], ioaddr + MAR_ADR + i);
1216 outb(saved_bank, ioaddr + CONFIG_1);
Komurod9a8a0a2005-08-06 12:01:43 +09001217
1218 outb(saved_config_0, ioaddr + CONFIG_0);
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 local_irq_restore(flags);
1221}