pcmcia: use pcmcia_loop_config in ISDN pcmcia drivers
Dominik Brodowski [Tue, 29 Jul 2008 06:38:55 +0000 (08:38 +0200)]
Use the config loop helper in ISDN pcmcia drivers.

CC: Karsten Keil <kkeil@suse.de>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>

drivers/isdn/hardware/avm/avm_cs.c
drivers/isdn/hisax/avma1_cs.c
drivers/isdn/hisax/elsa_cs.c
drivers/isdn/hisax/sedlbauer_cs.c
drivers/isdn/hisax/teles_cs.c

index a5b941c..7a1ead1 100644 (file)
@@ -154,78 +154,44 @@ static void avmcs_detach(struct pcmcia_device *link)
     
 ======================================================================*/
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
+static int avmcs_configcheck(struct pcmcia_device *p_dev,
+                            cistpl_cftable_entry_t *cf,
+                            void *priv_data)
 {
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
+       if (cf->io.nwin <= 0)
+               return -ENODEV;
+
+       p_dev->conf.ConfigIndex = cf->index;
+       p_dev->io.BasePort1 = cf->io.win[0].base;
+       p_dev->io.NumPorts1 = cf->io.win[0].len;
+       p_dev->io.NumPorts2 = 0;
+       printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
+              p_dev->io.BasePort1,
+              p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
+       return pcmcia_request_io(p_dev, &p_dev->io);
 }
 
 static int avmcs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     local_info_t *dev;
     int i;
-    u_char buf[64];
     char devname[128];
     int cardtype;
     int (*addcard)(unsigned int port, unsigned irq);
 
     dev = link->priv;
 
-    do {
-       devname[0] = 0;
-       if (link->prod_id[1])
-               strlcpy(devname, link->prod_id[1], sizeof(devname));
-
-       /*
-         * find IO port
-         */
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-       tuple.Attributes = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       i = first_tuple(link, &tuple, &parse);
-       while (i == CS_SUCCESS) {
-           if (cf->io.nwin > 0) {
-               link->conf.ConfigIndex = cf->index;
-               link->io.BasePort1 = cf->io.win[0].base;
-               link->io.NumPorts1 = cf->io.win[0].len;
-               link->io.NumPorts2 = 0;
-                printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
-                       link->io.BasePort1,
-                       link->io.BasePort1+link->io.NumPorts1-1);
-               i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS) goto found_port;
-           }
-           i = next_tuple(link, &tuple, &parse);
-       }
+    devname[0] = 0;
+    if (link->prod_id[1])
+           strlcpy(devname, link->prod_id[1], sizeof(devname));
 
-found_port:
-       if (i != CS_SUCCESS) {
-           cs_error(link, RequestIO, i);
-           break;
-       }
+    /*
+     * find IO port
+     */
+    if (pcmcia_loop_config(link, avmcs_configcheck, NULL))
+           return -ENODEV;
 
+    do {
        /*
         * allocate an interrupt line
         */
index fc6cc2c..8142d9f 100644 (file)
@@ -174,38 +174,28 @@ static void avma1cs_detach(struct pcmcia_device *link)
     
 ======================================================================*/
 
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
+static int avma1cs_configcheck(struct pcmcia_device *p_dev,
+                            cistpl_cftable_entry_t *cf,
+                            void *priv_data)
 {
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
+       if (cf->io.nwin <= 0)
+               return -ENODEV;
+
+       p_dev->conf.ConfigIndex = cf->index;
+       p_dev->io.BasePort1 = cf->io.win[0].base;
+       p_dev->io.NumPorts1 = cf->io.win[0].len;
+       p_dev->io.NumPorts2 = 0;
+       printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
+              p_dev->io.BasePort1,
+              p_dev->io.BasePort1+p_dev->io.NumPorts1-1);
+       return pcmcia_request_io(p_dev, &p_dev->io);
 }
 
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                    cisparse_t *parse)
-{
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
 
 static int avma1cs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
     local_info_t *dev;
     int i;
-    u_char buf[64];
     char devname[128];
     IsdnCard_t icard;
     int busy = 0;
@@ -214,40 +204,14 @@ static int avma1cs_config(struct pcmcia_device *link)
 
     DEBUG(0, "avma1cs_config(0x%p)\n", link);
 
-    do {
-       devname[0] = 0;
-       if (link->prod_id[1])
-               strlcpy(devname, link->prod_id[1], sizeof(devname));
+    devname[0] = 0;
+    if (link->prod_id[1])
+           strlcpy(devname, link->prod_id[1], sizeof(devname));
 
-       /*
-         * find IO port
-         */
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-       tuple.Attributes = 0;
-       tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-       i = first_tuple(link, &tuple, &parse);
-       while (i == CS_SUCCESS) {
-           if (cf->io.nwin > 0) {
-               link->conf.ConfigIndex = cf->index;
-               link->io.BasePort1 = cf->io.win[0].base;
-               link->io.NumPorts1 = cf->io.win[0].len;
-               link->io.NumPorts2 = 0;
-               printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
-                       link->io.BasePort1,
-                       link->io.BasePort1+link->io.NumPorts1 - 1);
-               i = pcmcia_request_io(link, &link->io);
-               if (i == CS_SUCCESS) goto found_port;
-           }
-           i = next_tuple(link, &tuple, &parse);
-       }
+    if (pcmcia_loop_config(link, avma1cs_configcheck, NULL))
+           return -ENODEV;
 
-found_port:
-       if (i != CS_SUCCESS) {
-           cs_error(link, RequestIO, i);
-           break;
-       }
-       
+    do {
        /*
         * allocate an interrupt line
         */
index db7e644..4498008 100644 (file)
@@ -203,68 +203,41 @@ static void elsa_cs_detach(struct pcmcia_device *link)
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
 
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
+static int elsa_cs_configcheck(struct pcmcia_device *p_dev,
+                              cistpl_cftable_entry_t *cf,
+                              void *priv_data)
 {
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
+       int j;
+
+       if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+               printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
+               p_dev->conf.ConfigIndex = cf->index;
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       } else {
+               printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
+               p_dev->conf.ConfigIndex = cf->index;
+               for (j = 0x2f0; j > 0x100; j -= 0x10) {
+                       p_dev->io.BasePort1 = j;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
 }
 
 static int elsa_cs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
     local_info_t *dev;
-    int i, j, last_fn;
-    u_short buf[128];
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    int i, last_fn;
     IsdnCard_t icard;
 
     DEBUG(0, "elsa_config(0x%p)\n", link);
     dev = link->priv;
 
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-    tuple.Attributes = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(link, &tuple, &parse);
-    while (i == CS_SUCCESS) {
-        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
-            printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
-            link->conf.ConfigIndex = cf->index;
-            link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-        } else {
-          printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
-          link->conf.ConfigIndex = cf->index;
-          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
-            link->io.BasePort1 = j;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-          }
-          break;
-        }
-        i = next_tuple(link, &tuple, &parse);
-    }
-
+    i = pcmcia_loop_config(link, elsa_cs_configcheck, NULL);
     if (i != CS_SUCCESS) {
        last_fn = RequestIO;
        goto cs_failed;
index 439cb53..0f80b56 100644 (file)
@@ -217,101 +217,68 @@ static void sedlbauer_detach(struct pcmcia_device *link)
 #define CS_CHECK(fn, ret) \
 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
 
-static int sedlbauer_config(struct pcmcia_device *link)
-{
-    local_info_t *dev = link->priv;
-    tuple_t tuple;
-    cisparse_t parse;
-    int last_fn, last_ret;
-    u8 buf[64];
-    config_info_t conf;
-    win_req_t req;
-    memreq_t map;
-    IsdnCard_t  icard;
-
-    DEBUG(0, "sedlbauer_config(0x%p)\n", link);
-
-    tuple.Attributes = 0;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
+struct sedlbauer_config_data {
+       cistpl_cftable_entry_t dflt;
+       config_info_t conf;
+       win_req_t req;
+};
 
-    CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
+static int sedlbauer_config_check(struct pcmcia_device *p_dev,
+                                 cistpl_cftable_entry_t *cfg,
+                                 void *priv_data)
+{
+       struct sedlbauer_config_data *cfg_mem = priv_data;
 
-    /*
-      In this loop, we scan the CIS for configuration table entries,
-      each of which describes a valid card configuration, including
-      voltage, IO window, memory window, and interrupt settings.
+       if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
+               cfg_mem->dflt = *cfg;
+       if (cfg->index == 0)
+               return -ENODEV;
+       p_dev->conf.ConfigIndex = cfg->index;
 
-      We make no assumptions about the card to be configured: we use
-      just the information available in the CIS.  In an ideal world,
-      this would work for any PCMCIA card, but it requires a complete
-      and accurate CIS.  In practice, a driver usually "knows" most of
-      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;
+               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->vcc.present & (1<<CISTPL_POWER_VNOM)) {
-           if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
-               goto next_entry;
-       } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
-           if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
-               goto next_entry;
+               if (cfg_mem->conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000)
+                       return -ENODEV;
+       } else if (cfg_mem->dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
+               if (cfg_mem->conf.Vcc != cfg_mem->dflt.vcc.param[CISTPL_POWER_VNOM]/10000)
+                       return -ENODEV;
        }
-           
+
        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;
-       
+               p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
+       else if (cfg_mem->dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
+               p_dev->conf.Vpp = cfg_mem->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;
-       
+       if (cfg->irq.IRQInfo1 || cfg_mem->dflt.irq.IRQInfo1)
+               p_dev->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;
-/* new in dummy.cs 2001/01/28 MN 
-            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;
+       p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
+       if ((cfg->io.nwin > 0) || (cfg_mem->dflt.io.nwin > 0)) {
+               cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &cfg_mem->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 */
+               if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
+                       return -ENODEV;
        }
 
        /*
@@ -325,30 +292,58 @@ static int sedlbauer_config(struct pcmcia_device *link)
          needs to be mapped to virtual space with ioremap() before it
          is used.
        */
-       if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
-           cistpl_mem_t *mem =
-               (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
-           req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
-           req.Attributes |= WIN_ENABLE;
-           req.Base = mem->win[0].host_addr;
-           req.Size = mem->win[0].len;
-/* new in dummy.cs 2001/01/28 MN 
-            if (req.Size < 0x1000)
-                req.Size = 0x1000;
-*/
-           req.AccessSpeed = 0;
-           if (pcmcia_request_window(&link, &req, &link->win) != 0)
-               goto next_entry;
-           map.Page = 0; map.CardOffset = mem->win[0].card_addr;
-           if (pcmcia_map_mem_page(link->win, &map) != 0)
-               goto next_entry;
+       if ((cfg->mem.nwin > 0) || (cfg_mem->dflt.mem.nwin > 0)) {
+               cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &cfg_mem->dflt.mem;
+               memreq_t map;
+               cfg_mem->req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
+               cfg_mem->req.Attributes |= WIN_ENABLE;
+               cfg_mem->req.Base = mem->win[0].host_addr;
+               cfg_mem->req.Size = mem->win[0].len;
+               cfg_mem->req.AccessSpeed = 0;
+               if (pcmcia_request_window(&p_dev, &cfg_mem->req, &p_dev->win) != 0)
+                       return -ENODEV;
+               map.Page = 0;
+               map.CardOffset = mem->win[0].card_addr;
+               if (pcmcia_map_mem_page(p_dev->win, &map) != 0)
+                       return -ENODEV;
        }
-       /* If we got this far, we're cool! */
-       break;
+       return 0;
+}
 
-    next_entry:
-       CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-    }
+
+
+static int sedlbauer_config(struct pcmcia_device *link)
+{
+    local_info_t *dev = link->priv;
+    struct sedlbauer_config_data *cfg_mem;
+    int last_fn, last_ret;
+    IsdnCard_t  icard;
+
+    DEBUG(0, "sedlbauer_config(0x%p)\n", link);
+
+    cfg_mem = kzalloc(sizeof(struct sedlbauer_config_data), GFP_KERNEL);
+    if (!cfg_mem)
+           return -ENOMEM;
+
+    /* Look up the current Vcc */
+    CS_CHECK(GetConfigurationInfo,
+            pcmcia_get_configuration_info(link, &cfg_mem->conf));
+
+    /*
+      In this loop, we scan the CIS for configuration table entries,
+      each of which describes a valid card configuration, including
+      voltage, IO window, memory window, and interrupt settings.
+
+      We make no assumptions about the card to be configured: we use
+      just the information available in the CIS.  In an ideal world,
+      this would work for any PCMCIA card, but it requires a complete
+      and accurate CIS.  In practice, a driver usually "knows" most of
+      these things without consulting the CIS, and most client drivers
+      will only use the CIS to fill in implementation-defined details.
+    */
+    last_ret = pcmcia_loop_config(link, sedlbauer_config_check, cfg_mem);
+    if (last_ret)
+           goto failed;
 
     /*
        Allocate an interrupt line.  Note that this does not assign a
@@ -387,8 +382,8 @@ static int sedlbauer_config(struct pcmcia_device *link)
        printk(" & 0x%04x-0x%04x", link->io.BasePort2,
               link->io.BasePort2+link->io.NumPorts2-1);
     if (link->win)
-       printk(", mem 0x%06lx-0x%06lx", req.Base,
-              req.Base+req.Size-1);
+       printk(", mem 0x%06lx-0x%06lx", cfg_mem->req.Base,
+              cfg_mem->req.Base+cfg_mem->req.Size-1);
     printk("\n");
 
     icard.para[0] = link->irq.AssignedIRQ;
@@ -409,6 +404,7 @@ static int sedlbauer_config(struct pcmcia_device *link)
 
 cs_failed:
     cs_error(link, last_fn, last_ret);
+failed:
     sedlbauer_release(link);
     return -ENODEV;
 
index ab4bd45..2b063a2 100644 (file)
@@ -193,68 +193,41 @@ static void teles_detach(struct pcmcia_device *link)
     device available to the system.
 
 ======================================================================*/
-static int get_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_tuple_data(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return pcmcia_parse_tuple(handle, tuple, parse);
-}
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
-{
-    int i = pcmcia_get_first_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
-}
 
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-                     cisparse_t *parse)
+static int teles_cs_configcheck(struct pcmcia_device *p_dev,
+                               cistpl_cftable_entry_t *cf,
+                               void *priv_data)
 {
-    int i = pcmcia_get_next_tuple(handle, tuple);
-    if (i != CS_SUCCESS) return i;
-    return get_tuple(handle, tuple, parse);
+       int j;
+
+       if ((cf->io.nwin > 0) && cf->io.win[0].base) {
+               printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
+               p_dev->conf.ConfigIndex = cf->index;
+               p_dev->io.BasePort1 = cf->io.win[0].base;
+               if (!pcmcia_request_io(p_dev, &p_dev->io))
+                       return 0;
+       } else {
+               printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
+               p_dev->conf.ConfigIndex = cf->index;
+               for (j = 0x2f0; j > 0x100; j -= 0x10) {
+                       p_dev->io.BasePort1 = j;
+                       if (!pcmcia_request_io(p_dev, &p_dev->io))
+                               return 0;
+               }
+       }
+       return -ENODEV;
 }
 
 static int teles_cs_config(struct pcmcia_device *link)
 {
-    tuple_t tuple;
-    cisparse_t parse;
     local_info_t *dev;
-    int i, j, last_fn;
-    u_short buf[128];
-    cistpl_cftable_entry_t *cf = &parse.cftable_entry;
+    int i, last_fn;
     IsdnCard_t icard;
 
     DEBUG(0, "teles_config(0x%p)\n", link);
     dev = link->priv;
 
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
-    tuple.Attributes = 0;
-    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
-    i = first_tuple(link, &tuple, &parse);
-    while (i == CS_SUCCESS) {
-        if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
-            printk(KERN_INFO "(teles_cs: looks like the 96 model)\n");
-            link->conf.ConfigIndex = cf->index;
-            link->io.BasePort1 = cf->io.win[0].base;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-        } else {
-          printk(KERN_INFO "(teles_cs: looks like the 97 model)\n");
-          link->conf.ConfigIndex = cf->index;
-          for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
-            link->io.BasePort1 = j;
-            i = pcmcia_request_io(link, &link->io);
-            if (i == CS_SUCCESS) break;
-          }
-          break;
-        }
-        i = next_tuple(link, &tuple, &parse);
-    }
-
+    i = pcmcia_loop_config(link, teles_cs_configcheck, NULL);
     if (i != CS_SUCCESS) {
        last_fn = RequestIO;
        goto cs_failed;