pcmcia: convert net pcmcia drivers to use new CIS helpers
authorDominik Brodowski <linux@dominikbrodowski.net>
Sun, 18 Oct 2009 21:54:24 +0000 (23:54 +0200)
committerDominik Brodowski <linux@dominikbrodowski.net>
Sun, 8 Nov 2009 17:23:05 +0000 (18:23 +0100)
Use the new CIS helpers in net pcmcia drivers, which allows for
a few code cleanups.

This revision does not remove the phys_addr assignment in
3c589_cs.c -- a bug noted by Komuro <komurojun-mbn@nifty.com>

CC: David S. Miller <davem@davemloft.net>
CC: netdev@vger.kernel.org
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
drivers/net/pcmcia/3c574_cs.c
drivers/net/pcmcia/3c589_cs.c
drivers/net/pcmcia/fmvj18x_cs.c
drivers/net/pcmcia/nmclan_cs.c
drivers/net/pcmcia/smc91c92_cs.c
drivers/net/pcmcia/xirc2ps_cs.c

index b58965a2b3ae256eba2642a7b98d1dbff4bfa9b9..6449290c62ffe1497b515d893243e1e8a5952001 100644 (file)
@@ -344,13 +344,13 @@ static int tc574_config(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
        struct el3_private *lp = netdev_priv(dev);
-       tuple_t tuple;
-       __le16 buf[32];
        int last_fn, last_ret, i, j;
        unsigned int ioaddr;
        __be16 *phys_addr;
        char *cardname;
        __u32 config;
+       u8 *buf;
+       size_t len;
 
        phys_addr = (__be16 *)dev->dev_addr;
 
@@ -378,16 +378,14 @@ static int tc574_config(struct pcmcia_device *link)
        /* The 3c574 normally uses an EEPROM for configuration info, including
           the hardware address.  The future products may include a modem chip
           and put the address in the CIS. */
-       tuple.Attributes = 0;
-       tuple.TupleData = (cisdata_t *)buf;
-       tuple.TupleDataMax = 64;
-       tuple.TupleOffset = 0;
-       tuple.DesiredTuple = 0x88;
-       if (pcmcia_get_first_tuple(link, &tuple) == 0) {
-               pcmcia_get_tuple_data(link, &tuple);
+
+       len = pcmcia_get_tuple(link, 0x88, &buf);
+       if (buf && len >= 6) {
                for (i = 0; i < 3; i++)
-                       phys_addr[i] = htons(le16_to_cpu(buf[i]));
+                       phys_addr[i] = htons(le16_to_cpu(buf[i * 2]));
+               kfree(buf);
        } else {
+               kfree(buf); /* 0 < len < 6 */
                EL3WINDOW(0);
                for (i = 0; i < 3; i++)
                        phys_addr[i] = htons(read_eeprom(ioaddr, i + 10));
index 569fb06793cf7da4da614a597113e7eadeeed022..fc6123ea6fa7743e3ec4e253b53d5a409f4ee438 100644 (file)
@@ -256,22 +256,16 @@ static int tc589_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct el3_private *lp = netdev_priv(dev);
-    tuple_t tuple;
-    __le16 buf[32];
     __be16 *phys_addr;
     int last_fn, last_ret, i, j, multi = 0, fifo;
     unsigned int ioaddr;
     char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
+    u8 *buf;
+    size_t len;
     
     DEBUG(0, "3c589_config(0x%p)\n", link);
 
     phys_addr = (__be16 *)dev->dev_addr;
-    tuple.Attributes = 0;
-    tuple.TupleData = (cisdata_t *)buf;
-    tuple.TupleDataMax = sizeof(buf);
-    tuple.TupleOffset = 0;
-    tuple.Attributes = TUPLE_RETURN_COMMON;
-
     /* Is this a 3c562? */
     if (link->manf_id != MANFID_3COM)
            printk(KERN_INFO "3c589_cs: hmmm, is this really a "
@@ -301,12 +295,13 @@ static int tc589_config(struct pcmcia_device *link)
 
     /* The 3c589 has an extra EEPROM for configuration info, including
        the hardware address.  The 3c562 puts the address in the CIS. */
-    tuple.DesiredTuple = 0x88;
-    if (pcmcia_get_first_tuple(link, &tuple) == 0) {
-       pcmcia_get_tuple_data(link, &tuple);
-       for (i = 0; i < 3; i++)
-           phys_addr[i] = htons(le16_to_cpu(buf[i]));
+    len = pcmcia_get_tuple(link, 0x88, &buf);
+    if (buf && len >= 6) {
+           for (i = 0; i < 3; i++)
+                   phys_addr[i] = htons(le16_to_cpu(buf[i*2]));
+           kfree(buf);
     } else {
+       kfree(buf); /* 0 < len < 6 */
        for (i = 0; i < 3; i++)
            phys_addr[i] = htons(read_eeprom(ioaddr, i));
        if (phys_addr[0] == htons(0x6060)) {
index c7a2bbfaf82182dd5d06aa395de1d2814b562cec..5b73b11411c8fdf26db8a8dbfc0f24d19a343c62 100644 (file)
@@ -350,32 +350,29 @@ static int fmvj18x_ioprobe(struct pcmcia_device *p_dev,
        return 0; /* strange, but that's what the code did already before... */
 }
 
-
 static int fmvj18x_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     local_info_t *lp = netdev_priv(dev);
-    tuple_t tuple;
-    u_short buf[32];
     int i, last_fn = RequestIO, last_ret = 0, ret;
     unsigned int ioaddr;
     cardtype_t cardtype;
     char *card_name = "unknown";
-    u_char *node_id;
+    u8 *buf;
+    size_t len;
+    u_char buggybuf[32];
 
     DEBUG(0, "fmvj18x_config(0x%p)\n", link);
 
-    tuple.TupleData = (u_char *)buf;
-    tuple.TupleDataMax = 64;
-    tuple.TupleOffset = 0;
-    tuple.DesiredTuple = CISTPL_FUNCE;
-    tuple.TupleOffset = 0;
-    if (pcmcia_get_first_tuple(link, &tuple) == 0) {
+    len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
+    kfree(buf);
+
+    if (len) {
+       /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
        last_ret = pcmcia_loop_config(link, fmvj18x_ioprobe, NULL);
        if (last_ret != 0)
                goto cs_failed;
 
-       /* Yes, I have CISTPL_FUNCE. Let's check CISTPL_MANFID */
        switch (link->manf_id) {
        case MANFID_TDK:
            cardtype = TDK;
@@ -482,21 +479,21 @@ static int fmvj18x_config(struct pcmcia_device *link)
     case CONTEC:
     case NEC:
     case KME:
-       tuple.DesiredTuple = CISTPL_FUNCE;
-       tuple.TupleOffset = 0;
-       CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-       tuple.TupleOffset = 0;
-       CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
        if (cardtype == MBH10304) {
-           /* MBH10304's CIS_FUNCE is corrupted */
-           node_id = &(tuple.TupleData[5]);
            card_name = "FMV-J182";
-       } else {
-           while (tuple.TupleData[0] != CISTPL_FUNCE_LAN_NODE_ID ) {
-               CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(link, &tuple));
-               CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
+
+           len = pcmcia_get_tuple(link, CISTPL_FUNCE, &buf);
+           if (len < 11) {
+                   kfree(buf);
+                   goto failed;
            }
-           node_id = &(tuple.TupleData[2]);
+           /* Read MACID from CIS */
+           for (i = 5; i < 11; i++)
+                   dev->dev_addr[i] = buf[i];
+           kfree(buf);
+       } else {
+           if (pcmcia_get_mac_from_cis(link, dev))
+               goto failed;
            if( cardtype == TDK ) {
                card_name = "TDK LAK-CD021";
            } else if( cardtype == LA501 ) {
@@ -509,9 +506,6 @@ static int fmvj18x_config(struct pcmcia_device *link)
                card_name = "C-NET(PC)C";
            }
        }
-       /* Read MACID from CIS */
-       for (i = 0; i < 6; i++)
-           dev->dev_addr[i] = node_id[i];
        break;
     case UNGERMANN:
        /* Read MACID from register */
@@ -521,12 +515,12 @@ static int fmvj18x_config(struct pcmcia_device *link)
        break;
     case XXX10304:
        /* Read MACID from Buggy CIS */
-       if (fmvj18x_get_hwinfo(link, tuple.TupleData) == -1) {
+       if (fmvj18x_get_hwinfo(link, buggybuf) == -1) {
            printk(KERN_NOTICE "fmvj18x_cs: unable to read hardware net address.\n");
            goto failed;
        }
        for (i = 0 ; i < 6; i++) {
-           dev->dev_addr[i] = tuple.TupleData[i];
+           dev->dev_addr[i] = buggybuf[i];
        }
        card_name = "FMV-J182";
        break;
index 5ed6339c52bcbb6e021e08b334b6e614eacf75f8..4b96b356d9793890f262c9a04980076e9f5d0538 100644 (file)
@@ -661,8 +661,8 @@ static int nmclan_config(struct pcmcia_device *link)
 {
   struct net_device *dev = link->priv;
   mace_private *lp = netdev_priv(dev);
-  tuple_t tuple;
-  u_char buf[64];
+  u8 *buf;
+  size_t len;
   int i, last_ret, last_fn;
   unsigned int ioaddr;
 
@@ -677,14 +677,13 @@ static int nmclan_config(struct pcmcia_device *link)
   ioaddr = dev->base_addr;
 
   /* Read the ethernet address from the CIS. */
-  tuple.DesiredTuple = 0x80 /* CISTPL_CFTABLE_ENTRY_MISC */;
-  tuple.TupleData = buf;
-  tuple.TupleDataMax = 64;
-  tuple.TupleOffset = 0;
-  tuple.Attributes = 0;
-  CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
-  CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
-  memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);
+  len = pcmcia_get_tuple(link, 0x80, &buf);
+  if (!buf || len < ETHER_ADDR_LEN) {
+         kfree(buf);
+         goto failed;
+  }
+  memcpy(dev->dev_addr, buf, ETHER_ADDR_LEN);
+  kfree(buf);
 
   /* Verify configuration by reading the MACE ID. */
   {
index af03759d186dd618fbf14feb0722a5c632e723b2..df92bcde9bcf24c2b7f523bdc0ea6b63706b043e 100644 (file)
@@ -126,12 +126,6 @@ struct smc_private {
     int                                rx_ovrn;
 };
 
-struct smc_cfg_mem {
-    tuple_t tuple;
-    cisparse_t parse;
-    u_char buf[255];
-};
-
 /* Special definitions for Megahertz multifunction cards */
 #define MEGAHERTZ_ISR          0x0380
 
@@ -408,34 +402,7 @@ static int cvt_ascii_address(struct net_device *dev, char *s)
     return 0;
 }
 
-/*====================================================================*/
-
-static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-               cisparse_t *parse)
-{
-       int i;
-
-       i = pcmcia_get_first_tuple(handle, tuple);
-       if (i != 0)
-               return i;
-       i = pcmcia_get_tuple_data(handle, tuple);
-       if (i != 0)
-               return i;
-       return pcmcia_parse_tuple(tuple, parse);
-}
-
-static int next_tuple(struct pcmcia_device *handle, tuple_t *tuple,
-               cisparse_t *parse)
-{
-       int i;
-
-       if ((i = pcmcia_get_next_tuple(handle, tuple)) != 0 ||
-                       (i = pcmcia_get_tuple_data(handle, tuple)) != 0)
-               return i;
-       return pcmcia_parse_tuple(tuple, parse);
-}
-
-/*======================================================================
+/*====================================================================
 
     Configuration stuff for Megahertz cards
 
@@ -490,15 +457,10 @@ static int mhz_mfc_config(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     struct smc_private *smc = netdev_priv(dev);
-    struct smc_cfg_mem *cfg_mem;
     win_req_t req;
     memreq_t mem;
     int i;
 
-    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
-    if (!cfg_mem)
-           return -ENOMEM;
-
     link->conf.Attributes |= CONF_ENABLE_SPKR;
     link->conf.Status = CCSR_AUDIO_ENA;
     link->irq.Attributes =
@@ -510,7 +472,8 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     /* The Megahertz combo cards have modem-like CIS entries, so
        we have to explicitly try a bunch of port combinations. */
     if (pcmcia_loop_config(link, mhz_mfc_config_check, NULL))
-       goto free_cfg_mem;
+           return -ENODEV;
+
     dev->base_addr = link->io.BasePort1;
 
     /* Allocate a memory window, for accessing the ISR */
@@ -519,7 +482,8 @@ static int mhz_mfc_config(struct pcmcia_device *link)
     req.AccessSpeed = 0;
     i = pcmcia_request_window(&link, &req, &link->win);
     if (i != 0)
-       goto free_cfg_mem;
+           return -ENODEV;
+
     smc->base = ioremap(req.Base, req.Size);
     mem.CardOffset = mem.Page = 0;
     if (smc->manfid == MANFID_MOTOROLA)
@@ -531,18 +495,32 @@ static int mhz_mfc_config(struct pcmcia_device *link)
        && (smc->cardid == PRODID_MEGAHERTZ_EM3288))
        mhz_3288_power(link);
 
-free_cfg_mem:
-    kfree(cfg_mem);
-    return -ENODEV;
+    return 0;
 }
 
+static int pcmcia_get_versmac(struct pcmcia_device *p_dev,
+                             tuple_t *tuple,
+                             void *priv)
+{
+       struct net_device *dev = priv;
+       cisparse_t parse;
+
+       if (pcmcia_parse_tuple(tuple, &parse))
+               return -EINVAL;
+
+       if ((parse.version_1.ns > 3) &&
+           (cvt_ascii_address(dev,
+                              (parse.version_1.str + parse.version_1.ofs[3]))))
+               return 0;
+
+       return -EINVAL;
+};
+
 static int mhz_setup(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    struct smc_cfg_mem *cfg_mem;
-    tuple_t *tuple;
-    cisparse_t *parse;
-    u_char *buf, *station_addr;
+    size_t len;
+    u8 *buf;
     int rc;
 
     /* Read the station address from the CIS.  It is stored as the last
@@ -552,56 +530,22 @@ static int mhz_setup(struct pcmcia_device *link)
            return 0;
 
     /* Workarounds for broken cards start here. */
-
-    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
-    if (!cfg_mem)
-       return -1;
-
-    tuple = &cfg_mem->tuple;
-    parse = &cfg_mem->parse;
-    buf = cfg_mem->buf;
-
-    tuple->Attributes = tuple->TupleOffset = 0;
-    tuple->TupleData = (cisdata_t *)buf;
-    tuple->TupleDataMax = 255;
-
     /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-    tuple->DesiredTuple = CISTPL_VERS_1;
-    if (first_tuple(link, tuple, parse) != 0) {
-       rc = -1;
-       goto free_cfg_mem;
-    }
-    /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
-    if (next_tuple(link, tuple, parse) != 0)
-       first_tuple(link, tuple, parse);
-    if (parse->version_1.ns > 3) {
-       station_addr = parse->version_1.str + parse->version_1.ofs[3];
-       if (cvt_ascii_address(dev, station_addr) == 0) {
-               rc = 0;
-               goto free_cfg_mem;
-       }
-    }
+    if (!pcmcia_loop_tuple(link, CISTPL_VERS_1, pcmcia_get_versmac, dev))
+           return 0;
 
     /* Another possibility: for the EM3288, in a special tuple */
-    tuple->DesiredTuple = 0x81;
-    if (pcmcia_get_first_tuple(link, tuple) != 0) {
-       rc = -1;
-       goto free_cfg_mem;
-    }
-    if (pcmcia_get_tuple_data(link, tuple) != 0) {
-       rc = -1;
-       goto free_cfg_mem;
-    }
-    buf[12] = '\0';
-    if (cvt_ascii_address(dev, buf) == 0) {
-       rc = 0;
-       goto free_cfg_mem;
-   }
     rc = -1;
-free_cfg_mem:
-   kfree(cfg_mem);
-   return rc;
-}
+    len = pcmcia_get_tuple(link, 0x81, &buf);
+    if (buf && len >= 13) {
+           buf[12] = '\0';
+           if (cvt_ascii_address(dev, buf))
+                   rc = 0;
+    }
+    kfree(buf);
+
+    return rc;
+};
 
 /*======================================================================
 
@@ -691,58 +635,21 @@ static int smc_config(struct pcmcia_device *link)
     return i;
 }
 
+
 static int smc_setup(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
-    struct smc_cfg_mem *cfg_mem;
-    tuple_t *tuple;
-    cisparse_t *parse;
-    cistpl_lan_node_id_t *node_id;
-    u_char *buf, *station_addr;
-    int i, rc;
-
-    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
-    if (!cfg_mem)
-           return -ENOMEM;
-
-    tuple = &cfg_mem->tuple;
-    parse = &cfg_mem->parse;
-    buf = cfg_mem->buf;
-
-    tuple->Attributes = tuple->TupleOffset = 0;
-    tuple->TupleData = (cisdata_t *)buf;
-    tuple->TupleDataMax = 255;
 
     /* Check for a LAN function extension tuple */
-    tuple->DesiredTuple = CISTPL_FUNCE;
-    i = first_tuple(link, tuple, parse);
-    while (i == 0) {
-       if (parse->funce.type == CISTPL_FUNCE_LAN_NODE_ID)
-           break;
-       i = next_tuple(link, tuple, parse);
-    }
-    if (i == 0) {
-       node_id = (cistpl_lan_node_id_t *)parse->funce.data;
-       if (node_id->nb == 6) {
-           for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = node_id->id[i];
-           rc = 0;
-           goto free_cfg_mem;
-       }
-    }
+    if (!pcmcia_get_mac_from_cis(link, dev))
+           return 0;
+
     /* Try the third string in the Version 1 Version/ID tuple. */
     if (link->prod_id[2]) {
-       station_addr = link->prod_id[2];
-       if (cvt_ascii_address(dev, station_addr) == 0) {
-               rc = 0;
-               goto free_cfg_mem;
-       }
+           if (cvt_ascii_address(dev, link->prod_id[2]) == 0)
+                   return 0;
     }
-
-    rc = -1;
-free_cfg_mem:
-    kfree(cfg_mem);
-    return rc;
+    return -1;
 }
 
 /*====================================================================*/
@@ -801,41 +708,31 @@ static int osi_load_firmware(struct pcmcia_device *link)
        return err;
 }
 
-static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
+static int pcmcia_osi_mac(struct pcmcia_device *p_dev,
+                         tuple_t *tuple,
+                         void *priv)
 {
-    struct net_device *dev = link->priv;
-    struct smc_cfg_mem *cfg_mem;
-    tuple_t *tuple;
-    u_char *buf;
-    int i, rc;
+       struct net_device *dev = priv;
+       int i;
 
-    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
-    if (!cfg_mem)
-        return -1;
+       if (tuple->TupleDataLen < 8)
+               return -EINVAL;
+       if (tuple->TupleData[0] != 0x04)
+               return -EINVAL;
+       for (i = 0; i < 6; i++)
+               dev->dev_addr[i] = tuple->TupleData[i+2];
+       return 0;
+};
 
-    tuple = &cfg_mem->tuple;
-    buf = cfg_mem->buf;
 
-    tuple->Attributes = TUPLE_RETURN_COMMON;
-    tuple->TupleData = (cisdata_t *)buf;
-    tuple->TupleDataMax = 255;
-    tuple->TupleOffset = 0;
+static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
+{
+    struct net_device *dev = link->priv;
+    int rc;
 
     /* Read the station address from tuple 0x90, subtuple 0x04 */
-    tuple->DesiredTuple = 0x90;
-    i = pcmcia_get_first_tuple(link, tuple);
-    while (i == 0) {
-       i = pcmcia_get_tuple_data(link, tuple);
-       if ((i != 0) || (buf[0] == 0x04))
-           break;
-       i = pcmcia_get_next_tuple(link, tuple);
-    }
-    if (i != 0) {
-       rc = -1;
-       goto free_cfg_mem;
-    }
-    for (i = 0; i < 6; i++)
-       dev->dev_addr[i] = buf[i+2];
+    if (pcmcia_loop_tuple(link, 0x90, pcmcia_osi_mac, dev))
+           return -1;
 
     if (((manfid == MANFID_OSITECH) &&
         (cardid == PRODID_OSITECH_SEVEN)) ||
@@ -843,7 +740,7 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
         (cardid == PRODID_PSION_NET100))) {
        rc = osi_load_firmware(link);
        if (rc)
-               goto free_cfg_mem;
+               return rc;
     } else if (manfid == MANFID_OSITECH) {
        /* Make sure both functions are powered up */
        set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);
@@ -853,10 +750,7 @@ static int osi_setup(struct pcmcia_device *link, u_short manfid, u_short cardid)
              inw(link->io.BasePort1 + OSITECH_AUI_PWR),
              inw(link->io.BasePort1 + OSITECH_RESET_ISR));
     }
-    rc = 0;
-free_cfg_mem:
-   kfree(cfg_mem);
-   return rc;
+    return 0;
 }
 
 static int smc91c92_suspend(struct pcmcia_device *link)
index 5e203230144ff794c66bda80d7fc54c02b8abfe3..925e8509662942c18ab3daa4abe2fad008ee2744 100644 (file)
@@ -359,7 +359,7 @@ static void xirc_tx_timeout(struct net_device *dev);
 static void xirc2ps_tx_timeout_task(struct work_struct *work);
 static void set_addresses(struct net_device *dev);
 static void set_multicast_list(struct net_device *dev);
-static int set_card_type(struct pcmcia_device *link, const void *s);
+static int set_card_type(struct pcmcia_device *link);
 static int do_config(struct net_device *dev, struct ifmap *map);
 static int do_open(struct net_device *dev);
 static int do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
@@ -371,28 +371,6 @@ static void do_powerdown(struct net_device *dev);
 static int do_stop(struct net_device *dev);
 
 /*=============== Helper functions =========================*/
-static int
-first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
-       int err;
-
-       if ((err = pcmcia_get_first_tuple(handle, tuple)) == 0 &&
-                       (err = pcmcia_get_tuple_data(handle, tuple)) == 0)
-               err = pcmcia_parse_tuple(tuple, parse);
-       return err;
-}
-
-static int
-next_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
-{
-       int err;
-
-       if ((err = pcmcia_get_next_tuple(handle, tuple)) == 0 &&
-                       (err = pcmcia_get_tuple_data(handle, tuple)) == 0)
-               err = pcmcia_parse_tuple(tuple, parse);
-       return err;
-}
-
 #define SelectPage(pgnr)   outb((pgnr), ioaddr + XIRCREG_PR)
 #define GetByte(reg)      ((unsigned)inb(ioaddr + (reg)))
 #define GetWord(reg)      ((unsigned)inw(ioaddr + (reg)))
@@ -644,15 +622,23 @@ xirc2ps_detach(struct pcmcia_device *link)
  *
  */
 static int
-set_card_type(struct pcmcia_device *link, const void *s)
+set_card_type(struct pcmcia_device *link)
 {
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
-  #ifdef PCMCIA_DEBUG
-    unsigned cisrev = ((const unsigned char *)s)[2];
-  #endif
-    unsigned mediaid= ((const unsigned char *)s)[3];
-    unsigned prodid = ((const unsigned char *)s)[4];
+    u8 *buf;
+    unsigned int cisrev, mediaid, prodid;
+    size_t len;
+
+    len = pcmcia_get_tuple(link, CISTPL_MANFID, &buf);
+    if (len < 5) {
+           dev_err(&link->dev, "invalid CIS -- sorry\n");
+           return 0;
+    }
+
+    cisrev = buf[2];
+    mediaid = buf[3];
+    prodid = buf[4];
 
     DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n",
          cisrev, mediaid, prodid);
@@ -761,6 +747,26 @@ xirc2ps_config_check(struct pcmcia_device *p_dev,
 
 }
 
+
+static int pcmcia_get_mac_ce(struct pcmcia_device *p_dev,
+                            tuple_t *tuple,
+                            void *priv)
+{
+       struct net_device *dev = priv;
+       int i;
+
+       if (tuple->TupleDataLen != 13)
+               return -EINVAL;
+       if ((tuple->TupleData[0] != 2) || (tuple->TupleData[1] != 1) ||
+               (tuple->TupleData[2] != 6))
+               return -EINVAL;
+       /* another try  (James Lehmer's CE2 version 4.1)*/
+       for (i = 2; i < 6; i++)
+               dev->dev_addr[i] = tuple->TupleData[i+2];
+       return 0;
+};
+
+
 /****************
  * xirc2ps_config() is scheduled to run after a CARD_INSERTION event
  * is received, to configure the PCMCIA socket, and to make the
@@ -772,25 +778,14 @@ xirc2ps_config(struct pcmcia_device * link)
     struct net_device *dev = link->priv;
     local_info_t *local = netdev_priv(dev);
     unsigned int ioaddr;
-    tuple_t tuple;
-    cisparse_t parse;
-    int err, i;
-    u_char buf[64];
-    cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
+    int err;
+    u8 *buf;
+    size_t len;
 
     local->dingo_ccr = NULL;
 
     DEBUG(0, "config(0x%p)\n", link);
 
-    /*
-     * This reads the card's CONFIG tuple to find its configuration
-     * registers.
-     */
-    tuple.Attributes = 0;
-    tuple.TupleData = buf;
-    tuple.TupleDataMax = 64;
-    tuple.TupleOffset = 0;
-
     /* Is this a valid card */
     if (link->has_manf_id == 0) {
        printk(KNOT_XIRC "manfid not found in CIS\n");
@@ -816,67 +811,41 @@ xirc2ps_config(struct pcmcia_device * link)
        break;
       default:
        printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n",
-              (unsigned)parse.manfid.manf);
+              (unsigned)link->manf_id);
        goto failure;
     }
     DEBUG(0, "found %s card\n", local->manf_str);
 
-    /* needed for the additional fields to be parsed by set_card_type() */
-    tuple.DesiredTuple = CISTPL_MANFID;
-    err = first_tuple(link, &tuple, &parse)
-    if (err) {
-       printk(KNOT_XIRC "manfid not found in CIS\n");
-       goto failure;
-    }
-    if (!set_card_type(link, buf)) {
+    if (!set_card_type(link)) {
        printk(KNOT_XIRC "this card is not supported\n");
        goto failure;
     }
 
     /* get the ethernet address from the CIS */
-    tuple.DesiredTuple = CISTPL_FUNCE;
-    for (err = first_tuple(link, &tuple, &parse); !err;
-                            err = next_tuple(link, &tuple, &parse)) {
-       /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries:
-        * the first one with a length of zero the second correct -
-        * so I skip all entries with length 0 */
-       if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID
-           && ((cistpl_lan_node_id_t *)parse.funce.data)->nb)
-           break;
-    }
-    if (err) { /* not found: try to get the node-id from tuple 0x89 */
-       tuple.DesiredTuple = 0x89;  /* data layout looks like tuple 0x22 */
-       if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 &&
-               (err = pcmcia_get_tuple_data(link, &tuple)) == 0) {
-           if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID)
-               memcpy(&parse, buf, 8);
-           else
-               err = -1;
-       }
-    }
-    if (err) { /* another try  (James Lehmer's CE2 version 4.1)*/
-       tuple.DesiredTuple = CISTPL_FUNCE;
-       for (err = first_tuple(link, &tuple, &parse); !err;
-                                err = next_tuple(link, &tuple, &parse)) {
-           if (parse.funce.type == 0x02 && parse.funce.data[0] == 1
-               && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) {
-               buf[1] = 4;
-               memcpy(&parse, buf+1, 8);
-               break;
+    err = pcmcia_get_mac_from_cis(link, dev);
+
+    /* not found: try to get the node-id from tuple 0x89 */
+    if (err) {
+           len = pcmcia_get_tuple(link, 0x89, &buf);
+           /* data layout looks like tuple 0x22 */
+           if (buf && len == 8) {
+                   if (*buf == CISTPL_FUNCE_LAN_NODE_ID) {
+                           int i;
+                           for (i = 2; i < 6; i++)
+                                   dev->dev_addr[i] = buf[i+2];
+                   } else
+                           err = -1;
            }
-       }
+           kfree(buf);
     }
+
+    if (err)
+       err = pcmcia_loop_tuple(link, CISTPL_FUNCE, pcmcia_get_mac_ce, dev);
+
     if (err) {
        printk(KNOT_XIRC "node-id not found in CIS\n");
        goto failure;
     }
-    node_id = (cistpl_lan_node_id_t *)parse.funce.data;
-    if (node_id->nb != 6) {
-       printk(KNOT_XIRC "malformed node-id in CIS\n");
-       goto failure;
-    }
-    for (i=0; i < 6; i++)
-       dev->dev_addr[i] = node_id->id[i];
 
     link->io.IOAddrLines =10;
     link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;