diff options
Diffstat (limited to 'drivers/net/wireless/atmel_cs.c')
-rw-r--r-- | drivers/net/wireless/atmel_cs.c | 121 |
1 files changed, 52 insertions, 69 deletions
diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 12617cd0b78..77406245dc7 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -158,7 +158,7 @@ static int atmel_probe(struct pcmcia_device *p_dev) DEBUG(0, "atmel_attach()\n"); /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_EXCLUSIVE; + p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; p_dev->irq.Handler = NULL; @@ -224,13 +224,58 @@ static int card_present(void *arg) return 0; } +static int atmel_config_check(struct pcmcia_device *p_dev, + cistpl_cftable_entry_t *cfg, + cistpl_cftable_entry_t *dflt, + unsigned int vcc, + void *priv_data) +{ + if (cfg->index == 0) + return -ENODEV; + + /* Does this card need audio output? */ + if (cfg->flags & CISTPL_CFTABLE_AUDIO) { + p_dev->conf.Attributes |= CONF_ENABLE_SPKR; + p_dev->conf.Status = CCSR_AUDIO_ENA; + } + + /* Use power settings for Vcc and Vpp if present */ + /* Note that the CIS values need to be rescaled */ + if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) + p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; + else if (dflt->vpp1.present & (1<<CISTPL_POWER_VNOM)) + p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; + + /* Do we need to allocate an interrupt? */ + if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) + p_dev->conf.Attributes |= CONF_ENABLE_IRQ; + + /* IO window settings */ + p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; + if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { + cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + if (!(io->flags & CISTPL_IO_8BIT)) + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; + if (!(io->flags & CISTPL_IO_16BIT)) + p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; + p_dev->io.BasePort1 = io->win[0].base; + p_dev->io.NumPorts1 = io->win[0].len; + if (io->nwin > 1) { + p_dev->io.Attributes2 = p_dev->io.Attributes1; + p_dev->io.BasePort2 = io->win[1].base; + p_dev->io.NumPorts2 = io->win[1].len; + } + } + + /* This reserves IO space but doesn't actually enable it */ + return pcmcia_request_io(p_dev, &p_dev->io); +} + static int atmel_config(struct pcmcia_device *link) { - tuple_t tuple; - cisparse_t parse; local_info_t *dev; int last_fn, last_ret; - u_char buf[64]; struct pcmcia_device_id *did; dev = link->priv; @@ -238,11 +283,6 @@ static int atmel_config(struct pcmcia_device *link) DEBUG(0, "atmel_config(0x%p)\n", link); - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - /* In this loop, we scan the CIS for configuration table entries, each of which describes a valid card configuration, including @@ -255,66 +295,8 @@ static int atmel_config(struct pcmcia_device *link) these things without consulting the CIS, and most client drivers will only use the CIS to fill in implementation-defined details. */ - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); - while (1) { - cistpl_cftable_entry_t dflt = { 0 }; - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(link, &tuple) != 0 || - pcmcia_parse_tuple(link, &tuple, &parse) != 0) - goto next_entry; - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg; - if (cfg->index == 0) goto next_entry; - link->conf.ConfigIndex = cfg->index; - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - link->io.Attributes2 = link->io.Attributes1; - link->io.BasePort2 = io->win[1].base; - link->io.NumPorts2 = io->win[1].len; - } - } - - /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(link, &link->io) != 0) - goto next_entry; - - /* If we got this far, we're cool! */ - break; - - next_entry: - CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple)); - } + if (pcmcia_loop_config(link, atmel_config_check, NULL)) + goto failed; /* Allocate an interrupt line. Note that this does not assign a @@ -360,6 +342,7 @@ static int atmel_config(struct pcmcia_device *link) cs_failed: cs_error(link, last_fn, last_ret); + failed: atmel_release(link); return -ENODEV; } |