pcmcia: pcmcia_config_loop() improvement by passing vcc
[deliverable/linux.git] / drivers / net / wireless / orinoco_cs.c
index 8b7f5768a10307d0ebd81446e8b78b4c71758e0a..c7b57d9d499dfcabfbbf90cadb67474983298f07 100644 (file)
@@ -164,6 +164,70 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
                last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
        } while (0)
 
+static int orinoco_cs_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)
+               goto next_entry;
+
+       /* Use power settings for Vcc and Vpp if present */
+       /* Note that the CIS values need to be rescaled */
+       if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+                       DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n",  vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+                       if (!ignore_cis_vcc)
+                               goto next_entry;
+               }
+       } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
+               if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
+                       DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n",  vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+                       if (!ignore_cis_vcc)
+                               goto next_entry;
+               }
+       }
+
+       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? */
+       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.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
+               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 */
+               if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+                       goto next_entry;
+       }
+       return 0;
+
+next_entry:
+       pcmcia_disable_device(p_dev);
+       return -ENODEV;
+};
+
 static int
 orinoco_cs_config(struct pcmcia_device *link)
 {
@@ -172,16 +236,8 @@ orinoco_cs_config(struct pcmcia_device *link)
        struct orinoco_pccard *card = priv->card;
        hermes_t *hw = &priv->hw;
        int last_fn, last_ret;
-       u_char buf[64];
-       config_info_t conf;
-       tuple_t tuple;
-       cisparse_t parse;
        void __iomem *mem;
 
-       /* Look up the current Vcc */
-       CS_CHECK(GetConfigurationInfo,
-                pcmcia_get_configuration_info(link, &conf));
-
        /*
         * In this loop, we scan the CIS for configuration table
         * entries, each of which describes a valid card
@@ -196,94 +252,14 @@ orinoco_cs_config(struct pcmcia_device *link)
         * and most client drivers will only use the CIS to fill in
         * implementation-defined details.
         */
-       tuple.Attributes = 0;
-       tuple.TupleData = buf;
-       tuple.TupleDataMax = sizeof(buf);
-       tuple.TupleOffset = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       while (1) {
-               cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
-               cistpl_cftable_entry_t dflt = { .index = 0 };
-
-               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;
-
-               /* Use power settings for Vcc and Vpp if present */
-               /* Note that the CIS values need to be rescaled */
-               if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                               DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, cfg CIS = %d)\n",  conf.Vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
-                               if (!ignore_cis_vcc)
-                                       goto next_entry;
-                       }
-               } else if (dflt.vcc.present & (1 << CISTPL_POWER_VNOM)) {
-                       if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM] / 10000) {
-                               DEBUG(2, "orinoco_cs_config: Vcc mismatch (conf.Vcc = %d, dflt CIS = %d)\n",  conf.Vcc, dflt.vcc.param[CISTPL_POWER_VNOM] / 10000);
-                               if(!ignore_cis_vcc)
-                                       goto next_entry;
-                       }
-               }
-
-               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? */
-               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.IOAddrLines =
-                           io->flags & CISTPL_IO_LINES_MASK;
-                       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:
-               pcmcia_disable_device(link);
-               last_ret = pcmcia_get_next_tuple(link, &tuple);
-               if (last_ret  == CS_NO_MORE_ITEMS) {
+       last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
+       if (last_ret) {
+               if (!ignore_cis_vcc)
                        printk(KERN_ERR PFX "GetNextTuple(): No matching "
                               "CIS configuration.  Maybe you need the "
                               "ignore_cis_vcc=1 parameter.\n");
-                       goto cs_failed;
-               }
+               cs_error(link, RequestIO, last_ret);
+               goto failed;
        }
 
        /*
@@ -334,7 +310,6 @@ orinoco_cs_config(struct pcmcia_device *link)
               "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
               link->irq.AssignedIRQ, link->io.BasePort1,
               link->io.BasePort1 + link->io.NumPorts1 - 1);
-
        return 0;
 
  cs_failed:
@@ -461,6 +436,7 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
        PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
        PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
+       PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
        PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
        PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
        PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
This page took 0.030924 seconds and 5 git commands to generate.