Annotation of Gnu-Mach/linux/pcmcia-cs/wireless/orinoco_cs.c, revision 1.1.1.1

1.1       root        1: /* orinoco_cs.c 0.13e  - (formerly known as dldwd_cs.c)
                      2:  *
                      3:  * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
                      4:  * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
                      5:  * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
                      6:  * It should also be usable on various Prism II based cards such as the
                      7:  * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
                      8:  * cards such as the 3Com AirConnect and Ericsson WLAN.
                      9:  * 
                     10:  * Copyright notice & release notes in file orinoco.c
                     11:  */
                     12: 
                     13: #include <linux/config.h>
                     14: #include <linux/module.h>
                     15: #include <linux/kernel.h>
                     16: #include <linux/init.h>
                     17: #include <linux/sched.h>
                     18: #include <linux/ptrace.h>
                     19: #include <linux/slab.h>
                     20: #include <linux/string.h>
                     21: #include <linux/ioport.h>
                     22: #include <linux/netdevice.h>
                     23: #include <linux/if_arp.h>
                     24: #include <linux/etherdevice.h>
                     25: #include <linux/wireless.h>
                     26: 
                     27: #include <pcmcia/version.h>
                     28: #include <pcmcia/cs_types.h>
                     29: #include <pcmcia/cs.h>
                     30: #include <pcmcia/cistpl.h>
                     31: #include <pcmcia/cisreg.h>
                     32: #include <pcmcia/ds.h>
                     33: 
                     34: #include <asm/uaccess.h>
                     35: #include <asm/io.h>
                     36: #include <asm/system.h>
                     37: 
                     38: #include "orinoco.h"
                     39: 
                     40: /********************************************************************/
                     41: /* Module stuff                                                            */
                     42: /********************************************************************/
                     43: 
                     44: MODULE_AUTHOR("David Gibson <[email protected]>");
                     45: MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
                     46: #ifdef MODULE_LICENSE
                     47: MODULE_LICENSE("Dual MPL/GPL");
                     48: #endif
                     49: 
                     50: /* Module parameters */
                     51: 
                     52: /* The old way: bit map of interrupts to choose from */
                     53: /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */
                     54: static uint irq_mask = 0xdeb8;
                     55: /* Newer, simpler way of listing specific interrupts */
                     56: static int irq_list[4] = { -1 };
                     57: 
                     58: /* Some D-Link cards have buggy CIS. They do work at 5v properly, but
                     59:  * don't have any CIS entry for it. This workaround it... */
                     60: static int ignore_cis_vcc; /* = 0 */
                     61: 
                     62: MODULE_PARM(irq_mask, "i");
                     63: MODULE_PARM(irq_list, "1-4i");
                     64: MODULE_PARM(ignore_cis_vcc, "i");
                     65: 
                     66: /********************************************************************/
                     67: /* Magic constants                                                 */
                     68: /********************************************************************/
                     69: 
                     70: /*
                     71:  * The dev_info variable is the "key" that is used to match up this
                     72:  * device driver with appropriate cards, through the card
                     73:  * configuration database.
                     74:  */
                     75: static dev_info_t dev_info = "orinoco_cs";
                     76: 
                     77: /********************************************************************/
                     78: /* Data structures                                                 */
                     79: /********************************************************************/
                     80: 
                     81: /* PCMCIA specific device information (goes in the card field of
                     82:  * struct orinoco_private */
                     83: struct orinoco_pccard {
                     84:        dev_link_t link;
                     85:        dev_node_t node;
                     86: 
                     87:        /* Used to handle hard reset */
                     88:        /* yuck, we need this hack to work around the insanity of the
                     89:          * PCMCIA layer */
                     90:        unsigned long hard_reset_in_progress; 
                     91: };
                     92: 
                     93: /*
                     94:  * A linked list of "instances" of the device.  Each actual PCMCIA
                     95:  * card corresponds to one device instance, and is described by one
                     96:  * dev_link_t structure (defined in ds.h).
                     97:  */
                     98: static dev_link_t *dev_list; /* = NULL */
                     99: 
                    100: /********************************************************************/
                    101: /* Function prototypes                                             */
                    102: /********************************************************************/
                    103: 
                    104: /* device methods */
                    105: static int orinoco_cs_hard_reset(struct orinoco_private *priv);
                    106: 
                    107: /* PCMCIA gumpf */
                    108: static void orinoco_cs_config(dev_link_t * link);
                    109: static void orinoco_cs_release(u_long arg);
                    110: static int orinoco_cs_event(event_t event, int priority,
                    111:                            event_callback_args_t * args);
                    112: 
                    113: static dev_link_t *orinoco_cs_attach(void);
                    114: static void orinoco_cs_detach(dev_link_t *);
                    115: 
                    116: /********************************************************************/
                    117: /* Device methods                                                  */
                    118: /********************************************************************/
                    119: 
                    120: static int
                    121: orinoco_cs_hard_reset(struct orinoco_private *priv)
                    122: {
                    123:        struct orinoco_pccard *card = priv->card;
                    124:        dev_link_t *link = &card->link;
                    125:        int err;
                    126: 
                    127:        /* We need atomic ops here, because we're not holding the lock */
                    128:        set_bit(0, &card->hard_reset_in_progress);
                    129: 
                    130:        err = CardServices(ResetCard, link->handle, NULL);
                    131:        if (err)
                    132:                return err;
                    133: 
                    134:        clear_bit(0, &card->hard_reset_in_progress);
                    135: 
                    136:        return 0;
                    137: }
                    138: 
                    139: /********************************************************************/
                    140: /* PCMCIA stuff                                                    */
                    141: /********************************************************************/
                    142: 
                    143: /* In 2.5 (as of 2.5.69 at least) there is a cs_error exported which
                    144:  * does this, but it's not in 2.4 so we do our own for now. */
                    145: static void
                    146: orinoco_cs_error(client_handle_t handle, int func, int ret)
                    147: {
                    148:        error_info_t err = { func, ret };
                    149:        CardServices(ReportError, handle, &err);
                    150: }
                    151: 
                    152: 
                    153: /* Remove zombie instances (card removed, detach pending) */
                    154: static void
                    155: flush_stale_links(void)
                    156: {
                    157:        dev_link_t *link, *next;
                    158: 
                    159:        TRACE_ENTER("");
                    160: 
                    161:        for (link = dev_list; link; link = next) {
                    162:                next = link->next;
                    163:                if (link->state & DEV_STALE_LINK) {
                    164:                        orinoco_cs_detach(link);
                    165:                }
                    166:        }
                    167:        TRACE_EXIT("");
                    168: }
                    169: 
                    170: /*
                    171:  * This creates an "instance" of the driver, allocating local data
                    172:  * structures for one device.  The device is registered with Card
                    173:  * Services.
                    174:  * 
                    175:  * The dev_link structure is initialized, but we don't actually
                    176:  * configure the card at this point -- we wait until we receive a card
                    177:  * insertion event.  */
                    178: static dev_link_t *
                    179: orinoco_cs_attach(void)
                    180: {
                    181:        struct net_device *dev;
                    182:        struct orinoco_private *priv;
                    183:        struct orinoco_pccard *card;
                    184:        dev_link_t *link;
                    185:        client_reg_t client_reg;
                    186:        int ret, i;
                    187: 
                    188:        /* A bit of cleanup */
                    189:        flush_stale_links();
                    190: 
                    191:        dev = alloc_orinocodev(sizeof(*card), orinoco_cs_hard_reset);
                    192:        if (! dev)
                    193:                return NULL;
                    194:        priv = dev->priv;
                    195:        card = priv->card;
                    196: 
                    197:        /* Link both structures together */
                    198:        link = &card->link;
                    199:        link->priv = dev;
                    200: 
                    201:        /* Initialize the dev_link_t structure */
                    202:        init_timer(&link->release);
                    203:        link->release.function = &orinoco_cs_release;
                    204:        link->release.data = (u_long) link;
                    205: 
                    206:        /* Interrupt setup */
                    207:        link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
                    208:        link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
                    209:        if (irq_list[0] == -1)
                    210:                link->irq.IRQInfo2 = irq_mask;
                    211:        else
                    212:                for (i = 0; i < 4; i++)
                    213:                        link->irq.IRQInfo2 |= 1 << irq_list[i];
                    214:        link->irq.Handler = NULL;
                    215: 
                    216:        /* General socket configuration defaults can go here.  In this
                    217:         * client, we assume very little, and rely on the CIS for
                    218:         * almost everything.  In most clients, many details (i.e.,
                    219:         * number, sizes, and attributes of IO windows) are fixed by
                    220:         * the nature of the device, and can be hard-wired here. */
                    221:        link->conf.Attributes = 0;
                    222:        link->conf.IntType = INT_MEMORY_AND_IO;
                    223: 
                    224:        /* Register with Card Services */
                    225:        /* FIXME: need a lock? */
                    226:        link->next = dev_list;
                    227:        dev_list = link;
                    228: 
                    229:        client_reg.dev_info = &dev_info;
                    230:        client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
                    231:        client_reg.EventMask =
                    232:                CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
                    233:                CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
                    234:                CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
                    235:        client_reg.event_handler = &orinoco_cs_event;
                    236:        client_reg.Version = 0x0210; /* FIXME: what does this mean? */
                    237:        client_reg.event_callback_args.client_data = link;
                    238: 
                    239:        ret = CardServices(RegisterClient, &link->handle, &client_reg);
                    240:        if (ret != CS_SUCCESS) {
                    241:                orinoco_cs_error(link->handle, RegisterClient, ret);
                    242:                orinoco_cs_detach(link);
                    243:                return NULL;
                    244:        }
                    245: 
                    246:        return link;
                    247: }                              /* orinoco_cs_attach */
                    248: 
                    249: /*
                    250:  * This deletes a driver "instance".  The device is de-registered with
                    251:  * Card Services.  If it has been released, all local data structures
                    252:  * are freed.  Otherwise, the structures will be freed when the device
                    253:  * is released.
                    254:  */
                    255: static void
                    256: orinoco_cs_detach(dev_link_t * link)
                    257: {
                    258:        dev_link_t **linkp;
                    259:        struct net_device *dev = link->priv;
                    260: 
                    261:        /* Locate device structure */
                    262:        for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
                    263:                if (*linkp == link)
                    264:                        break;
                    265:        if (*linkp == NULL) {
                    266:                BUG();
                    267:                return;
                    268:        }
                    269: 
                    270:        if (link->state & DEV_CONFIG) {
                    271:                orinoco_cs_release((u_long)link);
                    272:                if (link->state & DEV_CONFIG) {
                    273:                        link->state |= DEV_STALE_LINK;
                    274:                        return;
                    275:                }
                    276:        }
                    277: 
                    278:        /* Break the link with Card Services */
                    279:        if (link->handle)
                    280:                CardServices(DeregisterClient, link->handle);
                    281: 
                    282:        /* Unlink device structure, and free it */
                    283:        *linkp = link->next;
                    284:        DEBUG(0, "orinoco_cs: detach: link=%p link->dev=%p\n", link, link->dev);
                    285:        if (link->dev) {
                    286:                DEBUG(0, "orinoco_cs: About to unregister net device %p\n",
                    287:                      dev);
                    288:                unregister_netdev(dev);
                    289:        }
                    290:        kfree(dev);
                    291: }                              /* orinoco_cs_detach */
                    292: 
                    293: /*
                    294:  * orinoco_cs_config() is scheduled to run after a CARD_INSERTION
                    295:  * event is received, to configure the PCMCIA socket, and to make the
                    296:  * device available to the system.
                    297:  */
                    298: 
                    299: #define CS_CHECK(fn, args...) \
                    300:        while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed
                    301: 
                    302: #define CFG_CHECK(fn, args...) \
                    303:        if (CardServices(fn, args) != 0) goto next_entry
                    304: 
                    305: static void
                    306: orinoco_cs_config(dev_link_t *link)
                    307: {
                    308:        struct net_device *dev = link->priv;
                    309:        client_handle_t handle = link->handle;
                    310:        struct orinoco_private *priv = dev->priv;
                    311:        struct orinoco_pccard *card = priv->card;
                    312:        hermes_t *hw = &priv->hw;
                    313:        int last_fn, last_ret;
                    314:        u_char buf[64];
                    315:        config_info_t conf;
                    316:        cisinfo_t info;
                    317:        tuple_t tuple;
                    318:        cisparse_t parse;
                    319: 
                    320:        CS_CHECK(ValidateCIS, handle, &info);
                    321: 
                    322:        /*
                    323:         * This reads the card's CONFIG tuple to find its
                    324:         * configuration registers.
                    325:         */
                    326:        tuple.DesiredTuple = CISTPL_CONFIG;
                    327:        tuple.Attributes = 0;
                    328:        tuple.TupleData = buf;
                    329:        tuple.TupleDataMax = sizeof(buf);
                    330:        tuple.TupleOffset = 0;
                    331:        CS_CHECK(GetFirstTuple, handle, &tuple);
                    332:        CS_CHECK(GetTupleData, handle, &tuple);
                    333:        CS_CHECK(ParseTuple, handle, &tuple, &parse);
                    334:        link->conf.ConfigBase = parse.config.base;
                    335:        link->conf.Present = parse.config.rmask[0];
                    336: 
                    337:        /* Configure card */
                    338:        link->state |= DEV_CONFIG;
                    339: 
                    340:        /* Look up the current Vcc */
                    341:        CS_CHECK(GetConfigurationInfo, handle, &conf);
                    342:        link->conf.Vcc = conf.Vcc;
                    343: 
                    344:        /*
                    345:         * In this loop, we scan the CIS for configuration table
                    346:         * entries, each of which describes a valid card
                    347:         * configuration, including voltage, IO window, memory window,
                    348:         * and interrupt settings.
                    349:         *
                    350:         * We make no assumptions about the card to be configured: we
                    351:         * use just the information available in the CIS.  In an ideal
                    352:         * world, this would work for any PCMCIA card, but it requires
                    353:         * a complete and accurate CIS.  In practice, a driver usually
                    354:         * "knows" most of these things without consulting the CIS,
                    355:         * and most client drivers will only use the CIS to fill in
                    356:         * implementation-defined details.
                    357:         */
                    358:        tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
                    359:        CS_CHECK(GetFirstTuple, handle, &tuple);
                    360:        while (1) {
                    361:                cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
                    362:                cistpl_cftable_entry_t dflt = { .index = 0 };
                    363: 
                    364:                CFG_CHECK(GetTupleData, handle, &tuple);
                    365:                CFG_CHECK(ParseTuple, handle, &tuple, &parse);
                    366: 
                    367:                if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
                    368:                        dflt = *cfg;
                    369:                if (cfg->index == 0)
                    370:                        goto next_entry;
                    371:                link->conf.ConfigIndex = cfg->index;
                    372: 
                    373:                /* Does this card need audio output? */
                    374:                if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
                    375:                        link->conf.Attributes |= CONF_ENABLE_SPKR;
                    376:                        link->conf.Status = CCSR_AUDIO_ENA;
                    377:                }
                    378: 
                    379:                /* Use power settings for Vcc and Vpp if present */
                    380:                /* Note that the CIS values need to be rescaled */
                    381:                if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
                    382:                        if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
                    383:                                DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
                    384:                                if (!ignore_cis_vcc)
                    385:                                        goto next_entry;
                    386:                        }
                    387:                } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
                    388:                        if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
                    389:                                DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
                    390:                                if(!ignore_cis_vcc)
                    391:                                        goto next_entry;
                    392:                        }
                    393:                }
                    394: 
                    395:                if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
                    396:                        link->conf.Vpp1 = link->conf.Vpp2 =
                    397:                            cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
                    398:                else if (dflt.vpp1.present & (1 << CISTPL_POWER_VNOM))
                    399:                        link->conf.Vpp1 = link->conf.Vpp2 =
                    400:                            dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
                    401:                
                    402:                /* Do we need to allocate an interrupt? */
                    403:                if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
                    404:                        link->conf.Attributes |= CONF_ENABLE_IRQ;
                    405: 
                    406:                /* IO window settings */
                    407:                link->io.NumPorts1 = link->io.NumPorts2 = 0;
                    408:                if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
                    409:                        cistpl_io_t *io =
                    410:                            (cfg->io.nwin) ? &cfg->io : &dflt.io;
                    411:                        link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
                    412:                        if (!(io->flags & CISTPL_IO_8BIT))
                    413:                                link->io.Attributes1 =
                    414:                                    IO_DATA_PATH_WIDTH_16;
                    415:                        if (!(io->flags & CISTPL_IO_16BIT))
                    416:                                link->io.Attributes1 =
                    417:                                    IO_DATA_PATH_WIDTH_8;
                    418:                        link->io.IOAddrLines =
                    419:                            io->flags & CISTPL_IO_LINES_MASK;
                    420:                        link->io.BasePort1 = io->win[0].base;
                    421:                        link->io.NumPorts1 = io->win[0].len;
                    422:                        if (io->nwin > 1) {
                    423:                                link->io.Attributes2 =
                    424:                                    link->io.Attributes1;
                    425:                                link->io.BasePort2 = io->win[1].base;
                    426:                                link->io.NumPorts2 = io->win[1].len;
                    427:                        }
                    428: 
                    429:                        /* This reserves IO space but doesn't actually enable it */
                    430:                        CFG_CHECK(RequestIO, link->handle, &link->io);
                    431:                }
                    432: 
                    433: 
                    434:                /* If we got this far, we're cool! */
                    435: 
                    436:                break;
                    437:                
                    438:        next_entry:
                    439:                if (link->io.NumPorts1)
                    440:                        CardServices(ReleaseIO, link->handle, &link->io);
                    441:                last_ret = CardServices(GetNextTuple, handle, &tuple);
                    442:                if (last_ret  == CS_NO_MORE_ITEMS) {
                    443:                        printk(KERN_ERR "GetNextTuple().  No matching CIS configuration, "
                    444:                               "maybe you need the ignore_cis_vcc=1 parameter.\n");
                    445:                        goto cs_failed;
                    446:                }
                    447:        }
                    448: 
                    449:        /*
                    450:         * Allocate an interrupt line.  Note that this does not assign
                    451:         * a handler to the interrupt, unless the 'Handler' member of
                    452:         * the irq structure is initialized.
                    453:         */
                    454:        if (link->conf.Attributes & CONF_ENABLE_IRQ) {
                    455:                int i;
                    456: 
                    457:                link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
                    458:                link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID;
                    459:                if (irq_list[0] == -1)
                    460:                        link->irq.IRQInfo2 = irq_mask;
                    461:                else
                    462:                        for (i=0; i<4; i++)
                    463:                                link->irq.IRQInfo2 |= 1 << irq_list[i];
                    464:                
                    465:                link->irq.Handler = orinoco_interrupt; 
                    466:                link->irq.Instance = dev; 
                    467:                
                    468:                CS_CHECK(RequestIRQ, link->handle, &link->irq);
                    469:        }
                    470: 
                    471:        /* We initialize the hermes structure before completing PCMCIA
                    472:         * configuration just in case the interrupt handler gets
                    473:         * called. */
                    474:        hermes_struct_init(hw, link->io.BasePort1,
                    475:                                HERMES_IO, HERMES_16BIT_REGSPACING);
                    476: 
                    477:        /*
                    478:         * This actually configures the PCMCIA socket -- setting up
                    479:         * the I/O windows and the interrupt mapping, and putting the
                    480:         * card and host interface into "Memory and IO" mode.
                    481:         */
                    482:        CS_CHECK(RequestConfiguration, link->handle, &link->conf);
                    483: 
                    484:        /* Ok, we have the configuration, prepare to register the netdev */
                    485:        dev->base_addr = link->io.BasePort1;
                    486:        dev->irq = link->irq.AssignedIRQ;
                    487:        SET_MODULE_OWNER(dev);
                    488:        card->node.major = card->node.minor = 0;
                    489: 
                    490:        /* register_netdev will give us an ethX name */
                    491:        dev->name[0] = '\0';
                    492:        /* Tell the stack we exist */
                    493:        if (register_netdev(dev) != 0) {
                    494:                printk(KERN_ERR "orinoco_cs: register_netdev() failed\n");
                    495:                goto failed;
                    496:        }
                    497: 
                    498:        /* At this point, the dev_node_t structure(s) needs to be
                    499:         * initialized and arranged in a linked list at link->dev. */
                    500:        strcpy(card->node.dev_name, dev->name);
                    501:        link->dev = &card->node; /* link->dev being non-NULL is also
                    502:                                     used to indicate that the
                    503:                                     net_device has been registered */
                    504:        link->state &= ~DEV_CONFIG_PENDING;
                    505: 
                    506:        /* Finally, report what we've done */
                    507:        printk(KERN_DEBUG "%s: index 0x%02x: Vcc %d.%d",
                    508:               dev->name, link->conf.ConfigIndex,
                    509:               link->conf.Vcc / 10, link->conf.Vcc % 10);
                    510:        if (link->conf.Vpp1)
                    511:                printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
                    512:                       link->conf.Vpp1 % 10);
                    513:        if (link->conf.Attributes & CONF_ENABLE_IRQ)
                    514:                printk(", irq %d", link->irq.AssignedIRQ);
                    515:        if (link->io.NumPorts1)
                    516:                printk(", io 0x%04x-0x%04x", link->io.BasePort1,
                    517:                       link->io.BasePort1 + link->io.NumPorts1 - 1);
                    518:        if (link->io.NumPorts2)
                    519:                printk(" & 0x%04x-0x%04x", link->io.BasePort2,
                    520:                       link->io.BasePort2 + link->io.NumPorts2 - 1);
                    521:        printk("\n");
                    522: 
                    523:        return;
                    524: 
                    525:  cs_failed:
                    526:        orinoco_cs_error(link->handle, last_fn, last_ret);
                    527: 
                    528:  failed:
                    529:        orinoco_cs_release((u_long) link);
                    530: }                              /* orinoco_cs_config */
                    531: 
                    532: /*
                    533:  * After a card is removed, orinoco_cs_release() will unregister the
                    534:  * device, and release the PCMCIA configuration.  If the device is
                    535:  * still open, this will be postponed until it is closed.
                    536:  */
                    537: static void
                    538: orinoco_cs_release(u_long arg)
                    539: {
                    540:        dev_link_t *link = (dev_link_t *) arg;
                    541:        struct net_device *dev = link->priv;
                    542:        struct orinoco_private *priv = dev->priv;
                    543:        unsigned long flags;
                    544: 
                    545:        /* We're committed to taking the device away now, so mark the
                    546:         * hardware as unavailable */
                    547:        spin_lock_irqsave(&priv->lock, flags);
                    548:        priv->hw_unavailable++;
                    549:        spin_unlock_irqrestore(&priv->lock, flags);
                    550: 
                    551:        /* Don't bother checking to see if these succeed or not */
                    552:        CardServices(ReleaseConfiguration, link->handle);
                    553:        if (link->io.NumPorts1)
                    554:                CardServices(ReleaseIO, link->handle, &link->io);
                    555:        if (link->irq.AssignedIRQ)
                    556:                CardServices(ReleaseIRQ, link->handle, &link->irq);
                    557:        link->state &= ~DEV_CONFIG;
                    558: }                              /* orinoco_cs_release */
                    559: 
                    560: /*
                    561:  * The card status event handler.  Mostly, this schedules other stuff
                    562:  * to run after an event is received.
                    563:  */
                    564: static int
                    565: orinoco_cs_event(event_t event, int priority,
                    566:                       event_callback_args_t * args)
                    567: {
                    568:        dev_link_t *link = args->client_data;
                    569:        struct net_device *dev = link->priv;
                    570:        struct orinoco_private *priv = dev->priv;
                    571:        struct orinoco_pccard *card = priv->card;
                    572:        int err = 0;
                    573:        unsigned long flags;
                    574: 
                    575:        switch (event) {
                    576:        case CS_EVENT_CARD_REMOVAL:
                    577:                link->state &= ~DEV_PRESENT;
                    578:                if (link->state & DEV_CONFIG) {
                    579:                        orinoco_lock(priv, &flags);
                    580: 
                    581:                        netif_device_detach(dev);
                    582:                        priv->hw_unavailable++;
                    583: 
                    584:                        orinoco_unlock(priv, &flags);
                    585:                }
                    586:                break;
                    587: 
                    588:        case CS_EVENT_CARD_INSERTION:
                    589:                link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
                    590:                orinoco_cs_config(link);
                    591:                break;
                    592: 
                    593:        case CS_EVENT_PM_SUSPEND:
                    594:                link->state |= DEV_SUSPEND;
                    595:                /* Fall through... */
                    596:        case CS_EVENT_RESET_PHYSICAL:
                    597:                /* Mark the device as stopped, to block IO until later */
                    598:                if (link->state & DEV_CONFIG) {
                    599:                        /* This is probably racy, but I can't think of
                    600:                            a better way, short of rewriting the PCMCIA
                    601:                            layer to not suck :-( */
                    602:                        if (! test_bit(0, &card->hard_reset_in_progress)) {
                    603:                                spin_lock_irqsave(&priv->lock, flags);
                    604: 
                    605:                                err = __orinoco_down(dev);
                    606:                                if (err)
                    607:                                        printk(KERN_WARNING "%s: %s: Error %d downing interface\n",
                    608:                                               dev->name,
                    609:                                               event == CS_EVENT_PM_SUSPEND ? "SUSPEND" : "RESET_PHYSICAL",
                    610:                                               err);
                    611:                                
                    612:                                netif_device_detach(dev);
                    613:                                priv->hw_unavailable++;
                    614: 
                    615:                                spin_unlock_irqrestore(&priv->lock, flags);
                    616:                        }
                    617: 
                    618:                        CardServices(ReleaseConfiguration, link->handle);
                    619:                }
                    620:                break;
                    621: 
                    622:        case CS_EVENT_PM_RESUME:
                    623:                link->state &= ~DEV_SUSPEND;
                    624:                /* Fall through... */
                    625:        case CS_EVENT_CARD_RESET:
                    626:                if (link->state & DEV_CONFIG) {
                    627:                        /* FIXME: should we double check that this is
                    628:                         * the same card as we had before */
                    629:                        CardServices(RequestConfiguration, link->handle,
                    630:                                     &link->conf);
                    631: 
                    632:                        if (! test_bit(0, &card->hard_reset_in_progress)) {
                    633:                                err = orinoco_reinit_firmware(dev);
                    634:                                if (err) {
                    635:                                        printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
                    636:                                               dev->name, err);
                    637:                                        break;
                    638:                                }
                    639:                                
                    640:                                spin_lock_irqsave(&priv->lock, flags);
                    641:                                
                    642:                                netif_device_attach(dev);
                    643:                                priv->hw_unavailable--;
                    644:                                
                    645:                                if (priv->open && ! priv->hw_unavailable) {
                    646:                                        err = __orinoco_up(dev);
                    647:                                        if (err)
                    648:                                                printk(KERN_ERR "%s: Error %d restarting card\n",
                    649:                                                       dev->name, err);
                    650:                                        
                    651:                                }
                    652: 
                    653:                                spin_unlock_irqrestore(&priv->lock, flags);
                    654:                        }
                    655:                }
                    656:                break;
                    657:        }
                    658: 
                    659:        return err;
                    660: }                              /* orinoco_cs_event */
                    661: 
                    662: /********************************************************************/
                    663: /* Module initialization                                           */
                    664: /********************************************************************/
                    665: 
                    666: /* Can't be declared "const" or the whole __initdata section will
                    667:  * become const */
                    668: static char version[] __initdata = "orinoco_cs.c 0.13e (David Gibson <[email protected]> and others)";
                    669: 
                    670: static int __init
                    671: init_orinoco_cs(void)
                    672: {
                    673:        servinfo_t serv;
                    674: 
                    675:        printk(KERN_DEBUG "%s\n", version);
                    676: 
                    677:        CardServices(GetCardServicesInfo, &serv);
                    678:        if (serv.Revision != CS_RELEASE_CODE) {
                    679:                printk(KERN_NOTICE "orinoco_cs: Card Services release "
                    680:                       "does not match!\n");
                    681:                return -EINVAL;
                    682:        }
                    683: 
                    684:        register_pccard_driver(&dev_info, &orinoco_cs_attach, &orinoco_cs_detach);
                    685: 
                    686:        return 0;
                    687: }
                    688: 
                    689: static void __exit
                    690: exit_orinoco_cs(void)
                    691: {
                    692:        unregister_pccard_driver(&dev_info);
                    693: 
                    694:        if (dev_list)
                    695:                DEBUG(0, "orinoco_cs: Removing leftover devices.\n");
                    696:        while (dev_list != NULL) {
                    697:                if (dev_list->state & DEV_CONFIG)
                    698:                        orinoco_cs_release((u_long) dev_list);
                    699:                orinoco_cs_detach(dev_list);
                    700:        }
                    701: }
                    702: 
                    703: module_init(init_orinoco_cs);
                    704: module_exit(exit_orinoco_cs);
                    705: 

unix.superglobalmegacorp.com

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