xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/fujitsu/fmvj18x_cs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*======================================================================
2*4882a593Smuzhiyun     fmvj18x_cs.c 2.8 2002/03/23
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun     A fmvj18x (and its compatibles) PCMCIA client driver
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun     Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun     TDK LAK-CD021 and CONTEC C-NET(PC)C support added by
9*4882a593Smuzhiyun     Nobuhiro Katayama, kata-n@po.iijnet.or.jp
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun     The PCMCIA client code is based on code written by David Hinds.
12*4882a593Smuzhiyun     Network code is based on the "FMV-18x driver" by Yutaka TAMIYA
13*4882a593Smuzhiyun     but is actually largely Donald Becker's AT1700 driver, which
14*4882a593Smuzhiyun     carries the following attribution:
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun     Written 1993-94 by Donald Becker.
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun     Copyright 1993 United States Government as represented by the
19*4882a593Smuzhiyun     Director, National Security Agency.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun     This software may be used and distributed according to the terms
22*4882a593Smuzhiyun     of the GNU General Public License, incorporated herein by reference.
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun     The author may be reached as becker@scyld.com, or C/O
25*4882a593Smuzhiyun     Scyld Computing Corporation
26*4882a593Smuzhiyun     410 Severn Ave., Suite 210
27*4882a593Smuzhiyun     Annapolis MD 21403
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun ======================================================================*/
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define DRV_NAME	"fmvj18x_cs"
34*4882a593Smuzhiyun #define DRV_VERSION	"2.9"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #include <linux/module.h>
37*4882a593Smuzhiyun #include <linux/kernel.h>
38*4882a593Smuzhiyun #include <linux/ptrace.h>
39*4882a593Smuzhiyun #include <linux/slab.h>
40*4882a593Smuzhiyun #include <linux/string.h>
41*4882a593Smuzhiyun #include <linux/timer.h>
42*4882a593Smuzhiyun #include <linux/interrupt.h>
43*4882a593Smuzhiyun #include <linux/in.h>
44*4882a593Smuzhiyun #include <linux/delay.h>
45*4882a593Smuzhiyun #include <linux/ethtool.h>
46*4882a593Smuzhiyun #include <linux/netdevice.h>
47*4882a593Smuzhiyun #include <linux/etherdevice.h>
48*4882a593Smuzhiyun #include <linux/skbuff.h>
49*4882a593Smuzhiyun #include <linux/if_arp.h>
50*4882a593Smuzhiyun #include <linux/ioport.h>
51*4882a593Smuzhiyun #include <linux/crc32.h>
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #include <pcmcia/cistpl.h>
54*4882a593Smuzhiyun #include <pcmcia/ciscode.h>
55*4882a593Smuzhiyun #include <pcmcia/ds.h>
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun #include <linux/uaccess.h>
58*4882a593Smuzhiyun #include <asm/io.h>
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /*====================================================================*/
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun /* Module parameters */
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
65*4882a593Smuzhiyun MODULE_LICENSE("GPL");
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /* SRAM configuration */
70*4882a593Smuzhiyun /* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */
71*4882a593Smuzhiyun INT_MODULE_PARM(sram_config, 0);
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /*====================================================================*/
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun     PCMCIA event handlers
77*4882a593Smuzhiyun  */
78*4882a593Smuzhiyun static int fmvj18x_config(struct pcmcia_device *link);
79*4882a593Smuzhiyun static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
80*4882a593Smuzhiyun static int fmvj18x_setup_mfc(struct pcmcia_device *link);
81*4882a593Smuzhiyun static void fmvj18x_release(struct pcmcia_device *link);
82*4882a593Smuzhiyun static void fmvj18x_detach(struct pcmcia_device *p_dev);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun /*
85*4882a593Smuzhiyun     LAN controller(MBH86960A) specific routines
86*4882a593Smuzhiyun  */
87*4882a593Smuzhiyun static int fjn_config(struct net_device *dev, struct ifmap *map);
88*4882a593Smuzhiyun static int fjn_open(struct net_device *dev);
89*4882a593Smuzhiyun static int fjn_close(struct net_device *dev);
90*4882a593Smuzhiyun static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
91*4882a593Smuzhiyun 					struct net_device *dev);
92*4882a593Smuzhiyun static irqreturn_t fjn_interrupt(int irq, void *dev_id);
93*4882a593Smuzhiyun static void fjn_rx(struct net_device *dev);
94*4882a593Smuzhiyun static void fjn_reset(struct net_device *dev);
95*4882a593Smuzhiyun static void set_rx_mode(struct net_device *dev);
96*4882a593Smuzhiyun static void fjn_tx_timeout(struct net_device *dev, unsigned int txqueue);
97*4882a593Smuzhiyun static const struct ethtool_ops netdev_ethtool_ops;
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /*
100*4882a593Smuzhiyun     card type
101*4882a593Smuzhiyun  */
102*4882a593Smuzhiyun enum cardtype { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
103*4882a593Smuzhiyun 	       XXX10304, NEC, KME
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun     driver specific data structure
108*4882a593Smuzhiyun */
109*4882a593Smuzhiyun struct local_info {
110*4882a593Smuzhiyun 	struct pcmcia_device	*p_dev;
111*4882a593Smuzhiyun     long open_time;
112*4882a593Smuzhiyun     uint tx_started:1;
113*4882a593Smuzhiyun     uint tx_queue;
114*4882a593Smuzhiyun     u_short tx_queue_len;
115*4882a593Smuzhiyun     enum cardtype cardtype;
116*4882a593Smuzhiyun     u_short sent;
117*4882a593Smuzhiyun     u_char __iomem *base;
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun #define MC_FILTERBREAK 64
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun /*====================================================================*/
123*4882a593Smuzhiyun /*
124*4882a593Smuzhiyun     ioport offset from the base address
125*4882a593Smuzhiyun  */
126*4882a593Smuzhiyun #define TX_STATUS               0 /* transmit status register */
127*4882a593Smuzhiyun #define RX_STATUS               1 /* receive status register */
128*4882a593Smuzhiyun #define TX_INTR                 2 /* transmit interrupt mask register */
129*4882a593Smuzhiyun #define RX_INTR                 3 /* receive interrupt mask register */
130*4882a593Smuzhiyun #define TX_MODE                 4 /* transmit mode register */
131*4882a593Smuzhiyun #define RX_MODE                 5 /* receive mode register */
132*4882a593Smuzhiyun #define CONFIG_0                6 /* configuration register 0 */
133*4882a593Smuzhiyun #define CONFIG_1                7 /* configuration register 1 */
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun #define NODE_ID                 8 /* node ID register            (bank 0) */
136*4882a593Smuzhiyun #define MAR_ADR                 8 /* multicast address registers (bank 1) */
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun #define DATAPORT                8 /* buffer mem port registers   (bank 2) */
139*4882a593Smuzhiyun #define TX_START               10 /* transmit start register */
140*4882a593Smuzhiyun #define COL_CTRL               11 /* 16 collision control register */
141*4882a593Smuzhiyun #define BMPR12                 12 /* reserved */
142*4882a593Smuzhiyun #define BMPR13                 13 /* reserved */
143*4882a593Smuzhiyun #define RX_SKIP                14 /* skip received packet register */
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun #define LAN_CTRL               16 /* LAN card control register */
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun #define MAC_ID               0x1a /* hardware address */
148*4882a593Smuzhiyun #define UNGERMANN_MAC_ID     0x18 /* UNGERMANN-BASS hardware address */
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun /*
151*4882a593Smuzhiyun     control bits
152*4882a593Smuzhiyun  */
153*4882a593Smuzhiyun #define ENA_TMT_OK           0x80
154*4882a593Smuzhiyun #define ENA_TMT_REC          0x20
155*4882a593Smuzhiyun #define ENA_COL              0x04
156*4882a593Smuzhiyun #define ENA_16_COL           0x02
157*4882a593Smuzhiyun #define ENA_TBUS_ERR         0x01
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun #define ENA_PKT_RDY          0x80
160*4882a593Smuzhiyun #define ENA_BUS_ERR          0x40
161*4882a593Smuzhiyun #define ENA_LEN_ERR          0x08
162*4882a593Smuzhiyun #define ENA_ALG_ERR          0x04
163*4882a593Smuzhiyun #define ENA_CRC_ERR          0x02
164*4882a593Smuzhiyun #define ENA_OVR_FLO          0x01
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun /* flags */
167*4882a593Smuzhiyun #define F_TMT_RDY            0x80 /* can accept new packet */
168*4882a593Smuzhiyun #define F_NET_BSY            0x40 /* carrier is detected */
169*4882a593Smuzhiyun #define F_TMT_OK             0x20 /* send packet successfully */
170*4882a593Smuzhiyun #define F_SRT_PKT            0x10 /* short packet error */
171*4882a593Smuzhiyun #define F_COL_ERR            0x04 /* collision error */
172*4882a593Smuzhiyun #define F_16_COL             0x02 /* 16 collision error */
173*4882a593Smuzhiyun #define F_TBUS_ERR           0x01 /* bus read error */
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun #define F_PKT_RDY            0x80 /* packet(s) in buffer */
176*4882a593Smuzhiyun #define F_BUS_ERR            0x40 /* bus read error */
177*4882a593Smuzhiyun #define F_LEN_ERR            0x08 /* short packet */
178*4882a593Smuzhiyun #define F_ALG_ERR            0x04 /* frame error */
179*4882a593Smuzhiyun #define F_CRC_ERR            0x02 /* CRC error */
180*4882a593Smuzhiyun #define F_OVR_FLO            0x01 /* overflow error */
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun #define F_BUF_EMP            0x40 /* receive buffer is empty */
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun #define F_SKP_PKT            0x05 /* drop packet in buffer */
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun /* default bitmaps */
187*4882a593Smuzhiyun #define D_TX_INTR  ( ENA_TMT_OK )
188*4882a593Smuzhiyun #define D_RX_INTR  ( ENA_PKT_RDY | ENA_LEN_ERR \
189*4882a593Smuzhiyun 		   | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO )
190*4882a593Smuzhiyun #define TX_STAT_M  ( F_TMT_RDY )
191*4882a593Smuzhiyun #define RX_STAT_M  ( F_PKT_RDY | F_LEN_ERR \
192*4882a593Smuzhiyun                    | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO )
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun /* commands */
195*4882a593Smuzhiyun #define D_TX_MODE            0x06 /* no tests, detect carrier */
196*4882a593Smuzhiyun #define ID_MATCHED           0x02 /* (RX_MODE) */
197*4882a593Smuzhiyun #define RECV_ALL             0x03 /* (RX_MODE) */
198*4882a593Smuzhiyun #define CONFIG0_DFL          0x5a /* 16bit bus, 4K x 2 Tx queues */
199*4882a593Smuzhiyun #define CONFIG0_DFL_1        0x5e /* 16bit bus, 8K x 2 Tx queues */
200*4882a593Smuzhiyun #define CONFIG0_RST          0xda /* Data Link Controller off (CONFIG_0) */
201*4882a593Smuzhiyun #define CONFIG0_RST_1        0xde /* Data Link Controller off (CONFIG_0) */
202*4882a593Smuzhiyun #define BANK_0               0xa0 /* bank 0 (CONFIG_1) */
203*4882a593Smuzhiyun #define BANK_1               0xa4 /* bank 1 (CONFIG_1) */
204*4882a593Smuzhiyun #define BANK_2               0xa8 /* bank 2 (CONFIG_1) */
205*4882a593Smuzhiyun #define CHIP_OFF             0x80 /* contrl chip power off (CONFIG_1) */
206*4882a593Smuzhiyun #define DO_TX                0x80 /* do transmit packet */
207*4882a593Smuzhiyun #define SEND_PKT             0x81 /* send a packet */
208*4882a593Smuzhiyun #define AUTO_MODE            0x07 /* Auto skip packet on 16 col detected */
209*4882a593Smuzhiyun #define MANU_MODE            0x03 /* Stop and skip packet on 16 col */
210*4882a593Smuzhiyun #define TDK_AUTO_MODE        0x47 /* Auto skip packet on 16 col detected */
211*4882a593Smuzhiyun #define TDK_MANU_MODE        0x43 /* Stop and skip packet on 16 col */
212*4882a593Smuzhiyun #define INTR_OFF             0x0d /* LAN controller ignores interrupts */
213*4882a593Smuzhiyun #define INTR_ON              0x1d /* LAN controller will catch interrupts */
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun #define TX_TIMEOUT		((400*HZ)/1000)
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun #define BANK_0U              0x20 /* bank 0 (CONFIG_1) */
218*4882a593Smuzhiyun #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
219*4882a593Smuzhiyun #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun static const struct net_device_ops fjn_netdev_ops = {
222*4882a593Smuzhiyun 	.ndo_open 		= fjn_open,
223*4882a593Smuzhiyun 	.ndo_stop		= fjn_close,
224*4882a593Smuzhiyun 	.ndo_start_xmit 	= fjn_start_xmit,
225*4882a593Smuzhiyun 	.ndo_tx_timeout 	= fjn_tx_timeout,
226*4882a593Smuzhiyun 	.ndo_set_config 	= fjn_config,
227*4882a593Smuzhiyun 	.ndo_set_rx_mode	= set_rx_mode,
228*4882a593Smuzhiyun 	.ndo_set_mac_address 	= eth_mac_addr,
229*4882a593Smuzhiyun 	.ndo_validate_addr	= eth_validate_addr,
230*4882a593Smuzhiyun };
231*4882a593Smuzhiyun 
fmvj18x_probe(struct pcmcia_device * link)232*4882a593Smuzhiyun static int fmvj18x_probe(struct pcmcia_device *link)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun     struct local_info *lp;
235*4882a593Smuzhiyun     struct net_device *dev;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun     dev_dbg(&link->dev, "fmvj18x_attach()\n");
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     /* Make up a FMVJ18x specific data structure */
240*4882a593Smuzhiyun     dev = alloc_etherdev(sizeof(struct local_info));
241*4882a593Smuzhiyun     if (!dev)
242*4882a593Smuzhiyun 	return -ENOMEM;
243*4882a593Smuzhiyun     lp = netdev_priv(dev);
244*4882a593Smuzhiyun     link->priv = dev;
245*4882a593Smuzhiyun     lp->p_dev = link;
246*4882a593Smuzhiyun     lp->base = NULL;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun     /* The io structure describes IO port mapping */
249*4882a593Smuzhiyun     link->resource[0]->end = 32;
250*4882a593Smuzhiyun     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun     /* General socket configuration */
253*4882a593Smuzhiyun     link->config_flags |= CONF_ENABLE_IRQ;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun     dev->netdev_ops = &fjn_netdev_ops;
256*4882a593Smuzhiyun     dev->watchdog_timeo = TX_TIMEOUT;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun     dev->ethtool_ops = &netdev_ethtool_ops;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun     return fmvj18x_config(link);
261*4882a593Smuzhiyun } /* fmvj18x_attach */
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun /*====================================================================*/
264*4882a593Smuzhiyun 
fmvj18x_detach(struct pcmcia_device * link)265*4882a593Smuzhiyun static void fmvj18x_detach(struct pcmcia_device *link)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun     struct net_device *dev = link->priv;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun     dev_dbg(&link->dev, "fmvj18x_detach\n");
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun     unregister_netdev(dev);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun     fmvj18x_release(link);
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun     free_netdev(dev);
276*4882a593Smuzhiyun } /* fmvj18x_detach */
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun /*====================================================================*/
279*4882a593Smuzhiyun 
mfc_try_io_port(struct pcmcia_device * link)280*4882a593Smuzhiyun static int mfc_try_io_port(struct pcmcia_device *link)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun     int i, ret;
283*4882a593Smuzhiyun     static const unsigned int serial_base[5] =
284*4882a593Smuzhiyun 	{ 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     for (i = 0; i < 5; i++) {
287*4882a593Smuzhiyun 	link->resource[1]->start = serial_base[i];
288*4882a593Smuzhiyun 	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
289*4882a593Smuzhiyun 	if (link->resource[1]->start == 0) {
290*4882a593Smuzhiyun 	    link->resource[1]->end = 0;
291*4882a593Smuzhiyun 	    pr_notice("out of resource for serial\n");
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 	ret = pcmcia_request_io(link);
294*4882a593Smuzhiyun 	if (ret == 0)
295*4882a593Smuzhiyun 		return ret;
296*4882a593Smuzhiyun     }
297*4882a593Smuzhiyun     return ret;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
ungermann_try_io_port(struct pcmcia_device * link)300*4882a593Smuzhiyun static int ungermann_try_io_port(struct pcmcia_device *link)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun     int ret;
303*4882a593Smuzhiyun     unsigned int ioaddr;
304*4882a593Smuzhiyun     /*
305*4882a593Smuzhiyun 	Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
306*4882a593Smuzhiyun 	0x380,0x3c0 only for ioport.
307*4882a593Smuzhiyun     */
308*4882a593Smuzhiyun     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
309*4882a593Smuzhiyun 	link->resource[0]->start = ioaddr;
310*4882a593Smuzhiyun 	ret = pcmcia_request_io(link);
311*4882a593Smuzhiyun 	if (ret == 0) {
312*4882a593Smuzhiyun 	    /* calculate ConfigIndex value */
313*4882a593Smuzhiyun 	    link->config_index =
314*4882a593Smuzhiyun 		((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
315*4882a593Smuzhiyun 	    return ret;
316*4882a593Smuzhiyun 	}
317*4882a593Smuzhiyun     }
318*4882a593Smuzhiyun     return ret;	/* RequestIO failed */
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun 
fmvj18x_ioprobe(struct pcmcia_device * p_dev,void * priv_data)321*4882a593Smuzhiyun static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun 	return 0; /* strange, but that's what the code did already before... */
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun 
fmvj18x_config(struct pcmcia_device * link)326*4882a593Smuzhiyun static int fmvj18x_config(struct pcmcia_device *link)
327*4882a593Smuzhiyun {
328*4882a593Smuzhiyun     struct net_device *dev = link->priv;
329*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
330*4882a593Smuzhiyun     int i, ret;
331*4882a593Smuzhiyun     unsigned int ioaddr;
332*4882a593Smuzhiyun     enum cardtype cardtype;
333*4882a593Smuzhiyun     char *card_name = "unknown";
334*4882a593Smuzhiyun     u8 *buf;
335*4882a593Smuzhiyun     size_t len;
336*4882a593Smuzhiyun     u_char buggybuf[32];
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun     dev_dbg(&link->dev, "fmvj18x_config\n");
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun     link->io_lines = 5;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
343*4882a593Smuzhiyun     kfree(buf);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun     if (len) {
346*4882a593Smuzhiyun 	/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
347*4882a593Smuzhiyun 	ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL);
348*4882a593Smuzhiyun 	if (ret != 0)
349*4882a593Smuzhiyun 		goto failed;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	switch (link->manf_id) {
352*4882a593Smuzhiyun 	case MANFID_TDK:
353*4882a593Smuzhiyun 	    cardtype = TDK;
354*4882a593Smuzhiyun 	    if (link->card_id == PRODID_TDK_GN3410 ||
355*4882a593Smuzhiyun 		link->card_id == PRODID_TDK_NP9610 ||
356*4882a593Smuzhiyun 		link->card_id == PRODID_TDK_MN3200) {
357*4882a593Smuzhiyun 		/* MultiFunction Card */
358*4882a593Smuzhiyun 		link->config_base = 0x800;
359*4882a593Smuzhiyun 		link->config_index = 0x47;
360*4882a593Smuzhiyun 		link->resource[1]->end = 8;
361*4882a593Smuzhiyun 	    }
362*4882a593Smuzhiyun 	    break;
363*4882a593Smuzhiyun 	case MANFID_NEC:
364*4882a593Smuzhiyun 	    cardtype = NEC; /* MultiFunction Card */
365*4882a593Smuzhiyun 	    link->config_base = 0x800;
366*4882a593Smuzhiyun 	    link->config_index = 0x47;
367*4882a593Smuzhiyun 	    link->resource[1]->end = 8;
368*4882a593Smuzhiyun 	    break;
369*4882a593Smuzhiyun 	case MANFID_KME:
370*4882a593Smuzhiyun 	    cardtype = KME; /* MultiFunction Card */
371*4882a593Smuzhiyun 	    link->config_base = 0x800;
372*4882a593Smuzhiyun 	    link->config_index = 0x47;
373*4882a593Smuzhiyun 	    link->resource[1]->end = 8;
374*4882a593Smuzhiyun 	    break;
375*4882a593Smuzhiyun 	case MANFID_CONTEC:
376*4882a593Smuzhiyun 	    cardtype = CONTEC;
377*4882a593Smuzhiyun 	    break;
378*4882a593Smuzhiyun 	case MANFID_FUJITSU:
379*4882a593Smuzhiyun 	    if (link->config_base == 0x0fe0)
380*4882a593Smuzhiyun 		cardtype = MBH10302;
381*4882a593Smuzhiyun 	    else if (link->card_id == PRODID_FUJITSU_MBH10302)
382*4882a593Smuzhiyun                 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
383*4882a593Smuzhiyun                    but these are MBH10304 based card. */
384*4882a593Smuzhiyun 		cardtype = MBH10304;
385*4882a593Smuzhiyun 	    else if (link->card_id == PRODID_FUJITSU_MBH10304)
386*4882a593Smuzhiyun 		cardtype = MBH10304;
387*4882a593Smuzhiyun 	    else
388*4882a593Smuzhiyun 		cardtype = LA501;
389*4882a593Smuzhiyun 	    break;
390*4882a593Smuzhiyun 	default:
391*4882a593Smuzhiyun 	    cardtype = MBH10304;
392*4882a593Smuzhiyun 	}
393*4882a593Smuzhiyun     } else {
394*4882a593Smuzhiyun 	/* old type card */
395*4882a593Smuzhiyun 	switch (link->manf_id) {
396*4882a593Smuzhiyun 	case MANFID_FUJITSU:
397*4882a593Smuzhiyun 	    if (link->card_id == PRODID_FUJITSU_MBH10304) {
398*4882a593Smuzhiyun 		cardtype = XXX10304;    /* MBH10304 with buggy CIS */
399*4882a593Smuzhiyun 		link->config_index = 0x20;
400*4882a593Smuzhiyun 	    } else {
401*4882a593Smuzhiyun 		cardtype = MBH10302;    /* NextCom NC5310, etc. */
402*4882a593Smuzhiyun 		link->config_index = 1;
403*4882a593Smuzhiyun 	    }
404*4882a593Smuzhiyun 	    break;
405*4882a593Smuzhiyun 	case MANFID_UNGERMANN:
406*4882a593Smuzhiyun 	    cardtype = UNGERMANN;
407*4882a593Smuzhiyun 	    break;
408*4882a593Smuzhiyun 	default:
409*4882a593Smuzhiyun 	    cardtype = MBH10302;
410*4882a593Smuzhiyun 	    link->config_index = 1;
411*4882a593Smuzhiyun 	}
412*4882a593Smuzhiyun     }
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun     if (link->resource[1]->end != 0) {
415*4882a593Smuzhiyun 	ret = mfc_try_io_port(link);
416*4882a593Smuzhiyun 	if (ret != 0) goto failed;
417*4882a593Smuzhiyun     } else if (cardtype == UNGERMANN) {
418*4882a593Smuzhiyun 	ret = ungermann_try_io_port(link);
419*4882a593Smuzhiyun 	if (ret != 0) goto failed;
420*4882a593Smuzhiyun     } else {
421*4882a593Smuzhiyun 	    ret = pcmcia_request_io(link);
422*4882a593Smuzhiyun 	    if (ret)
423*4882a593Smuzhiyun 		    goto failed;
424*4882a593Smuzhiyun     }
425*4882a593Smuzhiyun     ret = pcmcia_request_irq(link, fjn_interrupt);
426*4882a593Smuzhiyun     if (ret)
427*4882a593Smuzhiyun 	    goto failed;
428*4882a593Smuzhiyun     ret = pcmcia_enable_device(link);
429*4882a593Smuzhiyun     if (ret)
430*4882a593Smuzhiyun 	    goto failed;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun     dev->irq = link->irq;
433*4882a593Smuzhiyun     dev->base_addr = link->resource[0]->start;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun     if (resource_size(link->resource[1]) != 0) {
436*4882a593Smuzhiyun 	ret = fmvj18x_setup_mfc(link);
437*4882a593Smuzhiyun 	if (ret != 0) goto failed;
438*4882a593Smuzhiyun     }
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun     ioaddr = dev->base_addr;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun     /* Reset controller */
443*4882a593Smuzhiyun     if (sram_config == 0)
444*4882a593Smuzhiyun 	outb(CONFIG0_RST, ioaddr + CONFIG_0);
445*4882a593Smuzhiyun     else
446*4882a593Smuzhiyun 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun     /* Power On chip and select bank 0 */
449*4882a593Smuzhiyun     if (cardtype == MBH10302)
450*4882a593Smuzhiyun 	outb(BANK_0, ioaddr + CONFIG_1);
451*4882a593Smuzhiyun     else
452*4882a593Smuzhiyun 	outb(BANK_0U, ioaddr + CONFIG_1);
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun     /* Set hardware address */
455*4882a593Smuzhiyun     switch (cardtype) {
456*4882a593Smuzhiyun     case MBH10304:
457*4882a593Smuzhiyun     case TDK:
458*4882a593Smuzhiyun     case LA501:
459*4882a593Smuzhiyun     case CONTEC:
460*4882a593Smuzhiyun     case NEC:
461*4882a593Smuzhiyun     case KME:
462*4882a593Smuzhiyun 	if (cardtype == MBH10304) {
463*4882a593Smuzhiyun 	    card_name = "FMV-J182";
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 	    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
466*4882a593Smuzhiyun 	    if (len < 11) {
467*4882a593Smuzhiyun 		    kfree(buf);
468*4882a593Smuzhiyun 		    goto failed;
469*4882a593Smuzhiyun 	    }
470*4882a593Smuzhiyun 	    /* Read MACID from CIS */
471*4882a593Smuzhiyun 	    for (i = 0; i < 6; i++)
472*4882a593Smuzhiyun 		    dev->dev_addr[i] = buf[i + 5];
473*4882a593Smuzhiyun 	    kfree(buf);
474*4882a593Smuzhiyun 	} else {
475*4882a593Smuzhiyun 	    if (pcmcia_get_mac_from_cis(link, dev))
476*4882a593Smuzhiyun 		goto failed;
477*4882a593Smuzhiyun 	    if( cardtype == TDK ) {
478*4882a593Smuzhiyun 		card_name = "TDK LAK-CD021";
479*4882a593Smuzhiyun 	    } else if( cardtype == LA501 ) {
480*4882a593Smuzhiyun 		card_name = "LA501";
481*4882a593Smuzhiyun 	    } else if( cardtype == NEC ) {
482*4882a593Smuzhiyun 		card_name = "PK-UG-J001";
483*4882a593Smuzhiyun 	    } else if( cardtype == KME ) {
484*4882a593Smuzhiyun 		card_name = "Panasonic";
485*4882a593Smuzhiyun 	    } else {
486*4882a593Smuzhiyun 		card_name = "C-NET(PC)C";
487*4882a593Smuzhiyun 	    }
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 	break;
490*4882a593Smuzhiyun     case UNGERMANN:
491*4882a593Smuzhiyun 	/* Read MACID from register */
492*4882a593Smuzhiyun 	for (i = 0; i < 6; i++)
493*4882a593Smuzhiyun 	    dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
494*4882a593Smuzhiyun 	card_name = "Access/CARD";
495*4882a593Smuzhiyun 	break;
496*4882a593Smuzhiyun     case XXX10304:
497*4882a593Smuzhiyun 	/* Read MACID from Buggy CIS */
498*4882a593Smuzhiyun 	if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
499*4882a593Smuzhiyun 	    pr_notice("unable to read hardware net address\n");
500*4882a593Smuzhiyun 	    goto failed;
501*4882a593Smuzhiyun 	}
502*4882a593Smuzhiyun 	for (i = 0 ; i < 6; i++) {
503*4882a593Smuzhiyun 	    dev->dev_addr[i] = buggybuf[i];
504*4882a593Smuzhiyun 	}
505*4882a593Smuzhiyun 	card_name = "FMV-J182";
506*4882a593Smuzhiyun 	break;
507*4882a593Smuzhiyun     case MBH10302:
508*4882a593Smuzhiyun     default:
509*4882a593Smuzhiyun 	/* Read MACID from register */
510*4882a593Smuzhiyun 	for (i = 0; i < 6; i++)
511*4882a593Smuzhiyun 	    dev->dev_addr[i] = inb(ioaddr + MAC_ID + i);
512*4882a593Smuzhiyun 	card_name = "FMV-J181";
513*4882a593Smuzhiyun 	break;
514*4882a593Smuzhiyun     }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun     lp->cardtype = cardtype;
517*4882a593Smuzhiyun     SET_NETDEV_DEV(dev, &link->dev);
518*4882a593Smuzhiyun 
519*4882a593Smuzhiyun     if (register_netdev(dev) != 0) {
520*4882a593Smuzhiyun 	pr_notice("register_netdev() failed\n");
521*4882a593Smuzhiyun 	goto failed;
522*4882a593Smuzhiyun     }
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun     /* print current configuration */
525*4882a593Smuzhiyun     netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n",
526*4882a593Smuzhiyun 		card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
527*4882a593Smuzhiyun 		dev->base_addr, dev->irq, dev->dev_addr);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun     return 0;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun failed:
532*4882a593Smuzhiyun     fmvj18x_release(link);
533*4882a593Smuzhiyun     return -ENODEV;
534*4882a593Smuzhiyun } /* fmvj18x_config */
535*4882a593Smuzhiyun /*====================================================================*/
536*4882a593Smuzhiyun 
fmvj18x_get_hwinfo(struct pcmcia_device * link,u_char * node_id)537*4882a593Smuzhiyun static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
538*4882a593Smuzhiyun {
539*4882a593Smuzhiyun     u_char __iomem *base;
540*4882a593Smuzhiyun     int i, j;
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun     /* Allocate a small memory window */
543*4882a593Smuzhiyun     link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
544*4882a593Smuzhiyun     link->resource[2]->start = 0; link->resource[2]->end = 0;
545*4882a593Smuzhiyun     i = pcmcia_request_window(link, link->resource[2], 0);
546*4882a593Smuzhiyun     if (i != 0)
547*4882a593Smuzhiyun 	return -1;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun     base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
550*4882a593Smuzhiyun     if (!base) {
551*4882a593Smuzhiyun 	pcmcia_release_window(link, link->resource[2]);
552*4882a593Smuzhiyun 	return -1;
553*4882a593Smuzhiyun     }
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun     pcmcia_map_mem_page(link, link->resource[2], 0);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun     /*
558*4882a593Smuzhiyun      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
559*4882a593Smuzhiyun      *  22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
560*4882a593Smuzhiyun      *  'xx' is garbage.
561*4882a593Smuzhiyun      *  'yy' is MAC address.
562*4882a593Smuzhiyun     */
563*4882a593Smuzhiyun     for (i = 0; i < 0x200; i++) {
564*4882a593Smuzhiyun 	if (readb(base+i*2) == 0x22) {
565*4882a593Smuzhiyun 		if (readb(base+(i-1)*2) == 0xff &&
566*4882a593Smuzhiyun 		    readb(base+(i+5)*2) == 0x04 &&
567*4882a593Smuzhiyun 		    readb(base+(i+6)*2) == 0x06 &&
568*4882a593Smuzhiyun 		    readb(base+(i+13)*2) == 0xff)
569*4882a593Smuzhiyun 			break;
570*4882a593Smuzhiyun 	}
571*4882a593Smuzhiyun     }
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun     if (i != 0x200) {
574*4882a593Smuzhiyun 	for (j = 0 ; j < 6; j++,i++) {
575*4882a593Smuzhiyun 	    node_id[j] = readb(base+(i+7)*2);
576*4882a593Smuzhiyun 	}
577*4882a593Smuzhiyun     }
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun     iounmap(base);
580*4882a593Smuzhiyun     j = pcmcia_release_window(link, link->resource[2]);
581*4882a593Smuzhiyun     return (i != 0x200) ? 0 : -1;
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun } /* fmvj18x_get_hwinfo */
584*4882a593Smuzhiyun /*====================================================================*/
585*4882a593Smuzhiyun 
fmvj18x_setup_mfc(struct pcmcia_device * link)586*4882a593Smuzhiyun static int fmvj18x_setup_mfc(struct pcmcia_device *link)
587*4882a593Smuzhiyun {
588*4882a593Smuzhiyun     int i;
589*4882a593Smuzhiyun     struct net_device *dev = link->priv;
590*4882a593Smuzhiyun     unsigned int ioaddr;
591*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun     /* Allocate a small memory window */
594*4882a593Smuzhiyun     link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
595*4882a593Smuzhiyun     link->resource[3]->start = link->resource[3]->end = 0;
596*4882a593Smuzhiyun     i = pcmcia_request_window(link, link->resource[3], 0);
597*4882a593Smuzhiyun     if (i != 0)
598*4882a593Smuzhiyun 	return -1;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun     lp->base = ioremap(link->resource[3]->start,
601*4882a593Smuzhiyun 		       resource_size(link->resource[3]));
602*4882a593Smuzhiyun     if (lp->base == NULL) {
603*4882a593Smuzhiyun 	netdev_notice(dev, "ioremap failed\n");
604*4882a593Smuzhiyun 	return -1;
605*4882a593Smuzhiyun     }
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun     i = pcmcia_map_mem_page(link, link->resource[3], 0);
608*4882a593Smuzhiyun     if (i != 0) {
609*4882a593Smuzhiyun 	iounmap(lp->base);
610*4882a593Smuzhiyun 	lp->base = NULL;
611*4882a593Smuzhiyun 	return -1;
612*4882a593Smuzhiyun     }
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun     ioaddr = dev->base_addr;
615*4882a593Smuzhiyun     writeb(0x47, lp->base+0x800);	/* Config Option Register of LAN */
616*4882a593Smuzhiyun     writeb(0x0,  lp->base+0x802);	/* Config and Status Register */
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun     writeb(ioaddr & 0xff, lp->base+0x80a);	  /* I/O Base(Low) of LAN */
619*4882a593Smuzhiyun     writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun     writeb(0x45, lp->base+0x820);	/* Config Option Register of Modem */
622*4882a593Smuzhiyun     writeb(0x8,  lp->base+0x822);	/* Config and Status Register */
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun     return 0;
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun }
627*4882a593Smuzhiyun /*====================================================================*/
628*4882a593Smuzhiyun 
fmvj18x_release(struct pcmcia_device * link)629*4882a593Smuzhiyun static void fmvj18x_release(struct pcmcia_device *link)
630*4882a593Smuzhiyun {
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun     struct net_device *dev = link->priv;
633*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
634*4882a593Smuzhiyun     u_char __iomem *tmp;
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun     dev_dbg(&link->dev, "fmvj18x_release\n");
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun     if (lp->base != NULL) {
639*4882a593Smuzhiyun 	tmp = lp->base;
640*4882a593Smuzhiyun 	lp->base = NULL;    /* set NULL before iounmap */
641*4882a593Smuzhiyun 	iounmap(tmp);
642*4882a593Smuzhiyun     }
643*4882a593Smuzhiyun 
644*4882a593Smuzhiyun     pcmcia_disable_device(link);
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun 
fmvj18x_suspend(struct pcmcia_device * link)648*4882a593Smuzhiyun static int fmvj18x_suspend(struct pcmcia_device *link)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun 	struct net_device *dev = link->priv;
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	if (link->open)
653*4882a593Smuzhiyun 		netif_device_detach(dev);
654*4882a593Smuzhiyun 
655*4882a593Smuzhiyun 	return 0;
656*4882a593Smuzhiyun }
657*4882a593Smuzhiyun 
fmvj18x_resume(struct pcmcia_device * link)658*4882a593Smuzhiyun static int fmvj18x_resume(struct pcmcia_device *link)
659*4882a593Smuzhiyun {
660*4882a593Smuzhiyun 	struct net_device *dev = link->priv;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	if (link->open) {
663*4882a593Smuzhiyun 		fjn_reset(dev);
664*4882a593Smuzhiyun 		netif_device_attach(dev);
665*4882a593Smuzhiyun 	}
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	return 0;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun /*====================================================================*/
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun static const struct pcmcia_device_id fmvj18x_ids[] = {
673*4882a593Smuzhiyun 	PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
674*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
675*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
676*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
677*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
678*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
679*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
680*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
681*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0       ", 0x8cef4d3a, 0x075fc7b6),
682*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0        ", 0x8cef4d3a, 0xbccf43e6),
683*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
684*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
685*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
686*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
687*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304  ES", 0x2599f454),
688*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
689*4882a593Smuzhiyun 	PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
690*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
691*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
692*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
693*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
694*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01),
695*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
696*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0b05),
697*4882a593Smuzhiyun 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
698*4882a593Smuzhiyun 	PCMCIA_DEVICE_NULL,
699*4882a593Smuzhiyun };
700*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun static struct pcmcia_driver fmvj18x_cs_driver = {
703*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
704*4882a593Smuzhiyun 	.name		= "fmvj18x_cs",
705*4882a593Smuzhiyun 	.probe		= fmvj18x_probe,
706*4882a593Smuzhiyun 	.remove		= fmvj18x_detach,
707*4882a593Smuzhiyun 	.id_table       = fmvj18x_ids,
708*4882a593Smuzhiyun 	.suspend	= fmvj18x_suspend,
709*4882a593Smuzhiyun 	.resume		= fmvj18x_resume,
710*4882a593Smuzhiyun };
711*4882a593Smuzhiyun module_pcmcia_driver(fmvj18x_cs_driver);
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun /*====================================================================*/
714*4882a593Smuzhiyun 
fjn_interrupt(int dummy,void * dev_id)715*4882a593Smuzhiyun static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun     struct net_device *dev = dev_id;
718*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
719*4882a593Smuzhiyun     unsigned int ioaddr;
720*4882a593Smuzhiyun     unsigned short tx_stat, rx_stat;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun     ioaddr = dev->base_addr;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun     /* avoid multiple interrupts */
725*4882a593Smuzhiyun     outw(0x0000, ioaddr + TX_INTR);
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun     /* wait for a while */
728*4882a593Smuzhiyun     udelay(1);
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun     /* get status */
731*4882a593Smuzhiyun     tx_stat = inb(ioaddr + TX_STATUS);
732*4882a593Smuzhiyun     rx_stat = inb(ioaddr + RX_STATUS);
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun     /* clear status */
735*4882a593Smuzhiyun     outb(tx_stat, ioaddr + TX_STATUS);
736*4882a593Smuzhiyun     outb(rx_stat, ioaddr + RX_STATUS);
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun     pr_debug("%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
739*4882a593Smuzhiyun     pr_debug("               tx_status %02x.\n", tx_stat);
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun     if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
742*4882a593Smuzhiyun 	/* there is packet(s) in rx buffer */
743*4882a593Smuzhiyun 	fjn_rx(dev);
744*4882a593Smuzhiyun     }
745*4882a593Smuzhiyun     if (tx_stat & F_TMT_RDY) {
746*4882a593Smuzhiyun 	dev->stats.tx_packets += lp->sent ;
747*4882a593Smuzhiyun         lp->sent = 0 ;
748*4882a593Smuzhiyun 	if (lp->tx_queue) {
749*4882a593Smuzhiyun 	    outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
750*4882a593Smuzhiyun 	    lp->sent = lp->tx_queue ;
751*4882a593Smuzhiyun 	    lp->tx_queue = 0;
752*4882a593Smuzhiyun 	    lp->tx_queue_len = 0;
753*4882a593Smuzhiyun 	    netif_trans_update(dev);
754*4882a593Smuzhiyun 	} else {
755*4882a593Smuzhiyun 	    lp->tx_started = 0;
756*4882a593Smuzhiyun 	}
757*4882a593Smuzhiyun 	netif_wake_queue(dev);
758*4882a593Smuzhiyun     }
759*4882a593Smuzhiyun     pr_debug("%s: exiting interrupt,\n", dev->name);
760*4882a593Smuzhiyun     pr_debug("    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun     outb(D_TX_INTR, ioaddr + TX_INTR);
763*4882a593Smuzhiyun     outb(D_RX_INTR, ioaddr + RX_INTR);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun     if (lp->base != NULL) {
766*4882a593Smuzhiyun 	/* Ack interrupt for multifunction card */
767*4882a593Smuzhiyun 	writeb(0x01, lp->base+0x802);
768*4882a593Smuzhiyun 	writeb(0x09, lp->base+0x822);
769*4882a593Smuzhiyun     }
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun     return IRQ_HANDLED;
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun } /* fjn_interrupt */
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun /*====================================================================*/
776*4882a593Smuzhiyun 
fjn_tx_timeout(struct net_device * dev,unsigned int txqueue)777*4882a593Smuzhiyun static void fjn_tx_timeout(struct net_device *dev, unsigned int txqueue)
778*4882a593Smuzhiyun {
779*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
780*4882a593Smuzhiyun     unsigned int ioaddr = dev->base_addr;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun     netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
783*4882a593Smuzhiyun 		  htons(inw(ioaddr + TX_STATUS)),
784*4882a593Smuzhiyun 		  inb(ioaddr + TX_STATUS) & F_TMT_RDY
785*4882a593Smuzhiyun 		  ? "IRQ conflict" : "network cable problem");
786*4882a593Smuzhiyun     netdev_notice(dev, "timeout registers: %04x %04x %04x "
787*4882a593Smuzhiyun 		  "%04x %04x %04x %04x %04x.\n",
788*4882a593Smuzhiyun 		  htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)),
789*4882a593Smuzhiyun 		  htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)),
790*4882a593Smuzhiyun 		  htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)),
791*4882a593Smuzhiyun 		  htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14)));
792*4882a593Smuzhiyun     dev->stats.tx_errors++;
793*4882a593Smuzhiyun     /* ToDo: We should try to restart the adaptor... */
794*4882a593Smuzhiyun     local_irq_disable();
795*4882a593Smuzhiyun     fjn_reset(dev);
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun     lp->tx_started = 0;
798*4882a593Smuzhiyun     lp->tx_queue = 0;
799*4882a593Smuzhiyun     lp->tx_queue_len = 0;
800*4882a593Smuzhiyun     lp->sent = 0;
801*4882a593Smuzhiyun     lp->open_time = jiffies;
802*4882a593Smuzhiyun     local_irq_enable();
803*4882a593Smuzhiyun     netif_wake_queue(dev);
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun 
fjn_start_xmit(struct sk_buff * skb,struct net_device * dev)806*4882a593Smuzhiyun static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
807*4882a593Smuzhiyun 					struct net_device *dev)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
810*4882a593Smuzhiyun     unsigned int ioaddr = dev->base_addr;
811*4882a593Smuzhiyun     short length = skb->len;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun     if (length < ETH_ZLEN)
814*4882a593Smuzhiyun     {
815*4882a593Smuzhiyun     	if (skb_padto(skb, ETH_ZLEN))
816*4882a593Smuzhiyun     		return NETDEV_TX_OK;
817*4882a593Smuzhiyun     	length = ETH_ZLEN;
818*4882a593Smuzhiyun     }
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun     netif_stop_queue(dev);
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun     {
823*4882a593Smuzhiyun 	unsigned char *buf = skb->data;
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	if (length > ETH_FRAME_LEN) {
826*4882a593Smuzhiyun 	    netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n",
827*4882a593Smuzhiyun 			  length);
828*4882a593Smuzhiyun 	    return NETDEV_TX_BUSY;
829*4882a593Smuzhiyun 	}
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	netdev_dbg(dev, "Transmitting a packet of length %lu\n",
832*4882a593Smuzhiyun 		   (unsigned long)skb->len);
833*4882a593Smuzhiyun 	dev->stats.tx_bytes += skb->len;
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 	/* Disable both interrupts. */
836*4882a593Smuzhiyun 	outw(0x0000, ioaddr + TX_INTR);
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 	/* wait for a while */
839*4882a593Smuzhiyun 	udelay(1);
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun 	outw(length, ioaddr + DATAPORT);
842*4882a593Smuzhiyun 	outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
843*4882a593Smuzhiyun 
844*4882a593Smuzhiyun 	lp->tx_queue++;
845*4882a593Smuzhiyun 	lp->tx_queue_len += ((length+3) & ~1);
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	if (lp->tx_started == 0) {
848*4882a593Smuzhiyun 	    /* If the Tx is idle, always trigger a transmit. */
849*4882a593Smuzhiyun 	    outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
850*4882a593Smuzhiyun 	    lp->sent = lp->tx_queue ;
851*4882a593Smuzhiyun 	    lp->tx_queue = 0;
852*4882a593Smuzhiyun 	    lp->tx_queue_len = 0;
853*4882a593Smuzhiyun 	    lp->tx_started = 1;
854*4882a593Smuzhiyun 	    netif_start_queue(dev);
855*4882a593Smuzhiyun 	} else {
856*4882a593Smuzhiyun 	    if( sram_config == 0 ) {
857*4882a593Smuzhiyun 		if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
858*4882a593Smuzhiyun 		    /* Yes, there is room for one more packet. */
859*4882a593Smuzhiyun 		    netif_start_queue(dev);
860*4882a593Smuzhiyun 	    } else {
861*4882a593Smuzhiyun 		if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
862*4882a593Smuzhiyun 						lp->tx_queue < 127 )
863*4882a593Smuzhiyun 		    /* Yes, there is room for one more packet. */
864*4882a593Smuzhiyun 		    netif_start_queue(dev);
865*4882a593Smuzhiyun 	    }
866*4882a593Smuzhiyun 	}
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	/* Re-enable interrupts */
869*4882a593Smuzhiyun 	outb(D_TX_INTR, ioaddr + TX_INTR);
870*4882a593Smuzhiyun 	outb(D_RX_INTR, ioaddr + RX_INTR);
871*4882a593Smuzhiyun     }
872*4882a593Smuzhiyun     dev_kfree_skb (skb);
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun     return NETDEV_TX_OK;
875*4882a593Smuzhiyun } /* fjn_start_xmit */
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun /*====================================================================*/
878*4882a593Smuzhiyun 
fjn_reset(struct net_device * dev)879*4882a593Smuzhiyun static void fjn_reset(struct net_device *dev)
880*4882a593Smuzhiyun {
881*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
882*4882a593Smuzhiyun     unsigned int ioaddr = dev->base_addr;
883*4882a593Smuzhiyun     int i;
884*4882a593Smuzhiyun 
885*4882a593Smuzhiyun     netdev_dbg(dev, "fjn_reset() called\n");
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun     /* Reset controller */
888*4882a593Smuzhiyun     if( sram_config == 0 )
889*4882a593Smuzhiyun 	outb(CONFIG0_RST, ioaddr + CONFIG_0);
890*4882a593Smuzhiyun     else
891*4882a593Smuzhiyun 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
892*4882a593Smuzhiyun 
893*4882a593Smuzhiyun     /* Power On chip and select bank 0 */
894*4882a593Smuzhiyun     if (lp->cardtype == MBH10302)
895*4882a593Smuzhiyun 	outb(BANK_0, ioaddr + CONFIG_1);
896*4882a593Smuzhiyun     else
897*4882a593Smuzhiyun 	outb(BANK_0U, ioaddr + CONFIG_1);
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun     /* Set Tx modes */
900*4882a593Smuzhiyun     outb(D_TX_MODE, ioaddr + TX_MODE);
901*4882a593Smuzhiyun     /* set Rx modes */
902*4882a593Smuzhiyun     outb(ID_MATCHED, ioaddr + RX_MODE);
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun     /* Set hardware address */
905*4882a593Smuzhiyun     for (i = 0; i < 6; i++)
906*4882a593Smuzhiyun         outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun     /* (re)initialize the multicast table */
909*4882a593Smuzhiyun     set_rx_mode(dev);
910*4882a593Smuzhiyun 
911*4882a593Smuzhiyun     /* Switch to bank 2 (runtime mode) */
912*4882a593Smuzhiyun     if (lp->cardtype == MBH10302)
913*4882a593Smuzhiyun 	outb(BANK_2, ioaddr + CONFIG_1);
914*4882a593Smuzhiyun     else
915*4882a593Smuzhiyun 	outb(BANK_2U, ioaddr + CONFIG_1);
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun     /* set 16col ctrl bits */
918*4882a593Smuzhiyun     if( lp->cardtype == TDK || lp->cardtype == CONTEC)
919*4882a593Smuzhiyun         outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
920*4882a593Smuzhiyun     else
921*4882a593Smuzhiyun         outb(AUTO_MODE, ioaddr + COL_CTRL);
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun     /* clear Reserved Regs */
924*4882a593Smuzhiyun     outb(0x00, ioaddr + BMPR12);
925*4882a593Smuzhiyun     outb(0x00, ioaddr + BMPR13);
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun     /* reset Skip packet reg. */
928*4882a593Smuzhiyun     outb(0x01, ioaddr + RX_SKIP);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun     /* Enable Tx and Rx */
931*4882a593Smuzhiyun     if( sram_config == 0 )
932*4882a593Smuzhiyun 	outb(CONFIG0_DFL, ioaddr + CONFIG_0);
933*4882a593Smuzhiyun     else
934*4882a593Smuzhiyun 	outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
935*4882a593Smuzhiyun 
936*4882a593Smuzhiyun     /* Init receive pointer ? */
937*4882a593Smuzhiyun     inw(ioaddr + DATAPORT);
938*4882a593Smuzhiyun     inw(ioaddr + DATAPORT);
939*4882a593Smuzhiyun 
940*4882a593Smuzhiyun     /* Clear all status */
941*4882a593Smuzhiyun     outb(0xff, ioaddr + TX_STATUS);
942*4882a593Smuzhiyun     outb(0xff, ioaddr + RX_STATUS);
943*4882a593Smuzhiyun 
944*4882a593Smuzhiyun     if (lp->cardtype == MBH10302)
945*4882a593Smuzhiyun 	outb(INTR_OFF, ioaddr + LAN_CTRL);
946*4882a593Smuzhiyun 
947*4882a593Smuzhiyun     /* Turn on Rx interrupts */
948*4882a593Smuzhiyun     outb(D_TX_INTR, ioaddr + TX_INTR);
949*4882a593Smuzhiyun     outb(D_RX_INTR, ioaddr + RX_INTR);
950*4882a593Smuzhiyun 
951*4882a593Smuzhiyun     /* Turn on interrupts from LAN card controller */
952*4882a593Smuzhiyun     if (lp->cardtype == MBH10302)
953*4882a593Smuzhiyun 	outb(INTR_ON, ioaddr + LAN_CTRL);
954*4882a593Smuzhiyun } /* fjn_reset */
955*4882a593Smuzhiyun 
956*4882a593Smuzhiyun /*====================================================================*/
957*4882a593Smuzhiyun 
fjn_rx(struct net_device * dev)958*4882a593Smuzhiyun static void fjn_rx(struct net_device *dev)
959*4882a593Smuzhiyun {
960*4882a593Smuzhiyun     unsigned int ioaddr = dev->base_addr;
961*4882a593Smuzhiyun     int boguscount = 10;	/* 5 -> 10: by agy 19940922 */
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun     pr_debug("%s: in rx_packet(), rx_status %02x.\n",
964*4882a593Smuzhiyun 	  dev->name, inb(ioaddr + RX_STATUS));
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun     while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
967*4882a593Smuzhiyun 	u_short status = inw(ioaddr + DATAPORT);
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n",
970*4882a593Smuzhiyun 		   inb(ioaddr + RX_MODE), status);
971*4882a593Smuzhiyun #ifndef final_version
972*4882a593Smuzhiyun 	if (status == 0) {
973*4882a593Smuzhiyun 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
974*4882a593Smuzhiyun 	    break;
975*4882a593Smuzhiyun 	}
976*4882a593Smuzhiyun #endif
977*4882a593Smuzhiyun 	if ((status & 0xF0) != 0x20) {	/* There was an error. */
978*4882a593Smuzhiyun 	    dev->stats.rx_errors++;
979*4882a593Smuzhiyun 	    if (status & F_LEN_ERR) dev->stats.rx_length_errors++;
980*4882a593Smuzhiyun 	    if (status & F_ALG_ERR) dev->stats.rx_frame_errors++;
981*4882a593Smuzhiyun 	    if (status & F_CRC_ERR) dev->stats.rx_crc_errors++;
982*4882a593Smuzhiyun 	    if (status & F_OVR_FLO) dev->stats.rx_over_errors++;
983*4882a593Smuzhiyun 	} else {
984*4882a593Smuzhiyun 	    u_short pkt_len = inw(ioaddr + DATAPORT);
985*4882a593Smuzhiyun 	    /* Malloc up new buffer. */
986*4882a593Smuzhiyun 	    struct sk_buff *skb;
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun 	    if (pkt_len > 1550) {
989*4882a593Smuzhiyun 		netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n",
990*4882a593Smuzhiyun 			      pkt_len);
991*4882a593Smuzhiyun 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
992*4882a593Smuzhiyun 		dev->stats.rx_errors++;
993*4882a593Smuzhiyun 		break;
994*4882a593Smuzhiyun 	    }
995*4882a593Smuzhiyun 	    skb = netdev_alloc_skb(dev, pkt_len + 2);
996*4882a593Smuzhiyun 	    if (skb == NULL) {
997*4882a593Smuzhiyun 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
998*4882a593Smuzhiyun 		dev->stats.rx_dropped++;
999*4882a593Smuzhiyun 		break;
1000*4882a593Smuzhiyun 	    }
1001*4882a593Smuzhiyun 
1002*4882a593Smuzhiyun 	    skb_reserve(skb, 2);
1003*4882a593Smuzhiyun 	    insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
1004*4882a593Smuzhiyun 		 (pkt_len + 1) >> 1);
1005*4882a593Smuzhiyun 	    skb->protocol = eth_type_trans(skb, dev);
1006*4882a593Smuzhiyun 
1007*4882a593Smuzhiyun 	    {
1008*4882a593Smuzhiyun 		int i;
1009*4882a593Smuzhiyun 		pr_debug("%s: Rxed packet of length %d: ",
1010*4882a593Smuzhiyun 			dev->name, pkt_len);
1011*4882a593Smuzhiyun 		for (i = 0; i < 14; i++)
1012*4882a593Smuzhiyun 			pr_debug(" %02x", skb->data[i]);
1013*4882a593Smuzhiyun 		pr_debug(".\n");
1014*4882a593Smuzhiyun 	    }
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun 	    netif_rx(skb);
1017*4882a593Smuzhiyun 	    dev->stats.rx_packets++;
1018*4882a593Smuzhiyun 	    dev->stats.rx_bytes += pkt_len;
1019*4882a593Smuzhiyun 	}
1020*4882a593Smuzhiyun 	if (--boguscount <= 0)
1021*4882a593Smuzhiyun 	    break;
1022*4882a593Smuzhiyun     }
1023*4882a593Smuzhiyun 
1024*4882a593Smuzhiyun     /* If any worth-while packets have been received, dev_rint()
1025*4882a593Smuzhiyun 	   has done a netif_wake_queue() for us and will work on them
1026*4882a593Smuzhiyun 	   when we get to the bottom-half routine. */
1027*4882a593Smuzhiyun /*
1028*4882a593Smuzhiyun     if (lp->cardtype != TDK) {
1029*4882a593Smuzhiyun 	int i;
1030*4882a593Smuzhiyun 	for (i = 0; i < 20; i++) {
1031*4882a593Smuzhiyun 	    if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
1032*4882a593Smuzhiyun 		break;
1033*4882a593Smuzhiyun 	    (void)inw(ioaddr + DATAPORT);  /+ dummy status read +/
1034*4882a593Smuzhiyun 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
1035*4882a593Smuzhiyun 	}
1036*4882a593Smuzhiyun 
1037*4882a593Smuzhiyun 	if (i > 0)
1038*4882a593Smuzhiyun 	    pr_debug("%s: Exint Rx packet with mode %02x after "
1039*4882a593Smuzhiyun 		  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
1040*4882a593Smuzhiyun     }
1041*4882a593Smuzhiyun */
1042*4882a593Smuzhiyun } /* fjn_rx */
1043*4882a593Smuzhiyun 
1044*4882a593Smuzhiyun /*====================================================================*/
1045*4882a593Smuzhiyun 
netdev_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)1046*4882a593Smuzhiyun static void netdev_get_drvinfo(struct net_device *dev,
1047*4882a593Smuzhiyun 			       struct ethtool_drvinfo *info)
1048*4882a593Smuzhiyun {
1049*4882a593Smuzhiyun 	strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
1050*4882a593Smuzhiyun 	strlcpy(info->version, DRV_VERSION, sizeof(info->version));
1051*4882a593Smuzhiyun 	snprintf(info->bus_info, sizeof(info->bus_info),
1052*4882a593Smuzhiyun 		"PCMCIA 0x%lx", dev->base_addr);
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun static const struct ethtool_ops netdev_ethtool_ops = {
1056*4882a593Smuzhiyun 	.get_drvinfo		= netdev_get_drvinfo,
1057*4882a593Smuzhiyun };
1058*4882a593Smuzhiyun 
fjn_config(struct net_device * dev,struct ifmap * map)1059*4882a593Smuzhiyun static int fjn_config(struct net_device *dev, struct ifmap *map){
1060*4882a593Smuzhiyun     return 0;
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun 
fjn_open(struct net_device * dev)1063*4882a593Smuzhiyun static int fjn_open(struct net_device *dev)
1064*4882a593Smuzhiyun {
1065*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
1066*4882a593Smuzhiyun     struct pcmcia_device *link = lp->p_dev;
1067*4882a593Smuzhiyun 
1068*4882a593Smuzhiyun     pr_debug("fjn_open('%s').\n", dev->name);
1069*4882a593Smuzhiyun 
1070*4882a593Smuzhiyun     if (!pcmcia_dev_present(link))
1071*4882a593Smuzhiyun 	return -ENODEV;
1072*4882a593Smuzhiyun 
1073*4882a593Smuzhiyun     link->open++;
1074*4882a593Smuzhiyun 
1075*4882a593Smuzhiyun     fjn_reset(dev);
1076*4882a593Smuzhiyun 
1077*4882a593Smuzhiyun     lp->tx_started = 0;
1078*4882a593Smuzhiyun     lp->tx_queue = 0;
1079*4882a593Smuzhiyun     lp->tx_queue_len = 0;
1080*4882a593Smuzhiyun     lp->open_time = jiffies;
1081*4882a593Smuzhiyun     netif_start_queue(dev);
1082*4882a593Smuzhiyun 
1083*4882a593Smuzhiyun     return 0;
1084*4882a593Smuzhiyun } /* fjn_open */
1085*4882a593Smuzhiyun 
1086*4882a593Smuzhiyun /*====================================================================*/
1087*4882a593Smuzhiyun 
fjn_close(struct net_device * dev)1088*4882a593Smuzhiyun static int fjn_close(struct net_device *dev)
1089*4882a593Smuzhiyun {
1090*4882a593Smuzhiyun     struct local_info *lp = netdev_priv(dev);
1091*4882a593Smuzhiyun     struct pcmcia_device *link = lp->p_dev;
1092*4882a593Smuzhiyun     unsigned int ioaddr = dev->base_addr;
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun     pr_debug("fjn_close('%s').\n", dev->name);
1095*4882a593Smuzhiyun 
1096*4882a593Smuzhiyun     lp->open_time = 0;
1097*4882a593Smuzhiyun     netif_stop_queue(dev);
1098*4882a593Smuzhiyun 
1099*4882a593Smuzhiyun     /* Set configuration register 0 to disable Tx and Rx. */
1100*4882a593Smuzhiyun     if( sram_config == 0 )
1101*4882a593Smuzhiyun 	outb(CONFIG0_RST ,ioaddr + CONFIG_0);
1102*4882a593Smuzhiyun     else
1103*4882a593Smuzhiyun 	outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
1104*4882a593Smuzhiyun 
1105*4882a593Smuzhiyun     /* Update the statistics -- ToDo. */
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun     /* Power-down the chip.  Green, green, green! */
1108*4882a593Smuzhiyun     outb(CHIP_OFF ,ioaddr + CONFIG_1);
1109*4882a593Smuzhiyun 
1110*4882a593Smuzhiyun     /* Set the ethernet adaptor disable IRQ */
1111*4882a593Smuzhiyun     if (lp->cardtype == MBH10302)
1112*4882a593Smuzhiyun 	outb(INTR_OFF, ioaddr + LAN_CTRL);
1113*4882a593Smuzhiyun 
1114*4882a593Smuzhiyun     link->open--;
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun     return 0;
1117*4882a593Smuzhiyun } /* fjn_close */
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun /*====================================================================*/
1120*4882a593Smuzhiyun 
1121*4882a593Smuzhiyun /*
1122*4882a593Smuzhiyun   Set the multicast/promiscuous mode for this adaptor.
1123*4882a593Smuzhiyun */
1124*4882a593Smuzhiyun 
set_rx_mode(struct net_device * dev)1125*4882a593Smuzhiyun static void set_rx_mode(struct net_device *dev)
1126*4882a593Smuzhiyun {
1127*4882a593Smuzhiyun     unsigned int ioaddr = dev->base_addr;
1128*4882a593Smuzhiyun     u_char mc_filter[8];		 /* Multicast hash filter */
1129*4882a593Smuzhiyun     u_long flags;
1130*4882a593Smuzhiyun     int i;
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun     int saved_bank;
1133*4882a593Smuzhiyun     int saved_config_0 = inb(ioaddr + CONFIG_0);
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun     local_irq_save(flags);
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun     /* Disable Tx and Rx */
1138*4882a593Smuzhiyun     if (sram_config == 0)
1139*4882a593Smuzhiyun 	outb(CONFIG0_RST, ioaddr + CONFIG_0);
1140*4882a593Smuzhiyun     else
1141*4882a593Smuzhiyun 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun     if (dev->flags & IFF_PROMISC) {
1144*4882a593Smuzhiyun 	memset(mc_filter, 0xff, sizeof(mc_filter));
1145*4882a593Smuzhiyun 	outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */
1146*4882a593Smuzhiyun     } else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
1147*4882a593Smuzhiyun 	       (dev->flags & IFF_ALLMULTI)) {
1148*4882a593Smuzhiyun 	/* Too many to filter perfectly -- accept all multicasts. */
1149*4882a593Smuzhiyun 	memset(mc_filter, 0xff, sizeof(mc_filter));
1150*4882a593Smuzhiyun 	outb(2, ioaddr + RX_MODE);	/* Use normal mode. */
1151*4882a593Smuzhiyun     } else if (netdev_mc_empty(dev)) {
1152*4882a593Smuzhiyun 	memset(mc_filter, 0x00, sizeof(mc_filter));
1153*4882a593Smuzhiyun 	outb(1, ioaddr + RX_MODE);	/* Ignore almost all multicasts. */
1154*4882a593Smuzhiyun     } else {
1155*4882a593Smuzhiyun 	struct netdev_hw_addr *ha;
1156*4882a593Smuzhiyun 
1157*4882a593Smuzhiyun 	memset(mc_filter, 0, sizeof(mc_filter));
1158*4882a593Smuzhiyun 	netdev_for_each_mc_addr(ha, dev) {
1159*4882a593Smuzhiyun 	    unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26;
1160*4882a593Smuzhiyun 	    mc_filter[bit >> 3] |= (1 << (bit & 7));
1161*4882a593Smuzhiyun 	}
1162*4882a593Smuzhiyun 	outb(2, ioaddr + RX_MODE);	/* Use normal mode. */
1163*4882a593Smuzhiyun     }
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun     /* Switch to bank 1 and set the multicast table. */
1166*4882a593Smuzhiyun     saved_bank = inb(ioaddr + CONFIG_1);
1167*4882a593Smuzhiyun     outb(0xe4, ioaddr + CONFIG_1);
1168*4882a593Smuzhiyun 
1169*4882a593Smuzhiyun     for (i = 0; i < 8; i++)
1170*4882a593Smuzhiyun 	outb(mc_filter[i], ioaddr + MAR_ADR + i);
1171*4882a593Smuzhiyun     outb(saved_bank, ioaddr + CONFIG_1);
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun     outb(saved_config_0, ioaddr + CONFIG_0);
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun     local_irq_restore(flags);
1176*4882a593Smuzhiyun }
1177