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

1.1     ! root        1: /*======================================================================
        !             2: 
        !             3:     A PCMCIA ethernet driver for the 3com 3c589 card.
        !             4:     
        !             5:     Copyright (C) 1999 David A. Hinds -- [email protected]
        !             6: 
        !             7:     3c589_cs.c 1.167 2003/08/25 15:57:40
        !             8: 
        !             9:     The network driver code is based on Donald Becker's 3c589 code:
        !            10:     
        !            11:     Written 1994 by Donald Becker.
        !            12:     Copyright 1993 United States Government as represented by the
        !            13:     Director, National Security Agency.  This software may be used and
        !            14:     distributed according to the terms of the GNU General Public License,
        !            15:     incorporated herein by reference.
        !            16:     Donald Becker may be reached at [email protected]
        !            17: 
        !            18: ======================================================================*/
        !            19: 
        !            20: #include <linux/module.h>
        !            21: #include <linux/init.h>
        !            22: #include <linux/kernel.h>
        !            23: #include <linux/sched.h>
        !            24: #include <linux/ptrace.h>
        !            25: #include <linux/slab.h>
        !            26: #include <linux/string.h>
        !            27: #include <linux/timer.h>
        !            28: #include <linux/interrupt.h>
        !            29: #include <linux/in.h>
        !            30: #include <linux/delay.h>
        !            31: #include <asm/io.h>
        !            32: #include <asm/system.h>
        !            33: #include <asm/bitops.h>
        !            34: 
        !            35: #include <linux/netdevice.h>
        !            36: #include <linux/etherdevice.h>
        !            37: #include <linux/skbuff.h>
        !            38: #include <linux/if_arp.h>
        !            39: #include <linux/ioport.h>
        !            40: 
        !            41: #include <pcmcia/version.h>
        !            42: #include <pcmcia/cs_types.h>
        !            43: #include <pcmcia/cs.h>
        !            44: #include <pcmcia/cistpl.h>
        !            45: #include <pcmcia/cisreg.h>
        !            46: #include <pcmcia/ciscode.h>
        !            47: #include <pcmcia/ds.h>
        !            48: 
        !            49: /* To minimize the size of the driver source I only define operating
        !            50:    constants if they are used several times.  You'll need the manual
        !            51:    if you want to understand driver details. */
        !            52: /* Offsets from base I/O address. */
        !            53: #define EL3_DATA       0x00
        !            54: #define EL3_TIMER      0x0a
        !            55: #define EL3_CMD                0x0e
        !            56: #define EL3_STATUS     0x0e
        !            57: 
        !            58: #define EEPROM_READ    0x0080
        !            59: #define EEPROM_BUSY    0x8000
        !            60: 
        !            61: #define EL3WINDOW(win_num) outw(SelectWindow + (win_num), ioaddr + EL3_CMD)
        !            62: 
        !            63: /* The top five bits written to EL3_CMD are a command, the lower
        !            64:    11 bits are the parameter, if applicable. */
        !            65: enum c509cmd {
        !            66:     TotalReset = 0<<11, SelectWindow = 1<<11, StartCoax = 2<<11,
        !            67:     RxDisable = 3<<11, RxEnable = 4<<11, RxReset = 5<<11, RxDiscard = 8<<11,
        !            68:     TxEnable = 9<<11, TxDisable = 10<<11, TxReset = 11<<11,
        !            69:     FakeIntr = 12<<11, AckIntr = 13<<11, SetIntrEnb = 14<<11,
        !            70:     SetStatusEnb = 15<<11, SetRxFilter = 16<<11, SetRxThreshold = 17<<11,
        !            71:     SetTxThreshold = 18<<11, SetTxStart = 19<<11, StatsEnable = 21<<11,
        !            72:     StatsDisable = 22<<11, StopCoax = 23<<11,
        !            73: };
        !            74: 
        !            75: enum c509status {
        !            76:     IntLatch = 0x0001, AdapterFailure = 0x0002, TxComplete = 0x0004,
        !            77:     TxAvailable = 0x0008, RxComplete = 0x0010, RxEarly = 0x0020,
        !            78:     IntReq = 0x0040, StatsFull = 0x0080, CmdBusy = 0x1000
        !            79: };
        !            80: 
        !            81: /* The SetRxFilter command accepts the following classes: */
        !            82: enum RxFilter {
        !            83:     RxStation = 1, RxMulticast = 2, RxBroadcast = 4, RxProm = 8
        !            84: };
        !            85: 
        !            86: /* Register window 1 offsets, the window used in normal operation. */
        !            87: #define TX_FIFO                0x00
        !            88: #define RX_FIFO                0x00
        !            89: #define RX_STATUS      0x08
        !            90: #define TX_STATUS      0x0B
        !            91: #define TX_FREE                0x0C    /* Remaining free bytes in Tx buffer. */
        !            92: 
        !            93: #define WN0_IRQ                0x08    /* Window 0: Set IRQ line in bits 12-15. */
        !            94: #define WN4_MEDIA      0x0A    /* Window 4: Various transcvr/media bits. */
        !            95: #define MEDIA_TP       0x00C0  /* Enable link beat and jabber for 10baseT. */
        !            96: #define MEDIA_LED      0x0001  /* Enable link light on 3C589E cards. */
        !            97: 
        !            98: /* Time in jiffies before concluding Tx hung */
        !            99: #define TX_TIMEOUT     ((400*HZ)/1000)
        !           100: 
        !           101: struct el3_private {
        !           102:     dev_link_t         link;
        !           103:     struct net_device  dev;
        !           104:     dev_node_t                 node;
        !           105:     struct net_device_stats stats;
        !           106:     /* For transceiver monitoring */
        !           107:     struct timer_list  media;
        !           108:     u_short            media_status;
        !           109:     u_short            fast_poll;
        !           110:     u_long             last_irq;
        !           111: };
        !           112: 
        !           113: static char *if_names[] = { "auto", "10baseT", "10base2", "AUI" };
        !           114: 
        !           115: /*====================================================================*/
        !           116: 
        !           117: /* Module parameters */
        !           118: 
        !           119: MODULE_AUTHOR("David Hinds <[email protected]>");
        !           120: MODULE_DESCRIPTION("3Com 3c589 series PCMCIA ethernet driver");
        !           121: MODULE_LICENSE("GPL");
        !           122: 
        !           123: #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
        !           124: 
        !           125: /* Special hook for setting if_port when module is loaded */
        !           126: INT_MODULE_PARM(if_port, 0);
        !           127: 
        !           128: /* Bit map of interrupts to choose from */
        !           129: INT_MODULE_PARM(irq_mask, 0xdeb8);
        !           130: static int irq_list[4] = { -1 };
        !           131: MODULE_PARM(irq_list, "1-4i");
        !           132: 
        !           133: #ifdef PCMCIA_DEBUG
        !           134: INT_MODULE_PARM(pc_debug, PCMCIA_DEBUG);
        !           135: #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
        !           136: static char *version =
        !           137: "3c589_cs.c 1.167 2003/08/25 15:57:40 (David Hinds)";
        !           138: #else
        !           139: #define DEBUG(n, args...)
        !           140: #endif
        !           141: 
        !           142: /*====================================================================*/
        !           143: 
        !           144: static void tc589_config(dev_link_t *link);
        !           145: static void tc589_release(u_long arg);
        !           146: static int tc589_event(event_t event, int priority,
        !           147:                       event_callback_args_t *args);
        !           148: 
        !           149: static u_short read_eeprom(ioaddr_t ioaddr, int index);
        !           150: static void tc589_reset(struct net_device *dev);
        !           151: static void media_check(u_long arg);
        !           152: static int el3_config(struct net_device *dev, struct ifmap *map);
        !           153: static int el3_open(struct net_device *dev);
        !           154: static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev);
        !           155: static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
        !           156: static void update_stats(struct net_device *dev);
        !           157: static struct net_device_stats *el3_get_stats(struct net_device *dev);
        !           158: static int el3_rx(struct net_device *dev);
        !           159: static int el3_close(struct net_device *dev);
        !           160: static void el3_tx_timeout(struct net_device *dev);
        !           161: static void set_multicast_list(struct net_device *dev);
        !           162: 
        !           163: static dev_info_t dev_info = "3c589_cs";
        !           164: 
        !           165: static dev_link_t *tc589_attach(void);
        !           166: static void tc589_detach(dev_link_t *);
        !           167: 
        !           168: static dev_link_t *dev_list = NULL;
        !           169: 
        !           170: /*======================================================================
        !           171: 
        !           172:     This bit of code is used to avoid unregistering network devices
        !           173:     at inappropriate times.  2.2 and later kernels are fairly picky
        !           174:     about when this can happen.
        !           175:     
        !           176: ======================================================================*/
        !           177: 
        !           178: static void flush_stale_links(void)
        !           179: {
        !           180:     dev_link_t *link, *next;
        !           181:     for (link = dev_list; link; link = next) {
        !           182:        next = link->next;
        !           183:        if (link->state & DEV_STALE_LINK)
        !           184:            tc589_detach(link);
        !           185:     }
        !           186: }
        !           187: 
        !           188: /*====================================================================*/
        !           189: 
        !           190: static void cs_error(client_handle_t handle, int func, int ret)
        !           191: {
        !           192:     error_info_t err = { func, ret };
        !           193:     CardServices(ReportError, handle, &err);
        !           194: }
        !           195: 
        !           196: /*======================================================================
        !           197: 
        !           198:     tc589_attach() creates an "instance" of the driver, allocating
        !           199:     local data structures for one device.  The device is registered
        !           200:     with Card Services.
        !           201: 
        !           202: ======================================================================*/
        !           203: 
        !           204: static dev_link_t *tc589_attach(void)
        !           205: {
        !           206:     struct el3_private *lp;
        !           207:     client_reg_t client_reg;
        !           208:     dev_link_t *link;
        !           209:     struct net_device *dev;
        !           210:     int i, ret;
        !           211: 
        !           212:     DEBUG(0, "3c589_attach()\n");
        !           213:     flush_stale_links();
        !           214:     
        !           215:     /* Create new ethernet device */
        !           216:     lp = kmalloc(sizeof(*lp), GFP_KERNEL);
        !           217:     if (!lp) return NULL;
        !           218:     memset(lp, 0, sizeof(*lp));
        !           219:     link = &lp->link; dev = &lp->dev;
        !           220:     link->priv = dev->priv = link->irq.Instance = lp;
        !           221: 
        !           222:     init_timer(&link->release);
        !           223:     link->release.function = &tc589_release;
        !           224:     link->release.data = (u_long)link;
        !           225:     link->io.NumPorts1 = 16;
        !           226:     link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
        !           227:     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
        !           228:     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
        !           229:     if (irq_list[0] == -1)
        !           230:        link->irq.IRQInfo2 = irq_mask;
        !           231:     else
        !           232:        for (i = 0; i < 4; i++)
        !           233:            link->irq.IRQInfo2 |= 1 << irq_list[i];
        !           234:     link->irq.Handler = &el3_interrupt;
        !           235:     link->conf.Attributes = CONF_ENABLE_IRQ;
        !           236:     link->conf.Vcc = 50;
        !           237:     link->conf.IntType = INT_MEMORY_AND_IO;
        !           238:     link->conf.ConfigIndex = 1;
        !           239:     link->conf.Present = PRESENT_OPTION;
        !           240:     
        !           241:     /* The EL3-specific entries in the device structure. */
        !           242:     dev->hard_start_xmit = &el3_start_xmit;
        !           243:     dev->set_config = &el3_config;
        !           244:     dev->get_stats = &el3_get_stats;
        !           245:     dev->set_multicast_list = &set_multicast_list;
        !           246:     ether_setup(dev);
        !           247:     init_dev_name(dev, lp->node);
        !           248:     dev->open = &el3_open;
        !           249:     dev->stop = &el3_close;
        !           250: #ifdef HAVE_TX_TIMEOUT
        !           251:     dev->tx_timeout = el3_tx_timeout;
        !           252:     dev->watchdog_timeo = TX_TIMEOUT;
        !           253: #endif
        !           254:     
        !           255:     /* Register with Card Services */
        !           256:     link->next = dev_list;
        !           257:     dev_list = link;
        !           258:     client_reg.dev_info = &dev_info;
        !           259:     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
        !           260:     client_reg.EventMask =
        !           261:        CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
        !           262:        CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
        !           263:        CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
        !           264:     client_reg.event_handler = &tc589_event;
        !           265:     client_reg.Version = 0x0210;
        !           266:     client_reg.event_callback_args.client_data = link;
        !           267:     ret = CardServices(RegisterClient, &link->handle, &client_reg);
        !           268:     if (ret != 0) {
        !           269:        cs_error(link->handle, RegisterClient, ret);
        !           270:        tc589_detach(link);
        !           271:        return NULL;
        !           272:     }
        !           273:     
        !           274:     return link;
        !           275: } /* tc589_attach */
        !           276: 
        !           277: /*======================================================================
        !           278: 
        !           279:     This deletes a driver "instance".  The device is de-registered
        !           280:     with Card Services.  If it has been released, all local data
        !           281:     structures are freed.  Otherwise, the structures will be freed
        !           282:     when the device is released.
        !           283: 
        !           284: ======================================================================*/
        !           285: 
        !           286: static void tc589_detach(dev_link_t *link)
        !           287: {
        !           288:     struct el3_private *lp = link->priv;
        !           289:     dev_link_t **linkp;
        !           290:     
        !           291:     DEBUG(0, "3c589_detach(0x%p)\n", link);
        !           292:     
        !           293:     /* Locate device structure */
        !           294:     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
        !           295:        if (*linkp == link) break;
        !           296:     if (*linkp == NULL)
        !           297:        return;
        !           298: 
        !           299:     del_timer(&link->release);
        !           300:     if (link->state & DEV_CONFIG) {
        !           301:        tc589_release((u_long)link);
        !           302:        if (link->state & DEV_STALE_CONFIG) {
        !           303:            link->state |= DEV_STALE_LINK;
        !           304:            return;
        !           305:        }
        !           306:     }
        !           307:     
        !           308:     if (link->handle)
        !           309:        CardServices(DeregisterClient, link->handle);
        !           310:     
        !           311:     /* Unlink device structure, free bits */
        !           312:     *linkp = link->next;
        !           313:     if (link->dev)
        !           314:        unregister_netdev(&lp->dev);
        !           315:     kfree(lp);
        !           316:     
        !           317: } /* tc589_detach */
        !           318: 
        !           319: /*======================================================================
        !           320: 
        !           321:     tc589_config() is scheduled to run after a CARD_INSERTION event
        !           322:     is received, to configure the PCMCIA socket, and to make the
        !           323:     ethernet device available to the system.
        !           324:     
        !           325: ======================================================================*/
        !           326: 
        !           327: #define CS_CHECK(fn, args...) \
        !           328: while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
        !           329: 
        !           330: static void tc589_config(dev_link_t *link)
        !           331: {
        !           332:     client_handle_t handle = link->handle;
        !           333:     struct el3_private *lp = link->priv;
        !           334:     struct net_device *dev = &lp->dev;
        !           335:     tuple_t tuple;
        !           336:     cisparse_t parse;
        !           337:     u_short buf[32], *phys_addr;
        !           338:     int last_fn, last_ret, i, j, multi = 0;
        !           339:     ioaddr_t ioaddr;
        !           340:     char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
        !           341:     
        !           342:     DEBUG(0, "3c589_config(0x%p)\n", link);
        !           343: 
        !           344:     phys_addr = (u_short *)dev->dev_addr;
        !           345:     tuple.Attributes = 0;
        !           346:     tuple.DesiredTuple = CISTPL_CONFIG;
        !           347:     CS_CHECK(GetFirstTuple, handle, &tuple);
        !           348:     tuple.TupleData = (cisdata_t *)buf;
        !           349:     tuple.TupleDataMax = sizeof(buf);
        !           350:     tuple.TupleOffset = 0;
        !           351:     CS_CHECK(GetTupleData, handle, &tuple);
        !           352:     CS_CHECK(ParseTuple, handle, &tuple, &parse);
        !           353:     link->conf.ConfigBase = parse.config.base;
        !           354:     link->conf.Present = parse.config.rmask[0];
        !           355:     
        !           356:     /* Is this a 3c562? */
        !           357:     tuple.DesiredTuple = CISTPL_MANFID;
        !           358:     tuple.Attributes = TUPLE_RETURN_COMMON;
        !           359:     if ((CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) &&
        !           360:        (CardServices(GetTupleData, handle, &tuple) == CS_SUCCESS)) {
        !           361:        if (le16_to_cpu(buf[0]) != MANFID_3COM)
        !           362:            printk(KERN_INFO "3c589_cs: hmmm, is this really a "
        !           363:                   "3Com card??\n");
        !           364:        multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562);
        !           365:     }
        !           366:     
        !           367:     /* Configure card */
        !           368:     link->state |= DEV_CONFIG;
        !           369: 
        !           370:     /* For the 3c562, the base address must be xx00-xx7f */
        !           371:     link->io.IOAddrLines = 16;
        !           372:     for (i = j = 0; j < 0x400; j += 0x10) {
        !           373:        if (multi && (j & 0x80)) continue;
        !           374:        link->io.BasePort1 = j ^ 0x300;
        !           375:        i = CardServices(RequestIO, link->handle, &link->io);
        !           376:        if (i == CS_SUCCESS) break;
        !           377:     }
        !           378:     if (i != CS_SUCCESS) {
        !           379:        cs_error(link->handle, RequestIO, i);
        !           380:        goto failed;
        !           381:     }
        !           382:     CS_CHECK(RequestIRQ, link->handle, &link->irq);
        !           383:     CS_CHECK(RequestConfiguration, link->handle, &link->conf);
        !           384:        
        !           385:     dev->irq = link->irq.AssignedIRQ;
        !           386:     dev->base_addr = link->io.BasePort1;
        !           387:     if (register_netdev(dev) != 0) {
        !           388:        printk(KERN_NOTICE "3c589_cs: register_netdev() failed\n");
        !           389:        goto failed;
        !           390:     }
        !           391:     
        !           392:     ioaddr = dev->base_addr;
        !           393:     EL3WINDOW(0);
        !           394: 
        !           395:     /* The 3c589 has an extra EEPROM for configuration info, including
        !           396:        the hardware address.  The 3c562 puts the address in the CIS. */
        !           397:     tuple.DesiredTuple = 0x88;
        !           398:     if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) {
        !           399:        CardServices(GetTupleData, handle, &tuple);
        !           400:        for (i = 0; i < 3; i++)
        !           401:            phys_addr[i] = htons(buf[i]);
        !           402:     } else {
        !           403:        for (i = 0; i < 3; i++)
        !           404:            phys_addr[i] = htons(read_eeprom(ioaddr, i));
        !           405:        if (phys_addr[0] == 0x6060) {
        !           406:            printk(KERN_NOTICE "3c589_cs: IO port conflict at 0x%03lx"
        !           407:                   "-0x%03lx\n", dev->base_addr, dev->base_addr+15);
        !           408:            goto failed;
        !           409:        }
        !           410:     }
        !           411: 
        !           412:     copy_dev_name(lp->node, dev);
        !           413:     link->dev = &lp->node;
        !           414:     
        !           415:     /* The address and resource configuration register aren't loaded from
        !           416:        the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */
        !           417:     outw(0x3f00, ioaddr + 8);
        !           418: 
        !           419:     /* The if_port symbol can be set when the module is loaded */
        !           420:     if ((if_port >= 0) && (if_port <= 3))
        !           421:        dev->if_port = if_port;
        !           422:     else
        !           423:        printk(KERN_NOTICE "3c589_cs: invalid if_port requested\n");
        !           424:     
        !           425:     printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ",
        !           426:           dev->name, (multi ? "562" : "589"), dev->base_addr,
        !           427:           dev->irq);
        !           428:     for (i = 0; i < 6; i++)
        !           429:        printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
        !           430:     i = inl(ioaddr);
        !           431:     printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",
        !           432:           (i & 7) ? 32 : 8, ram_split[(i >> 16) & 3],
        !           433:           if_names[dev->if_port]);
        !           434:     link->state &= ~DEV_CONFIG_PENDING;
        !           435:     return;
        !           436: 
        !           437: cs_failed:
        !           438:     cs_error(link->handle, last_fn, last_ret);
        !           439: failed:
        !           440:     tc589_release((u_long)link);
        !           441:     link->state &= ~DEV_CONFIG_PENDING;
        !           442:     return;
        !           443:     
        !           444: } /* tc589_config */
        !           445: 
        !           446: /*======================================================================
        !           447: 
        !           448:     After a card is removed, tc589_release() will unregister the net
        !           449:     device, and release the PCMCIA configuration.  If the device is
        !           450:     still open, this will be postponed until it is closed.
        !           451:     
        !           452: ======================================================================*/
        !           453: 
        !           454: static void tc589_release(u_long arg)
        !           455: {
        !           456:     dev_link_t *link = (dev_link_t *)arg;
        !           457: 
        !           458:     DEBUG(0, "3c589_release(0x%p)\n", link);
        !           459:     
        !           460:     if (link->open) {
        !           461:        DEBUG(1, "3c589_cs: release postponed, '%s' still open\n",
        !           462:              link->dev->dev_name);
        !           463:        link->state |= DEV_STALE_CONFIG;
        !           464:        return;
        !           465:     }
        !           466:     
        !           467:     CardServices(ReleaseConfiguration, link->handle);
        !           468:     CardServices(ReleaseIO, link->handle, &link->io);
        !           469:     CardServices(ReleaseIRQ, link->handle, &link->irq);
        !           470:     
        !           471:     link->state &= ~DEV_CONFIG;
        !           472:     
        !           473: } /* tc589_release */
        !           474: 
        !           475: /*======================================================================
        !           476: 
        !           477:     The card status event handler.  Mostly, this schedules other
        !           478:     stuff to run after an event is received.  A CARD_REMOVAL event
        !           479:     also sets some flags to discourage the net drivers from trying
        !           480:     to talk to the card any more.
        !           481:     
        !           482: ======================================================================*/
        !           483: 
        !           484: static int tc589_event(event_t event, int priority,
        !           485:                       event_callback_args_t *args)
        !           486: {
        !           487:     dev_link_t *link = args->client_data;
        !           488:     struct el3_private *lp = link->priv;
        !           489:     struct net_device *dev = &lp->dev;
        !           490:     
        !           491:     DEBUG(1, "3c589_event(0x%06x)\n", event);
        !           492:     
        !           493:     switch (event) {
        !           494:     case CS_EVENT_CARD_REMOVAL:
        !           495:        link->state &= ~DEV_PRESENT;
        !           496:        if (link->state & DEV_CONFIG) {
        !           497:            netif_device_detach(dev);
        !           498:            mod_timer(&link->release, jiffies + HZ/20);
        !           499:        }
        !           500:        break;
        !           501:     case CS_EVENT_CARD_INSERTION:
        !           502:        link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
        !           503:        tc589_config(link);
        !           504:        break;
        !           505:     case CS_EVENT_PM_SUSPEND:
        !           506:        link->state |= DEV_SUSPEND;
        !           507:        /* Fall through... */
        !           508:     case CS_EVENT_RESET_PHYSICAL:
        !           509:        if (link->state & DEV_CONFIG) {
        !           510:            if (link->open)
        !           511:                netif_device_detach(dev);
        !           512:            CardServices(ReleaseConfiguration, link->handle);
        !           513:        }
        !           514:        break;
        !           515:     case CS_EVENT_PM_RESUME:
        !           516:        link->state &= ~DEV_SUSPEND;
        !           517:        /* Fall through... */
        !           518:     case CS_EVENT_CARD_RESET:
        !           519:        if (link->state & DEV_CONFIG) {
        !           520:            CardServices(RequestConfiguration, link->handle, &link->conf);
        !           521:            if (link->open) {
        !           522:                tc589_reset(dev);
        !           523:                netif_device_attach(dev);
        !           524:            }
        !           525:        }
        !           526:        break;
        !           527:     }
        !           528:     return 0;
        !           529: } /* tc589_event */
        !           530: 
        !           531: /*====================================================================*/
        !           532: 
        !           533: /*
        !           534:   Use this for commands that may take time to finish
        !           535: */
        !           536: static void tc589_wait_for_completion(struct net_device *dev, int cmd)
        !           537: {
        !           538:     int i = 100;
        !           539:     outw(cmd, dev->base_addr + EL3_CMD);
        !           540:     while (--i > 0)
        !           541:        if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;
        !           542:     if (i == 0)
        !           543:        printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n",
        !           544:               dev->name, cmd);
        !           545: }
        !           546: 
        !           547: /*
        !           548:   Read a word from the EEPROM using the regular EEPROM access register.
        !           549:   Assume that we are in register window zero.
        !           550: */
        !           551: static u_short read_eeprom(ioaddr_t ioaddr, int index)
        !           552: {
        !           553:     int i;
        !           554:     outw(EEPROM_READ + index, ioaddr + 10);
        !           555:     /* Reading the eeprom takes 162 us */
        !           556:     for (i = 1620; i >= 0; i--)
        !           557:        if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)
        !           558:            break;
        !           559:     return inw(ioaddr + 12);
        !           560: }
        !           561: 
        !           562: /*
        !           563:   Set transceiver type, perhaps to something other than what the user
        !           564:   specified in dev->if_port.
        !           565: */
        !           566: static void tc589_set_xcvr(struct net_device *dev, int if_port)
        !           567: {
        !           568:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           569:     ioaddr_t ioaddr = dev->base_addr;
        !           570:     
        !           571:     EL3WINDOW(0);
        !           572:     switch (if_port) {
        !           573:     case 0: case 1: outw(0, ioaddr + 6); break;
        !           574:     case 2: outw(3<<14, ioaddr + 6); break;
        !           575:     case 3: outw(1<<14, ioaddr + 6); break;
        !           576:     }
        !           577:     /* On PCMCIA, this just turns on the LED */
        !           578:     outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD);
        !           579:     /* 10baseT interface, enable link beat and jabber check. */
        !           580:     EL3WINDOW(4);
        !           581:     outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA);
        !           582:     EL3WINDOW(1);
        !           583:     if (if_port == 2)
        !           584:        lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000);
        !           585:     else
        !           586:        lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800);
        !           587: }
        !           588: 
        !           589: static void dump_status(struct net_device *dev)
        !           590: {
        !           591:     ioaddr_t ioaddr = dev->base_addr;
        !           592:     EL3WINDOW(1);
        !           593:     printk(KERN_INFO "  irq status %04x, rx status %04x, tx status "
        !           594:           "%02x  tx free %04x\n", inw(ioaddr+EL3_STATUS),
        !           595:           inw(ioaddr+RX_STATUS), inb(ioaddr+TX_STATUS),
        !           596:           inw(ioaddr+TX_FREE));
        !           597:     EL3WINDOW(4);
        !           598:     printk(KERN_INFO "  diagnostics: fifo %04x net %04x ethernet %04x"
        !           599:           " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),
        !           600:           inw(ioaddr+0x08), inw(ioaddr+0x0a));
        !           601:     EL3WINDOW(1);
        !           602: }
        !           603: 
        !           604: /* Reset and restore all of the 3c589 registers. */
        !           605: static void tc589_reset(struct net_device *dev)
        !           606: {
        !           607:     ioaddr_t ioaddr = dev->base_addr;
        !           608:     int i;
        !           609:     
        !           610:     EL3WINDOW(0);
        !           611:     outw(0x0001, ioaddr + 4);                  /* Activate board. */ 
        !           612:     outw(0x3f00, ioaddr + 8);                  /* Set the IRQ line. */
        !           613:     
        !           614:     /* Set the station address in window 2. */
        !           615:     EL3WINDOW(2);
        !           616:     for (i = 0; i < 6; i++)
        !           617:        outb(dev->dev_addr[i], ioaddr + i);
        !           618: 
        !           619:     tc589_set_xcvr(dev, dev->if_port);
        !           620:     
        !           621:     /* Switch to the stats window, and clear all stats by reading. */
        !           622:     outw(StatsDisable, ioaddr + EL3_CMD);
        !           623:     EL3WINDOW(6);
        !           624:     for (i = 0; i < 9; i++)
        !           625:        inb(ioaddr+i);
        !           626:     inw(ioaddr + 10);
        !           627:     inw(ioaddr + 12);
        !           628:     
        !           629:     /* Switch to register set 1 for normal use. */
        !           630:     EL3WINDOW(1);
        !           631: 
        !           632:     /* Accept b-cast and phys addr only. */
        !           633:     outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);
        !           634:     outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */
        !           635:     outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */
        !           636:     outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */
        !           637:     /* Allow status bits to be seen. */
        !           638:     outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);
        !           639:     /* Ack all pending events, and set active indicator mask. */
        !           640:     outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,
        !           641:         ioaddr + EL3_CMD);
        !           642:     outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull
        !           643:         | AdapterFailure, ioaddr + EL3_CMD);
        !           644: }
        !           645: 
        !           646: static int el3_config(struct net_device *dev, struct ifmap *map)
        !           647: {
        !           648:     if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
        !           649:        if (map->port <= 3) {
        !           650:            dev->if_port = map->port;
        !           651:            printk(KERN_INFO "%s: switched to %s port\n",
        !           652:                   dev->name, if_names[dev->if_port]);
        !           653:            tc589_set_xcvr(dev, dev->if_port);
        !           654:        } else
        !           655:            return -EINVAL;
        !           656:     }
        !           657:     return 0;
        !           658: }
        !           659: 
        !           660: static int el3_open(struct net_device *dev)
        !           661: {
        !           662:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           663:     dev_link_t *link = &lp->link;
        !           664:     
        !           665:     if (!DEV_OK(link))
        !           666:        return -ENODEV;
        !           667: 
        !           668:     link->open++;
        !           669:     MOD_INC_USE_COUNT;
        !           670:     netif_start_queue(dev);
        !           671:     netif_mark_up(dev);
        !           672:     
        !           673:     tc589_reset(dev);
        !           674:     lp->media.function = &media_check;
        !           675:     lp->media.data = (u_long)lp;
        !           676:     lp->media.expires = jiffies + HZ;
        !           677:     add_timer(&lp->media);
        !           678: 
        !           679:     DEBUG(1, "%s: opened, status %4.4x.\n",
        !           680:          dev->name, inw(dev->base_addr + EL3_STATUS));
        !           681:     
        !           682:     return 0;
        !           683: }
        !           684: 
        !           685: static void el3_tx_timeout(struct net_device *dev)
        !           686: {
        !           687:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           688:     ioaddr_t ioaddr = dev->base_addr;
        !           689:     
        !           690:     printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);
        !           691:     dump_status(dev);
        !           692:     lp->stats.tx_errors++;
        !           693:     dev->trans_start = jiffies;
        !           694:     /* Issue TX_RESET and TX_START commands. */
        !           695:     tc589_wait_for_completion(dev, TxReset);
        !           696:     outw(TxEnable, ioaddr + EL3_CMD);
        !           697:     netif_wake_queue(dev);
        !           698: }
        !           699: 
        !           700: static void pop_tx_status(struct net_device *dev)
        !           701: {
        !           702:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           703:     ioaddr_t ioaddr = dev->base_addr;
        !           704:     int i;
        !           705:     
        !           706:     /* Clear the Tx status stack. */
        !           707:     for (i = 32; i > 0; i--) {
        !           708:        u_char tx_status = inb(ioaddr + TX_STATUS);
        !           709:        if (!(tx_status & 0x84)) break;
        !           710:        /* reset transmitter on jabber error or underrun */
        !           711:        if (tx_status & 0x30)
        !           712:            tc589_wait_for_completion(dev, TxReset);
        !           713:        if (tx_status & 0x38) {
        !           714:            DEBUG(1, "%s: transmit error: status 0x%02x\n",
        !           715:                  dev->name, tx_status);
        !           716:            outw(TxEnable, ioaddr + EL3_CMD);
        !           717:            lp->stats.tx_aborted_errors++;
        !           718:        }
        !           719:        outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
        !           720:     }
        !           721: }
        !           722: 
        !           723: static int el3_start_xmit(struct sk_buff *skb, struct net_device *dev)
        !           724: {
        !           725:     ioaddr_t ioaddr = dev->base_addr;
        !           726: 
        !           727:     tx_timeout_check(dev, el3_tx_timeout);
        !           728:     skb_tx_check(dev, skb);
        !           729: 
        !           730:     DEBUG(3, "%s: el3_start_xmit(length = %ld) called, "
        !           731:          "status %4.4x.\n", dev->name, (long)skb->len,
        !           732:          inw(ioaddr + EL3_STATUS));
        !           733: 
        !           734:     add_tx_bytes(&((struct el3_private *)dev->priv)->stats, skb->len);
        !           735: 
        !           736:     /* Put out the doubleword header... */
        !           737:     outw(skb->len, ioaddr + TX_FIFO);
        !           738:     outw(0x00, ioaddr + TX_FIFO);
        !           739:     /* ... and the packet rounded to a doubleword. */
        !           740:     outsl(ioaddr + TX_FIFO, skb->data, (skb->len + 3) >> 2);
        !           741: 
        !           742:     dev->trans_start = jiffies;
        !           743:     if (inw(ioaddr + TX_FREE) > 1536) {
        !           744:        netif_start_queue(dev);
        !           745:     } else
        !           746:        /* Interrupt us when the FIFO has room for max-sized packet. */
        !           747:        outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
        !           748: 
        !           749:     DEV_KFREE_SKB(skb);
        !           750:     pop_tx_status(dev);
        !           751:     
        !           752:     return 0;
        !           753: }
        !           754: 
        !           755: /* The EL3 interrupt handler. */
        !           756: static void el3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        !           757: {
        !           758:     struct el3_private *lp = dev_id;
        !           759:     struct net_device *dev = &lp->dev;
        !           760:     ioaddr_t ioaddr, status;
        !           761:     int i = 0;
        !           762:     
        !           763:     if (!netif_device_present(dev))
        !           764:        return;
        !           765:     ioaddr = dev->base_addr;
        !           766: 
        !           767:     DEBUG(3, "%s: interrupt, status %4.4x.\n",
        !           768:          dev->name, inw(ioaddr + EL3_STATUS));
        !           769:     
        !           770:     while ((status = inw(ioaddr + EL3_STATUS)) &
        !           771:        (IntLatch | RxComplete | StatsFull)) {
        !           772:        if (!netif_device_present(dev) ||
        !           773:            ((status & 0xe000) != 0x2000)) {
        !           774:            DEBUG(1, "%s: interrupt from dead card\n", dev->name);
        !           775:            break;
        !           776:        }
        !           777:        
        !           778:        if (status & RxComplete)
        !           779:            el3_rx(dev);
        !           780:        
        !           781:        if (status & TxAvailable) {
        !           782:            DEBUG(3, "    TX room bit was handled.\n");
        !           783:            /* There's room in the FIFO for a full-sized packet. */
        !           784:            outw(AckIntr | TxAvailable, ioaddr + EL3_CMD);
        !           785:            netif_wake_queue(dev);
        !           786:        }
        !           787:        
        !           788:        if (status & TxComplete)
        !           789:            pop_tx_status(dev);
        !           790: 
        !           791:        if (status & (AdapterFailure | RxEarly | StatsFull)) {
        !           792:            /* Handle all uncommon interrupts. */
        !           793:            if (status & StatsFull)             /* Empty statistics. */
        !           794:                update_stats(dev);
        !           795:            if (status & RxEarly) {             /* Rx early is unused. */
        !           796:                el3_rx(dev);
        !           797:                outw(AckIntr | RxEarly, ioaddr + EL3_CMD);
        !           798:            }
        !           799:            if (status & AdapterFailure) {
        !           800:                u16 fifo_diag;
        !           801:                EL3WINDOW(4);
        !           802:                fifo_diag = inw(ioaddr + 4);
        !           803:                EL3WINDOW(1);
        !           804:                printk(KERN_NOTICE "%s: adapter failure, FIFO diagnostic"
        !           805:                       " register %04x.\n", dev->name, fifo_diag);
        !           806:                if (fifo_diag & 0x0400) {
        !           807:                    /* Tx overrun */
        !           808:                    tc589_wait_for_completion(dev, TxReset);
        !           809:                    outw(TxEnable, ioaddr + EL3_CMD);
        !           810:                }
        !           811:                if (fifo_diag & 0x2000) {
        !           812:                    /* Rx underrun */
        !           813:                    tc589_wait_for_completion(dev, RxReset);
        !           814:                    set_multicast_list(dev);
        !           815:                    outw(RxEnable, ioaddr + EL3_CMD);
        !           816:                }
        !           817:                outw(AckIntr | AdapterFailure, ioaddr + EL3_CMD);
        !           818:            }
        !           819:        }
        !           820:        
        !           821:        if (++i > 10) {
        !           822:            printk(KERN_NOTICE "%s: infinite loop in interrupt, "
        !           823:                   "status %4.4x.\n", dev->name, status);
        !           824:            /* Clear all interrupts */
        !           825:            outw(AckIntr | 0xFF, ioaddr + EL3_CMD);
        !           826:            break;
        !           827:        }
        !           828:        /* Acknowledge the IRQ. */
        !           829:        outw(AckIntr | IntReq | IntLatch, ioaddr + EL3_CMD);
        !           830:     }
        !           831: 
        !           832:     lp->last_irq = jiffies;
        !           833:     DEBUG(3, "%s: exiting interrupt, status %4.4x.\n",
        !           834:          dev->name, inw(ioaddr + EL3_STATUS));
        !           835:     return;
        !           836: }
        !           837: 
        !           838: static void media_check(u_long arg)
        !           839: {
        !           840:     struct el3_private *lp = (struct el3_private *)(arg);
        !           841:     struct net_device *dev = &lp->dev;
        !           842:     ioaddr_t ioaddr = dev->base_addr;
        !           843:     u_short media, errs;
        !           844:     u_long flags;
        !           845: 
        !           846:     if (!netif_device_present(dev)) goto reschedule;
        !           847: 
        !           848:     EL3WINDOW(1);
        !           849:     /* Check for pending interrupt with expired latency timer: with
        !           850:        this, we can limp along even if the interrupt is blocked */
        !           851:     if ((inw(ioaddr + EL3_STATUS) & IntLatch) &&
        !           852:        (inb(ioaddr + EL3_TIMER) == 0xff)) {
        !           853:        if (!lp->fast_poll)
        !           854:            printk(KERN_INFO "%s: interrupt(s) dropped!\n", dev->name);
        !           855:        el3_interrupt(dev->irq, lp, NULL);
        !           856:        lp->fast_poll = HZ;
        !           857:     }
        !           858:     if (lp->fast_poll) {
        !           859:        lp->fast_poll--;
        !           860:        lp->media.expires = jiffies + 1;
        !           861:        add_timer(&lp->media);
        !           862:        return;
        !           863:     }
        !           864:     
        !           865:     save_flags(flags);
        !           866:     cli();
        !           867:     EL3WINDOW(4);
        !           868:     media = inw(ioaddr+WN4_MEDIA) & 0xc810;
        !           869: 
        !           870:     /* Ignore collisions unless we've had no irq's recently */
        !           871:     if (jiffies - lp->last_irq < HZ) {
        !           872:        media &= ~0x0010;
        !           873:     } else {
        !           874:        /* Try harder to detect carrier errors */
        !           875:        EL3WINDOW(6);
        !           876:        outw(StatsDisable, ioaddr + EL3_CMD);
        !           877:        errs = inb(ioaddr + 0);
        !           878:        outw(StatsEnable, ioaddr + EL3_CMD);
        !           879:        lp->stats.tx_carrier_errors += errs;
        !           880:        if (errs || (lp->media_status & 0x0010)) media |= 0x0010;
        !           881:     }
        !           882: 
        !           883:     if (media != lp->media_status) {
        !           884:        if ((media & lp->media_status & 0x8000) &&
        !           885:            ((lp->media_status ^ media) & 0x0800))
        !           886:            printk(KERN_INFO "%s: %s link beat\n", dev->name,
        !           887:                   (lp->media_status & 0x0800 ? "lost" : "found"));
        !           888:        else if ((media & lp->media_status & 0x4000) &&
        !           889:                 ((lp->media_status ^ media) & 0x0010))
        !           890:            printk(KERN_INFO "%s: coax cable %s\n", dev->name,
        !           891:                   (lp->media_status & 0x0010 ? "ok" : "problem"));
        !           892:        if (dev->if_port == 0) {
        !           893:            if (media & 0x8000) {
        !           894:                if (media & 0x0800)
        !           895:                    printk(KERN_INFO "%s: flipped to 10baseT\n",
        !           896:                           dev->name);
        !           897:                else
        !           898:                    tc589_set_xcvr(dev, 2);
        !           899:            } else if (media & 0x4000) {
        !           900:                if (media & 0x0010)
        !           901:                    tc589_set_xcvr(dev, 1);
        !           902:                else
        !           903:                    printk(KERN_INFO "%s: flipped to 10base2\n",
        !           904:                           dev->name);
        !           905:            }
        !           906:        }
        !           907:        lp->media_status = media;
        !           908:     }
        !           909:     
        !           910:     EL3WINDOW(1);
        !           911:     restore_flags(flags);
        !           912: 
        !           913: reschedule:
        !           914:     lp->media.expires = jiffies + HZ;
        !           915:     add_timer(&lp->media);
        !           916: }
        !           917: 
        !           918: static struct net_device_stats *el3_get_stats(struct net_device *dev)
        !           919: {
        !           920:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           921:     unsigned long flags;
        !           922:     dev_link_t *link = &lp->link;
        !           923: 
        !           924:     if (DEV_OK(link)) {
        !           925:        save_flags(flags);
        !           926:        cli();
        !           927:        update_stats(dev);
        !           928:        restore_flags(flags);
        !           929:     }
        !           930:     return &lp->stats;
        !           931: }
        !           932: 
        !           933: /*
        !           934:   Update statistics.  We change to register window 6, so this should be run
        !           935:   single-threaded if the device is active. This is expected to be a rare
        !           936:   operation, and it's simpler for the rest of the driver to assume that
        !           937:   window 1 is always valid rather than use a special window-state variable.
        !           938: */
        !           939: static void update_stats(struct net_device *dev)
        !           940: {
        !           941:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           942:     ioaddr_t ioaddr = dev->base_addr;
        !           943: 
        !           944:     DEBUG(2, "%s: updating the statistics.\n", dev->name);
        !           945:     /* Turn off statistics updates while reading. */
        !           946:     outw(StatsDisable, ioaddr + EL3_CMD);
        !           947:     /* Switch to the stats window, and read everything. */
        !           948:     EL3WINDOW(6);
        !           949:     lp->stats.tx_carrier_errors        += inb(ioaddr + 0);
        !           950:     lp->stats.tx_heartbeat_errors      += inb(ioaddr + 1);
        !           951:     /* Multiple collisions. */         inb(ioaddr + 2);
        !           952:     lp->stats.collisions               += inb(ioaddr + 3);
        !           953:     lp->stats.tx_window_errors         += inb(ioaddr + 4);
        !           954:     lp->stats.rx_fifo_errors           += inb(ioaddr + 5);
        !           955:     lp->stats.tx_packets               += inb(ioaddr + 6);
        !           956:     /* Rx packets   */                 inb(ioaddr + 7);
        !           957:     /* Tx deferrals */                 inb(ioaddr + 8);
        !           958:     /* Rx octets */                    inw(ioaddr + 10);
        !           959:     /* Tx octets */                    inw(ioaddr + 12);
        !           960:     
        !           961:     /* Back to window 1, and turn statistics back on. */
        !           962:     EL3WINDOW(1);
        !           963:     outw(StatsEnable, ioaddr + EL3_CMD);
        !           964: }
        !           965: 
        !           966: static int el3_rx(struct net_device *dev)
        !           967: {
        !           968:     struct el3_private *lp = (struct el3_private *)dev->priv;
        !           969:     ioaddr_t ioaddr = dev->base_addr;
        !           970:     int worklimit = 32;
        !           971:     short rx_status;
        !           972:     
        !           973:     DEBUG(3, "%s: in rx_packet(), status %4.4x, rx_status %4.4x.\n",
        !           974:          dev->name, inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
        !           975:     while (!((rx_status = inw(ioaddr + RX_STATUS)) & 0x8000) &&
        !           976:           (--worklimit >= 0)) {
        !           977:        if (rx_status & 0x4000) { /* Error, update stats. */
        !           978:            short error = rx_status & 0x3800;
        !           979:            lp->stats.rx_errors++;
        !           980:            switch (error) {
        !           981:            case 0x0000:        lp->stats.rx_over_errors++; break;
        !           982:            case 0x0800:        lp->stats.rx_length_errors++; break;
        !           983:            case 0x1000:        lp->stats.rx_frame_errors++; break;
        !           984:            case 0x1800:        lp->stats.rx_length_errors++; break;
        !           985:            case 0x2000:        lp->stats.rx_frame_errors++; break;
        !           986:            case 0x2800:        lp->stats.rx_crc_errors++; break;
        !           987:            }
        !           988:        } else {
        !           989:            short pkt_len = rx_status & 0x7ff;
        !           990:            struct sk_buff *skb;
        !           991:            
        !           992:            skb = dev_alloc_skb(pkt_len+5);
        !           993:            
        !           994:            DEBUG(3, "    Receiving packet size %d status %4.4x.\n",
        !           995:                  pkt_len, rx_status);
        !           996:            if (skb != NULL) {
        !           997:                skb->dev = dev;
        !           998:                skb_reserve(skb, 2);
        !           999:                insl(ioaddr+RX_FIFO, skb_put(skb, pkt_len),
        !          1000:                     (pkt_len+3)>>2);
        !          1001:                skb->protocol = eth_type_trans(skb, dev);
        !          1002:                netif_rx(skb);
        !          1003:                dev->last_rx = jiffies;
        !          1004:                lp->stats.rx_packets++;
        !          1005:                add_rx_bytes(&lp->stats, pkt_len);
        !          1006:            } else {
        !          1007:                DEBUG(1, "%s: couldn't allocate a sk_buff of"
        !          1008:                      " size %d.\n", dev->name, pkt_len);
        !          1009:                lp->stats.rx_dropped++;
        !          1010:            }
        !          1011:        }
        !          1012:        /* Pop the top of the Rx FIFO */
        !          1013:        tc589_wait_for_completion(dev, RxDiscard);
        !          1014:     }
        !          1015:     if (worklimit == 0)
        !          1016:        printk(KERN_NOTICE "%s: too much work in el3_rx!\n", dev->name);
        !          1017:     return 0;
        !          1018: }
        !          1019: 
        !          1020: static void set_multicast_list(struct net_device *dev)
        !          1021: {
        !          1022:     struct el3_private *lp = dev->priv;
        !          1023:     dev_link_t *link = &lp->link;
        !          1024:     ioaddr_t ioaddr = dev->base_addr;
        !          1025:     u_short opts = SetRxFilter | RxStation | RxBroadcast;
        !          1026: 
        !          1027:     if (!(DEV_OK(link))) return;
        !          1028:     if (dev->flags & IFF_PROMISC)
        !          1029:        opts |= RxMulticast | RxProm;
        !          1030:     else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
        !          1031:        opts |= RxMulticast;
        !          1032:     outw(opts, ioaddr + EL3_CMD);
        !          1033: }
        !          1034: 
        !          1035: static int el3_close(struct net_device *dev)
        !          1036: {
        !          1037:     struct el3_private *lp = dev->priv;
        !          1038:     dev_link_t *link = &lp->link;
        !          1039:     ioaddr_t ioaddr = dev->base_addr;
        !          1040:     
        !          1041:     DEBUG(1, "%s: shutting down ethercard.\n", dev->name);
        !          1042: 
        !          1043:     if (DEV_OK(link)) {
        !          1044:        /* Turn off statistics ASAP.  We update lp->stats below. */
        !          1045:        outw(StatsDisable, ioaddr + EL3_CMD);
        !          1046:        
        !          1047:        /* Disable the receiver and transmitter. */
        !          1048:        outw(RxDisable, ioaddr + EL3_CMD);
        !          1049:        outw(TxDisable, ioaddr + EL3_CMD);
        !          1050:        
        !          1051:        if (dev->if_port == 2)
        !          1052:            /* Turn off thinnet power.  Green! */
        !          1053:            outw(StopCoax, ioaddr + EL3_CMD);
        !          1054:        else if (dev->if_port == 1) {
        !          1055:            /* Disable link beat and jabber */
        !          1056:            EL3WINDOW(4);
        !          1057:            outw(0, ioaddr + WN4_MEDIA);
        !          1058:        }
        !          1059:        
        !          1060:        /* Switching back to window 0 disables the IRQ. */
        !          1061:        EL3WINDOW(0);
        !          1062:        /* But we explicitly zero the IRQ line select anyway. */
        !          1063:        outw(0x0f00, ioaddr + WN0_IRQ);
        !          1064:         
        !          1065:        /* Check if the card still exists */
        !          1066:        if ((inw(ioaddr+EL3_STATUS) & 0xe000) == 0x2000)
        !          1067:            update_stats(dev);
        !          1068:     }
        !          1069: 
        !          1070:     link->open--;
        !          1071:     netif_stop_queue(dev);
        !          1072:     netif_mark_down(dev);
        !          1073:     del_timer(&lp->media);
        !          1074:     if (link->state & DEV_STALE_CONFIG)
        !          1075:        mod_timer(&link->release, jiffies + HZ/20);
        !          1076:     
        !          1077:     MOD_DEC_USE_COUNT;
        !          1078:     
        !          1079:     return 0;
        !          1080: }
        !          1081: 
        !          1082: /*====================================================================*/
        !          1083: 
        !          1084: static int __init init_3c589_cs(void)
        !          1085: {
        !          1086:     servinfo_t serv;
        !          1087:     DEBUG(0, "%s\n", version);
        !          1088:     CardServices(GetCardServicesInfo, &serv);
        !          1089:     if (serv.Revision != CS_RELEASE_CODE) {
        !          1090:        printk(KERN_NOTICE "3c589_cs: Card Services release "
        !          1091:               "does not match!\n");
        !          1092:        return -EINVAL;
        !          1093:     }
        !          1094:     register_pccard_driver(&dev_info, &tc589_attach, &tc589_detach);
        !          1095:     return 0;
        !          1096: }
        !          1097: 
        !          1098: static void __exit exit_3c589_cs(void)
        !          1099: {
        !          1100:     DEBUG(0, "3c589_cs: unloading\n");
        !          1101:     unregister_pccard_driver(&dev_info);
        !          1102:     while (dev_list != NULL)
        !          1103:        tc589_detach(dev_list);
        !          1104: }
        !          1105: 
        !          1106: module_init(init_3c589_cs);
        !          1107: module_exit(exit_3c589_cs);

unix.superglobalmegacorp.com

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