Annotation of Gnu-Mach/linux/pcmcia-cs/clients/fmvj18x_cs.c, revision 1.1

1.1     ! root        1: /*======================================================================
        !             2:     fmvj18x_cs.c 2.8 2002/03/23
        !             3: 
        !             4:     A fmvj18x (and its compatibles) PCMCIA client driver
        !             5: 
        !             6:     Contributed by Shingo Fujimoto, [email protected]
        !             7: 
        !             8:     TDK LAK-CD021 and CONTEC C-NET(PC)C support added by 
        !             9:     Nobuhiro Katayama, [email protected]
        !            10: 
        !            11:     The PCMCIA client code is based on code written by David Hinds.
        !            12:     Network code is based on the "FMV-18x driver" by Yutaka TAMIYA
        !            13:     but is actually largely Donald Becker's AT1700 driver, which
        !            14:     carries the following attribution:
        !            15: 
        !            16:     Written 1993-94 by Donald Becker.
        !            17: 
        !            18:     Copyright 1993 United States Government as represented by the
        !            19:     Director, National Security Agency.
        !            20:     
        !            21:     This software may be used and distributed according to the terms
        !            22:     of the GNU General Public License, incorporated herein by reference.
        !            23:     
        !            24:     The author may be reached as [email protected], or C/O
        !            25:     Scyld Computing Corporation
        !            26:     410 Severn Ave., Suite 210
        !            27:     Annapolis MD 21403
        !            28:    
        !            29: ======================================================================*/
        !            30: 
        !            31: #include <linux/module.h>
        !            32: #include <linux/kernel.h>
        !            33: #include <linux/init.h>
        !            34: #include <linux/sched.h>
        !            35: #include <linux/ptrace.h>
        !            36: #include <linux/slab.h>
        !            37: #include <linux/string.h>
        !            38: #include <linux/timer.h>
        !            39: #include <linux/interrupt.h>
        !            40: #include <linux/in.h>
        !            41: #include <linux/delay.h>
        !            42: #include <asm/io.h>
        !            43: #include <asm/system.h>
        !            44: 
        !            45: #include <linux/netdevice.h>
        !            46: #include <linux/etherdevice.h>
        !            47: #include <linux/skbuff.h>
        !            48: #include <linux/if_arp.h>
        !            49: #include <linux/ioport.h>
        !            50: #include <linux/crc32.h>
        !            51: 
        !            52: #include <pcmcia/version.h>
        !            53: #include <pcmcia/cs_types.h>
        !            54: #include <pcmcia/cs.h>
        !            55: #include <pcmcia/cistpl.h>
        !            56: #include <pcmcia/ciscode.h>
        !            57: #include <pcmcia/ds.h>
        !            58: 
        !            59: /*====================================================================*/
        !            60: 
        !            61: /* Module parameters */
        !            62: 
        !            63: MODULE_DESCRIPTION("fmvj18x and compatible PCMCIA ethernet driver");
        !            64: MODULE_LICENSE("GPL");
        !            65: 
        !            66: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
        !            67: 
        !            68: /* Bit map of interrupts to choose from */
        !            69: /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
        !            70: INT_MODULE_PARM(irq_mask, 0xdeb8);
        !            71: static int irq_list[4] = { -1 };
        !            72: MODULE_PARM(irq_list, "1-4i");
        !            73: 
        !            74: /* SRAM configuration */
        !            75: /* 0:4KB*2 TX buffer   else:8KB*2 TX buffer */
        !            76: INT_MODULE_PARM(sram_config, 0);
        !            77: 
        !            78: #ifdef PCMCIA_DEBUG
        !            79: INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
        !            80: #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
        !            81: static char *version = "fmvj18x_cs.c 2.8 2002/03/23";
        !            82: #else
        !            83: #define DEBUG(n, args...)
        !            84: #endif
        !            85: 
        !            86: /*====================================================================*/
        !            87: /*
        !            88:     PCMCIA event handlers
        !            89:  */
        !            90: static void fmvj18x_config(dev_link_t *link);
        !            91: static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id);
        !            92: static int fmvj18x_setup_mfc(dev_link_t *link);
        !            93: static void fmvj18x_release(u_long arg);
        !            94: static int fmvj18x_event(event_t event, int priority,
        !            95:                          event_callback_args_t *args);
        !            96: static dev_link_t *fmvj18x_attach(void);
        !            97: static void fmvj18x_detach(dev_link_t *);
        !            98: 
        !            99: /*
        !           100:     LAN controller(MBH86960A) specific routines
        !           101:  */
        !           102: static int fjn_config(struct net_device *dev, struct ifmap *map);
        !           103: static int fjn_open(struct net_device *dev);
        !           104: static int fjn_close(struct net_device *dev);
        !           105: static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev);
        !           106: static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           107: static void fjn_rx(struct net_device *dev);
        !           108: static void fjn_reset(struct net_device *dev);
        !           109: static struct net_device_stats *fjn_get_stats(struct net_device *dev);
        !           110: static void set_rx_mode(struct net_device *dev);
        !           111: static void fjn_tx_timeout(struct net_device *dev);
        !           112: 
        !           113: static dev_info_t dev_info = "fmvj18x_cs";
        !           114: static dev_link_t *dev_list;
        !           115: 
        !           116: /*
        !           117:     card type
        !           118:  */
        !           119: typedef enum { MBH10302, MBH10304, TDK, CONTEC, LA501, UNGERMANN, 
        !           120:               XXX10304
        !           121: } cardtype_t;
        !           122: 
        !           123: /*
        !           124:     driver specific data structure
        !           125: */
        !           126: typedef struct local_info_t {
        !           127:     dev_link_t link;
        !           128:     struct net_device dev;
        !           129:     dev_node_t node;
        !           130:     struct net_device_stats stats;
        !           131:     long open_time;
        !           132:     uint tx_started:1;
        !           133:     uint tx_queue;
        !           134:     u_short tx_queue_len;
        !           135:     cardtype_t cardtype;
        !           136:     u_short sent;
        !           137:     u_char mc_filter[8];
        !           138: } local_info_t;
        !           139: 
        !           140: #define MC_FILTERBREAK 64
        !           141: 
        !           142: /*====================================================================*/
        !           143: /* 
        !           144:     ioport offset from the base address 
        !           145:  */
        !           146: #define TX_STATUS               0 /* transmit status register */
        !           147: #define RX_STATUS               1 /* receive status register */
        !           148: #define TX_INTR                 2 /* transmit interrupt mask register */
        !           149: #define RX_INTR                 3 /* receive interrupt mask register */
        !           150: #define TX_MODE                 4 /* transmit mode register */
        !           151: #define RX_MODE                 5 /* receive mode register */
        !           152: #define CONFIG_0                6 /* configuration register 0 */
        !           153: #define CONFIG_1                7 /* configuration register 1 */
        !           154: 
        !           155: #define NODE_ID                 8 /* node ID register            (bank 0) */
        !           156: #define MAR_ADR                 8 /* multicast address registers (bank 1) */
        !           157: 
        !           158: #define DATAPORT                8 /* buffer mem port registers   (bank 2) */
        !           159: #define TX_START               10 /* transmit start register */
        !           160: #define COL_CTRL               11 /* 16 collision control register */
        !           161: #define BMPR12                 12 /* reserved */
        !           162: #define BMPR13                 13 /* reserved */
        !           163: #define RX_SKIP                14 /* skip received packet register */
        !           164: 
        !           165: #define LAN_CTRL               16 /* LAN card control register */
        !           166: 
        !           167: #define MAC_ID               0x1a /* hardware address */
        !           168: #define UNGERMANN_MAC_ID     0x18 /* UNGERMANN-BASS hardware address */
        !           169: 
        !           170: /* 
        !           171:     control bits 
        !           172:  */
        !           173: #define ENA_TMT_OK           0x80
        !           174: #define ENA_TMT_REC          0x20
        !           175: #define ENA_COL              0x04
        !           176: #define ENA_16_COL           0x02
        !           177: #define ENA_TBUS_ERR         0x01
        !           178: 
        !           179: #define ENA_PKT_RDY          0x80
        !           180: #define ENA_BUS_ERR          0x40
        !           181: #define ENA_LEN_ERR          0x08
        !           182: #define ENA_ALG_ERR          0x04
        !           183: #define ENA_CRC_ERR          0x02
        !           184: #define ENA_OVR_FLO          0x01
        !           185: 
        !           186: /* flags */
        !           187: #define F_TMT_RDY            0x80 /* can accept new packet */
        !           188: #define F_NET_BSY            0x40 /* carrier is detected */
        !           189: #define F_TMT_OK             0x20 /* send packet successfully */
        !           190: #define F_SRT_PKT            0x10 /* short packet error */
        !           191: #define F_COL_ERR            0x04 /* collision error */
        !           192: #define F_16_COL             0x02 /* 16 collision error */
        !           193: #define F_TBUS_ERR           0x01 /* bus read error */
        !           194: 
        !           195: #define F_PKT_RDY            0x80 /* packet(s) in buffer */
        !           196: #define F_BUS_ERR            0x40 /* bus read error */
        !           197: #define F_LEN_ERR            0x08 /* short packet */
        !           198: #define F_ALG_ERR            0x04 /* frame error */
        !           199: #define F_CRC_ERR            0x02 /* CRC error */
        !           200: #define F_OVR_FLO            0x01 /* overflow error */
        !           201: 
        !           202: #define F_BUF_EMP            0x40 /* receive buffer is empty */
        !           203: 
        !           204: #define F_SKP_PKT            0x05 /* drop packet in buffer */
        !           205: 
        !           206: /* default bitmaps */
        !           207: #define D_TX_INTR  ( ENA_TMT_OK )
        !           208: #define D_RX_INTR  ( ENA_PKT_RDY | ENA_LEN_ERR \
        !           209:                   | ENA_ALG_ERR | ENA_CRC_ERR | ENA_OVR_FLO )
        !           210: #define TX_STAT_M  ( F_TMT_RDY )
        !           211: #define RX_STAT_M  ( F_PKT_RDY | F_LEN_ERR \
        !           212:                    | F_ALG_ERR | F_CRC_ERR | F_OVR_FLO )
        !           213: 
        !           214: /* commands */
        !           215: #define D_TX_MODE            0x06 /* no tests, detect carrier */
        !           216: #define ID_MATCHED           0x02 /* (RX_MODE) */
        !           217: #define RECV_ALL             0x03 /* (RX_MODE) */
        !           218: #define CONFIG0_DFL          0x5a /* 16bit bus, 4K x 2 Tx queues */
        !           219: #define CONFIG0_DFL_1        0x5e /* 16bit bus, 8K x 2 Tx queues */
        !           220: #define CONFIG0_RST          0xda /* Data Link Controller off (CONFIG_0) */
        !           221: #define CONFIG0_RST_1        0xde /* Data Link Controller off (CONFIG_0) */
        !           222: #define BANK_0               0xa0 /* bank 0 (CONFIG_1) */
        !           223: #define BANK_1               0xa4 /* bank 1 (CONFIG_1) */
        !           224: #define BANK_2               0xa8 /* bank 2 (CONFIG_1) */
        !           225: #define CHIP_OFF             0x80 /* contrl chip power off (CONFIG_1) */
        !           226: #define DO_TX                0x80 /* do transmit packet */
        !           227: #define SEND_PKT             0x81 /* send a packet */
        !           228: #define AUTO_MODE            0x07 /* Auto skip packet on 16 col detected */
        !           229: #define MANU_MODE            0x03 /* Stop and skip packet on 16 col */
        !           230: #define TDK_AUTO_MODE        0x47 /* Auto skip packet on 16 col detected */
        !           231: #define TDK_MANU_MODE        0x43 /* Stop and skip packet on 16 col */
        !           232: #define INTR_OFF             0x0d /* LAN controller ignores interrupts */
        !           233: #define INTR_ON              0x1d /* LAN controller will catch interrupts */
        !           234: 
        !           235: #define TX_TIMEOUT             ((400*HZ)/1000)
        !           236: 
        !           237: #define BANK_0U              0x20 /* bank 0 (CONFIG_1) */
        !           238: #define BANK_1U              0x24 /* bank 1 (CONFIG_1) */
        !           239: #define BANK_2U              0x28 /* bank 2 (CONFIG_1) */
        !           240: 
        !           241: /*======================================================================
        !           242: 
        !           243:     This bit of code is used to avoid unregistering network devices
        !           244:     at inappropriate times.  2.2 and later kernels are fairly picky
        !           245:     about when this can happen.
        !           246:     
        !           247: ======================================================================*/
        !           248: 
        !           249: static void flush_stale_links(void)
        !           250: {
        !           251:     dev_link_t *link, *next;
        !           252:     for (link = dev_list; link; link = next) {
        !           253:        next = link->next;
        !           254:        if (link->state & DEV_STALE_LINK)
        !           255:            fmvj18x_detach(link);
        !           256:     }
        !           257: }
        !           258: 
        !           259: /*====================================================================*/
        !           260: 
        !           261: static void cs_error(client_handle_t handle, int func, int ret)
        !           262: {
        !           263:     error_info_t err = { func, ret };
        !           264:     CardServices(ReportError, handle, &err);
        !           265: }
        !           266: 
        !           267: /*====================================================================*/
        !           268: 
        !           269: static dev_link_t *fmvj18x_attach(void)
        !           270: {
        !           271:     local_info_t *lp;
        !           272:     dev_link_t *link;
        !           273:     struct net_device *dev;
        !           274:     client_reg_t client_reg;
        !           275:     int i, ret;
        !           276:     
        !           277:     DEBUG(0, "fmvj18x_attach()\n");
        !           278:     flush_stale_links();
        !           279: 
        !           280:     /* Make up a FMVJ18x specific data structure */
        !           281:     lp = kmalloc(sizeof(*lp), GFP_KERNEL);
        !           282:     if (!lp) return NULL;
        !           283:     memset(lp, 0, sizeof(*lp));
        !           284:     link = &lp->link; dev = &lp->dev;
        !           285:     link->priv = dev->priv = link->irq.Instance = lp;
        !           286: 
        !           287:     init_timer(&link->release);
        !           288:     link->release.function = &fmvj18x_release;
        !           289:     link->release.data = (u_long)link;
        !           290: 
        !           291:     /* The io structure describes IO port mapping */
        !           292:     link->io.NumPorts1 = 32;
        !           293:     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
        !           294:     link->io.IOAddrLines = 5;
        !           295: 
        !           296:     /* Interrupt setup */
        !           297:     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
        !           298:     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
        !           299:     if (irq_list[0] == -1)
        !           300:        link->irq.IRQInfo2 = irq_mask;
        !           301:     else
        !           302:        for (i = 0; i < 4; i++)
        !           303:            link->irq.IRQInfo2 |= 1 << irq_list[i];
        !           304:     link->irq.Handler = &fjn_interrupt;
        !           305:     
        !           306:     /* General socket configuration */
        !           307:     link->conf.Attributes = CONF_ENABLE_IRQ;
        !           308:     link->conf.Vcc = 50;
        !           309:     link->conf.IntType = INT_MEMORY_AND_IO;
        !           310: 
        !           311:     /* The FMVJ18x specific entries in the device structure. */
        !           312:     dev->hard_start_xmit = &fjn_start_xmit;
        !           313:     dev->set_config = &fjn_config;
        !           314:     dev->get_stats = &fjn_get_stats;
        !           315:     dev->set_multicast_list = &set_rx_mode;
        !           316:     ether_setup(dev);
        !           317:     init_dev_name(dev, lp->node);
        !           318:     dev->open = &fjn_open;
        !           319:     dev->stop = &fjn_close;
        !           320: #ifdef HAVE_TX_TIMEOUT
        !           321:     dev->tx_timeout = fjn_tx_timeout;
        !           322:     dev->watchdog_timeo = TX_TIMEOUT;
        !           323: #endif
        !           324:     
        !           325:     /* Register with Card Services */
        !           326:     link->next = dev_list;
        !           327:     dev_list = link;
        !           328:     client_reg.dev_info = &dev_info;
        !           329:     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
        !           330:     client_reg.EventMask =
        !           331:        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
        !           332:        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
        !           333:        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
        !           334:     client_reg.event_handler = &fmvj18x_event;
        !           335:     client_reg.Version = 0x0210;
        !           336:     client_reg.event_callback_args.client_data = link;
        !           337:     ret = CardServices(RegisterClient, &link->handle, &client_reg);
        !           338:     if (ret != 0) {
        !           339:        cs_error(link->handle, RegisterClient, ret);
        !           340:        fmvj18x_detach(link);
        !           341:        return NULL;
        !           342:     }
        !           343: 
        !           344:     return link;
        !           345: } /* fmvj18x_attach */
        !           346: 
        !           347: /*====================================================================*/
        !           348: 
        !           349: static void fmvj18x_detach(dev_link_t *link)
        !           350: {
        !           351:     local_info_t *lp = link->priv;
        !           352:     dev_link_t **linkp;
        !           353:     
        !           354:     DEBUG(0, "fmvj18x_detach(0x%p)\n", link);
        !           355:     
        !           356:     /* Locate device structure */
        !           357:     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        !           358:        if (*linkp == link) break;
        !           359:     if (*linkp == NULL)
        !           360:        return;
        !           361: 
        !           362:     del_timer(&link->release);
        !           363:     if (link->state & DEV_CONFIG) {
        !           364:        fmvj18x_release((u_long)link);
        !           365:        if (link->state & DEV_STALE_CONFIG) {
        !           366:            link->state |= DEV_STALE_LINK;
        !           367:            return;
        !           368:        }
        !           369:     }
        !           370: 
        !           371:     /* Break the link with Card Services */
        !           372:     if (link->handle)
        !           373:        CardServices(DeregisterClient, link->handle);
        !           374:     
        !           375:     /* Unlink device structure, free pieces */
        !           376:     *linkp = link->next;
        !           377:     if (link->dev)
        !           378:        unregister_netdev(&lp->dev);
        !           379:     kfree(lp);
        !           380:     
        !           381: } /* fmvj18x_detach */
        !           382: 
        !           383: /*====================================================================*/
        !           384: 
        !           385: #define CS_CHECK(fn, args...) \
        !           386: while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
        !           387: 
        !           388: static int mfc_try_io_port(dev_link_t *link)
        !           389: {
        !           390:     int i, ret;
        !           391:     static ioaddr_t serial_base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 };
        !           392: 
        !           393:     for (i = 0; i < 5; i++) {
        !           394:        link->io.BasePort2 = serial_base[i];
        !           395:        link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
        !           396:        if (link->io.BasePort2 == 0) {
        !           397:            link->io.NumPorts2 = 0;
        !           398:            printk(KERN_NOTICE "fmvj18x_cs: out of resource for serial\n");
        !           399:        }
        !           400:        ret = CardServices(RequestIO, link->handle, &link->io);
        !           401:        if (ret == CS_SUCCESS) return ret;
        !           402:     }
        !           403:     return ret;
        !           404: }
        !           405: 
        !           406: static int ungermann_try_io_port(dev_link_t *link)
        !           407: {
        !           408:     int ret;
        !           409:     ioaddr_t ioaddr;
        !           410:     /*
        !           411:        Ungermann-Bass Access/CARD accepts 0x300,0x320,0x340,0x360
        !           412:        0x380,0x3c0 only for ioport.
        !           413:     */
        !           414:     for (ioaddr = 0x300; ioaddr < 0x3e0; ioaddr += 0x20) {
        !           415:        link->io.BasePort1 = ioaddr;
        !           416:        ret = CardServices(RequestIO, link->handle, &link->io);
        !           417:        if (ret == CS_SUCCESS) {
        !           418:            /* calculate ConfigIndex value */
        !           419:            link->conf.ConfigIndex = 
        !           420:                ((link->io.BasePort1 & 0x0f0) >> 3) | 0x22;
        !           421:            return ret;
        !           422:        }
        !           423:     }
        !           424:     return ret;        /* RequestIO failed */
        !           425: }
        !           426: 
        !           427: static void fmvj18x_config(dev_link_t *link)
        !           428: {
        !           429:     client_handle_t handle = link->handle;
        !           430:     local_info_t *lp = link->priv;
        !           431:     struct net_device *dev = &lp->dev;
        !           432:     tuple_t tuple;
        !           433:     cisparse_t parse;
        !           434:     u_short buf[32];
        !           435:     int i, last_fn, last_ret, ret;
        !           436:     ioaddr_t ioaddr;
        !           437:     cardtype_t cardtype;
        !           438:     char *card_name = "unknown";
        !           439:     u_char *node_id;
        !           440: 
        !           441:     DEBUG(0, "fmvj18x_config(0x%p)\n", link);
        !           442: 
        !           443:     /*
        !           444:        This reads the card's CONFIG tuple to find its configuration
        !           445:        registers.
        !           446:     */
        !           447:     tuple.DesiredTuple = CISTPL_CONFIG;
        !           448:     CS_CHECK(GetFirstTuple, handle, &tuple);
        !           449:     tuple.TupleData = (u_char *)buf;
        !           450:     tuple.TupleDataMax = 64;
        !           451:     tuple.TupleOffset = 0;
        !           452:     CS_CHECK(GetTupleData, handle, &tuple);
        !           453:     CS_CHECK(ParseTuple, handle, &tuple, &parse);
        !           454:     
        !           455:     /* Configure card */
        !           456:     link->state |= DEV_CONFIG;
        !           457: 
        !           458:     link->conf.ConfigBase = parse.config.base; 
        !           459:     link->conf.Present = parse.config.rmask[0];
        !           460: 
        !           461:     tuple.DesiredTuple = CISTPL_FUNCE;
        !           462:     tuple.TupleOffset = 0;
        !           463:     if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) {
        !           464:        /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
        !           465:        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
        !           466:        CS_CHECK(GetFirstTuple, handle, &tuple);
        !           467:        CS_CHECK(GetTupleData, handle, &tuple);
        !           468:        CS_CHECK(ParseTuple, handle, &tuple, &parse);
        !           469:        link->conf.ConfigIndex = parse.cftable_entry.index;
        !           470:        tuple.DesiredTuple = CISTPL_MANFID;
        !           471:        if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS)
        !           472:            CS_CHECK(GetTupleData, handle, &tuple);
        !           473:        else
        !           474:            buf[0] = 0xffff;
        !           475:        switch (le16_to_cpu(buf[0])) {
        !           476:        case MANFID_TDK:
        !           477:            cardtype = TDK;
        !           478:            if (le16_to_cpu(buf[1]) == PRODID_TDK_CF010) {
        !           479:                cs_status_t status;
        !           480:                CardServices(GetStatus, handle, &status);
        !           481:                if (status.CardState & CS_EVENT_3VCARD)
        !           482:                    link->conf.Vcc = 33; /* inserted in 3.3V slot */
        !           483:            } else if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410) {
        !           484:                /* MultiFunction Card */
        !           485:                link->conf.ConfigBase = 0x800;
        !           486:                link->conf.ConfigIndex = 0x47;
        !           487:                link->io.NumPorts2 = 8;
        !           488:            }
        !           489:            break;
        !           490:        case MANFID_CONTEC:
        !           491:            cardtype = CONTEC;
        !           492:            break;
        !           493:        case MANFID_FUJITSU:
        !           494:            if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302)
        !           495:                 /* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
        !           496:                    but these are MBH10304 based card. */ 
        !           497:                cardtype = MBH10304;
        !           498:            else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304)
        !           499:                cardtype = MBH10304;
        !           500:            else
        !           501:                cardtype = LA501;
        !           502:            break;
        !           503:        default:
        !           504:            cardtype = MBH10304;
        !           505:        }
        !           506:     } else {
        !           507:        /* old type card */
        !           508:        tuple.DesiredTuple = CISTPL_MANFID;
        !           509:        if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS)
        !           510:            CS_CHECK(GetTupleData, handle, &tuple);
        !           511:        else
        !           512:            buf[0] = 0xffff;
        !           513:        switch (le16_to_cpu(buf[0])) {
        !           514:        case MANFID_FUJITSU:
        !           515:            if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) {
        !           516:                cardtype = XXX10304;    /* MBH10304 with buggy CIS */
        !           517:                link->conf.ConfigIndex = 0x20;
        !           518:            } else {
        !           519:                cardtype = MBH10302;    /* NextCom NC5310, etc. */
        !           520:                link->conf.ConfigIndex = 1;
        !           521:            }
        !           522:            break;
        !           523:        case MANFID_UNGERMANN:
        !           524:            cardtype = UNGERMANN;
        !           525:            break;
        !           526:        default:
        !           527:            cardtype = MBH10302;
        !           528:            link->conf.ConfigIndex = 1;
        !           529:        }
        !           530:     }
        !           531: 
        !           532:     if (link->io.NumPorts2 != 0) {
        !           533:        link->irq.Attributes =
        !           534:            IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;
        !           535:        ret = mfc_try_io_port(link);
        !           536:        if (ret != CS_SUCCESS) goto cs_failed;
        !           537:     } else if (cardtype == UNGERMANN) {
        !           538:        ret = ungermann_try_io_port(link);
        !           539:        if (ret != CS_SUCCESS) goto cs_failed;
        !           540:     } else { 
        !           541:        CS_CHECK(RequestIO, link->handle, &link->io);
        !           542:     }
        !           543:     CS_CHECK(RequestIRQ, link->handle, &link->irq);
        !           544:     CS_CHECK(RequestConfiguration, link->handle, &link->conf);
        !           545:     dev->irq = link->irq.AssignedIRQ;
        !           546:     dev->base_addr = link->io.BasePort1;
        !           547:     if (register_netdev(dev) != 0) {
        !           548:        printk(KERN_NOTICE "fmvj18x_cs: register_netdev() failed\n");
        !           549:        goto failed;
        !           550:     }
        !           551: 
        !           552:     if (link->io.BasePort2 != 0)
        !           553:        fmvj18x_setup_mfc(link);
        !           554: 
        !           555:     ioaddr = dev->base_addr;
        !           556: 
        !           557:     /* Reset controller */
        !           558:     if (sram_config == 0) 
        !           559:        outb(CONFIG0_RST, ioaddr + CONFIG_0);
        !           560:     else
        !           561:        outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
        !           562: 
        !           563:     /* Power On chip and select bank 0 */
        !           564:     if (cardtype == MBH10302)
        !           565:        outb(BANK_0, ioaddr + CONFIG_1);
        !           566:     else
        !           567:        outb(BANK_0U, ioaddr + CONFIG_1);
        !           568:     
        !           569:     /* Set hardware address */
        !           570:     switch (cardtype) {
        !           571:     case MBH10304:
        !           572:     case TDK:
        !           573:     case LA501:
        !           574:     case CONTEC:
        !           575:        tuple.DesiredTuple = CISTPL_FUNCE;
        !           576:        tuple.TupleOffset = 0;
        !           577:        CS_CHECK(GetFirstTuple, handle, &tuple);
        !           578:        tuple.TupleOffset = 0;
        !           579:        CS_CHECK(GetTupleData, handle, &tuple);
        !           580:        if (cardtype == MBH10304) {
        !           581:            /* MBH10304's CIS_FUNCE is corrupted */
        !           582:            node_id = &(tuple.TupleData[5]);
        !           583:            card_name = "FMV-J182";
        !           584:        } else {
        !           585:            while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
        !           586:                CS_CHECK(GetNextTuple, handle, &tuple) ;
        !           587:                CS_CHECK(GetTupleData, handle, &tuple) ;
        !           588:            }
        !           589:            node_id = &(tuple.TupleData[2]);
        !           590:            if( cardtype == TDK ) {
        !           591:                card_name = "TDK LAK-CD021";
        !           592:            } else if( cardtype == LA501 ) {
        !           593:                card_name = "LA501";
        !           594:            } else {
        !           595:                card_name = "C-NET(PC)C";
        !           596:            }
        !           597:        }
        !           598:        /* Read MACID from CIS */
        !           599:        for (i = 0; i < 6; i++)
        !           600:            dev->dev_addr[i] = node_id[i];
        !           601:        break;
        !           602:     case UNGERMANN:
        !           603:        /* Read MACID from register */
        !           604:        for (i = 0; i < 6; i++) 
        !           605:            dev->dev_addr[i] = inb(ioaddr + UNGERMANN_MAC_ID + i);
        !           606:        card_name = "Access/CARD";
        !           607:        break;
        !           608:     case XXX10304:
        !           609:        /* Read MACID from Buggy CIS */
        !           610:        if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) {
        !           611:            printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.");
        !           612:            unregister_netdev(dev);
        !           613:            goto failed;
        !           614:        }
        !           615:        for (i = 0 ; i < 6; i++) {
        !           616:            dev->dev_addr[i] = tuple.TupleData[i];
        !           617:        }
        !           618:        card_name = "FMV-J182";
        !           619:        break;
        !           620:     case MBH10302:
        !           621:     default:
        !           622:        /* Read MACID from register */
        !           623:        for (i = 0; i < 6; i++) 
        !           624:            dev->dev_addr[i] = inb(ioaddr + MAC_ID + i);
        !           625:        card_name = "FMV-J181";
        !           626:        break;
        !           627:     }
        !           628: 
        !           629:     copy_dev_name(lp->node, dev);
        !           630:     link->dev = &lp->node;
        !           631: 
        !           632:     lp->cardtype = cardtype;
        !           633:     /* print current configuration */
        !           634:     printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, hw_addr ", 
        !           635:           dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2", 
        !           636:           dev->base_addr, dev->irq);
        !           637:     for (i = 0; i < 6; i++)
        !           638:        printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
        !           639: 
        !           640:     link->state &= ~DEV_CONFIG_PENDING;
        !           641:     return;
        !           642:     
        !           643: cs_failed:
        !           644:     /* All Card Services errors end up here */
        !           645:     cs_error(link->handle, last_fn, last_ret);
        !           646: failed:
        !           647:     fmvj18x_release((u_long)link);
        !           648:     link->state &= ~DEV_CONFIG_PENDING;
        !           649: 
        !           650: } /* fmvj18x_config */
        !           651: /*====================================================================*/
        !           652: 
        !           653: static int fmvj18x_get_hwinfo(dev_link_t *link, u_char *node_id)
        !           654: {
        !           655:     win_req_t req;
        !           656:     memreq_t mem;
        !           657:     u_char *base;
        !           658:     int i, j;
        !           659: 
        !           660:     /* Allocate a small memory window */
        !           661:     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
        !           662:     req.Base = 0; req.Size = 0;
        !           663:     req.AccessSpeed = 0;
        !           664:     link->win = (window_handle_t)link->handle;
        !           665:     i = CardServices(RequestWindow, &link->win, &req);
        !           666:     if (i != CS_SUCCESS) {
        !           667:        cs_error(link->handle, RequestWindow, i);
        !           668:        return -1;
        !           669:     }
        !           670: 
        !           671:     base = ioremap(req.Base, req.Size);
        !           672:     mem.Page = 0;
        !           673:     mem.CardOffset = 0;
        !           674:     CardServices(MapMemPage, link->win, &mem);
        !           675: 
        !           676:     /*
        !           677:      *  MBH10304 CISTPL_FUNCE_LAN_NODE_ID format
        !           678:      *  22 0d xx xx xx 04 06 yy yy yy yy yy yy ff
        !           679:      *  'xx' is garbage.
        !           680:      *  'yy' is MAC address.
        !           681:     */ 
        !           682:     for (i = 0; i < 0x200; i++) {
        !           683:        if (readb(base+i*2) == 0x22) {  
        !           684:            if (readb(base+(i-1)*2) == 0xff
        !           685:             && readb(base+(i+5)*2) == 0x04
        !           686:             && readb(base+(i+6)*2) == 0x06
        !           687:             && readb(base+(i+13)*2) == 0xff) 
        !           688:                break;
        !           689:        }
        !           690:     }
        !           691: 
        !           692:     if (i != 0x200) {
        !           693:        for (j = 0 ; j < 6; j++,i++) {
        !           694:            node_id[j] = readb(base+(i+7)*2);
        !           695:        }
        !           696:     }
        !           697: 
        !           698:     iounmap(base);
        !           699:     j = CardServices(ReleaseWindow, link->win);
        !           700:     if (j != CS_SUCCESS)
        !           701:        cs_error(link->handle, ReleaseWindow, j);
        !           702:     return (i != 0x200) ? 0 : -1;
        !           703: 
        !           704: } /* fmvj18x_get_hwinfo */
        !           705: /*====================================================================*/
        !           706: 
        !           707: static int fmvj18x_setup_mfc(dev_link_t *link)
        !           708: {
        !           709:     win_req_t req;
        !           710:     memreq_t mem;
        !           711:     u_char *base;
        !           712:     int i, j;
        !           713:     local_info_t *lp = link->priv;
        !           714:     struct net_device *dev = &lp->dev;
        !           715:     ioaddr_t ioaddr;
        !           716: 
        !           717:     /* Allocate a small memory window */
        !           718:     req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
        !           719:     req.Base = 0; req.Size = 0;
        !           720:     req.AccessSpeed = 0;
        !           721:     link->win = (window_handle_t)link->handle;
        !           722:     i = CardServices(RequestWindow, &link->win, &req);
        !           723:     if (i != CS_SUCCESS) {
        !           724:        cs_error(link->handle, RequestWindow, i);
        !           725:        return -1;
        !           726:     }
        !           727: 
        !           728:     base = ioremap(req.Base, req.Size);
        !           729:     mem.Page = 0;
        !           730:     mem.CardOffset = 0;
        !           731:     CardServices(MapMemPage, link->win, &mem);
        !           732: 
        !           733:     ioaddr = dev->base_addr;
        !           734:     writeb(0x47, base+0x800);  /* Config Option Register of LAN */
        !           735:     writeb(0x0, base+0x802);   /* Config and Status Register */
        !           736: 
        !           737:     writeb(ioaddr & 0xff, base+0x80a);         /* I/O Base(Low) of LAN */
        !           738:     writeb((ioaddr >> 8) & 0xff, base+0x80c);  /* I/O Base(High) of LAN */
        !           739:    
        !           740:     writeb(0x45, base+0x820);  /* Config Option Register of Modem */
        !           741:     writeb(0x8, base+0x822);   /* Config and Status Register */
        !           742: 
        !           743:     iounmap(base);
        !           744:     j = CardServices(ReleaseWindow, link->win);
        !           745:     if (j != CS_SUCCESS)
        !           746:        cs_error(link->handle, ReleaseWindow, j);
        !           747:     return 0;
        !           748: 
        !           749: }
        !           750: /*====================================================================*/
        !           751: 
        !           752: static void fmvj18x_release(u_long arg)
        !           753: {
        !           754:     dev_link_t *link = (dev_link_t *)arg;
        !           755: 
        !           756:     DEBUG(0, "fmvj18x_release(0x%p)\n", link);
        !           757: 
        !           758:     /*
        !           759:        If the device is currently in use, we won't release until it
        !           760:        is actually closed.
        !           761:     */
        !           762:     if (link->open) {
        !           763:        DEBUG(1, "fmvj18x_cs: release postponed, '%s' "
        !           764:              "still open\n", link->dev->dev_name);
        !           765:        link->state |= DEV_STALE_CONFIG;
        !           766:        return;
        !           767:     }
        !           768: 
        !           769:     /* Don't bother checking to see if these succeed or not */
        !           770:     CardServices(ReleaseWindow, link->win);
        !           771:     CardServices(ReleaseConfiguration, link->handle);
        !           772:     CardServices(ReleaseIO, link->handle, &link->io);
        !           773:     CardServices(ReleaseIRQ, link->handle, &link->irq);
        !           774:     
        !           775:     link->state &= ~DEV_CONFIG;
        !           776:     
        !           777: } /* fmvj18x_release */
        !           778: 
        !           779: /*====================================================================*/
        !           780: 
        !           781: static int fmvj18x_event(event_t event, int priority,
        !           782:                          event_callback_args_t *args)
        !           783: {
        !           784:     dev_link_t *link = args->client_data;
        !           785:     local_info_t *lp = link->priv;
        !           786:     struct net_device *dev = &lp->dev;
        !           787: 
        !           788:     DEBUG(1, "fmvj18x_event(0x%06x)\n", event);
        !           789:     
        !           790:     switch (event) {
        !           791:     case CS_EVENT_CARD_REMOVAL:
        !           792:        link->state &= ~DEV_PRESENT;
        !           793:        if (link->state & DEV_CONFIG) {
        !           794:            netif_device_detach(dev);
        !           795:            mod_timer(&link->release, jiffies + HZ/20);
        !           796:        }
        !           797:        break;
        !           798:     case CS_EVENT_CARD_INSERTION:
        !           799:        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        !           800:        fmvj18x_config(link);
        !           801:        break;
        !           802:     case CS_EVENT_PM_SUSPEND:
        !           803:        link->state |= DEV_SUSPEND;
        !           804:        /* Fall through... */
        !           805:     case CS_EVENT_RESET_PHYSICAL:
        !           806:        if (link->state & DEV_CONFIG) {
        !           807:            if (link->open)
        !           808:                netif_device_detach(dev);
        !           809:            CardServices(ReleaseConfiguration, link->handle);
        !           810:        }
        !           811:        break;
        !           812:     case CS_EVENT_PM_RESUME:
        !           813:        link->state &= ~DEV_SUSPEND;
        !           814:        /* Fall through... */
        !           815:     case CS_EVENT_CARD_RESET:
        !           816:        if (link->state & DEV_CONFIG) {
        !           817:            CardServices(RequestConfiguration, link->handle, &link->conf);
        !           818:            if (link->open) {
        !           819:                fjn_reset(dev);
        !           820:                netif_device_attach(dev);
        !           821:            }
        !           822:        }
        !           823:        break;
        !           824:     }
        !           825:     return 0;
        !           826: } /* fmvj18x_event */
        !           827: 
        !           828: /*====================================================================*/
        !           829: 
        !           830: static int __init init_fmvj18x_cs(void)
        !           831: {
        !           832:     servinfo_t serv;
        !           833:     DEBUG(0, "%s\n", version);
        !           834:     CardServices(GetCardServicesInfo, &serv);
        !           835:     if (serv.Revision != CS_RELEASE_CODE) {
        !           836:        printk(KERN_NOTICE "fmvj18x: Card Services release "
        !           837:               "does not match!\n");
        !           838:        return -EINVAL;
        !           839:     }
        !           840:     register_pccard_driver(&dev_info, &fmvj18x_attach, &fmvj18x_detach);
        !           841:     return 0;
        !           842: }
        !           843: 
        !           844: static void __exit exit_fmvj18x_cs(void)
        !           845: {
        !           846:     DEBUG(0, "fmvj18x_cs: unloading\n");
        !           847:     unregister_pccard_driver(&dev_info);
        !           848:     while (dev_list != NULL)
        !           849:        fmvj18x_detach(dev_list);
        !           850: }
        !           851: 
        !           852: module_init(init_fmvj18x_cs);
        !           853: module_exit(exit_fmvj18x_cs);
        !           854: 
        !           855: /*====================================================================*/
        !           856: 
        !           857: static void fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        !           858: {
        !           859:     local_info_t *lp = dev_id;
        !           860:     struct net_device *dev = &lp->dev;
        !           861:     ioaddr_t ioaddr;
        !           862:     unsigned short tx_stat, rx_stat;
        !           863: 
        !           864:     if (lp == NULL) {
        !           865:         printk(KERN_NOTICE "fjn_interrupt(): irq %d for "
        !           866:               "unknown device.\n", irq);
        !           867:         return;
        !           868:     }
        !           869:     ioaddr = dev->base_addr;
        !           870: 
        !           871:     /* avoid multiple interrupts */
        !           872:     outw(0x0000, ioaddr + TX_INTR);
        !           873: 
        !           874:     /* wait for a while */
        !           875:     udelay(1);
        !           876: 
        !           877:     /* get status */
        !           878:     tx_stat = inb(ioaddr + TX_STATUS);
        !           879:     rx_stat = inb(ioaddr + RX_STATUS);
        !           880: 
        !           881:     /* clear status */
        !           882:     outb(tx_stat, ioaddr + TX_STATUS);
        !           883:     outb(rx_stat, ioaddr + RX_STATUS);
        !           884:     
        !           885:     DEBUG(4, "%s: interrupt, rx_status %02x.\n", dev->name, rx_stat);
        !           886:     DEBUG(4, "               tx_status %02x.\n", tx_stat);
        !           887:     
        !           888:     if (rx_stat || (inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
        !           889:        /* there is packet(s) in rx buffer */
        !           890:        fjn_rx(dev);
        !           891:     }
        !           892:     if (tx_stat & F_TMT_RDY) {
        !           893:        lp->stats.tx_packets += lp->sent ;
        !           894:         lp->sent = 0 ;
        !           895:        if (lp->tx_queue) {
        !           896:            outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
        !           897:            lp->sent = lp->tx_queue ;
        !           898:            lp->tx_queue = 0;
        !           899:            lp->tx_queue_len = 0;
        !           900:            dev->trans_start = jiffies;
        !           901:        } else {
        !           902:            lp->tx_started = 0;
        !           903:        }
        !           904:        netif_wake_queue(dev);
        !           905:     }
        !           906:     DEBUG(4, "%s: exiting interrupt,\n", dev->name);
        !           907:     DEBUG(4, "    tx_status %02x, rx_status %02x.\n", tx_stat, rx_stat);
        !           908: 
        !           909:     outb(D_TX_INTR, ioaddr + TX_INTR);
        !           910:     outb(D_RX_INTR, ioaddr + RX_INTR);
        !           911: 
        !           912: } /* fjn_interrupt */
        !           913: 
        !           914: /*====================================================================*/
        !           915: 
        !           916: static void fjn_tx_timeout(struct net_device *dev)
        !           917: {
        !           918:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !           919:     ioaddr_t ioaddr = dev->base_addr;
        !           920: 
        !           921:     printk(KERN_NOTICE "%s: transmit timed out with status %04x, %s?\n",
        !           922:           dev->name, htons(inw(ioaddr + TX_STATUS)),
        !           923:           inb(ioaddr + TX_STATUS) & F_TMT_RDY
        !           924:           ? "IRQ conflict" : "network cable problem");
        !           925:     printk(KERN_NOTICE "%s: timeout registers: %04x %04x %04x "
        !           926:           "%04x %04x %04x %04x %04x.\n",
        !           927:           dev->name, htons(inw(ioaddr + 0)),
        !           928:           htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
        !           929:           htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
        !           930:           htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
        !           931:           htons(inw(ioaddr +14)));
        !           932:     lp->stats.tx_errors++;
        !           933:     /* ToDo: We should try to restart the adaptor... */
        !           934:     cli();
        !           935: 
        !           936:     fjn_reset(dev);
        !           937: 
        !           938:     lp->tx_started = 0;
        !           939:     lp->tx_queue = 0;
        !           940:     lp->tx_queue_len = 0;
        !           941:     lp->sent = 0;
        !           942:     lp->open_time = jiffies;
        !           943:     sti();
        !           944:     netif_wake_queue(dev);
        !           945: }
        !           946: 
        !           947: static int fjn_start_xmit(struct sk_buff *skb, struct net_device *dev)
        !           948: {
        !           949:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !           950:     ioaddr_t ioaddr = dev->base_addr;
        !           951: 
        !           952:     tx_timeout_check(dev, fjn_tx_timeout);
        !           953:     skb_tx_check(dev, skb);
        !           954: 
        !           955:     {
        !           956:        short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
        !           957:        unsigned char *buf = skb->data;
        !           958: 
        !           959:        if (length > ETH_FRAME_LEN) {
        !           960:            printk(KERN_NOTICE "%s: Attempting to send a large packet"
        !           961:                   " (%d bytes).\n", dev->name, length);
        !           962:            return 1;
        !           963:        }
        !           964: 
        !           965:        DEBUG(4, "%s: Transmitting a packet of length %lu.\n",
        !           966:              dev->name, (unsigned long)skb->len);
        !           967:        add_tx_bytes(&lp->stats, skb->len);
        !           968: 
        !           969:        /* Disable both interrupts. */
        !           970:        outw(0x0000, ioaddr + TX_INTR);
        !           971: 
        !           972:        /* wait for a while */
        !           973:        udelay(1);
        !           974: 
        !           975:        outw(length, ioaddr + DATAPORT);
        !           976:        outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
        !           977: 
        !           978:        lp->tx_queue++;
        !           979:        lp->tx_queue_len += ((length+3) & ~1);
        !           980: 
        !           981:        if (lp->tx_started == 0) {
        !           982:            /* If the Tx is idle, always trigger a transmit. */
        !           983:            outb(DO_TX | lp->tx_queue, ioaddr + TX_START);
        !           984:            lp->sent = lp->tx_queue ;
        !           985:            lp->tx_queue = 0;
        !           986:            lp->tx_queue_len = 0;
        !           987:            dev->trans_start = jiffies;
        !           988:            lp->tx_started = 1;
        !           989:            netif_start_queue(dev);
        !           990:        } else {
        !           991:            if( sram_config == 0 ) {
        !           992:                if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) )
        !           993:                    /* Yes, there is room for one more packet. */
        !           994:                    netif_start_queue(dev);
        !           995:            } else {
        !           996:                if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) && 
        !           997:                                                lp->tx_queue < 127 )
        !           998:                    /* Yes, there is room for one more packet. */
        !           999:                    netif_start_queue(dev);
        !          1000:            }
        !          1001:        }
        !          1002: 
        !          1003:        /* Re-enable interrupts */
        !          1004:        outb(D_TX_INTR, ioaddr + TX_INTR);
        !          1005:        outb(D_RX_INTR, ioaddr + RX_INTR);
        !          1006:     }
        !          1007:     DEV_KFREE_SKB (skb);
        !          1008: 
        !          1009:     return 0;
        !          1010: } /* fjn_start_xmit */
        !          1011: 
        !          1012: /*====================================================================*/
        !          1013: 
        !          1014: static void fjn_reset(struct net_device *dev)
        !          1015: {
        !          1016:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !          1017:     ioaddr_t ioaddr = dev->base_addr;
        !          1018:     int i;
        !          1019: 
        !          1020:     DEBUG(4, "fjn_reset(%s) called.\n",dev->name);
        !          1021: 
        !          1022:     /* Reset controller */
        !          1023:     if( sram_config == 0 ) 
        !          1024:        outb(CONFIG0_RST, ioaddr + CONFIG_0);
        !          1025:     else
        !          1026:        outb(CONFIG0_RST_1, ioaddr + CONFIG_0);
        !          1027: 
        !          1028:     /* Power On chip and select bank 0 */
        !          1029:     if (lp->cardtype == MBH10302)
        !          1030:        outb(BANK_0, ioaddr + CONFIG_1);
        !          1031:     else
        !          1032:        outb(BANK_0U, ioaddr + CONFIG_1);
        !          1033: 
        !          1034:     /* Set Tx modes */
        !          1035:     outb(D_TX_MODE, ioaddr + TX_MODE);
        !          1036:     /* set Rx modes */
        !          1037:     outb(ID_MATCHED, ioaddr + RX_MODE);
        !          1038: 
        !          1039:     /* Set hardware address */
        !          1040:     for (i = 0; i < 6; i++) 
        !          1041:         outb(dev->dev_addr[i], ioaddr + NODE_ID + i);
        !          1042: 
        !          1043:     /* Switch to bank 1 */
        !          1044:     if (lp->cardtype == MBH10302)
        !          1045:        outb(BANK_1, ioaddr + CONFIG_1);
        !          1046:     else
        !          1047:        outb(BANK_1U, ioaddr + CONFIG_1);
        !          1048: 
        !          1049:     /* set the multicast table to accept none. */
        !          1050:     for (i = 0; i < 6; i++) 
        !          1051:         outb(0x00, ioaddr + MAR_ADR + i);
        !          1052: 
        !          1053:     /* Switch to bank 2 (runtime mode) */
        !          1054:     if (lp->cardtype == MBH10302)
        !          1055:        outb(BANK_2, ioaddr + CONFIG_1);
        !          1056:     else
        !          1057:        outb(BANK_2U, ioaddr + CONFIG_1);
        !          1058: 
        !          1059:     /* set 16col ctrl bits */
        !          1060:     if( lp->cardtype == TDK || lp->cardtype == CONTEC) 
        !          1061:         outb(TDK_AUTO_MODE, ioaddr + COL_CTRL);
        !          1062:     else
        !          1063:         outb(AUTO_MODE, ioaddr + COL_CTRL);
        !          1064: 
        !          1065:     /* clear Reserved Regs */
        !          1066:     outb(0x00, ioaddr + BMPR12);
        !          1067:     outb(0x00, ioaddr + BMPR13);
        !          1068: 
        !          1069:     /* reset Skip packet reg. */
        !          1070:     outb(0x01, ioaddr + RX_SKIP);
        !          1071: 
        !          1072:     /* Enable Tx and Rx */
        !          1073:     if( sram_config == 0 )
        !          1074:        outb(CONFIG0_DFL, ioaddr + CONFIG_0);
        !          1075:     else
        !          1076:        outb(CONFIG0_DFL_1, ioaddr + CONFIG_0);
        !          1077: 
        !          1078:     /* Init receive pointer ? */
        !          1079:     inw(ioaddr + DATAPORT);
        !          1080:     inw(ioaddr + DATAPORT);
        !          1081: 
        !          1082:     /* Clear all status */
        !          1083:     outb(0xff, ioaddr + TX_STATUS);
        !          1084:     outb(0xff, ioaddr + RX_STATUS);
        !          1085: 
        !          1086:     if (lp->cardtype == MBH10302)
        !          1087:        outb(INTR_OFF, ioaddr + LAN_CTRL);
        !          1088: 
        !          1089:     /* Turn on Rx interrupts */
        !          1090:     outb(D_TX_INTR, ioaddr + TX_INTR);
        !          1091:     outb(D_RX_INTR, ioaddr + RX_INTR);
        !          1092: 
        !          1093:     /* Turn on interrupts from LAN card controller */
        !          1094:     if (lp->cardtype == MBH10302)
        !          1095:        outb(INTR_ON, ioaddr + LAN_CTRL);
        !          1096: } /* fjn_reset */
        !          1097: 
        !          1098: /*====================================================================*/
        !          1099: 
        !          1100: static void fjn_rx(struct net_device *dev)
        !          1101: {
        !          1102:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !          1103:     ioaddr_t ioaddr = dev->base_addr;
        !          1104:     int boguscount = 10;       /* 5 -> 10: by agy 19940922 */
        !          1105: 
        !          1106:     DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n",
        !          1107:          dev->name, inb(ioaddr + RX_STATUS));
        !          1108: 
        !          1109:     while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) {
        !          1110:        u_short status = inw(ioaddr + DATAPORT);
        !          1111: 
        !          1112:        DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n",
        !          1113:              dev->name, inb(ioaddr + RX_MODE), status);
        !          1114: #ifndef final_version
        !          1115:        if (status == 0) {
        !          1116:            outb(F_SKP_PKT, ioaddr + RX_SKIP);
        !          1117:            break;
        !          1118:        }
        !          1119: #endif
        !          1120:        if ((status & 0xF0) != 0x20) {  /* There was an error. */
        !          1121:            lp->stats.rx_errors++;
        !          1122:            if (status & F_LEN_ERR) lp->stats.rx_length_errors++;
        !          1123:            if (status & F_ALG_ERR) lp->stats.rx_frame_errors++;
        !          1124:            if (status & F_CRC_ERR) lp->stats.rx_crc_errors++;
        !          1125:            if (status & F_OVR_FLO) lp->stats.rx_over_errors++;
        !          1126:        } else {
        !          1127:            u_short pkt_len = inw(ioaddr + DATAPORT);
        !          1128:            /* Malloc up new buffer. */
        !          1129:            struct sk_buff *skb;
        !          1130: 
        !          1131:            if (pkt_len > 1550) {
        !          1132:                printk(KERN_NOTICE "%s: The FMV-18x claimed a very "
        !          1133:                       "large packet, size %d.\n", dev->name, pkt_len);
        !          1134:                outb(F_SKP_PKT, ioaddr + RX_SKIP);
        !          1135:                lp->stats.rx_errors++;
        !          1136:                break;
        !          1137:            }
        !          1138:            skb = dev_alloc_skb(pkt_len+2);
        !          1139:            if (skb == NULL) {
        !          1140:                printk(KERN_NOTICE "%s: Memory squeeze, dropping "
        !          1141:                       "packet (len %d).\n", dev->name, pkt_len);
        !          1142:                outb(F_SKP_PKT, ioaddr + RX_SKIP);
        !          1143:                lp->stats.rx_dropped++;
        !          1144:                break;
        !          1145:            }
        !          1146:            skb->dev = dev;
        !          1147: 
        !          1148:            skb_reserve(skb, 2);
        !          1149:            insw(ioaddr + DATAPORT, skb_put(skb, pkt_len),
        !          1150:                 (pkt_len + 1) >> 1);
        !          1151:            skb->protocol = eth_type_trans(skb, dev);
        !          1152: 
        !          1153: #ifdef PCMCIA_DEBUG
        !          1154:            if (pc_debug > 5) {
        !          1155:                int i;
        !          1156:                printk(KERN_DEBUG "%s: Rxed packet of length %d: ",
        !          1157:                       dev->name, pkt_len);
        !          1158:                for (i = 0; i < 14; i++)
        !          1159:                    printk(" %02x", skb->data[i]);
        !          1160:                printk(".\n");
        !          1161:            }
        !          1162: #endif
        !          1163: 
        !          1164:            netif_rx(skb);
        !          1165:            dev->last_rx = jiffies;
        !          1166:            lp->stats.rx_packets++;
        !          1167:            add_rx_bytes(&lp->stats, pkt_len);
        !          1168:        }
        !          1169:        if (--boguscount <= 0)
        !          1170:            break;
        !          1171:     }
        !          1172: 
        !          1173:     /* If any worth-while packets have been received, dev_rint()
        !          1174:           has done a netif_wake_queue() for us and will work on them
        !          1175:           when we get to the bottom-half routine. */
        !          1176: /*
        !          1177:     if (lp->cardtype != TDK) {
        !          1178:        int i;
        !          1179:        for (i = 0; i < 20; i++) {
        !          1180:            if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP)
        !          1181:                break;
        !          1182:            (void)inw(ioaddr + DATAPORT);  /+ dummy status read +/
        !          1183:            outb(F_SKP_PKT, ioaddr + RX_SKIP);
        !          1184:        }
        !          1185: 
        !          1186:        if (i > 0)
        !          1187:            DEBUG(5, "%s: Exint Rx packet with mode %02x after "
        !          1188:                  "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i);
        !          1189:     }
        !          1190: */
        !          1191: 
        !          1192:     return;
        !          1193: } /* fjn_rx */
        !          1194: 
        !          1195: /*====================================================================*/
        !          1196: 
        !          1197: static int fjn_config(struct net_device *dev, struct ifmap *map){
        !          1198:     return 0;
        !          1199: }
        !          1200: 
        !          1201: static int fjn_open(struct net_device *dev)
        !          1202: {
        !          1203:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !          1204:     dev_link_t *link = &lp->link;
        !          1205: 
        !          1206:     DEBUG(4, "fjn_open('%s').\n", dev->name);
        !          1207: 
        !          1208:     if (!DEV_OK(link))
        !          1209:        return -ENODEV;
        !          1210:     
        !          1211:     link->open++;
        !          1212:     
        !          1213:     fjn_reset(dev);
        !          1214:     
        !          1215:     lp->tx_started = 0;
        !          1216:     lp->tx_queue = 0;
        !          1217:     lp->tx_queue_len = 0;
        !          1218:     lp->open_time = jiffies;
        !          1219:     netif_mark_up(dev);
        !          1220:     netif_start_queue(dev);
        !          1221:     
        !          1222:     MOD_INC_USE_COUNT;
        !          1223: 
        !          1224:     return 0;
        !          1225: } /* fjn_open */
        !          1226: 
        !          1227: /*====================================================================*/
        !          1228: 
        !          1229: static int fjn_close(struct net_device *dev)
        !          1230: {
        !          1231:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !          1232:     dev_link_t *link = &lp->link;
        !          1233:     ioaddr_t ioaddr = dev->base_addr;
        !          1234: 
        !          1235:     DEBUG(4, "fjn_close('%s').\n", dev->name);
        !          1236: 
        !          1237:     lp->open_time = 0;
        !          1238:     netif_stop_queue(dev);
        !          1239:     netif_mark_down(dev);
        !          1240: 
        !          1241:     /* Set configuration register 0 to disable Tx and Rx. */
        !          1242:     if( sram_config == 0 ) 
        !          1243:        outb(CONFIG0_RST ,ioaddr + CONFIG_0);
        !          1244:     else
        !          1245:        outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0);
        !          1246: 
        !          1247:     /* Update the statistics -- ToDo. */
        !          1248: 
        !          1249:     /* Power-down the chip.  Green, green, green! */
        !          1250:     outb(CHIP_OFF ,ioaddr + CONFIG_1);
        !          1251: 
        !          1252:     /* Set the ethernet adaptor disable IRQ */
        !          1253:     if (lp->cardtype == MBH10302)
        !          1254:        outb(INTR_OFF, ioaddr + LAN_CTRL);
        !          1255: 
        !          1256:     link->open--;
        !          1257:     if (link->state & DEV_STALE_CONFIG)
        !          1258:        mod_timer(&link->release, jiffies + HZ/20);
        !          1259:     MOD_DEC_USE_COUNT;
        !          1260: 
        !          1261:     return 0;
        !          1262: } /* fjn_close */
        !          1263: 
        !          1264: /*====================================================================*/
        !          1265: 
        !          1266: static struct net_device_stats *fjn_get_stats(struct net_device *dev)
        !          1267: {
        !          1268:     local_info_t *lp = (local_info_t *)dev->priv;
        !          1269:     return &lp->stats;
        !          1270: } /* fjn_get_stats */
        !          1271: 
        !          1272: /*====================================================================*/
        !          1273: 
        !          1274: /*
        !          1275:   Set the multicast/promiscuous mode for this adaptor.
        !          1276: */
        !          1277: 
        !          1278: static void set_rx_mode(struct net_device *dev)
        !          1279: {
        !          1280:     ioaddr_t ioaddr = dev->base_addr;
        !          1281:     struct local_info_t *lp = (struct local_info_t *)dev->priv;
        !          1282:     u_char mc_filter[8];                /* Multicast hash filter */
        !          1283:     u_long flags;
        !          1284:     int i;
        !          1285:     
        !          1286:     if (dev->flags & IFF_PROMISC) {
        !          1287:        /* Unconditionally log net taps. */
        !          1288:        printk("%s: Promiscuous mode enabled.\n", dev->name);
        !          1289:        memset(mc_filter, 0xff, sizeof(mc_filter));
        !          1290:        outb(3, ioaddr + RX_MODE);      /* Enable promiscuous mode */
        !          1291:     } else if (dev->mc_count > MC_FILTERBREAK
        !          1292:               ||  (dev->flags & IFF_ALLMULTI)) {
        !          1293:        /* Too many to filter perfectly -- accept all multicasts. */
        !          1294:        memset(mc_filter, 0xff, sizeof(mc_filter));
        !          1295:        outb(2, ioaddr + RX_MODE);      /* Use normal mode. */
        !          1296:     } else if (dev->mc_count == 0) {
        !          1297:        memset(mc_filter, 0x00, sizeof(mc_filter));
        !          1298:        outb(1, ioaddr + RX_MODE);      /* Ignore almost all multicasts. */
        !          1299:     } else {
        !          1300:        struct dev_mc_list *mclist;
        !          1301:        int i;
        !          1302:        
        !          1303:        memset(mc_filter, 0, sizeof(mc_filter));
        !          1304:        for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
        !          1305:             i++, mclist = mclist->next)
        !          1306:            set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f,
        !          1307:                    mc_filter);
        !          1308:     }
        !          1309:     
        !          1310:     save_flags(flags);
        !          1311:     cli();
        !          1312:     if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) {
        !          1313:        int saved_bank = inb(ioaddr + CONFIG_1);
        !          1314:        /* Switch to bank 1 and set the multicast table. */
        !          1315:        outb(0xe4, ioaddr + CONFIG_1);
        !          1316:        for (i = 0; i < 8; i++)
        !          1317:            outb(mc_filter[i], ioaddr + 8 + i);
        !          1318:        memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter));
        !          1319:        outb(saved_bank, ioaddr + CONFIG_1);
        !          1320:     }
        !          1321:     restore_flags(flags);
        !          1322: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.