blob: d9c83b290095380b1c109c5af72f16721d1280b6 [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"
32#define DRV_VERSION "2.8"
33
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);
100static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
101static 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);
106static struct ethtool_ops netdev_ethtool_ops;
107
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 Brodowskif8cfa612005-11-14 21:25:51 +0100275 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200276 return fmvj18x_config(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277} /* fmvj18x_attach */
278
279/*====================================================================*/
280
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200281static void fmvj18x_detach(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282{
283 struct net_device *dev = link->priv;
Dominik Brodowskib4635812005-11-14 21:25:35 +0100284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286
Dominik Brodowskifd238232006-03-05 10:45:09 +0100287 if (link->dev_node)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 unregister_netdev(dev);
289
290 if (link->state & DEV_CONFIG)
291 fmvj18x_release(link);
292
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 free_netdev(dev);
294} /* fmvj18x_detach */
295
296/*====================================================================*/
297
298#define CS_CHECK(fn, ret) \
299do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
300
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200301static int mfc_try_io_port(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302{
303 int i, ret;
Arjan van de Venf71e1302006-03-03 21:33:57 -0500304 static const kio_addr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
306 for (i = 0; i < 5; i++) {
307 link->io.BasePort2 = serial_base[i];
308 link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
309 if (link->io.BasePort2 == 0) {
310 link->io.NumPorts2 = 0;
311 printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
312 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200313 ret = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 if (ret == CS_SUCCESS) return ret;
315 }
316 return ret;
317}
318
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200319static int ungermann_try_io_port(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
321 int ret;
322 kio_addr_t ioaddr;
323 /*
324 Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
325 0x380,0x3c0 only for ioport.
326 */
327 for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
328 link->io.BasePort1 = ioaddr;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200329 ret = pcmcia_request_io(link, &link->io);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 if (ret == CS_SUCCESS) {
331 /* calculate ConfigIndex value */
332 link->conf.ConfigIndex =
333 ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
334 return ret;
335 }
336 }
337 return ret; /* RequestIO failed */
338}
339
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200340static int fmvj18x_config(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 struct net_device *dev = link->priv;
343 local_info_t *lp = netdev_priv(dev);
344 tuple_t tuple;
345 cisparse_t parse;
346 u_short buf[32];
347 int i, last_fn, last_ret, ret;
348 kio_addr_t ioaddr;
349 cardtype_t cardtype;
350 char *card_name = "unknown";
351 u_char *node_id;
352
353 DEBUG(0, "fmvj18x_config(0x%p)\n", link);
354
355 /*
356 This reads the card's CONFIG tuple to find its configuration
357 registers.
358 */
359 tuple.DesiredTuple = CISTPL_CONFIG;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200360 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 tuple.TupleData = (u_char *)buf;
362 tuple.TupleDataMax = 64;
363 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200364 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
365 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 /* Configure card */
368 link->state |= DEV_CONFIG;
369
370 link->conf.ConfigBase = parse.config.base;
371 link->conf.Present = parse.config.rmask[0];
372
373 tuple.DesiredTuple = CISTPL_FUNCE;
374 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200375 if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
377 tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200378 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
379 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
380 CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 link->conf.ConfigIndex = parse.cftable_entry.index;
382 tuple.DesiredTuple = CISTPL_MANFID;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200383 if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
384 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 else
386 buf[0] = 0xffff;
387 switch (le16_to_cpu(buf[0])) {
388 case MANFID_TDK:
389 cardtype = TDK;
Dominik Brodowski70294b42006-01-15 12:43:16 +0100390 if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
Jun Komurof4d75102005-06-27 16:28:44 -0700391 || le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
392 || le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 /* MultiFunction Card */
394 link->conf.ConfigBase = 0x800;
395 link->conf.ConfigIndex = 0x47;
396 link->io.NumPorts2 = 8;
397 }
398 break;
399 case MANFID_CONTEC:
400 cardtype = CONTEC;
401 break;
402 case MANFID_FUJITSU:
403 if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302)
404 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
405 but these are MBH10304 based card. */
406 cardtype = MBH10304;
407 else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304)
408 cardtype = MBH10304;
409 else
410 cardtype = LA501;
411 break;
412 default:
413 cardtype = MBH10304;
414 }
415 } else {
416 /* old type card */
417 tuple.DesiredTuple = CISTPL_MANFID;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200418 if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
419 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 else
421 buf[0] = 0xffff;
422 switch (le16_to_cpu(buf[0])) {
423 case MANFID_FUJITSU:
424 if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) {
425 cardtype = XXX10304; /* MBH10304 with buggy CIS */
426 link->conf.ConfigIndex = 0x20;
427 } else {
428 cardtype = MBH10302; /* NextCom NC5310, etc. */
429 link->conf.ConfigIndex = 1;
430 }
431 break;
432 case MANFID_UNGERMANN:
433 cardtype = UNGERMANN;
434 break;
435 default:
436 cardtype = MBH10302;
437 link->conf.ConfigIndex = 1;
438 }
439 }
440
441 if (link->io.NumPorts2 != 0) {
442 link->irq.Attributes =
443 IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
444 ret = mfc_try_io_port(link);
445 if (ret != CS_SUCCESS) goto cs_failed;
446 } else if (cardtype == UNGERMANN) {
447 ret = ungermann_try_io_port(link);
448 if (ret != CS_SUCCESS) goto cs_failed;
449 } else {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200450 CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 }
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200452 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
453 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 dev->irq = link->irq.AssignedIRQ;
455 dev->base_addr = link->io.BasePort1;
456
457 if (link->io.BasePort2 != 0)
458 fmvj18x_setup_mfc(link);
459
460 ioaddr = dev->base_addr;
461
462 /* Reset controller */
463 if (sram_config == 0)
464 outb(CONFIG0_RST, ioaddr + CONFIG_0);
465 else
466 outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
467
468 /* Power On chip and select bank 0 */
469 if (cardtype == MBH10302)
470 outb(BANK_0, ioaddr + CONFIG_1);
471 else
472 outb(BANK_0U, ioaddr + CONFIG_1);
473
474 /* Set hardware address */
475 switch (cardtype) {
476 case MBH10304:
477 case TDK:
478 case LA501:
479 case CONTEC:
480 tuple.DesiredTuple = CISTPL_FUNCE;
481 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200482 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 tuple.TupleOffset = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200484 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 if (cardtype == MBH10304) {
486 /* MBH10304's CIS_FUNCE is corrupted */
487 node_id = &(tuple.TupleData[5]);
488 card_name = "FMV-J182";
489 } else {
490 while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200491 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
492 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 }
494 node_id = &(tuple.TupleData[2]);
495 if( cardtype == TDK ) {
496 card_name = "TDK LAK-CD021";
497 } else if( cardtype == LA501 ) {
498 card_name = "LA501";
499 } else {
500 card_name = "C-NET(PC)C";
501 }
502 }
503 /* Read MACID from CIS */
504 for (i = 0; i < 6; i++)
505 dev->dev_addr[i] = node_id[i];
506 break;
507 case UNGERMANN:
508 /* Read MACID from register */
509 for (i = 0; i < 6; i++)
510 dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
511 card_name = "Access/CARD";
512 break;
513 case XXX10304:
514 /* Read MACID from Buggy CIS */
515 if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) {
516 printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
517 goto failed;
518 }
519 for (i = 0 ; i < 6; i++) {
520 dev->dev_addr[i] = tuple.TupleData[i];
521 }
522 card_name = "FMV-J182";
523 break;
524 case MBH10302:
525 default:
526 /* Read MACID from register */
527 for (i = 0; i < 6; i++)
528 dev->dev_addr[i] = inb(ioaddr + MAC_ID + i);
529 card_name = "FMV-J181";
530 break;
531 }
532
533 lp->cardtype = cardtype;
Dominik Brodowskifd238232006-03-05 10:45:09 +0100534 link->dev_node = &lp->node;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 link->state &= ~DEV_CONFIG_PENDING;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200536 SET_NETDEV_DEV(dev, &handle_to_dev(link));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
538 if (register_netdev(dev) != 0) {
539 printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
Dominik Brodowskifd238232006-03-05 10:45:09 +0100540 link->dev_node = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 goto failed;
542 }
543
544 strcpy(lp->node.dev_name, dev->name);
545
546 /* print current configuration */
547 printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ",
548 dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
549 dev->base_addr, dev->irq);
550 for (i = 0; i < 6; i++)
551 printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
552
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200553 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
555cs_failed:
556 /* All Card Services errors end up here */
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200557 cs_error(link, last_fn, last_ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558failed:
559 fmvj18x_release(link);
560 link->state &= ~DEV_CONFIG_PENDING;
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200561 return -ENODEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562} /* fmvj18x_config */
563/*====================================================================*/
564
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200565static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566{
567 win_req_t req;
568 memreq_t mem;
569 u_char __iomem *base;
570 int i, j;
571
572 /* Allocate a small memory window */
573 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
574 req.Base = 0; req.Size = 0;
575 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200576 i = pcmcia_request_window(&link, &req, &link->win);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200578 cs_error(link, RequestWindow, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 return -1;
580 }
581
582 base = ioremap(req.Base, req.Size);
583 mem.Page = 0;
584 mem.CardOffset = 0;
585 pcmcia_map_mem_page(link->win, &mem);
586
587 /*
588 * MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
589 * 22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
590 * 'xx' is garbage.
591 * 'yy' is MAC address.
592 */
593 for (i = 0; i < 0x200; i++) {
594 if (readb(base+i*2) == 0x22) {
595 if (readb(base+(i-1)*2) == 0xff
596 && readb(base+(i+5)*2) == 0x04
597 && readb(base+(i+6)*2) == 0x06
598 && readb(base+(i+13)*2) == 0xff)
599 break;
600 }
601 }
602
603 if (i != 0x200) {
604 for (j = 0 ; j < 6; j++,i++) {
605 node_id[j] = readb(base+(i+7)*2);
606 }
607 }
608
609 iounmap(base);
610 j = pcmcia_release_window(link->win);
611 if (j != CS_SUCCESS)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200612 cs_error(link, ReleaseWindow, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 return (i != 0x200) ? 0 : -1;
614
615} /* fmvj18x_get_hwinfo */
616/*====================================================================*/
617
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200618static int fmvj18x_setup_mfc(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619{
620 win_req_t req;
621 memreq_t mem;
622 u_char __iomem *base;
623 int i, j;
624 struct net_device *dev = link->priv;
625 kio_addr_t ioaddr;
626
627 /* Allocate a small memory window */
628 req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
629 req.Base = 0; req.Size = 0;
630 req.AccessSpeed = 0;
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200631 i = pcmcia_request_window(&link, &req, &link->win);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (i != CS_SUCCESS) {
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200633 cs_error(link, RequestWindow, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 return -1;
635 }
636
637 base = ioremap(req.Base, req.Size);
638 mem.Page = 0;
639 mem.CardOffset = 0;
640 pcmcia_map_mem_page(link->win, &mem);
641
642 ioaddr = dev->base_addr;
643 writeb(0x47, base+0x800); /* Config Option Register of LAN */
644 writeb(0x0, base+0x802); /* Config and Status Register */
645
646 writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */
647 writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */
648
649 writeb(0x45, base+0x820); /* Config Option Register of Modem */
650 writeb(0x8, base+0x822); /* Config and Status Register */
651
652 iounmap(base);
653 j = pcmcia_release_window(link->win);
654 if (j != CS_SUCCESS)
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200655 cs_error(link, ReleaseWindow, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 return 0;
657
658}
659/*====================================================================*/
660
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200661static void fmvj18x_release(struct pcmcia_device *link)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
Dominik Brodowski5f2a71f2006-01-15 09:32:39 +0100663 DEBUG(0, "fmvj18x_release(0x%p)\n", link);
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200664 pcmcia_disable_device(link);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200667static int fmvj18x_suspend(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100668{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100669 struct net_device *dev = link->priv;
670
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100671 if ((link->state & DEV_CONFIG) && (link->open))
672 netif_device_detach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100673
674 return 0;
675}
676
Dominik Brodowskifba395e2006-03-31 17:21:06 +0200677static int fmvj18x_resume(struct pcmcia_device *link)
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100678{
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100679 struct net_device *dev = link->priv;
680
Dominik Brodowski8661bb52006-03-02 00:02:33 +0100681 if ((link->state & DEV_CONFIG) && (link->open)) {
682 fjn_reset(dev);
683 netif_device_attach(dev);
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100684 }
685
686 return 0;
687}
688
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689/*====================================================================*/
690
Dominik Brodowskicda4de82005-06-27 16:28:22 -0700691static struct pcmcia_device_id fmvj18x_ids[] = {
692 PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
693 PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
694 PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
695 PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
696 PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
697 PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
698 PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
699 PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
700 PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0 ", 0x8cef4d3a, 0x075fc7b6),
701 PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0 ", 0x8cef4d3a, 0xbccf43e6),
702 PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
703 PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
704 PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
705 PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
706 PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304 ES", 0x2599f454),
707 PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
708 PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
709 PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
Jun Komurof4d75102005-06-27 16:28:44 -0700710 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
711 PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
Dominik Brodowskicda4de82005-06-27 16:28:22 -0700712 PCMCIA_DEVICE_NULL,
713};
714MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
715
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716static struct pcmcia_driver fmvj18x_cs_driver = {
717 .owner = THIS_MODULE,
718 .drv = {
719 .name = "fmvj18x_cs",
720 },
Dominik Brodowski15b99ac2006-03-31 17:26:06 +0200721 .probe = fmvj18x_probe,
Dominik Brodowskicc3b4862005-11-14 21:23:14 +0100722 .remove = fmvj18x_detach,
Dominik Brodowskicda4de82005-06-27 16:28:22 -0700723 .id_table = fmvj18x_ids,
Dominik Brodowski98e4c282005-11-14 21:21:18 +0100724 .suspend = fmvj18x_suspend,
725 .resume = fmvj18x_resume,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726};
727
728static int __init init_fmvj18x_cs(void)
729{
730 return pcmcia_register_driver(&fmvj18x_cs_driver);
731}
732
733static void __exit exit_fmvj18x_cs(void)
734{
735 pcmcia_unregister_driver(&fmvj18x_cs_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736}
737
738module_init(init_fmvj18x_cs);
739module_exit(exit_fmvj18x_cs);
740
741/*====================================================================*/
742
743static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
744{
745 struct net_device *dev = dev_id;
746 local_info_t *lp = netdev_priv(dev);
747 kio_addr_t ioaddr;
748 unsigned short tx_stat, rx_stat;
749
750 if (lp == NULL) {
751 printk(KERN_NOTICE "fjn_interrupt(): irq %d for "
752 "unknown device.\n", irq);
753 return IRQ_NONE;
754 }
755 ioaddr = dev->base_addr;
756
757 /* avoid multiple interrupts */
758 outw(0x0000, ioaddr + TX_INTR);
759
760 /* wait for a while */
761 udelay(1);
762
763 /* get status */
764 tx_stat = inb(ioaddr + TX_STATUS);
765 rx_stat = inb(ioaddr + RX_STATUS);
766
767 /* clear status */
768 outb(tx_stat, ioaddr + TX_STATUS);
769 outb(rx_stat, ioaddr + RX_STATUS);
770
771 DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
772 DEBUG(4, " tx_status %02x.\n", tx_stat);
773
774 if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
775 /* there is packet(s) in rx buffer */
776 fjn_rx(dev);
777 }
778 if (tx_stat & F_TMT_RDY) {
779 lp->stats.tx_packets += lp->sent ;
780 lp->sent = 0 ;
781 if (lp->tx_queue) {
782 outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
783 lp->sent = lp->tx_queue ;
784 lp->tx_queue = 0;
785 lp->tx_queue_len = 0;
786 dev->trans_start = jiffies;
787 } else {
788 lp->tx_started = 0;
789 }
790 netif_wake_queue(dev);
791 }
792 DEBUG(4, "%s: exiting interrupt,\n", dev->name);
793 DEBUG(4, " tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
794
795 outb(D_TX_INTR, ioaddr + TX_INTR);
796 outb(D_RX_INTR, ioaddr + RX_INTR);
797 return IRQ_HANDLED;
798
799} /* fjn_interrupt */
800
801/*====================================================================*/
802
803static void fjn_tx_timeout(struct net_device *dev)
804{
805 struct local_info_t *lp = netdev_priv(dev);
806 kio_addr_t ioaddr = dev->base_addr;
807
808 printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
809 dev->name, htons(inw(ioaddr + TX_STATUS)),
810 inb(ioaddr + TX_STATUS) & F_TMT_RDY
811 ? "IRQ conflict" : "network cable problem");
812 printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
813 "%04x %04x %04x %04x %04x.\n",
814 dev->name, htons(inw(ioaddr + 0)),
815 htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
816 htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
817 htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
818 htons(inw(ioaddr +14)));
819 lp->stats.tx_errors++;
820 /* ToDo: We should try to restart the adaptor... */
821 local_irq_disable();
822 fjn_reset(dev);
823
824 lp->tx_started = 0;
825 lp->tx_queue = 0;
826 lp->tx_queue_len = 0;
827 lp->sent = 0;
828 lp->open_time = jiffies;
829 local_irq_enable();
830 netif_wake_queue(dev);
831}
832
833static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
834{
835 struct local_info_t *lp = netdev_priv(dev);
836 kio_addr_t ioaddr = dev->base_addr;
837 short length = skb->len;
838
839 if (length < ETH_ZLEN)
840 {
841 skb = skb_padto(skb, ETH_ZLEN);
842 if (skb == NULL)
843 return 0;
844 length = ETH_ZLEN;
845 }
846
847 netif_stop_queue(dev);
848
849 {
850 unsigned char *buf = skb->data;
851
852 if (length > ETH_FRAME_LEN) {
853 printk(KERN_NOTICE "%s: Attempting to send a large packet"
854 " (%d bytes).\n", dev->name, length);
855 return 1;
856 }
857
858 DEBUG(4, "%s: Transmitting a packet of length %lu.\n",
859 dev->name, (unsigned long)skb->len);
860 lp->stats.tx_bytes += skb->len;
861
862 /* Disable both interrupts. */
863 outw(0x0000, ioaddr + TX_INTR);
864
865 /* wait for a while */
866 udelay(1);
867
868 outw(length, ioaddr + DATAPORT);
869 outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
870
871 lp->tx_queue++;
872 lp->tx_queue_len += ((length+3) & ~1);
873
874 if (lp->tx_started == 0) {
875 /* If the Tx is idle, always trigger a transmit. */
876 outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
877 lp->sent = lp->tx_queue ;
878 lp->tx_queue = 0;
879 lp->tx_queue_len = 0;
880 dev->trans_start = jiffies;
881 lp->tx_started = 1;
882 netif_start_queue(dev);
883 } else {
884 if( sram_config == 0 ) {
885 if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
886 /* Yes, there is room for one more packet. */
887 netif_start_queue(dev);
888 } else {
889 if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
890 lp->tx_queue < 127 )
891 /* Yes, there is room for one more packet. */
892 netif_start_queue(dev);
893 }
894 }
895
896 /* Re-enable interrupts */
897 outb(D_TX_INTR, ioaddr + TX_INTR);
898 outb(D_RX_INTR, ioaddr + RX_INTR);
899 }
900 dev_kfree_skb (skb);
901
902 return 0;
903} /* fjn_start_xmit */
904
905/*====================================================================*/
906
907static void fjn_reset(struct net_device *dev)
908{
909 struct local_info_t *lp = netdev_priv(dev);
910 kio_addr_t ioaddr = dev->base_addr;
911 int i;
912
913 DEBUG(4, "fjn_reset(%s) called.\n",dev->name);
914
915 /* Reset controller */
916 if( sram_config == 0 )
917 outb(CONFIG0_RST, ioaddr + CONFIG_0);
918 else
919 outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
920
921 /* Power On chip and select bank 0 */
922 if (lp->cardtype == MBH10302)
923 outb(BANK_0, ioaddr + CONFIG_1);
924 else
925 outb(BANK_0U, ioaddr + CONFIG_1);
926
927 /* Set Tx modes */
928 outb(D_TX_MODE, ioaddr + TX_MODE);
929 /* set Rx modes */
930 outb(ID_MATCHED, ioaddr + RX_MODE);
931
932 /* Set hardware address */
933 for (i = 0; i < 6; i++)
934 outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
935
Komuroab808822005-12-01 02:37:17 -0500936 /* (re)initialize the multicast table */
937 set_rx_mode(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
939 /* Switch to bank 2 (runtime mode) */
940 if (lp->cardtype == MBH10302)
941 outb(BANK_2, ioaddr + CONFIG_1);
942 else
943 outb(BANK_2U, ioaddr + CONFIG_1);
944
945 /* set 16col ctrl bits */
946 if( lp->cardtype == TDK || lp->cardtype == CONTEC)
947 outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
948 else
949 outb(AUTO_MODE, ioaddr + COL_CTRL);
950
951 /* clear Reserved Regs */
952 outb(0x00, ioaddr + BMPR12);
953 outb(0x00, ioaddr + BMPR13);
954
955 /* reset Skip packet reg. */
956 outb(0x01, ioaddr + RX_SKIP);
957
958 /* Enable Tx and Rx */
959 if( sram_config == 0 )
960 outb(CONFIG0_DFL, ioaddr + CONFIG_0);
961 else
962 outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
963
964 /* Init receive pointer ? */
965 inw(ioaddr + DATAPORT);
966 inw(ioaddr + DATAPORT);
967
968 /* Clear all status */
969 outb(0xff, ioaddr + TX_STATUS);
970 outb(0xff, ioaddr + RX_STATUS);
971
972 if (lp->cardtype == MBH10302)
973 outb(INTR_OFF, ioaddr + LAN_CTRL);
974
975 /* Turn on Rx interrupts */
976 outb(D_TX_INTR, ioaddr + TX_INTR);
977 outb(D_RX_INTR, ioaddr + RX_INTR);
978
979 /* Turn on interrupts from LAN card controller */
980 if (lp->cardtype == MBH10302)
981 outb(INTR_ON, ioaddr + LAN_CTRL);
982} /* fjn_reset */
983
984/*====================================================================*/
985
986static void fjn_rx(struct net_device *dev)
987{
988 struct local_info_t *lp = netdev_priv(dev);
989 kio_addr_t ioaddr = dev->base_addr;
990 int boguscount = 10; /* 5 -> 10: by agy 19940922 */
991
992 DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n",
993 dev->name, inb(ioaddr + RX_STATUS));
994
995 while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
996 u_short status = inw(ioaddr + DATAPORT);
997
998 DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n",
999 dev->name, inb(ioaddr + RX_MODE), status);
1000#ifndef final_version
1001 if (status == 0) {
1002 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1003 break;
1004 }
1005#endif
1006 if ((status & 0xF0) != 0x20) { /* There was an error. */
1007 lp->stats.rx_errors++;
1008 if (status & F_LEN_ERR) lp->stats.rx_length_errors++;
1009 if (status & F_ALG_ERR) lp->stats.rx_frame_errors++;
1010 if (status & F_CRC_ERR) lp->stats.rx_crc_errors++;
1011 if (status & F_OVR_FLO) lp->stats.rx_over_errors++;
1012 } else {
1013 u_short pkt_len = inw(ioaddr + DATAPORT);
1014 /* Malloc up new buffer. */
1015 struct sk_buff *skb;
1016
1017 if (pkt_len > 1550) {
1018 printk(KERN_NOTICE "%s: The FMV-18x claimed a very "
1019 "large packet, size %d.\n", dev->name, pkt_len);
1020 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1021 lp->stats.rx_errors++;
1022 break;
1023 }
1024 skb = dev_alloc_skb(pkt_len+2);
1025 if (skb == NULL) {
1026 printk(KERN_NOTICE "%s: Memory squeeze, dropping "
1027 "packet (len %d).\n", dev->name, pkt_len);
1028 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1029 lp->stats.rx_dropped++;
1030 break;
1031 }
1032 skb->dev = dev;
1033
1034 skb_reserve(skb, 2);
1035 insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
1036 (pkt_len + 1) >> 1);
1037 skb->protocol = eth_type_trans(skb, dev);
1038
1039#ifdef PCMCIA_DEBUG
1040 if (pc_debug > 5) {
1041 int i;
1042 printk(KERN_DEBUG "%s: Rxed packet of length %d: ",
1043 dev->name, pkt_len);
1044 for (i = 0; i < 14; i++)
1045 printk(" %02x", skb->data[i]);
1046 printk(".\n");
1047 }
1048#endif
1049
1050 netif_rx(skb);
1051 dev->last_rx = jiffies;
1052 lp->stats.rx_packets++;
1053 lp->stats.rx_bytes += pkt_len;
1054 }
1055 if (--boguscount <= 0)
1056 break;
1057 }
1058
1059 /* If any worth-while packets have been received, dev_rint()
1060 has done a netif_wake_queue() for us and will work on them
1061 when we get to the bottom-half routine. */
1062/*
1063 if (lp->cardtype != TDK) {
1064 int i;
1065 for (i = 0; i < 20; i++) {
1066 if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
1067 break;
1068 (void)inw(ioaddr + DATAPORT); /+ dummy status read +/
1069 outb(F_SKP_PKT, ioaddr + RX_SKIP);
1070 }
1071
1072 if (i > 0)
1073 DEBUG(5, "%s: Exint Rx packet with mode %02x after "
1074 "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
1075 }
1076*/
1077
1078 return;
1079} /* fjn_rx */
1080
1081/*====================================================================*/
1082
1083static void netdev_get_drvinfo(struct net_device *dev,
1084 struct ethtool_drvinfo *info)
1085{
1086 strcpy(info->driver, DRV_NAME);
1087 strcpy(info->version, DRV_VERSION);
1088 sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);
1089}
1090
1091#ifdef PCMCIA_DEBUG
1092static u32 netdev_get_msglevel(struct net_device *dev)
1093{
1094 return pc_debug;
1095}
1096
1097static void netdev_set_msglevel(struct net_device *dev, u32 level)
1098{
1099 pc_debug = level;
1100}
1101#endif /* PCMCIA_DEBUG */
1102
1103static struct ethtool_ops netdev_ethtool_ops = {
1104 .get_drvinfo = netdev_get_drvinfo,
1105#ifdef PCMCIA_DEBUG
1106 .get_msglevel = netdev_get_msglevel,
1107 .set_msglevel = netdev_set_msglevel,
1108#endif /* PCMCIA_DEBUG */
1109};
1110
1111static int fjn_config(struct net_device *dev, struct ifmap *map){
1112 return 0;
1113}
1114
1115static int fjn_open(struct net_device *dev)
1116{
1117 struct local_info_t *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001118 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
1120 DEBUG(4, "fjn_open('%s').\n", dev->name);
1121
1122 if (!DEV_OK(link))
1123 return -ENODEV;
1124
1125 link->open++;
1126
1127 fjn_reset(dev);
1128
1129 lp->tx_started = 0;
1130 lp->tx_queue = 0;
1131 lp->tx_queue_len = 0;
1132 lp->open_time = jiffies;
1133 netif_start_queue(dev);
1134
1135 return 0;
1136} /* fjn_open */
1137
1138/*====================================================================*/
1139
1140static int fjn_close(struct net_device *dev)
1141{
1142 struct local_info_t *lp = netdev_priv(dev);
Dominik Brodowskifba395e2006-03-31 17:21:06 +02001143 struct pcmcia_device *link = lp->p_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 kio_addr_t ioaddr = dev->base_addr;
1145
1146 DEBUG(4, "fjn_close('%s').\n", dev->name);
1147
1148 lp->open_time = 0;
1149 netif_stop_queue(dev);
1150
1151 /* Set configuration register 0 to disable Tx and Rx. */
1152 if( sram_config == 0 )
1153 outb(CONFIG0_RST ,ioaddr + CONFIG_0);
1154 else
1155 outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
1156
1157 /* Update the statistics -- ToDo. */
1158
1159 /* Power-down the chip. Green, green, green! */
1160 outb(CHIP_OFF ,ioaddr + CONFIG_1);
1161
1162 /* Set the ethernet adaptor disable IRQ */
1163 if (lp->cardtype == MBH10302)
1164 outb(INTR_OFF, ioaddr + LAN_CTRL);
1165
1166 link->open--;
1167
1168 return 0;
1169} /* fjn_close */
1170
1171/*====================================================================*/
1172
1173static struct net_device_stats *fjn_get_stats(struct net_device *dev)
1174{
1175 local_info_t *lp = netdev_priv(dev);
1176 return &lp->stats;
1177} /* fjn_get_stats */
1178
1179/*====================================================================*/
1180
1181/*
1182 Set the multicast/promiscuous mode for this adaptor.
1183*/
1184
1185static void set_rx_mode(struct net_device *dev)
1186{
1187 kio_addr_t ioaddr = dev->base_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 u_char mc_filter[8]; /* Multicast hash filter */
1189 u_long flags;
1190 int i;
1191
Komuroab808822005-12-01 02:37:17 -05001192 int saved_bank;
Komurod9a8a0a2005-08-06 12:01:43 +09001193 int saved_config_0 = inb(ioaddr + CONFIG_0);
1194
1195 local_irq_save(flags);
1196
1197 /* Disable Tx and Rx */
1198 if (sram_config == 0)
1199 outb(CONFIG0_RST, ioaddr + CONFIG_0);
1200 else
1201 outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
1202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 if (dev->flags & IFF_PROMISC) {
1204 /* Unconditionally log net taps. */
1205 printk("%s: Promiscuous mode enabled.\n", dev->name);
1206 memset(mc_filter, 0xff, sizeof(mc_filter));
1207 outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
1208 } else if (dev->mc_count > MC_FILTERBREAK
1209 || (dev->flags & IFF_ALLMULTI)) {
1210 /* Too many to filter perfectly -- accept all multicasts. */
1211 memset(mc_filter, 0xff, sizeof(mc_filter));
1212 outb(2, ioaddr + RX_MODE); /* Use normal mode. */
1213 } else if (dev->mc_count == 0) {
1214 memset(mc_filter, 0x00, sizeof(mc_filter));
1215 outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */
1216 } else {
1217 struct dev_mc_list *mclist;
1218 int i;
1219
1220 memset(mc_filter, 0, sizeof(mc_filter));
1221 for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
1222 i++, mclist = mclist->next) {
1223 unsigned int bit =
Komurod9a8a0a2005-08-06 12:01:43 +09001224 ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 26;
1225 mc_filter[bit >> 3] |= (1 << (bit & 7));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 }
Komurod9a8a0a2005-08-06 12:01:43 +09001227 outb(2, ioaddr + RX_MODE); /* Use normal mode. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 }
1229
Komuroab808822005-12-01 02:37:17 -05001230 /* Switch to bank 1 and set the multicast table. */
1231 saved_bank = inb(ioaddr + CONFIG_1);
1232 outb(0xe4, ioaddr + CONFIG_1);
1233
1234 for (i = 0; i < 8; i++)
1235 outb(mc_filter[i], ioaddr + MAR_ADR + i);
1236 outb(saved_bank, ioaddr + CONFIG_1);
Komurod9a8a0a2005-08-06 12:01:43 +09001237
1238 outb(saved_config_0, ioaddr + CONFIG_0);
1239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 local_irq_restore(flags);
1241}