xref: /linux/drivers/net/ethernet/fujitsu/fmvj18x_cs.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
15346ebf6SJeff Kirsher /*======================================================================
25346ebf6SJeff Kirsher     fmvj18x_cs.c 2.8 2002/03/23
35346ebf6SJeff Kirsher 
45346ebf6SJeff Kirsher     A fmvj18x (and its compatibles) PCMCIA client driver
55346ebf6SJeff Kirsher 
65346ebf6SJeff Kirsher     Contributed by Shingo Fujimoto, shingo@flab.fujitsu.co.jp
75346ebf6SJeff Kirsher 
85346ebf6SJeff Kirsher     TDK LAK-CD021 and CONTEC C-NET(PC)C support added by
95346ebf6SJeff Kirsher     Nobuhiro Katayama, kata-n@po.iijnet.or.jp
105346ebf6SJeff Kirsher 
115346ebf6SJeff Kirsher     The PCMCIA client code is based on code written by David Hinds.
125346ebf6SJeff Kirsher     Network code is based on the "FMV-18x driver" by Yutaka TAMIYA
135346ebf6SJeff Kirsher     but is actually largely Donald Becker's AT1700 driver, which
145346ebf6SJeff Kirsher     carries the following attribution:
155346ebf6SJeff Kirsher 
165346ebf6SJeff Kirsher     Written 1993-94 by Donald Becker.
175346ebf6SJeff Kirsher 
185346ebf6SJeff Kirsher     Copyright 1993 United States Government as represented by the
195346ebf6SJeff Kirsher     Director, National Security Agency.
205346ebf6SJeff Kirsher 
215346ebf6SJeff Kirsher     This software may be used and distributed according to the terms
225346ebf6SJeff Kirsher     of the GNU General Public License, incorporated herein by reference.
235346ebf6SJeff Kirsher 
245346ebf6SJeff Kirsher     The author may be reached as becker@scyld.com, or C/O
255346ebf6SJeff Kirsher     Scyld Computing Corporation
265346ebf6SJeff Kirsher     410 Severn Ave., Suite 210
275346ebf6SJeff Kirsher     Annapolis MD 21403
285346ebf6SJeff Kirsher 
295346ebf6SJeff Kirsher ======================================================================*/
305346ebf6SJeff Kirsher 
315346ebf6SJeff Kirsher #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
325346ebf6SJeff Kirsher 
335346ebf6SJeff Kirsher #define DRV_NAME	"fmvj18x_cs"
345346ebf6SJeff Kirsher #define DRV_VERSION	"2.9"
355346ebf6SJeff Kirsher 
365346ebf6SJeff Kirsher #include <linux/module.h>
375346ebf6SJeff Kirsher #include <linux/kernel.h>
385346ebf6SJeff Kirsher #include <linux/ptrace.h>
395346ebf6SJeff Kirsher #include <linux/slab.h>
405346ebf6SJeff Kirsher #include <linux/string.h>
415346ebf6SJeff Kirsher #include <linux/timer.h>
425346ebf6SJeff Kirsher #include <linux/interrupt.h>
435346ebf6SJeff Kirsher #include <linux/in.h>
445346ebf6SJeff Kirsher #include <linux/delay.h>
455346ebf6SJeff Kirsher #include <linux/ethtool.h>
465346ebf6SJeff Kirsher #include <linux/netdevice.h>
475346ebf6SJeff Kirsher #include <linux/etherdevice.h>
485346ebf6SJeff Kirsher #include <linux/skbuff.h>
495346ebf6SJeff Kirsher #include <linux/if_arp.h>
505346ebf6SJeff Kirsher #include <linux/ioport.h>
515346ebf6SJeff Kirsher #include <linux/crc32.h>
525346ebf6SJeff Kirsher 
535346ebf6SJeff Kirsher #include <pcmcia/cistpl.h>
545346ebf6SJeff Kirsher #include <pcmcia/ciscode.h>
555346ebf6SJeff Kirsher #include <pcmcia/ds.h>
565346ebf6SJeff Kirsher 
577c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
585346ebf6SJeff Kirsher #include <asm/io.h>
595346ebf6SJeff Kirsher 
605346ebf6SJeff Kirsher /*====================================================================*/
615346ebf6SJeff Kirsher 
625346ebf6SJeff Kirsher /* Module parameters */
635346ebf6SJeff Kirsher 
645346ebf6SJeff Kirsher MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
655346ebf6SJeff Kirsher MODULE_LICENSE("GPL");
665346ebf6SJeff Kirsher 
675346ebf6SJeff Kirsher #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0)
685346ebf6SJeff Kirsher 
695346ebf6SJeff Kirsher /* SRAM configuration */
705346ebf6SJeff Kirsher /* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */
715346ebf6SJeff Kirsher INT_MODULE_PARM(sram_config, 0);
725346ebf6SJeff Kirsher 
735346ebf6SJeff Kirsher 
745346ebf6SJeff Kirsher /*====================================================================*/
755346ebf6SJeff Kirsher /*
765346ebf6SJeff Kirsher     PCMCIA event handlers
775346ebf6SJeff Kirsher  */
785346ebf6SJeff Kirsher static int fmvj18x_config(struct pcmcia_device *link);
795346ebf6SJeff Kirsher static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id);
805346ebf6SJeff Kirsher static int fmvj18x_setup_mfc(struct pcmcia_device *link);
815346ebf6SJeff Kirsher static void fmvj18x_release(struct pcmcia_device *link);
825346ebf6SJeff Kirsher static void fmvj18x_detach(struct pcmcia_device *p_dev);
835346ebf6SJeff Kirsher 
845346ebf6SJeff Kirsher /*
855346ebf6SJeff Kirsher     LAN controller(MBH86960A) specific routines
865346ebf6SJeff Kirsher  */
875346ebf6SJeff Kirsher static int fjn_config(struct net_device *dev, struct ifmap *map);
885346ebf6SJeff Kirsher static int fjn_open(struct net_device *dev);
895346ebf6SJeff Kirsher static int fjn_close(struct net_device *dev);
905346ebf6SJeff Kirsher static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
915346ebf6SJeff Kirsher 					struct net_device *dev);
925346ebf6SJeff Kirsher static irqreturn_t fjn_interrupt(int irq, void *dev_id);
935346ebf6SJeff Kirsher static void fjn_rx(struct net_device *dev);
945346ebf6SJeff Kirsher static void fjn_reset(struct net_device *dev);
955346ebf6SJeff Kirsher static void set_rx_mode(struct net_device *dev);
960290bd29SMichael S. Tsirkin static void fjn_tx_timeout(struct net_device *dev, unsigned int txqueue);
975346ebf6SJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops;
985346ebf6SJeff Kirsher 
995346ebf6SJeff Kirsher /*
1005346ebf6SJeff Kirsher     card type
1015346ebf6SJeff Kirsher  */
102f073d52dSHimangi Saraogi enum cardtype { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN,
1035346ebf6SJeff Kirsher 	       XXX10304, NEC, KME
104f073d52dSHimangi Saraogi };
1055346ebf6SJeff Kirsher 
1065346ebf6SJeff Kirsher /*
1075346ebf6SJeff Kirsher     driver specific data structure
1085346ebf6SJeff Kirsher */
109f073d52dSHimangi Saraogi struct local_info {
1105346ebf6SJeff Kirsher 	struct pcmcia_device	*p_dev;
1115346ebf6SJeff Kirsher     long open_time;
1125346ebf6SJeff Kirsher     uint tx_started:1;
1135346ebf6SJeff Kirsher     uint tx_queue;
1145346ebf6SJeff Kirsher     u_short tx_queue_len;
115f073d52dSHimangi Saraogi     enum cardtype cardtype;
1165346ebf6SJeff Kirsher     u_short sent;
1175346ebf6SJeff Kirsher     u_char __iomem *base;
118f073d52dSHimangi Saraogi };
1195346ebf6SJeff Kirsher 
1205346ebf6SJeff Kirsher #define MC_FILTERBREAK 64
1215346ebf6SJeff Kirsher 
1225346ebf6SJeff Kirsher /*====================================================================*/
1235346ebf6SJeff Kirsher /*
1245346ebf6SJeff Kirsher     ioport offset from the base address
1255346ebf6SJeff Kirsher  */
1265346ebf6SJeff Kirsher #define TX_STATUS               0 /* transmit status register */
1275346ebf6SJeff Kirsher #define RX_STATUS               1 /* receive status register */
1285346ebf6SJeff Kirsher #define TX_INTR                 2 /* transmit interrupt mask register */
1295346ebf6SJeff Kirsher #define RX_INTR                 3 /* receive interrupt mask register */
1305346ebf6SJeff Kirsher #define TX_MODE                 4 /* transmit mode register */
1315346ebf6SJeff Kirsher #define RX_MODE                 5 /* receive mode register */
1325346ebf6SJeff Kirsher #define CONFIG_0                6 /* configuration register 0 */
1335346ebf6SJeff Kirsher #define CONFIG_1                7 /* configuration register 1 */
1345346ebf6SJeff Kirsher 
1355346ebf6SJeff Kirsher #define NODE_ID                 8 /* node ID register            (bank 0) */
1365346ebf6SJeff Kirsher #define MAR_ADR                 8 /* multicast address registers (bank 1) */
1375346ebf6SJeff Kirsher 
1385346ebf6SJeff Kirsher #define DATAPORT                8 /* buffer mem port registers   (bank 2) */
1395346ebf6SJeff Kirsher #define TX_START               10 /* transmit start register */
1405346ebf6SJeff Kirsher #define COL_CTRL               11 /* 16 collision control register */
1415346ebf6SJeff Kirsher #define BMPR12                 12 /* reserved */
1425346ebf6SJeff Kirsher #define BMPR13                 13 /* reserved */
1435346ebf6SJeff Kirsher #define RX_SKIP                14 /* skip received packet register */
1445346ebf6SJeff Kirsher 
1455346ebf6SJeff Kirsher #define LAN_CTRL               16 /* LAN card control register */
1465346ebf6SJeff Kirsher 
1475346ebf6SJeff Kirsher #define MAC_ID               0x1a /* hardware address */
1485346ebf6SJeff Kirsher #define UNGERMANN_MAC_ID     0x18 /* UNGERMANN-BASS hardware address */
1495346ebf6SJeff Kirsher 
1505346ebf6SJeff Kirsher /*
1515346ebf6SJeff Kirsher     control bits
1525346ebf6SJeff Kirsher  */
1535346ebf6SJeff Kirsher #define ENA_TMT_OK           0x80
1545346ebf6SJeff Kirsher #define ENA_TMT_REC          0x20
1555346ebf6SJeff Kirsher #define ENA_COL              0x04
1565346ebf6SJeff Kirsher #define ENA_16_COL           0x02
1575346ebf6SJeff Kirsher #define ENA_TBUS_ERR         0x01
1585346ebf6SJeff Kirsher 
1595346ebf6SJeff Kirsher #define ENA_PKT_RDY          0x80
1605346ebf6SJeff Kirsher #define ENA_BUS_ERR          0x40
1615346ebf6SJeff Kirsher #define ENA_LEN_ERR          0x08
1625346ebf6SJeff Kirsher #define ENA_ALG_ERR          0x04
1635346ebf6SJeff Kirsher #define ENA_CRC_ERR          0x02
1645346ebf6SJeff Kirsher #define ENA_OVR_FLO          0x01
1655346ebf6SJeff Kirsher 
1665346ebf6SJeff Kirsher /* flags */
1675346ebf6SJeff Kirsher #define F_TMT_RDY            0x80 /* can accept new packet */
1685346ebf6SJeff Kirsher #define F_NET_BSY            0x40 /* carrier is detected */
1695346ebf6SJeff Kirsher #define F_TMT_OK             0x20 /* send packet successfully */
1705346ebf6SJeff Kirsher #define F_SRT_PKT            0x10 /* short packet error */
1715346ebf6SJeff Kirsher #define F_COL_ERR            0x04 /* collision error */
1725346ebf6SJeff Kirsher #define F_16_COL             0x02 /* 16 collision error */
1735346ebf6SJeff Kirsher #define F_TBUS_ERR           0x01 /* bus read error */
1745346ebf6SJeff Kirsher 
1755346ebf6SJeff Kirsher #define F_PKT_RDY            0x80 /* packet(s) in buffer */
1765346ebf6SJeff Kirsher #define F_BUS_ERR            0x40 /* bus read error */
1775346ebf6SJeff Kirsher #define F_LEN_ERR            0x08 /* short packet */
1785346ebf6SJeff Kirsher #define F_ALG_ERR            0x04 /* frame error */
1795346ebf6SJeff Kirsher #define F_CRC_ERR            0x02 /* CRC error */
1805346ebf6SJeff Kirsher #define F_OVR_FLO            0x01 /* overflow error */
1815346ebf6SJeff Kirsher 
1825346ebf6SJeff Kirsher #define F_BUF_EMP            0x40 /* receive buffer is empty */
1835346ebf6SJeff Kirsher 
1845346ebf6SJeff Kirsher #define F_SKP_PKT            0x05 /* drop packet in buffer */
1855346ebf6SJeff Kirsher 
1865346ebf6SJeff Kirsher /* default bitmaps */
1875346ebf6SJeff Kirsher #define D_TX_INTR  ( ENA_TMT_OK )
1885346ebf6SJeff Kirsher #define D_RX_INTR  ( ENA_PKT_RDY | ENA_LEN_ERR \
1895346ebf6SJeff Kirsher 		   | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO )
1905346ebf6SJeff Kirsher #define TX_STAT_M  ( F_TMT_RDY )
1915346ebf6SJeff Kirsher #define RX_STAT_M  ( F_PKT_RDY | F_LEN_ERR \
1925346ebf6SJeff Kirsher                    | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO )
1935346ebf6SJeff Kirsher 
1945346ebf6SJeff Kirsher /* commands */
1955346ebf6SJeff Kirsher #define D_TX_MODE            0x06 /* no tests, detect carrier */
1965346ebf6SJeff Kirsher #define ID_MATCHED           0x02 /* (RX_MODE) */
1975346ebf6SJeff Kirsher #define RECV_ALL             0x03 /* (RX_MODE) */
1985346ebf6SJeff Kirsher #define CONFIG0_DFL          0x5a /* 16bit bus, 4K x 2 Tx queues */
1995346ebf6SJeff Kirsher #define CONFIG0_DFL_1        0x5e /* 16bit bus, 8K x 2 Tx queues */
2005346ebf6SJeff Kirsher #define CONFIG0_RST          0xda /* Data Link Controller off (CONFIG_0) */
2015346ebf6SJeff Kirsher #define CONFIG0_RST_1        0xde /* Data Link Controller off (CONFIG_0) */
2025346ebf6SJeff Kirsher #define BANK_0               0xa0 /* bank 0 (CONFIG_1) */
2035346ebf6SJeff Kirsher #define BANK_1               0xa4 /* bank 1 (CONFIG_1) */
2045346ebf6SJeff Kirsher #define BANK_2               0xa8 /* bank 2 (CONFIG_1) */
2055346ebf6SJeff Kirsher #define CHIP_OFF             0x80 /* contrl chip power off (CONFIG_1) */
2065346ebf6SJeff Kirsher #define DO_TX                0x80 /* do transmit packet */
2075346ebf6SJeff Kirsher #define SEND_PKT             0x81 /* send a packet */
2085346ebf6SJeff Kirsher #define AUTO_MODE            0x07 /* Auto skip packet on 16 col detected */
2095346ebf6SJeff Kirsher #define MANU_MODE            0x03 /* Stop and skip packet on 16 col */
2105346ebf6SJeff Kirsher #define TDK_AUTO_MODE        0x47 /* Auto skip packet on 16 col detected */
2115346ebf6SJeff Kirsher #define TDK_MANU_MODE        0x43 /* Stop and skip packet on 16 col */
2125346ebf6SJeff Kirsher #define INTR_OFF             0x0d /* LAN controller ignores interrupts */
2135346ebf6SJeff Kirsher #define INTR_ON              0x1d /* LAN controller will catch interrupts */
2145346ebf6SJeff Kirsher 
2155346ebf6SJeff Kirsher #define TX_TIMEOUT		((400*HZ)/1000)
2165346ebf6SJeff Kirsher 
2175346ebf6SJeff Kirsher #define BANK_0U              0x20 /* bank 0 (CONFIG_1) */
2185346ebf6SJeff Kirsher #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
2195346ebf6SJeff Kirsher #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
2205346ebf6SJeff Kirsher 
2215346ebf6SJeff Kirsher static const struct net_device_ops fjn_netdev_ops = {
2225346ebf6SJeff Kirsher 	.ndo_open 		= fjn_open,
2235346ebf6SJeff Kirsher 	.ndo_stop		= fjn_close,
2245346ebf6SJeff Kirsher 	.ndo_start_xmit 	= fjn_start_xmit,
2255346ebf6SJeff Kirsher 	.ndo_tx_timeout 	= fjn_tx_timeout,
2265346ebf6SJeff Kirsher 	.ndo_set_config 	= fjn_config,
227afc4b13dSJiri Pirko 	.ndo_set_rx_mode	= set_rx_mode,
2285346ebf6SJeff Kirsher 	.ndo_set_mac_address 	= eth_mac_addr,
2295346ebf6SJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
2305346ebf6SJeff Kirsher };
2315346ebf6SJeff Kirsher 
fmvj18x_probe(struct pcmcia_device * link)2325346ebf6SJeff Kirsher static int fmvj18x_probe(struct pcmcia_device *link)
2335346ebf6SJeff Kirsher {
234f073d52dSHimangi Saraogi     struct local_info *lp;
2355346ebf6SJeff Kirsher     struct net_device *dev;
2365346ebf6SJeff Kirsher 
2375346ebf6SJeff Kirsher     dev_dbg(&link->dev, "fmvj18x_attach()\n");
2385346ebf6SJeff Kirsher 
2395346ebf6SJeff Kirsher     /* Make up a FMVJ18x specific data structure */
240f073d52dSHimangi Saraogi     dev = alloc_etherdev(sizeof(struct local_info));
2415346ebf6SJeff Kirsher     if (!dev)
2425346ebf6SJeff Kirsher 	return -ENOMEM;
2435346ebf6SJeff Kirsher     lp = netdev_priv(dev);
2445346ebf6SJeff Kirsher     link->priv = dev;
2455346ebf6SJeff Kirsher     lp->p_dev = link;
2465346ebf6SJeff Kirsher     lp->base = NULL;
2475346ebf6SJeff Kirsher 
2485346ebf6SJeff Kirsher     /* The io structure describes IO port mapping */
2495346ebf6SJeff Kirsher     link->resource[0]->end = 32;
2505346ebf6SJeff Kirsher     link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
2515346ebf6SJeff Kirsher 
2525346ebf6SJeff Kirsher     /* General socket configuration */
2535346ebf6SJeff Kirsher     link->config_flags |= CONF_ENABLE_IRQ;
2545346ebf6SJeff Kirsher 
2555346ebf6SJeff Kirsher     dev->netdev_ops = &fjn_netdev_ops;
2565346ebf6SJeff Kirsher     dev->watchdog_timeo = TX_TIMEOUT;
2575346ebf6SJeff Kirsher 
2587ad24ea4SWilfried Klaebe     dev->ethtool_ops = &netdev_ethtool_ops;
2595346ebf6SJeff Kirsher 
2605346ebf6SJeff Kirsher     return fmvj18x_config(link);
2615346ebf6SJeff Kirsher } /* fmvj18x_attach */
2625346ebf6SJeff Kirsher 
2635346ebf6SJeff Kirsher /*====================================================================*/
2645346ebf6SJeff Kirsher 
fmvj18x_detach(struct pcmcia_device * link)2655346ebf6SJeff Kirsher static void fmvj18x_detach(struct pcmcia_device *link)
2665346ebf6SJeff Kirsher {
2675346ebf6SJeff Kirsher     struct net_device *dev = link->priv;
2685346ebf6SJeff Kirsher 
2695346ebf6SJeff Kirsher     dev_dbg(&link->dev, "fmvj18x_detach\n");
2705346ebf6SJeff Kirsher 
2715346ebf6SJeff Kirsher     unregister_netdev(dev);
2725346ebf6SJeff Kirsher 
2735346ebf6SJeff Kirsher     fmvj18x_release(link);
2745346ebf6SJeff Kirsher 
2755346ebf6SJeff Kirsher     free_netdev(dev);
2765346ebf6SJeff Kirsher } /* fmvj18x_detach */
2775346ebf6SJeff Kirsher 
2785346ebf6SJeff Kirsher /*====================================================================*/
2795346ebf6SJeff Kirsher 
mfc_try_io_port(struct pcmcia_device * link)2805346ebf6SJeff Kirsher static int mfc_try_io_port(struct pcmcia_device *link)
2815346ebf6SJeff Kirsher {
2825346ebf6SJeff Kirsher     int i, ret;
2835346ebf6SJeff Kirsher     static const unsigned int serial_base[5] =
2845346ebf6SJeff Kirsher 	{ 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
2855346ebf6SJeff Kirsher 
2865346ebf6SJeff Kirsher     for (i = 0; i < 5; i++) {
2875346ebf6SJeff Kirsher 	link->resource[1]->start = serial_base[i];
2885346ebf6SJeff Kirsher 	link->resource[1]->flags |= IO_DATA_PATH_WIDTH_8;
2895346ebf6SJeff Kirsher 	if (link->resource[1]->start == 0) {
2905346ebf6SJeff Kirsher 	    link->resource[1]->end = 0;
2915346ebf6SJeff Kirsher 	    pr_notice("out of resource for serial\n");
2925346ebf6SJeff Kirsher 	}
2935346ebf6SJeff Kirsher 	ret = pcmcia_request_io(link);
2945346ebf6SJeff Kirsher 	if (ret == 0)
2955346ebf6SJeff Kirsher 		return ret;
2965346ebf6SJeff Kirsher     }
2975346ebf6SJeff Kirsher     return ret;
2985346ebf6SJeff Kirsher }
2995346ebf6SJeff Kirsher 
ungermann_try_io_port(struct pcmcia_device * link)3005346ebf6SJeff Kirsher static int ungermann_try_io_port(struct pcmcia_device *link)
3015346ebf6SJeff Kirsher {
3025346ebf6SJeff Kirsher     int ret;
3035346ebf6SJeff Kirsher     unsigned int ioaddr;
3045346ebf6SJeff Kirsher     /*
3055346ebf6SJeff Kirsher 	Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
3065346ebf6SJeff Kirsher 	0x380,0x3c0 only for ioport.
3075346ebf6SJeff Kirsher     */
3085346ebf6SJeff Kirsher     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
3095346ebf6SJeff Kirsher 	link->resource[0]->start = ioaddr;
3105346ebf6SJeff Kirsher 	ret = pcmcia_request_io(link);
3115346ebf6SJeff Kirsher 	if (ret == 0) {
3125346ebf6SJeff Kirsher 	    /* calculate ConfigIndex value */
3135346ebf6SJeff Kirsher 	    link->config_index =
3145346ebf6SJeff Kirsher 		((link->resource[0]->start & 0x0f0) >> 3) | 0x22;
3155346ebf6SJeff Kirsher 	    return ret;
3165346ebf6SJeff Kirsher 	}
3175346ebf6SJeff Kirsher     }
3185346ebf6SJeff Kirsher     return ret;	/* RequestIO failed */
3195346ebf6SJeff Kirsher }
3205346ebf6SJeff Kirsher 
fmvj18x_ioprobe(struct pcmcia_device * p_dev,void * priv_data)3215346ebf6SJeff Kirsher static int fmvj18x_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
3225346ebf6SJeff Kirsher {
3235346ebf6SJeff Kirsher 	return 0; /* strange, but that's what the code did already before... */
3245346ebf6SJeff Kirsher }
3255346ebf6SJeff Kirsher 
fmvj18x_config(struct pcmcia_device * link)3265346ebf6SJeff Kirsher static int fmvj18x_config(struct pcmcia_device *link)
3275346ebf6SJeff Kirsher {
3285346ebf6SJeff Kirsher     struct net_device *dev = link->priv;
329f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
3305346ebf6SJeff Kirsher     int i, ret;
3315346ebf6SJeff Kirsher     unsigned int ioaddr;
332f073d52dSHimangi Saraogi     enum cardtype cardtype;
3335346ebf6SJeff Kirsher     char *card_name = "unknown";
3345346ebf6SJeff Kirsher     u8 *buf;
3355346ebf6SJeff Kirsher     size_t len;
3365346ebf6SJeff Kirsher     u_char buggybuf[32];
3374abd7cffSJakub Kicinski     u8 addr[ETH_ALEN];
3385346ebf6SJeff Kirsher 
3395346ebf6SJeff Kirsher     dev_dbg(&link->dev, "fmvj18x_config\n");
3405346ebf6SJeff Kirsher 
3415346ebf6SJeff Kirsher     link->io_lines = 5;
3425346ebf6SJeff Kirsher 
3435346ebf6SJeff Kirsher     len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
3445346ebf6SJeff Kirsher     kfree(buf);
3455346ebf6SJeff Kirsher 
3465346ebf6SJeff Kirsher     if (len) {
3475346ebf6SJeff Kirsher 	/* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
3485346ebf6SJeff Kirsher 	ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL);
3495346ebf6SJeff Kirsher 	if (ret != 0)
3505346ebf6SJeff Kirsher 		goto failed;
3515346ebf6SJeff Kirsher 
3525346ebf6SJeff Kirsher 	switch (link->manf_id) {
3535346ebf6SJeff Kirsher 	case MANFID_TDK:
3545346ebf6SJeff Kirsher 	    cardtype = TDK;
3555346ebf6SJeff Kirsher 	    if (link->card_id == PRODID_TDK_GN3410 ||
3565346ebf6SJeff Kirsher 		link->card_id == PRODID_TDK_NP9610 ||
3575346ebf6SJeff Kirsher 		link->card_id == PRODID_TDK_MN3200) {
3585346ebf6SJeff Kirsher 		/* MultiFunction Card */
3595346ebf6SJeff Kirsher 		link->config_base = 0x800;
3605346ebf6SJeff Kirsher 		link->config_index = 0x47;
3615346ebf6SJeff Kirsher 		link->resource[1]->end = 8;
3625346ebf6SJeff Kirsher 	    }
3635346ebf6SJeff Kirsher 	    break;
3645346ebf6SJeff Kirsher 	case MANFID_NEC:
3655346ebf6SJeff Kirsher 	    cardtype = NEC; /* MultiFunction Card */
3665346ebf6SJeff Kirsher 	    link->config_base = 0x800;
3675346ebf6SJeff Kirsher 	    link->config_index = 0x47;
3685346ebf6SJeff Kirsher 	    link->resource[1]->end = 8;
3695346ebf6SJeff Kirsher 	    break;
3705346ebf6SJeff Kirsher 	case MANFID_KME:
3715346ebf6SJeff Kirsher 	    cardtype = KME; /* MultiFunction Card */
3725346ebf6SJeff Kirsher 	    link->config_base = 0x800;
3735346ebf6SJeff Kirsher 	    link->config_index = 0x47;
3745346ebf6SJeff Kirsher 	    link->resource[1]->end = 8;
3755346ebf6SJeff Kirsher 	    break;
3765346ebf6SJeff Kirsher 	case MANFID_CONTEC:
3775346ebf6SJeff Kirsher 	    cardtype = CONTEC;
3785346ebf6SJeff Kirsher 	    break;
3795346ebf6SJeff Kirsher 	case MANFID_FUJITSU:
3805346ebf6SJeff Kirsher 	    if (link->config_base == 0x0fe0)
3815346ebf6SJeff Kirsher 		cardtype = MBH10302;
3825346ebf6SJeff Kirsher 	    else if (link->card_id == PRODID_FUJITSU_MBH10302)
3835346ebf6SJeff Kirsher                 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
3845346ebf6SJeff Kirsher                    but these are MBH10304 based card. */
3855346ebf6SJeff Kirsher 		cardtype = MBH10304;
3865346ebf6SJeff Kirsher 	    else if (link->card_id == PRODID_FUJITSU_MBH10304)
3875346ebf6SJeff Kirsher 		cardtype = MBH10304;
3885346ebf6SJeff Kirsher 	    else
3895346ebf6SJeff Kirsher 		cardtype = LA501;
3905346ebf6SJeff Kirsher 	    break;
3915346ebf6SJeff Kirsher 	default:
3925346ebf6SJeff Kirsher 	    cardtype = MBH10304;
3935346ebf6SJeff Kirsher 	}
3945346ebf6SJeff Kirsher     } else {
3955346ebf6SJeff Kirsher 	/* old type card */
3965346ebf6SJeff Kirsher 	switch (link->manf_id) {
3975346ebf6SJeff Kirsher 	case MANFID_FUJITSU:
3985346ebf6SJeff Kirsher 	    if (link->card_id == PRODID_FUJITSU_MBH10304) {
3995346ebf6SJeff Kirsher 		cardtype = XXX10304;    /* MBH10304 with buggy CIS */
4005346ebf6SJeff Kirsher 		link->config_index = 0x20;
4015346ebf6SJeff Kirsher 	    } else {
4025346ebf6SJeff Kirsher 		cardtype = MBH10302;    /* NextCom NC5310, etc. */
4035346ebf6SJeff Kirsher 		link->config_index = 1;
4045346ebf6SJeff Kirsher 	    }
4055346ebf6SJeff Kirsher 	    break;
4065346ebf6SJeff Kirsher 	case MANFID_UNGERMANN:
4075346ebf6SJeff Kirsher 	    cardtype = UNGERMANN;
4085346ebf6SJeff Kirsher 	    break;
4095346ebf6SJeff Kirsher 	default:
4105346ebf6SJeff Kirsher 	    cardtype = MBH10302;
4115346ebf6SJeff Kirsher 	    link->config_index = 1;
4125346ebf6SJeff Kirsher 	}
4135346ebf6SJeff Kirsher     }
4145346ebf6SJeff Kirsher 
4155346ebf6SJeff Kirsher     if (link->resource[1]->end != 0) {
4165346ebf6SJeff Kirsher 	ret = mfc_try_io_port(link);
4175346ebf6SJeff Kirsher 	if (ret != 0) goto failed;
4185346ebf6SJeff Kirsher     } else if (cardtype == UNGERMANN) {
4195346ebf6SJeff Kirsher 	ret = ungermann_try_io_port(link);
4205346ebf6SJeff Kirsher 	if (ret != 0) goto failed;
4215346ebf6SJeff Kirsher     } else {
4225346ebf6SJeff Kirsher 	    ret = pcmcia_request_io(link);
4235346ebf6SJeff Kirsher 	    if (ret)
4245346ebf6SJeff Kirsher 		    goto failed;
4255346ebf6SJeff Kirsher     }
4265346ebf6SJeff Kirsher     ret = pcmcia_request_irq(link, fjn_interrupt);
4275346ebf6SJeff Kirsher     if (ret)
4285346ebf6SJeff Kirsher 	    goto failed;
4295346ebf6SJeff Kirsher     ret = pcmcia_enable_device(link);
4305346ebf6SJeff Kirsher     if (ret)
4315346ebf6SJeff Kirsher 	    goto failed;
4325346ebf6SJeff Kirsher 
4335346ebf6SJeff Kirsher     dev->irq = link->irq;
4345346ebf6SJeff Kirsher     dev->base_addr = link->resource[0]->start;
4355346ebf6SJeff Kirsher 
4365346ebf6SJeff Kirsher     if (resource_size(link->resource[1]) != 0) {
4375346ebf6SJeff Kirsher 	ret = fmvj18x_setup_mfc(link);
4385346ebf6SJeff Kirsher 	if (ret != 0) goto failed;
4395346ebf6SJeff Kirsher     }
4405346ebf6SJeff Kirsher 
4415346ebf6SJeff Kirsher     ioaddr = dev->base_addr;
4425346ebf6SJeff Kirsher 
4435346ebf6SJeff Kirsher     /* Reset controller */
4445346ebf6SJeff Kirsher     if (sram_config == 0)
4455346ebf6SJeff Kirsher 	outb(CONFIG0_RST, ioaddr + CONFIG_0);
4465346ebf6SJeff Kirsher     else
4475346ebf6SJeff Kirsher 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
4485346ebf6SJeff Kirsher 
4495346ebf6SJeff Kirsher     /* Power On chip and select bank 0 */
4505346ebf6SJeff Kirsher     if (cardtype == MBH10302)
4515346ebf6SJeff Kirsher 	outb(BANK_0, ioaddr + CONFIG_1);
4525346ebf6SJeff Kirsher     else
4535346ebf6SJeff Kirsher 	outb(BANK_0U, ioaddr + CONFIG_1);
4545346ebf6SJeff Kirsher 
4555346ebf6SJeff Kirsher     /* Set hardware address */
4565346ebf6SJeff Kirsher     switch (cardtype) {
4575346ebf6SJeff Kirsher     case MBH10304:
4585346ebf6SJeff Kirsher     case TDK:
4595346ebf6SJeff Kirsher     case LA501:
4605346ebf6SJeff Kirsher     case CONTEC:
4615346ebf6SJeff Kirsher     case NEC:
4625346ebf6SJeff Kirsher     case KME:
4635346ebf6SJeff Kirsher 	if (cardtype == MBH10304) {
4645346ebf6SJeff Kirsher 	    card_name = "FMV-J182";
4655346ebf6SJeff Kirsher 
4665346ebf6SJeff Kirsher 	    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
4675346ebf6SJeff Kirsher 	    if (len < 11) {
4685346ebf6SJeff Kirsher 		    kfree(buf);
4695346ebf6SJeff Kirsher 		    goto failed;
4705346ebf6SJeff Kirsher 	    }
4715346ebf6SJeff Kirsher 	    /* Read MACID from CIS */
472562ef98aSJakub Kicinski 	    eth_hw_addr_set(dev, &buf[5]);
4735346ebf6SJeff Kirsher 	    kfree(buf);
4745346ebf6SJeff Kirsher 	} else {
4755346ebf6SJeff Kirsher 	    if (pcmcia_get_mac_from_cis(link, dev))
4765346ebf6SJeff Kirsher 		goto failed;
4775346ebf6SJeff Kirsher 	    if( cardtype == TDK ) {
4785346ebf6SJeff Kirsher 		card_name = "TDK LAK-CD021";
4795346ebf6SJeff Kirsher 	    } else if( cardtype == LA501 ) {
4805346ebf6SJeff Kirsher 		card_name = "LA501";
4815346ebf6SJeff Kirsher 	    } else if( cardtype == NEC ) {
4825346ebf6SJeff Kirsher 		card_name = "PK-UG-J001";
4835346ebf6SJeff Kirsher 	    } else if( cardtype == KME ) {
4845346ebf6SJeff Kirsher 		card_name = "Panasonic";
4855346ebf6SJeff Kirsher 	    } else {
4865346ebf6SJeff Kirsher 		card_name = "C-NET(PC)C";
4875346ebf6SJeff Kirsher 	    }
4885346ebf6SJeff Kirsher 	}
4895346ebf6SJeff Kirsher 	break;
4905346ebf6SJeff Kirsher     case UNGERMANN:
4915346ebf6SJeff Kirsher 	/* Read MACID from register */
4925346ebf6SJeff Kirsher 	for (i = 0; i < 6; i++)
4934abd7cffSJakub Kicinski 	    addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
4944abd7cffSJakub Kicinski 	eth_hw_addr_set(dev, addr);
4955346ebf6SJeff Kirsher 	card_name = "Access/CARD";
4965346ebf6SJeff Kirsher 	break;
4975346ebf6SJeff Kirsher     case XXX10304:
4985346ebf6SJeff Kirsher 	/* Read MACID from Buggy CIS */
4995346ebf6SJeff Kirsher 	if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
5005346ebf6SJeff Kirsher 	    pr_notice("unable to read hardware net address\n");
5015346ebf6SJeff Kirsher 	    goto failed;
5025346ebf6SJeff Kirsher 	}
503562ef98aSJakub Kicinski 	eth_hw_addr_set(dev, buggybuf);
5045346ebf6SJeff Kirsher 	card_name = "FMV-J182";
5055346ebf6SJeff Kirsher 	break;
5065346ebf6SJeff Kirsher     case MBH10302:
5075346ebf6SJeff Kirsher     default:
5085346ebf6SJeff Kirsher 	/* Read MACID from register */
5095346ebf6SJeff Kirsher 	for (i = 0; i < 6; i++)
5104abd7cffSJakub Kicinski 	    addr[i] = inb(ioaddr + MAC_ID + i);
5114abd7cffSJakub Kicinski 	eth_hw_addr_set(dev, addr);
5125346ebf6SJeff Kirsher 	card_name = "FMV-J181";
5135346ebf6SJeff Kirsher 	break;
5145346ebf6SJeff Kirsher     }
5155346ebf6SJeff Kirsher 
5165346ebf6SJeff Kirsher     lp->cardtype = cardtype;
5175346ebf6SJeff Kirsher     SET_NETDEV_DEV(dev, &link->dev);
5185346ebf6SJeff Kirsher 
5195346ebf6SJeff Kirsher     if (register_netdev(dev) != 0) {
5205346ebf6SJeff Kirsher 	pr_notice("register_netdev() failed\n");
5215346ebf6SJeff Kirsher 	goto failed;
5225346ebf6SJeff Kirsher     }
5235346ebf6SJeff Kirsher 
5245346ebf6SJeff Kirsher     /* print current configuration */
5255346ebf6SJeff Kirsher     netdev_info(dev, "%s, sram %s, port %#3lx, irq %d, hw_addr %pM\n",
5265346ebf6SJeff Kirsher 		card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
5275346ebf6SJeff Kirsher 		dev->base_addr, dev->irq, dev->dev_addr);
5285346ebf6SJeff Kirsher 
5295346ebf6SJeff Kirsher     return 0;
5305346ebf6SJeff Kirsher 
5315346ebf6SJeff Kirsher failed:
5325346ebf6SJeff Kirsher     fmvj18x_release(link);
5335346ebf6SJeff Kirsher     return -ENODEV;
5345346ebf6SJeff Kirsher } /* fmvj18x_config */
5355346ebf6SJeff Kirsher /*====================================================================*/
5365346ebf6SJeff Kirsher 
fmvj18x_get_hwinfo(struct pcmcia_device * link,u_char * node_id)5375346ebf6SJeff Kirsher static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
5385346ebf6SJeff Kirsher {
5395346ebf6SJeff Kirsher     u_char __iomem *base;
5405346ebf6SJeff Kirsher     int i, j;
5415346ebf6SJeff Kirsher 
5425346ebf6SJeff Kirsher     /* Allocate a small memory window */
5435346ebf6SJeff Kirsher     link->resource[2]->flags |= WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
5445346ebf6SJeff Kirsher     link->resource[2]->start = 0; link->resource[2]->end = 0;
5455346ebf6SJeff Kirsher     i = pcmcia_request_window(link, link->resource[2], 0);
5465346ebf6SJeff Kirsher     if (i != 0)
5475346ebf6SJeff Kirsher 	return -1;
5485346ebf6SJeff Kirsher 
5495346ebf6SJeff Kirsher     base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
5509f4d6358SKangjie Lu     if (!base) {
5519f4d6358SKangjie Lu 	pcmcia_release_window(link, link->resource[2]);
55252202be1SAnirudh Rayabharam 	return -1;
5539f4d6358SKangjie Lu     }
5549f4d6358SKangjie Lu 
5555346ebf6SJeff Kirsher     pcmcia_map_mem_page(link, link->resource[2], 0);
5565346ebf6SJeff Kirsher 
5575346ebf6SJeff Kirsher     /*
5585346ebf6SJeff Kirsher      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
5595346ebf6SJeff Kirsher      *  22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
5605346ebf6SJeff Kirsher      *  'xx' is garbage.
5615346ebf6SJeff Kirsher      *  'yy' is MAC address.
5625346ebf6SJeff Kirsher     */
5635346ebf6SJeff Kirsher     for (i = 0; i < 0x200; i++) {
5645346ebf6SJeff Kirsher 	if (readb(base+i*2) == 0x22) {
5655346ebf6SJeff Kirsher 		if (readb(base+(i-1)*2) == 0xff &&
5665346ebf6SJeff Kirsher 		    readb(base+(i+5)*2) == 0x04 &&
5675346ebf6SJeff Kirsher 		    readb(base+(i+6)*2) == 0x06 &&
5685346ebf6SJeff Kirsher 		    readb(base+(i+13)*2) == 0xff)
5695346ebf6SJeff Kirsher 			break;
5705346ebf6SJeff Kirsher 	}
5715346ebf6SJeff Kirsher     }
5725346ebf6SJeff Kirsher 
5735346ebf6SJeff Kirsher     if (i != 0x200) {
5745346ebf6SJeff Kirsher 	for (j = 0 ; j < 6; j++,i++) {
5755346ebf6SJeff Kirsher 	    node_id[j] = readb(base+(i+7)*2);
5765346ebf6SJeff Kirsher 	}
5775346ebf6SJeff Kirsher     }
5785346ebf6SJeff Kirsher 
5795346ebf6SJeff Kirsher     iounmap(base);
5805346ebf6SJeff Kirsher     j = pcmcia_release_window(link, link->resource[2]);
5815346ebf6SJeff Kirsher     return (i != 0x200) ? 0 : -1;
5825346ebf6SJeff Kirsher 
5835346ebf6SJeff Kirsher } /* fmvj18x_get_hwinfo */
5845346ebf6SJeff Kirsher /*====================================================================*/
5855346ebf6SJeff Kirsher 
fmvj18x_setup_mfc(struct pcmcia_device * link)5865346ebf6SJeff Kirsher static int fmvj18x_setup_mfc(struct pcmcia_device *link)
5875346ebf6SJeff Kirsher {
5885346ebf6SJeff Kirsher     int i;
5895346ebf6SJeff Kirsher     struct net_device *dev = link->priv;
5905346ebf6SJeff Kirsher     unsigned int ioaddr;
591f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
5925346ebf6SJeff Kirsher 
5935346ebf6SJeff Kirsher     /* Allocate a small memory window */
5945346ebf6SJeff Kirsher     link->resource[3]->flags = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
5955346ebf6SJeff Kirsher     link->resource[3]->start = link->resource[3]->end = 0;
5965346ebf6SJeff Kirsher     i = pcmcia_request_window(link, link->resource[3], 0);
5975346ebf6SJeff Kirsher     if (i != 0)
5985346ebf6SJeff Kirsher 	return -1;
5995346ebf6SJeff Kirsher 
6005346ebf6SJeff Kirsher     lp->base = ioremap(link->resource[3]->start,
6015346ebf6SJeff Kirsher 		       resource_size(link->resource[3]));
6025346ebf6SJeff Kirsher     if (lp->base == NULL) {
6035346ebf6SJeff Kirsher 	netdev_notice(dev, "ioremap failed\n");
6045346ebf6SJeff Kirsher 	return -1;
6055346ebf6SJeff Kirsher     }
6065346ebf6SJeff Kirsher 
6075346ebf6SJeff Kirsher     i = pcmcia_map_mem_page(link, link->resource[3], 0);
6085346ebf6SJeff Kirsher     if (i != 0) {
6095346ebf6SJeff Kirsher 	iounmap(lp->base);
6105346ebf6SJeff Kirsher 	lp->base = NULL;
6115346ebf6SJeff Kirsher 	return -1;
6125346ebf6SJeff Kirsher     }
6135346ebf6SJeff Kirsher 
6145346ebf6SJeff Kirsher     ioaddr = dev->base_addr;
6155346ebf6SJeff Kirsher     writeb(0x47, lp->base+0x800);	/* Config Option Register of LAN */
6165346ebf6SJeff Kirsher     writeb(0x0,  lp->base+0x802);	/* Config and Status Register */
6175346ebf6SJeff Kirsher 
6185346ebf6SJeff Kirsher     writeb(ioaddr & 0xff, lp->base+0x80a);	  /* I/O Base(Low) of LAN */
6195346ebf6SJeff Kirsher     writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
6205346ebf6SJeff Kirsher 
6215346ebf6SJeff Kirsher     writeb(0x45, lp->base+0x820);	/* Config Option Register of Modem */
6225346ebf6SJeff Kirsher     writeb(0x8,  lp->base+0x822);	/* Config and Status Register */
6235346ebf6SJeff Kirsher 
6245346ebf6SJeff Kirsher     return 0;
6255346ebf6SJeff Kirsher 
6265346ebf6SJeff Kirsher }
6275346ebf6SJeff Kirsher /*====================================================================*/
6285346ebf6SJeff Kirsher 
fmvj18x_release(struct pcmcia_device * link)6295346ebf6SJeff Kirsher static void fmvj18x_release(struct pcmcia_device *link)
6305346ebf6SJeff Kirsher {
6315346ebf6SJeff Kirsher 
6325346ebf6SJeff Kirsher     struct net_device *dev = link->priv;
633f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
6345346ebf6SJeff Kirsher     u_char __iomem *tmp;
6355346ebf6SJeff Kirsher 
6365346ebf6SJeff Kirsher     dev_dbg(&link->dev, "fmvj18x_release\n");
6375346ebf6SJeff Kirsher 
6385346ebf6SJeff Kirsher     if (lp->base != NULL) {
6395346ebf6SJeff Kirsher 	tmp = lp->base;
6405346ebf6SJeff Kirsher 	lp->base = NULL;    /* set NULL before iounmap */
6415346ebf6SJeff Kirsher 	iounmap(tmp);
6425346ebf6SJeff Kirsher     }
6435346ebf6SJeff Kirsher 
6445346ebf6SJeff Kirsher     pcmcia_disable_device(link);
6455346ebf6SJeff Kirsher 
6465346ebf6SJeff Kirsher }
6475346ebf6SJeff Kirsher 
fmvj18x_suspend(struct pcmcia_device * link)6485346ebf6SJeff Kirsher static int fmvj18x_suspend(struct pcmcia_device *link)
6495346ebf6SJeff Kirsher {
6505346ebf6SJeff Kirsher 	struct net_device *dev = link->priv;
6515346ebf6SJeff Kirsher 
6525346ebf6SJeff Kirsher 	if (link->open)
6535346ebf6SJeff Kirsher 		netif_device_detach(dev);
6545346ebf6SJeff Kirsher 
6555346ebf6SJeff Kirsher 	return 0;
6565346ebf6SJeff Kirsher }
6575346ebf6SJeff Kirsher 
fmvj18x_resume(struct pcmcia_device * link)6585346ebf6SJeff Kirsher static int fmvj18x_resume(struct pcmcia_device *link)
6595346ebf6SJeff Kirsher {
6605346ebf6SJeff Kirsher 	struct net_device *dev = link->priv;
6615346ebf6SJeff Kirsher 
6625346ebf6SJeff Kirsher 	if (link->open) {
6635346ebf6SJeff Kirsher 		fjn_reset(dev);
6645346ebf6SJeff Kirsher 		netif_device_attach(dev);
6655346ebf6SJeff Kirsher 	}
6665346ebf6SJeff Kirsher 
6675346ebf6SJeff Kirsher 	return 0;
6685346ebf6SJeff Kirsher }
6695346ebf6SJeff Kirsher 
6705346ebf6SJeff Kirsher /*====================================================================*/
6715346ebf6SJeff Kirsher 
6725346ebf6SJeff Kirsher static const struct pcmcia_device_id fmvj18x_ids[] = {
6735346ebf6SJeff Kirsher 	PCMCIA_DEVICE_MANF_CARD(0x0004, 0x0004),
6745346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("EAGLE Technology", "NE200 ETHERNET LAN MBH10302 04", 0x528c88c4, 0x74f91e59),
6755346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("Eiger Labs,Inc", "EPX-10BT PC Card Ethernet 10BT", 0x53af556e, 0x877f9922),
6765346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("Eiger labs,Inc.", "EPX-10BT PC Card Ethernet 10BT", 0xf47e6c66, 0x877f9922),
6775346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("FUJITSU", "LAN Card(FMV-J182)", 0x6ee5a3d8, 0x5baf31db),
6785346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("FUJITSU", "MBH10308", 0x6ee5a3d8, 0x3f04875e),
6795346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("FUJITSU TOWA", "LA501", 0xb8451188, 0x12939ba2),
6805346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("HITACHI", "HT-4840-11", 0xf4f43949, 0x773910f4),
6815346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310B Ver1.0       ", 0x8cef4d3a, 0x075fc7b6),
6825346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("NextComK.K.", "NC5310 Ver1.0        ", 0x8cef4d3a, 0xbccf43e6),
6835346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("RATOC System Inc.", "10BASE_T CARD R280", 0x85c10e17, 0xd9413666),
6845346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CD02x", 0x1eae9475, 0x8fa0ee70),
6855346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID12("TDK", "LAC-CF010", 0x1eae9475, 0x7683bc9a),
6865346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID1("CONTEC Co.,Ltd.", 0x58d8fee2),
6875346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID1("PCMCIA LAN MBH10304  ES", 0x2599f454),
6885346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID1("PCMCIA MBH10302", 0x8f4005da),
6895346ebf6SJeff Kirsher 	PCMCIA_DEVICE_PROD_ID1("UBKK,V2.0", 0x90888080),
6905346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "TDK", "GlobalNetworker 3410/3412", 0x1eae9475, 0xd9a93bed),
6915346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_PROD_ID12(0, "NEC", "PK-UG-J001" ,0x18df0ba0 ,0x831b1064),
6925346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0d0a),
6935346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0105, 0x0e0a),
6945346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0e01),
6955346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0a05),
6965346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x0b05),
6975346ebf6SJeff Kirsher 	PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0032, 0x1101),
6985346ebf6SJeff Kirsher 	PCMCIA_DEVICE_NULL,
6995346ebf6SJeff Kirsher };
7005346ebf6SJeff Kirsher MODULE_DEVICE_TABLE(pcmcia, fmvj18x_ids);
7015346ebf6SJeff Kirsher 
7025346ebf6SJeff Kirsher static struct pcmcia_driver fmvj18x_cs_driver = {
7035346ebf6SJeff Kirsher 	.owner		= THIS_MODULE,
7045346ebf6SJeff Kirsher 	.name		= "fmvj18x_cs",
7055346ebf6SJeff Kirsher 	.probe		= fmvj18x_probe,
7065346ebf6SJeff Kirsher 	.remove		= fmvj18x_detach,
7075346ebf6SJeff Kirsher 	.id_table       = fmvj18x_ids,
7085346ebf6SJeff Kirsher 	.suspend	= fmvj18x_suspend,
7095346ebf6SJeff Kirsher 	.resume		= fmvj18x_resume,
7105346ebf6SJeff Kirsher };
711fdd3f29eSH Hartley Sweeten module_pcmcia_driver(fmvj18x_cs_driver);
7125346ebf6SJeff Kirsher 
7135346ebf6SJeff Kirsher /*====================================================================*/
7145346ebf6SJeff Kirsher 
fjn_interrupt(int dummy,void * dev_id)7155346ebf6SJeff Kirsher static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
7165346ebf6SJeff Kirsher {
7175346ebf6SJeff Kirsher     struct net_device *dev = dev_id;
718f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
7195346ebf6SJeff Kirsher     unsigned int ioaddr;
7205346ebf6SJeff Kirsher     unsigned short tx_stat, rx_stat;
7215346ebf6SJeff Kirsher 
7225346ebf6SJeff Kirsher     ioaddr = dev->base_addr;
7235346ebf6SJeff Kirsher 
7245346ebf6SJeff Kirsher     /* avoid multiple interrupts */
7255346ebf6SJeff Kirsher     outw(0x0000, ioaddr + TX_INTR);
7265346ebf6SJeff Kirsher 
7275346ebf6SJeff Kirsher     /* wait for a while */
7285346ebf6SJeff Kirsher     udelay(1);
7295346ebf6SJeff Kirsher 
7305346ebf6SJeff Kirsher     /* get status */
7315346ebf6SJeff Kirsher     tx_stat = inb(ioaddr + TX_STATUS);
7325346ebf6SJeff Kirsher     rx_stat = inb(ioaddr + RX_STATUS);
7335346ebf6SJeff Kirsher 
7345346ebf6SJeff Kirsher     /* clear status */
7355346ebf6SJeff Kirsher     outb(tx_stat, ioaddr + TX_STATUS);
7365346ebf6SJeff Kirsher     outb(rx_stat, ioaddr + RX_STATUS);
7375346ebf6SJeff Kirsher 
7385346ebf6SJeff Kirsher     pr_debug("%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
7395346ebf6SJeff Kirsher     pr_debug("               tx_status %02x.\n", tx_stat);
7405346ebf6SJeff Kirsher 
7415346ebf6SJeff Kirsher     if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
7425346ebf6SJeff Kirsher 	/* there is packet(s) in rx buffer */
7435346ebf6SJeff Kirsher 	fjn_rx(dev);
7445346ebf6SJeff Kirsher     }
7455346ebf6SJeff Kirsher     if (tx_stat & F_TMT_RDY) {
7465346ebf6SJeff Kirsher 	dev->stats.tx_packets += lp->sent ;
7475346ebf6SJeff Kirsher         lp->sent = 0 ;
7485346ebf6SJeff Kirsher 	if (lp->tx_queue) {
7495346ebf6SJeff Kirsher 	    outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
7505346ebf6SJeff Kirsher 	    lp->sent = lp->tx_queue ;
7515346ebf6SJeff Kirsher 	    lp->tx_queue = 0;
7525346ebf6SJeff Kirsher 	    lp->tx_queue_len = 0;
753860e9538SFlorian Westphal 	    netif_trans_update(dev);
7545346ebf6SJeff Kirsher 	} else {
7555346ebf6SJeff Kirsher 	    lp->tx_started = 0;
7565346ebf6SJeff Kirsher 	}
7575346ebf6SJeff Kirsher 	netif_wake_queue(dev);
7585346ebf6SJeff Kirsher     }
7595346ebf6SJeff Kirsher     pr_debug("%s: exiting interrupt,\n", dev->name);
7605346ebf6SJeff Kirsher     pr_debug("    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
7615346ebf6SJeff Kirsher 
7625346ebf6SJeff Kirsher     outb(D_TX_INTR, ioaddr + TX_INTR);
7635346ebf6SJeff Kirsher     outb(D_RX_INTR, ioaddr + RX_INTR);
7645346ebf6SJeff Kirsher 
7655346ebf6SJeff Kirsher     if (lp->base != NULL) {
7665346ebf6SJeff Kirsher 	/* Ack interrupt for multifunction card */
7675346ebf6SJeff Kirsher 	writeb(0x01, lp->base+0x802);
7685346ebf6SJeff Kirsher 	writeb(0x09, lp->base+0x822);
7695346ebf6SJeff Kirsher     }
7705346ebf6SJeff Kirsher 
7715346ebf6SJeff Kirsher     return IRQ_HANDLED;
7725346ebf6SJeff Kirsher 
7735346ebf6SJeff Kirsher } /* fjn_interrupt */
7745346ebf6SJeff Kirsher 
7755346ebf6SJeff Kirsher /*====================================================================*/
7765346ebf6SJeff Kirsher 
fjn_tx_timeout(struct net_device * dev,unsigned int txqueue)7770290bd29SMichael S. Tsirkin static void fjn_tx_timeout(struct net_device *dev, unsigned int txqueue)
7785346ebf6SJeff Kirsher {
779f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
7805346ebf6SJeff Kirsher     unsigned int ioaddr = dev->base_addr;
7815346ebf6SJeff Kirsher 
7825346ebf6SJeff Kirsher     netdev_notice(dev, "transmit timed out with status %04x, %s?\n",
7835346ebf6SJeff Kirsher 		  htons(inw(ioaddr + TX_STATUS)),
7845346ebf6SJeff Kirsher 		  inb(ioaddr + TX_STATUS) & F_TMT_RDY
7855346ebf6SJeff Kirsher 		  ? "IRQ conflict" : "network cable problem");
7865346ebf6SJeff Kirsher     netdev_notice(dev, "timeout registers: %04x %04x %04x "
7875346ebf6SJeff Kirsher 		  "%04x %04x %04x %04x %04x.\n",
7885346ebf6SJeff Kirsher 		  htons(inw(ioaddr + 0)), htons(inw(ioaddr + 2)),
7895346ebf6SJeff Kirsher 		  htons(inw(ioaddr + 4)), htons(inw(ioaddr + 6)),
7905346ebf6SJeff Kirsher 		  htons(inw(ioaddr + 8)), htons(inw(ioaddr + 10)),
7915346ebf6SJeff Kirsher 		  htons(inw(ioaddr + 12)), htons(inw(ioaddr + 14)));
7925346ebf6SJeff Kirsher     dev->stats.tx_errors++;
7935346ebf6SJeff Kirsher     /* ToDo: We should try to restart the adaptor... */
7945346ebf6SJeff Kirsher     local_irq_disable();
7955346ebf6SJeff Kirsher     fjn_reset(dev);
7965346ebf6SJeff Kirsher 
7975346ebf6SJeff Kirsher     lp->tx_started = 0;
7985346ebf6SJeff Kirsher     lp->tx_queue = 0;
7995346ebf6SJeff Kirsher     lp->tx_queue_len = 0;
8005346ebf6SJeff Kirsher     lp->sent = 0;
8015346ebf6SJeff Kirsher     lp->open_time = jiffies;
8025346ebf6SJeff Kirsher     local_irq_enable();
8035346ebf6SJeff Kirsher     netif_wake_queue(dev);
8045346ebf6SJeff Kirsher }
8055346ebf6SJeff Kirsher 
fjn_start_xmit(struct sk_buff * skb,struct net_device * dev)8065346ebf6SJeff Kirsher static netdev_tx_t fjn_start_xmit(struct sk_buff *skb,
8075346ebf6SJeff Kirsher 					struct net_device *dev)
8085346ebf6SJeff Kirsher {
809f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
8105346ebf6SJeff Kirsher     unsigned int ioaddr = dev->base_addr;
8115346ebf6SJeff Kirsher     short length = skb->len;
8125346ebf6SJeff Kirsher 
8135346ebf6SJeff Kirsher     if (length < ETH_ZLEN)
8145346ebf6SJeff Kirsher     {
8155346ebf6SJeff Kirsher 	if (skb_padto(skb, ETH_ZLEN))
8165346ebf6SJeff Kirsher 		return NETDEV_TX_OK;
8175346ebf6SJeff Kirsher 	length = ETH_ZLEN;
8185346ebf6SJeff Kirsher     }
8195346ebf6SJeff Kirsher 
8205346ebf6SJeff Kirsher     netif_stop_queue(dev);
8215346ebf6SJeff Kirsher 
8225346ebf6SJeff Kirsher     {
8235346ebf6SJeff Kirsher 	unsigned char *buf = skb->data;
8245346ebf6SJeff Kirsher 
8255346ebf6SJeff Kirsher 	if (length > ETH_FRAME_LEN) {
8265346ebf6SJeff Kirsher 	    netdev_notice(dev, "Attempting to send a large packet (%d bytes)\n",
8275346ebf6SJeff Kirsher 			  length);
8285346ebf6SJeff Kirsher 	    return NETDEV_TX_BUSY;
8295346ebf6SJeff Kirsher 	}
8305346ebf6SJeff Kirsher 
8315346ebf6SJeff Kirsher 	netdev_dbg(dev, "Transmitting a packet of length %lu\n",
8325346ebf6SJeff Kirsher 		   (unsigned long)skb->len);
8335346ebf6SJeff Kirsher 	dev->stats.tx_bytes += skb->len;
8345346ebf6SJeff Kirsher 
8355346ebf6SJeff Kirsher 	/* Disable both interrupts. */
8365346ebf6SJeff Kirsher 	outw(0x0000, ioaddr + TX_INTR);
8375346ebf6SJeff Kirsher 
8385346ebf6SJeff Kirsher 	/* wait for a while */
8395346ebf6SJeff Kirsher 	udelay(1);
8405346ebf6SJeff Kirsher 
8415346ebf6SJeff Kirsher 	outw(length, ioaddr + DATAPORT);
8425346ebf6SJeff Kirsher 	outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
8435346ebf6SJeff Kirsher 
8445346ebf6SJeff Kirsher 	lp->tx_queue++;
8455346ebf6SJeff Kirsher 	lp->tx_queue_len += ((length+3) & ~1);
8465346ebf6SJeff Kirsher 
8475346ebf6SJeff Kirsher 	if (lp->tx_started == 0) {
8485346ebf6SJeff Kirsher 	    /* If the Tx is idle, always trigger a transmit. */
8495346ebf6SJeff Kirsher 	    outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
8505346ebf6SJeff Kirsher 	    lp->sent = lp->tx_queue ;
8515346ebf6SJeff Kirsher 	    lp->tx_queue = 0;
8525346ebf6SJeff Kirsher 	    lp->tx_queue_len = 0;
8535346ebf6SJeff Kirsher 	    lp->tx_started = 1;
8545346ebf6SJeff Kirsher 	    netif_start_queue(dev);
8555346ebf6SJeff Kirsher 	} else {
8565346ebf6SJeff Kirsher 	    if( sram_config == 0 ) {
8575346ebf6SJeff Kirsher 		if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
8585346ebf6SJeff Kirsher 		    /* Yes, there is room for one more packet. */
8595346ebf6SJeff Kirsher 		    netif_start_queue(dev);
8605346ebf6SJeff Kirsher 	    } else {
8615346ebf6SJeff Kirsher 		if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) &&
8625346ebf6SJeff Kirsher 						lp->tx_queue < 127 )
8635346ebf6SJeff Kirsher 		    /* Yes, there is room for one more packet. */
8645346ebf6SJeff Kirsher 		    netif_start_queue(dev);
8655346ebf6SJeff Kirsher 	    }
8665346ebf6SJeff Kirsher 	}
8675346ebf6SJeff Kirsher 
8685346ebf6SJeff Kirsher 	/* Re-enable interrupts */
8695346ebf6SJeff Kirsher 	outb(D_TX_INTR, ioaddr + TX_INTR);
8705346ebf6SJeff Kirsher 	outb(D_RX_INTR, ioaddr + RX_INTR);
8715346ebf6SJeff Kirsher     }
8725346ebf6SJeff Kirsher     dev_kfree_skb (skb);
8735346ebf6SJeff Kirsher 
8745346ebf6SJeff Kirsher     return NETDEV_TX_OK;
8755346ebf6SJeff Kirsher } /* fjn_start_xmit */
8765346ebf6SJeff Kirsher 
8775346ebf6SJeff Kirsher /*====================================================================*/
8785346ebf6SJeff Kirsher 
fjn_reset(struct net_device * dev)8795346ebf6SJeff Kirsher static void fjn_reset(struct net_device *dev)
8805346ebf6SJeff Kirsher {
881f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
8825346ebf6SJeff Kirsher     unsigned int ioaddr = dev->base_addr;
8835346ebf6SJeff Kirsher     int i;
8845346ebf6SJeff Kirsher 
8855346ebf6SJeff Kirsher     netdev_dbg(dev, "fjn_reset() called\n");
8865346ebf6SJeff Kirsher 
8875346ebf6SJeff Kirsher     /* Reset controller */
8885346ebf6SJeff Kirsher     if( sram_config == 0 )
8895346ebf6SJeff Kirsher 	outb(CONFIG0_RST, ioaddr + CONFIG_0);
8905346ebf6SJeff Kirsher     else
8915346ebf6SJeff Kirsher 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
8925346ebf6SJeff Kirsher 
8935346ebf6SJeff Kirsher     /* Power On chip and select bank 0 */
8945346ebf6SJeff Kirsher     if (lp->cardtype == MBH10302)
8955346ebf6SJeff Kirsher 	outb(BANK_0, ioaddr + CONFIG_1);
8965346ebf6SJeff Kirsher     else
8975346ebf6SJeff Kirsher 	outb(BANK_0U, ioaddr + CONFIG_1);
8985346ebf6SJeff Kirsher 
8995346ebf6SJeff Kirsher     /* Set Tx modes */
9005346ebf6SJeff Kirsher     outb(D_TX_MODE, ioaddr + TX_MODE);
9015346ebf6SJeff Kirsher     /* set Rx modes */
9025346ebf6SJeff Kirsher     outb(ID_MATCHED, ioaddr + RX_MODE);
9035346ebf6SJeff Kirsher 
9045346ebf6SJeff Kirsher     /* Set hardware address */
9055346ebf6SJeff Kirsher     for (i = 0; i < 6; i++)
9065346ebf6SJeff Kirsher         outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
9075346ebf6SJeff Kirsher 
9085346ebf6SJeff Kirsher     /* (re)initialize the multicast table */
9095346ebf6SJeff Kirsher     set_rx_mode(dev);
9105346ebf6SJeff Kirsher 
9115346ebf6SJeff Kirsher     /* Switch to bank 2 (runtime mode) */
9125346ebf6SJeff Kirsher     if (lp->cardtype == MBH10302)
9135346ebf6SJeff Kirsher 	outb(BANK_2, ioaddr + CONFIG_1);
9145346ebf6SJeff Kirsher     else
9155346ebf6SJeff Kirsher 	outb(BANK_2U, ioaddr + CONFIG_1);
9165346ebf6SJeff Kirsher 
9175346ebf6SJeff Kirsher     /* set 16col ctrl bits */
9185346ebf6SJeff Kirsher     if( lp->cardtype == TDK || lp->cardtype == CONTEC)
9195346ebf6SJeff Kirsher         outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
9205346ebf6SJeff Kirsher     else
9215346ebf6SJeff Kirsher         outb(AUTO_MODE, ioaddr + COL_CTRL);
9225346ebf6SJeff Kirsher 
9235346ebf6SJeff Kirsher     /* clear Reserved Regs */
9245346ebf6SJeff Kirsher     outb(0x00, ioaddr + BMPR12);
9255346ebf6SJeff Kirsher     outb(0x00, ioaddr + BMPR13);
9265346ebf6SJeff Kirsher 
9275346ebf6SJeff Kirsher     /* reset Skip packet reg. */
9285346ebf6SJeff Kirsher     outb(0x01, ioaddr + RX_SKIP);
9295346ebf6SJeff Kirsher 
9305346ebf6SJeff Kirsher     /* Enable Tx and Rx */
9315346ebf6SJeff Kirsher     if( sram_config == 0 )
9325346ebf6SJeff Kirsher 	outb(CONFIG0_DFL, ioaddr + CONFIG_0);
9335346ebf6SJeff Kirsher     else
9345346ebf6SJeff Kirsher 	outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
9355346ebf6SJeff Kirsher 
9365346ebf6SJeff Kirsher     /* Init receive pointer ? */
9375346ebf6SJeff Kirsher     inw(ioaddr + DATAPORT);
9385346ebf6SJeff Kirsher     inw(ioaddr + DATAPORT);
9395346ebf6SJeff Kirsher 
9405346ebf6SJeff Kirsher     /* Clear all status */
9415346ebf6SJeff Kirsher     outb(0xff, ioaddr + TX_STATUS);
9425346ebf6SJeff Kirsher     outb(0xff, ioaddr + RX_STATUS);
9435346ebf6SJeff Kirsher 
9445346ebf6SJeff Kirsher     if (lp->cardtype == MBH10302)
9455346ebf6SJeff Kirsher 	outb(INTR_OFF, ioaddr + LAN_CTRL);
9465346ebf6SJeff Kirsher 
9475346ebf6SJeff Kirsher     /* Turn on Rx interrupts */
9485346ebf6SJeff Kirsher     outb(D_TX_INTR, ioaddr + TX_INTR);
9495346ebf6SJeff Kirsher     outb(D_RX_INTR, ioaddr + RX_INTR);
9505346ebf6SJeff Kirsher 
9515346ebf6SJeff Kirsher     /* Turn on interrupts from LAN card controller */
9525346ebf6SJeff Kirsher     if (lp->cardtype == MBH10302)
9535346ebf6SJeff Kirsher 	outb(INTR_ON, ioaddr + LAN_CTRL);
9545346ebf6SJeff Kirsher } /* fjn_reset */
9555346ebf6SJeff Kirsher 
9565346ebf6SJeff Kirsher /*====================================================================*/
9575346ebf6SJeff Kirsher 
fjn_rx(struct net_device * dev)9585346ebf6SJeff Kirsher static void fjn_rx(struct net_device *dev)
9595346ebf6SJeff Kirsher {
9605346ebf6SJeff Kirsher     unsigned int ioaddr = dev->base_addr;
9615346ebf6SJeff Kirsher     int boguscount = 10;	/* 5 -> 10: by agy 19940922 */
9625346ebf6SJeff Kirsher 
9635346ebf6SJeff Kirsher     pr_debug("%s: in rx_packet(), rx_status %02x.\n",
9645346ebf6SJeff Kirsher 	  dev->name, inb(ioaddr + RX_STATUS));
9655346ebf6SJeff Kirsher 
9665346ebf6SJeff Kirsher     while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
9675346ebf6SJeff Kirsher 	u_short status = inw(ioaddr + DATAPORT);
9685346ebf6SJeff Kirsher 
9695346ebf6SJeff Kirsher 	netdev_dbg(dev, "Rxing packet mode %02x status %04x.\n",
9705346ebf6SJeff Kirsher 		   inb(ioaddr + RX_MODE), status);
9715346ebf6SJeff Kirsher #ifndef final_version
9725346ebf6SJeff Kirsher 	if (status == 0) {
9735346ebf6SJeff Kirsher 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
9745346ebf6SJeff Kirsher 	    break;
9755346ebf6SJeff Kirsher 	}
9765346ebf6SJeff Kirsher #endif
9775346ebf6SJeff Kirsher 	if ((status & 0xF0) != 0x20) {	/* There was an error. */
9785346ebf6SJeff Kirsher 	    dev->stats.rx_errors++;
9795346ebf6SJeff Kirsher 	    if (status & F_LEN_ERR) dev->stats.rx_length_errors++;
9805346ebf6SJeff Kirsher 	    if (status & F_ALG_ERR) dev->stats.rx_frame_errors++;
9815346ebf6SJeff Kirsher 	    if (status & F_CRC_ERR) dev->stats.rx_crc_errors++;
9825346ebf6SJeff Kirsher 	    if (status & F_OVR_FLO) dev->stats.rx_over_errors++;
9835346ebf6SJeff Kirsher 	} else {
9845346ebf6SJeff Kirsher 	    u_short pkt_len = inw(ioaddr + DATAPORT);
9855346ebf6SJeff Kirsher 	    /* Malloc up new buffer. */
9865346ebf6SJeff Kirsher 	    struct sk_buff *skb;
9875346ebf6SJeff Kirsher 
9885346ebf6SJeff Kirsher 	    if (pkt_len > 1550) {
9895346ebf6SJeff Kirsher 		netdev_notice(dev, "The FMV-18x claimed a very large packet, size %d\n",
9905346ebf6SJeff Kirsher 			      pkt_len);
9915346ebf6SJeff Kirsher 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
9925346ebf6SJeff Kirsher 		dev->stats.rx_errors++;
9935346ebf6SJeff Kirsher 		break;
9945346ebf6SJeff Kirsher 	    }
995c056b734SPradeep A Dalvi 	    skb = netdev_alloc_skb(dev, pkt_len + 2);
9965346ebf6SJeff Kirsher 	    if (skb == NULL) {
9975346ebf6SJeff Kirsher 		outb(F_SKP_PKT, ioaddr + RX_SKIP);
9985346ebf6SJeff Kirsher 		dev->stats.rx_dropped++;
9995346ebf6SJeff Kirsher 		break;
10005346ebf6SJeff Kirsher 	    }
10015346ebf6SJeff Kirsher 
10025346ebf6SJeff Kirsher 	    skb_reserve(skb, 2);
10035346ebf6SJeff Kirsher 	    insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
10045346ebf6SJeff Kirsher 		 (pkt_len + 1) >> 1);
10055346ebf6SJeff Kirsher 	    skb->protocol = eth_type_trans(skb, dev);
10065346ebf6SJeff Kirsher 
10075346ebf6SJeff Kirsher 	    {
10085346ebf6SJeff Kirsher 		int i;
10095346ebf6SJeff Kirsher 		pr_debug("%s: Rxed packet of length %d: ",
10105346ebf6SJeff Kirsher 			dev->name, pkt_len);
10115346ebf6SJeff Kirsher 		for (i = 0; i < 14; i++)
10125346ebf6SJeff Kirsher 			pr_debug(" %02x", skb->data[i]);
10135346ebf6SJeff Kirsher 		pr_debug(".\n");
10145346ebf6SJeff Kirsher 	    }
10155346ebf6SJeff Kirsher 
10165346ebf6SJeff Kirsher 	    netif_rx(skb);
10175346ebf6SJeff Kirsher 	    dev->stats.rx_packets++;
10185346ebf6SJeff Kirsher 	    dev->stats.rx_bytes += pkt_len;
10195346ebf6SJeff Kirsher 	}
10205346ebf6SJeff Kirsher 	if (--boguscount <= 0)
10215346ebf6SJeff Kirsher 	    break;
10225346ebf6SJeff Kirsher     }
10235346ebf6SJeff Kirsher 
10245346ebf6SJeff Kirsher     /* If any worth-while packets have been received, dev_rint()
10255346ebf6SJeff Kirsher 	   has done a netif_wake_queue() for us and will work on them
10265346ebf6SJeff Kirsher 	   when we get to the bottom-half routine. */
10275346ebf6SJeff Kirsher /*
10285346ebf6SJeff Kirsher     if (lp->cardtype != TDK) {
10295346ebf6SJeff Kirsher 	int i;
10305346ebf6SJeff Kirsher 	for (i = 0; i < 20; i++) {
10315346ebf6SJeff Kirsher 	    if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
10325346ebf6SJeff Kirsher 		break;
10335346ebf6SJeff Kirsher 	    (void)inw(ioaddr + DATAPORT);  /+ dummy status read +/
10345346ebf6SJeff Kirsher 	    outb(F_SKP_PKT, ioaddr + RX_SKIP);
10355346ebf6SJeff Kirsher 	}
10365346ebf6SJeff Kirsher 
10375346ebf6SJeff Kirsher 	if (i > 0)
10385346ebf6SJeff Kirsher 	    pr_debug("%s: Exint Rx packet with mode %02x after "
10395346ebf6SJeff Kirsher 		  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
10405346ebf6SJeff Kirsher     }
10415346ebf6SJeff Kirsher */
10425346ebf6SJeff Kirsher } /* fjn_rx */
10435346ebf6SJeff Kirsher 
10445346ebf6SJeff Kirsher /*====================================================================*/
10455346ebf6SJeff Kirsher 
netdev_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)10465346ebf6SJeff Kirsher static void netdev_get_drvinfo(struct net_device *dev,
10475346ebf6SJeff Kirsher 			       struct ethtool_drvinfo *info)
10485346ebf6SJeff Kirsher {
1049*f029c781SWolfram Sang 	strscpy(info->driver, DRV_NAME, sizeof(info->driver));
1050*f029c781SWolfram Sang 	strscpy(info->version, DRV_VERSION, sizeof(info->version));
105133a5ba14SRick Jones 	snprintf(info->bus_info, sizeof(info->bus_info),
105233a5ba14SRick Jones 		"PCMCIA 0x%lx", dev->base_addr);
10535346ebf6SJeff Kirsher }
10545346ebf6SJeff Kirsher 
10555346ebf6SJeff Kirsher static const struct ethtool_ops netdev_ethtool_ops = {
10565346ebf6SJeff Kirsher 	.get_drvinfo		= netdev_get_drvinfo,
10575346ebf6SJeff Kirsher };
10585346ebf6SJeff Kirsher 
fjn_config(struct net_device * dev,struct ifmap * map)10595346ebf6SJeff Kirsher static int fjn_config(struct net_device *dev, struct ifmap *map){
10605346ebf6SJeff Kirsher     return 0;
10615346ebf6SJeff Kirsher }
10625346ebf6SJeff Kirsher 
fjn_open(struct net_device * dev)10635346ebf6SJeff Kirsher static int fjn_open(struct net_device *dev)
10645346ebf6SJeff Kirsher {
1065f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
10665346ebf6SJeff Kirsher     struct pcmcia_device *link = lp->p_dev;
10675346ebf6SJeff Kirsher 
10685346ebf6SJeff Kirsher     pr_debug("fjn_open('%s').\n", dev->name);
10695346ebf6SJeff Kirsher 
10705346ebf6SJeff Kirsher     if (!pcmcia_dev_present(link))
10715346ebf6SJeff Kirsher 	return -ENODEV;
10725346ebf6SJeff Kirsher 
10735346ebf6SJeff Kirsher     link->open++;
10745346ebf6SJeff Kirsher 
10755346ebf6SJeff Kirsher     fjn_reset(dev);
10765346ebf6SJeff Kirsher 
10775346ebf6SJeff Kirsher     lp->tx_started = 0;
10785346ebf6SJeff Kirsher     lp->tx_queue = 0;
10795346ebf6SJeff Kirsher     lp->tx_queue_len = 0;
10805346ebf6SJeff Kirsher     lp->open_time = jiffies;
10815346ebf6SJeff Kirsher     netif_start_queue(dev);
10825346ebf6SJeff Kirsher 
10835346ebf6SJeff Kirsher     return 0;
10845346ebf6SJeff Kirsher } /* fjn_open */
10855346ebf6SJeff Kirsher 
10865346ebf6SJeff Kirsher /*====================================================================*/
10875346ebf6SJeff Kirsher 
fjn_close(struct net_device * dev)10885346ebf6SJeff Kirsher static int fjn_close(struct net_device *dev)
10895346ebf6SJeff Kirsher {
1090f073d52dSHimangi Saraogi     struct local_info *lp = netdev_priv(dev);
10915346ebf6SJeff Kirsher     struct pcmcia_device *link = lp->p_dev;
10925346ebf6SJeff Kirsher     unsigned int ioaddr = dev->base_addr;
10935346ebf6SJeff Kirsher 
10945346ebf6SJeff Kirsher     pr_debug("fjn_close('%s').\n", dev->name);
10955346ebf6SJeff Kirsher 
10965346ebf6SJeff Kirsher     lp->open_time = 0;
10975346ebf6SJeff Kirsher     netif_stop_queue(dev);
10985346ebf6SJeff Kirsher 
10995346ebf6SJeff Kirsher     /* Set configuration register 0 to disable Tx and Rx. */
11005346ebf6SJeff Kirsher     if( sram_config == 0 )
11015346ebf6SJeff Kirsher 	outb(CONFIG0_RST ,ioaddr + CONFIG_0);
11025346ebf6SJeff Kirsher     else
11035346ebf6SJeff Kirsher 	outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
11045346ebf6SJeff Kirsher 
11055346ebf6SJeff Kirsher     /* Update the statistics -- ToDo. */
11065346ebf6SJeff Kirsher 
11075346ebf6SJeff Kirsher     /* Power-down the chip.  Green, green, green! */
11085346ebf6SJeff Kirsher     outb(CHIP_OFF ,ioaddr + CONFIG_1);
11095346ebf6SJeff Kirsher 
11105346ebf6SJeff Kirsher     /* Set the ethernet adaptor disable IRQ */
11115346ebf6SJeff Kirsher     if (lp->cardtype == MBH10302)
11125346ebf6SJeff Kirsher 	outb(INTR_OFF, ioaddr + LAN_CTRL);
11135346ebf6SJeff Kirsher 
11145346ebf6SJeff Kirsher     link->open--;
11155346ebf6SJeff Kirsher 
11165346ebf6SJeff Kirsher     return 0;
11175346ebf6SJeff Kirsher } /* fjn_close */
11185346ebf6SJeff Kirsher 
11195346ebf6SJeff Kirsher /*====================================================================*/
11205346ebf6SJeff Kirsher 
11215346ebf6SJeff Kirsher /*
11225346ebf6SJeff Kirsher   Set the multicast/promiscuous mode for this adaptor.
11235346ebf6SJeff Kirsher */
11245346ebf6SJeff Kirsher 
set_rx_mode(struct net_device * dev)11255346ebf6SJeff Kirsher static void set_rx_mode(struct net_device *dev)
11265346ebf6SJeff Kirsher {
11275346ebf6SJeff Kirsher     unsigned int ioaddr = dev->base_addr;
11285346ebf6SJeff Kirsher     u_char mc_filter[8];		 /* Multicast hash filter */
11295346ebf6SJeff Kirsher     u_long flags;
11305346ebf6SJeff Kirsher     int i;
11315346ebf6SJeff Kirsher 
11325346ebf6SJeff Kirsher     int saved_bank;
11335346ebf6SJeff Kirsher     int saved_config_0 = inb(ioaddr + CONFIG_0);
11345346ebf6SJeff Kirsher 
11355346ebf6SJeff Kirsher     local_irq_save(flags);
11365346ebf6SJeff Kirsher 
11375346ebf6SJeff Kirsher     /* Disable Tx and Rx */
11385346ebf6SJeff Kirsher     if (sram_config == 0)
11395346ebf6SJeff Kirsher 	outb(CONFIG0_RST, ioaddr + CONFIG_0);
11405346ebf6SJeff Kirsher     else
11415346ebf6SJeff Kirsher 	outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
11425346ebf6SJeff Kirsher 
11435346ebf6SJeff Kirsher     if (dev->flags & IFF_PROMISC) {
11445346ebf6SJeff Kirsher 	memset(mc_filter, 0xff, sizeof(mc_filter));
11455346ebf6SJeff Kirsher 	outb(3, ioaddr + RX_MODE);	/* Enable promiscuous mode */
11465346ebf6SJeff Kirsher     } else if (netdev_mc_count(dev) > MC_FILTERBREAK ||
11475346ebf6SJeff Kirsher 	       (dev->flags & IFF_ALLMULTI)) {
11485346ebf6SJeff Kirsher 	/* Too many to filter perfectly -- accept all multicasts. */
11495346ebf6SJeff Kirsher 	memset(mc_filter, 0xff, sizeof(mc_filter));
11505346ebf6SJeff Kirsher 	outb(2, ioaddr + RX_MODE);	/* Use normal mode. */
11515346ebf6SJeff Kirsher     } else if (netdev_mc_empty(dev)) {
11525346ebf6SJeff Kirsher 	memset(mc_filter, 0x00, sizeof(mc_filter));
11535346ebf6SJeff Kirsher 	outb(1, ioaddr + RX_MODE);	/* Ignore almost all multicasts. */
11545346ebf6SJeff Kirsher     } else {
11555346ebf6SJeff Kirsher 	struct netdev_hw_addr *ha;
11565346ebf6SJeff Kirsher 
11575346ebf6SJeff Kirsher 	memset(mc_filter, 0, sizeof(mc_filter));
11585346ebf6SJeff Kirsher 	netdev_for_each_mc_addr(ha, dev) {
11595346ebf6SJeff Kirsher 	    unsigned int bit = ether_crc_le(ETH_ALEN, ha->addr) >> 26;
11605346ebf6SJeff Kirsher 	    mc_filter[bit >> 3] |= (1 << (bit & 7));
11615346ebf6SJeff Kirsher 	}
11625346ebf6SJeff Kirsher 	outb(2, ioaddr + RX_MODE);	/* Use normal mode. */
11635346ebf6SJeff Kirsher     }
11645346ebf6SJeff Kirsher 
11655346ebf6SJeff Kirsher     /* Switch to bank 1 and set the multicast table. */
11665346ebf6SJeff Kirsher     saved_bank = inb(ioaddr + CONFIG_1);
11675346ebf6SJeff Kirsher     outb(0xe4, ioaddr + CONFIG_1);
11685346ebf6SJeff Kirsher 
11695346ebf6SJeff Kirsher     for (i = 0; i < 8; i++)
11705346ebf6SJeff Kirsher 	outb(mc_filter[i], ioaddr + MAR_ADR + i);
11715346ebf6SJeff Kirsher     outb(saved_bank, ioaddr + CONFIG_1);
11725346ebf6SJeff Kirsher 
11735346ebf6SJeff Kirsher     outb(saved_config_0, ioaddr + CONFIG_0);
11745346ebf6SJeff Kirsher 
11755346ebf6SJeff Kirsher     local_irq_restore(flags);
11765346ebf6SJeff Kirsher }
1177