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