linux/drivers/pcmcia/cistpl.c
<<
>>
Prefs
   1/*
   2 * cistpl.c -- 16-bit PCMCIA Card Information Structure parser
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 *
   8 * The initial developer of the original code is David A. Hinds
   9 * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  10 * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  11 *
  12 * (C) 1999             David A. Hinds
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/moduleparam.h>
  17#include <linux/kernel.h>
  18#include <linux/string.h>
  19#include <linux/major.h>
  20#include <linux/errno.h>
  21#include <linux/timer.h>
  22#include <linux/slab.h>
  23#include <linux/mm.h>
  24#include <linux/pci.h>
  25#include <linux/ioport.h>
  26#include <asm/io.h>
  27#include <asm/byteorder.h>
  28#include <asm/unaligned.h>
  29
  30#include <pcmcia/cs_types.h>
  31#include <pcmcia/ss.h>
  32#include <pcmcia/cs.h>
  33#include <pcmcia/cisreg.h>
  34#include <pcmcia/cistpl.h>
  35#include "cs_internal.h"
  36
  37static const u_char mantissa[] = {
  38    10, 12, 13, 15, 20, 25, 30, 35,
  39    40, 45, 50, 55, 60, 70, 80, 90
  40};
  41
  42static const u_int exponent[] = {
  43    1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
  44};
  45
  46/* Convert an extended speed byte to a time in nanoseconds */
  47#define SPEED_CVT(v) \
  48    (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
  49/* Convert a power byte to a current in 0.1 microamps */
  50#define POWER_CVT(v) \
  51    (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
  52#define POWER_SCALE(v)          (exponent[(v)&7])
  53
  54/* Upper limit on reasonable # of tuples */
  55#define MAX_TUPLES              200
  56
  57/*====================================================================*/
  58
  59/* Parameters that can be set with 'insmod' */
  60
  61/* 16-bit CIS? */
  62static int cis_width;
  63module_param(cis_width, int, 0444);
  64
  65void release_cis_mem(struct pcmcia_socket *s)
  66{
  67    if (s->cis_mem.flags & MAP_ACTIVE) {
  68        s->cis_mem.flags &= ~MAP_ACTIVE;
  69        s->ops->set_mem_map(s, &s->cis_mem);
  70        if (s->cis_mem.res) {
  71            release_resource(s->cis_mem.res);
  72            kfree(s->cis_mem.res);
  73            s->cis_mem.res = NULL;
  74        }
  75        iounmap(s->cis_virt);
  76        s->cis_virt = NULL;
  77    }
  78}
  79EXPORT_SYMBOL(release_cis_mem);
  80
  81/*
  82 * Map the card memory at "card_offset" into virtual space.
  83 * If flags & MAP_ATTRIB, map the attribute space, otherwise
  84 * map the memory space.
  85 */
  86static void __iomem *
  87set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
  88{
  89        pccard_mem_map *mem = &s->cis_mem;
  90        int ret;
  91
  92        if (!(s->features & SS_CAP_STATIC_MAP) && (mem->res == NULL)) {
  93                mem->res = pcmcia_find_mem_region(0, s->map_size, s->map_size, 0, s);
  94                if (mem->res == NULL) {
  95                        dev_printk(KERN_NOTICE, &s->dev,
  96                                   "cs: unable to map card memory!\n");
  97                        return NULL;
  98                }
  99                s->cis_virt = NULL;
 100        }
 101
 102        if (!(s->features & SS_CAP_STATIC_MAP) && (!s->cis_virt))
 103                s->cis_virt = ioremap(mem->res->start, s->map_size);
 104
 105        mem->card_start = card_offset;
 106        mem->flags = flags;
 107
 108        ret = s->ops->set_mem_map(s, mem);
 109        if (ret) {
 110                iounmap(s->cis_virt);
 111                s->cis_virt = NULL;
 112                return NULL;
 113        }
 114
 115        if (s->features & SS_CAP_STATIC_MAP) {
 116                if (s->cis_virt)
 117                        iounmap(s->cis_virt);
 118                s->cis_virt = ioremap(mem->static_start, s->map_size);
 119        }
 120
 121        return s->cis_virt;
 122}
 123
 124/*======================================================================
 125
 126    Low-level functions to read and write CIS memory.  I think the
 127    write routine is only useful for writing one-byte registers.
 128    
 129======================================================================*/
 130
 131/* Bits in attr field */
 132#define IS_ATTR         1
 133#define IS_INDIRECT     8
 134
 135int pcmcia_read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 136                 u_int len, void *ptr)
 137{
 138    void __iomem *sys, *end;
 139    unsigned char *buf = ptr;
 140    
 141    cs_dbg(s, 3, "pcmcia_read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 142
 143    if (attr & IS_INDIRECT) {
 144        /* Indirect accesses use a bunch of special registers at fixed
 145           locations in common memory */
 146        u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
 147        if (attr & IS_ATTR) {
 148            addr *= 2;
 149            flags = ICTRL0_AUTOINC;
 150        }
 151
 152        sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
 153        if (!sys) {
 154            memset(ptr, 0xff, len);
 155            return -1;
 156        }
 157
 158        writeb(flags, sys+CISREG_ICTRL0);
 159        writeb(addr & 0xff, sys+CISREG_IADDR0);
 160        writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
 161        writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
 162        writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
 163        for ( ; len > 0; len--, buf++)
 164            *buf = readb(sys+CISREG_IDATA0);
 165    } else {
 166        u_int inc = 1, card_offset, flags;
 167
 168        flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
 169        if (attr) {
 170            flags |= MAP_ATTRIB;
 171            inc++;
 172            addr *= 2;
 173        }
 174
 175        card_offset = addr & ~(s->map_size-1);
 176        while (len) {
 177            sys = set_cis_map(s, card_offset, flags);
 178            if (!sys) {
 179                memset(ptr, 0xff, len);
 180                return -1;
 181            }
 182            end = sys + s->map_size;
 183            sys = sys + (addr & (s->map_size-1));
 184            for ( ; len > 0; len--, buf++, sys += inc) {
 185                if (sys == end)
 186                    break;
 187                *buf = readb(sys);
 188            }
 189            card_offset += s->map_size;
 190            addr = 0;
 191        }
 192    }
 193    cs_dbg(s, 3, "  %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
 194          *(u_char *)(ptr+0), *(u_char *)(ptr+1),
 195          *(u_char *)(ptr+2), *(u_char *)(ptr+3));
 196    return 0;
 197}
 198EXPORT_SYMBOL(pcmcia_read_cis_mem);
 199
 200
 201void pcmcia_write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
 202                   u_int len, void *ptr)
 203{
 204    void __iomem *sys, *end;
 205    unsigned char *buf = ptr;
 206    
 207    cs_dbg(s, 3, "pcmcia_write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
 208
 209    if (attr & IS_INDIRECT) {
 210        /* Indirect accesses use a bunch of special registers at fixed
 211           locations in common memory */
 212        u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
 213        if (attr & IS_ATTR) {
 214            addr *= 2;
 215            flags = ICTRL0_AUTOINC;
 216        }
 217
 218        sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
 219        if (!sys)
 220                return; /* FIXME: Error */
 221
 222        writeb(flags, sys+CISREG_ICTRL0);
 223        writeb(addr & 0xff, sys+CISREG_IADDR0);
 224        writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
 225        writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
 226        writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
 227        for ( ; len > 0; len--, buf++)
 228            writeb(*buf, sys+CISREG_IDATA0);
 229    } else {
 230        u_int inc = 1, card_offset, flags;
 231
 232        flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
 233        if (attr & IS_ATTR) {
 234            flags |= MAP_ATTRIB;
 235            inc++;
 236            addr *= 2;
 237        }
 238
 239        card_offset = addr & ~(s->map_size-1);
 240        while (len) {
 241            sys = set_cis_map(s, card_offset, flags);
 242            if (!sys)
 243                return; /* FIXME: error */
 244
 245            end = sys + s->map_size;
 246            sys = sys + (addr & (s->map_size-1));
 247            for ( ; len > 0; len--, buf++, sys += inc) {
 248                if (sys == end)
 249                    break;
 250                writeb(*buf, sys);
 251            }
 252            card_offset += s->map_size;
 253            addr = 0;
 254        }
 255    }
 256}
 257EXPORT_SYMBOL(pcmcia_write_cis_mem);
 258
 259
 260/*======================================================================
 261
 262    This is a wrapper around read_cis_mem, with the same interface,
 263    but which caches information, for cards whose CIS may not be
 264    readable all the time.
 265    
 266======================================================================*/
 267
 268static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
 269                           size_t len, void *ptr)
 270{
 271    struct cis_cache_entry *cis;
 272    int ret;
 273
 274    if (s->fake_cis) {
 275        if (s->fake_cis_len >= addr+len)
 276            memcpy(ptr, s->fake_cis+addr, len);
 277        else
 278            memset(ptr, 0xff, len);
 279        return;
 280    }
 281
 282    list_for_each_entry(cis, &s->cis_cache, node) {
 283        if (cis->addr == addr && cis->len == len && cis->attr == attr) {
 284            memcpy(ptr, cis->cache, len);
 285            return;
 286        }
 287    }
 288
 289#ifdef CONFIG_CARDBUS
 290    if (s->state & SOCKET_CARDBUS)
 291        ret = read_cb_mem(s, attr, addr, len, ptr);
 292    else
 293#endif
 294        ret = pcmcia_read_cis_mem(s, attr, addr, len, ptr);
 295
 296        if (ret == 0) {
 297                /* Copy data into the cache */
 298                cis = kmalloc(sizeof(struct cis_cache_entry) + len, GFP_KERNEL);
 299                if (cis) {
 300                        cis->addr = addr;
 301                        cis->len = len;
 302                        cis->attr = attr;
 303                        memcpy(cis->cache, ptr, len);
 304                        list_add(&cis->node, &s->cis_cache);
 305                }
 306        }
 307}
 308
 309static void
 310remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
 311{
 312        struct cis_cache_entry *cis;
 313
 314        list_for_each_entry(cis, &s->cis_cache, node)
 315                if (cis->addr == addr && cis->len == len && cis->attr == attr) {
 316                        list_del(&cis->node);
 317                        kfree(cis);
 318                        break;
 319                }
 320}
 321
 322void destroy_cis_cache(struct pcmcia_socket *s)
 323{
 324        struct list_head *l, *n;
 325
 326        list_for_each_safe(l, n, &s->cis_cache) {
 327                struct cis_cache_entry *cis = list_entry(l, struct cis_cache_entry, node);
 328
 329                list_del(&cis->node);
 330                kfree(cis);
 331        }
 332
 333        /*
 334         * If there was a fake CIS, destroy that as well.
 335         */
 336        kfree(s->fake_cis);
 337        s->fake_cis = NULL;
 338}
 339EXPORT_SYMBOL(destroy_cis_cache);
 340
 341/*======================================================================
 342
 343    This verifies if the CIS of a card matches what is in the CIS
 344    cache.
 345    
 346======================================================================*/
 347
 348int verify_cis_cache(struct pcmcia_socket *s)
 349{
 350        struct cis_cache_entry *cis;
 351        char *buf;
 352
 353        buf = kmalloc(256, GFP_KERNEL);
 354        if (buf == NULL) {
 355                dev_printk(KERN_WARNING, &s->dev,
 356                           "no memory for verifying CIS\n");
 357                return -ENOMEM;
 358        }
 359        list_for_each_entry(cis, &s->cis_cache, node) {
 360                int len = cis->len;
 361
 362                if (len > 256)
 363                        len = 256;
 364#ifdef CONFIG_CARDBUS
 365                if (s->state & SOCKET_CARDBUS)
 366                        read_cb_mem(s, cis->attr, cis->addr, len, buf);
 367                else
 368#endif
 369                        pcmcia_read_cis_mem(s, cis->attr, cis->addr, len, buf);
 370
 371                if (memcmp(buf, cis->cache, len) != 0) {
 372                        kfree(buf);
 373                        return -1;
 374                }
 375        }
 376        kfree(buf);
 377        return 0;
 378}
 379
 380/*======================================================================
 381
 382    For really bad cards, we provide a facility for uploading a
 383    replacement CIS.
 384    
 385======================================================================*/
 386
 387int pcmcia_replace_cis(struct pcmcia_socket *s,
 388                       const u8 *data, const size_t len)
 389{
 390        if (len > CISTPL_MAX_CIS_SIZE) {
 391                dev_printk(KERN_WARNING, &s->dev, "replacement CIS too big\n");
 392                return -EINVAL;
 393        }
 394        kfree(s->fake_cis);
 395        s->fake_cis = kmalloc(len, GFP_KERNEL);
 396        if (s->fake_cis == NULL) {
 397                dev_printk(KERN_WARNING, &s->dev, "no memory to replace CIS\n");
 398                return -ENOMEM;
 399        }
 400        s->fake_cis_len = len;
 401        memcpy(s->fake_cis, data, len);
 402        return 0;
 403}
 404EXPORT_SYMBOL(pcmcia_replace_cis);
 405
 406/*======================================================================
 407
 408    The high-level CIS tuple services
 409    
 410======================================================================*/
 411
 412typedef struct tuple_flags {
 413    u_int               link_space:4;
 414    u_int               has_link:1;
 415    u_int               mfc_fn:3;
 416    u_int               space:4;
 417} tuple_flags;
 418
 419#define LINK_SPACE(f)   (((tuple_flags *)(&(f)))->link_space)
 420#define HAS_LINK(f)     (((tuple_flags *)(&(f)))->has_link)
 421#define MFC_FN(f)       (((tuple_flags *)(&(f)))->mfc_fn)
 422#define SPACE(f)        (((tuple_flags *)(&(f)))->space)
 423
 424int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int func, tuple_t *tuple);
 425
 426int pccard_get_first_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
 427{
 428    if (!s)
 429        return -EINVAL;
 430    if (!(s->state & SOCKET_PRESENT))
 431        return -ENODEV;
 432    tuple->TupleLink = tuple->Flags = 0;
 433#ifdef CONFIG_CARDBUS
 434    if (s->state & SOCKET_CARDBUS) {
 435        struct pci_dev *dev = s->cb_dev;
 436        u_int ptr;
 437        pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr);
 438        tuple->CISOffset = ptr & ~7;
 439        SPACE(tuple->Flags) = (ptr & 7);
 440    } else
 441#endif
 442    {
 443        /* Assume presence of a LONGLINK_C to address 0 */
 444        tuple->CISOffset = tuple->LinkOffset = 0;
 445        SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
 446    }
 447    if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
 448        !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
 449        cisdata_t req = tuple->DesiredTuple;
 450        tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
 451        if (pccard_get_next_tuple(s, function, tuple) == 0) {
 452            tuple->DesiredTuple = CISTPL_LINKTARGET;
 453            if (pccard_get_next_tuple(s, function, tuple) != 0)
 454                return -ENOSPC;
 455        } else
 456            tuple->CISOffset = tuple->TupleLink = 0;
 457        tuple->DesiredTuple = req;
 458    }
 459    return pccard_get_next_tuple(s, function, tuple);
 460}
 461EXPORT_SYMBOL(pccard_get_first_tuple);
 462
 463static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
 464{
 465    u_char link[5];
 466    u_int ofs;
 467
 468    if (MFC_FN(tuple->Flags)) {
 469        /* Get indirect link from the MFC tuple */
 470        read_cis_cache(s, LINK_SPACE(tuple->Flags),
 471                       tuple->LinkOffset, 5, link);
 472        ofs = get_unaligned_le32(link + 1);
 473        SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
 474        /* Move to the next indirect link */
 475        tuple->LinkOffset += 5;
 476        MFC_FN(tuple->Flags)--;
 477    } else if (HAS_LINK(tuple->Flags)) {
 478        ofs = tuple->LinkOffset;
 479        SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
 480        HAS_LINK(tuple->Flags) = 0;
 481    } else {
 482        return -1;
 483    }
 484    if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) {
 485        /* This is ugly, but a common CIS error is to code the long
 486           link offset incorrectly, so we check the right spot... */
 487        read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
 488        if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
 489            (strncmp(link+2, "CIS", 3) == 0))
 490            return ofs;
 491        remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
 492        /* Then, we try the wrong spot... */
 493        ofs = ofs >> 1;
 494    }
 495    read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
 496    if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
 497        (strncmp(link+2, "CIS", 3) == 0))
 498        return ofs;
 499    remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
 500    return -1;
 501}
 502
 503int pccard_get_next_tuple(struct pcmcia_socket *s, unsigned int function, tuple_t *tuple)
 504{
 505    u_char link[2], tmp;
 506    int ofs, i, attr;
 507
 508    if (!s)
 509        return -EINVAL;
 510    if (!(s->state & SOCKET_PRESENT))
 511        return -ENODEV;
 512
 513    link[1] = tuple->TupleLink;
 514    ofs = tuple->CISOffset + tuple->TupleLink;
 515    attr = SPACE(tuple->Flags);
 516
 517    for (i = 0; i < MAX_TUPLES; i++) {
 518        if (link[1] == 0xff) {
 519            link[0] = CISTPL_END;
 520        } else {
 521            read_cis_cache(s, attr, ofs, 2, link);
 522            if (link[0] == CISTPL_NULL) {
 523                ofs++; continue;
 524            }
 525        }
 526        
 527        /* End of chain?  Follow long link if possible */
 528        if (link[0] == CISTPL_END) {
 529            if ((ofs = follow_link(s, tuple)) < 0)
 530                return -ENOSPC;
 531            attr = SPACE(tuple->Flags);
 532            read_cis_cache(s, attr, ofs, 2, link);
 533        }
 534
 535        /* Is this a link tuple?  Make a note of it */
 536        if ((link[0] == CISTPL_LONGLINK_A) ||
 537            (link[0] == CISTPL_LONGLINK_C) ||
 538            (link[0] == CISTPL_LONGLINK_MFC) ||
 539            (link[0] == CISTPL_LINKTARGET) ||
 540            (link[0] == CISTPL_INDIRECT) ||
 541            (link[0] == CISTPL_NO_LINK)) {
 542            switch (link[0]) {
 543            case CISTPL_LONGLINK_A:
 544                HAS_LINK(tuple->Flags) = 1;
 545                LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
 546                read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
 547                break;
 548            case CISTPL_LONGLINK_C:
 549                HAS_LINK(tuple->Flags) = 1;
 550                LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
 551                read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
 552                break;
 553            case CISTPL_INDIRECT:
 554                HAS_LINK(tuple->Flags) = 1;
 555                LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
 556                tuple->LinkOffset = 0;
 557                break;
 558            case CISTPL_LONGLINK_MFC:
 559                tuple->LinkOffset = ofs + 3;
 560                LINK_SPACE(tuple->Flags) = attr;
 561                if (function == BIND_FN_ALL) {
 562                    /* Follow all the MFC links */
 563                    read_cis_cache(s, attr, ofs+2, 1, &tmp);
 564                    MFC_FN(tuple->Flags) = tmp;
 565                } else {
 566                    /* Follow exactly one of the links */
 567                    MFC_FN(tuple->Flags) = 1;
 568                    tuple->LinkOffset += function * 5;
 569                }
 570                break;
 571            case CISTPL_NO_LINK:
 572                HAS_LINK(tuple->Flags) = 0;
 573                break;
 574            }
 575            if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
 576                (tuple->DesiredTuple == RETURN_FIRST_TUPLE))
 577                break;
 578        } else
 579            if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
 580                break;
 581        
 582        if (link[0] == tuple->DesiredTuple)
 583            break;
 584        ofs += link[1] + 2;
 585    }
 586    if (i == MAX_TUPLES) {
 587        cs_dbg(s, 1, "cs: overrun in pcmcia_get_next_tuple\n");
 588        return -ENOSPC;
 589    }
 590    
 591    tuple->TupleCode = link[0];
 592    tuple->TupleLink = link[1];
 593    tuple->CISOffset = ofs + 2;
 594    return 0;
 595}
 596EXPORT_SYMBOL(pccard_get_next_tuple);
 597
 598/*====================================================================*/
 599
 600#define _MIN(a, b)              (((a) < (b)) ? (a) : (b))
 601
 602int pccard_get_tuple_data(struct pcmcia_socket *s, tuple_t *tuple)
 603{
 604    u_int len;
 605
 606    if (!s)
 607        return -EINVAL;
 608
 609    if (tuple->TupleLink < tuple->TupleOffset)
 610        return -ENOSPC;
 611    len = tuple->TupleLink - tuple->TupleOffset;
 612    tuple->TupleDataLen = tuple->TupleLink;
 613    if (len == 0)
 614        return 0;
 615    read_cis_cache(s, SPACE(tuple->Flags),
 616                   tuple->CISOffset + tuple->TupleOffset,
 617                   _MIN(len, tuple->TupleDataMax), tuple->TupleData);
 618    return 0;
 619}
 620EXPORT_SYMBOL(pccard_get_tuple_data);
 621
 622
 623/*======================================================================
 624
 625    Parsing routines for individual tuples
 626    
 627======================================================================*/
 628
 629static int parse_device(tuple_t *tuple, cistpl_device_t *device)
 630{
 631    int i;
 632    u_char scale;
 633    u_char *p, *q;
 634
 635    p = (u_char *)tuple->TupleData;
 636    q = p + tuple->TupleDataLen;
 637
 638    device->ndev = 0;
 639    for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
 640        
 641        if (*p == 0xff) break;
 642        device->dev[i].type = (*p >> 4);
 643        device->dev[i].wp = (*p & 0x08) ? 1 : 0;
 644        switch (*p & 0x07) {
 645        case 0: device->dev[i].speed = 0;   break;
 646        case 1: device->dev[i].speed = 250; break;
 647        case 2: device->dev[i].speed = 200; break;
 648        case 3: device->dev[i].speed = 150; break;
 649        case 4: device->dev[i].speed = 100; break;
 650        case 7:
 651            if (++p == q)
 652                    return -EINVAL;
 653            device->dev[i].speed = SPEED_CVT(*p);
 654            while (*p & 0x80)
 655                if (++p == q)
 656                        return -EINVAL;
 657            break;
 658        default:
 659            return -EINVAL;
 660        }
 661
 662        if (++p == q)
 663                return -EINVAL;
 664        if (*p == 0xff)
 665                break;
 666        scale = *p & 7;
 667        if (scale == 7)
 668                return -EINVAL;
 669        device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
 670        device->ndev++;
 671        if (++p == q)
 672                break;
 673    }
 674    
 675    return 0;
 676}
 677
 678/*====================================================================*/
 679
 680static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
 681{
 682    u_char *p;
 683    if (tuple->TupleDataLen < 5)
 684        return -EINVAL;
 685    p = (u_char *) tuple->TupleData;
 686    csum->addr = tuple->CISOffset + get_unaligned_le16(p) - 2;
 687    csum->len = get_unaligned_le16(p + 2);
 688    csum->sum = *(p + 4);
 689    return 0;
 690}
 691
 692/*====================================================================*/
 693
 694static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
 695{
 696    if (tuple->TupleDataLen < 4)
 697        return -EINVAL;
 698    link->addr = get_unaligned_le32(tuple->TupleData);
 699    return 0;
 700}
 701
 702/*====================================================================*/
 703
 704static int parse_longlink_mfc(tuple_t *tuple,
 705                              cistpl_longlink_mfc_t *link)
 706{
 707    u_char *p;
 708    int i;
 709    
 710    p = (u_char *)tuple->TupleData;
 711    
 712    link->nfn = *p; p++;
 713    if (tuple->TupleDataLen <= link->nfn*5)
 714        return -EINVAL;
 715    for (i = 0; i < link->nfn; i++) {
 716        link->fn[i].space = *p; p++;
 717        link->fn[i].addr = get_unaligned_le32(p);
 718        p += 4;
 719    }
 720    return 0;
 721}
 722
 723/*====================================================================*/
 724
 725static int parse_strings(u_char *p, u_char *q, int max,
 726                         char *s, u_char *ofs, u_char *found)
 727{
 728    int i, j, ns;
 729
 730    if (p == q)
 731            return -EINVAL;
 732    ns = 0; j = 0;
 733    for (i = 0; i < max; i++) {
 734        if (*p == 0xff)
 735                break;
 736        ofs[i] = j;
 737        ns++;
 738        for (;;) {
 739            s[j++] = (*p == 0xff) ? '\0' : *p;
 740            if ((*p == '\0') || (*p == 0xff)) break;
 741            if (++p == q)
 742                    return -EINVAL;
 743        }
 744        if ((*p == 0xff) || (++p == q)) break;
 745    }
 746    if (found) {
 747        *found = ns;
 748        return 0;
 749    } else {
 750        return (ns == max) ? 0 : -EINVAL;
 751    }
 752}
 753
 754/*====================================================================*/
 755
 756static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
 757{
 758    u_char *p, *q;
 759    
 760    p = (u_char *)tuple->TupleData;
 761    q = p + tuple->TupleDataLen;
 762    
 763    vers_1->major = *p; p++;
 764    vers_1->minor = *p; p++;
 765    if (p >= q)
 766            return -EINVAL;
 767
 768    return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
 769                         vers_1->str, vers_1->ofs, &vers_1->ns);
 770}
 771
 772/*====================================================================*/
 773
 774static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
 775{
 776    u_char *p, *q;
 777    
 778    p = (u_char *)tuple->TupleData;
 779    q = p + tuple->TupleDataLen;
 780    
 781    return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
 782                         altstr->str, altstr->ofs, &altstr->ns);
 783}
 784
 785/*====================================================================*/
 786
 787static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
 788{
 789    u_char *p, *q;
 790    int nid;
 791
 792    p = (u_char *)tuple->TupleData;
 793    q = p + tuple->TupleDataLen;
 794
 795    for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
 796        if (p > q-2) break;
 797        jedec->id[nid].mfr = p[0];
 798        jedec->id[nid].info = p[1];
 799        p += 2;
 800    }
 801    jedec->nid = nid;
 802    return 0;
 803}
 804
 805/*====================================================================*/
 806
 807static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
 808{
 809    if (tuple->TupleDataLen < 4)
 810        return -EINVAL;
 811    m->manf = get_unaligned_le16(tuple->TupleData);
 812    m->card = get_unaligned_le16(tuple->TupleData + 2);
 813    return 0;
 814}
 815
 816/*====================================================================*/
 817
 818static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
 819{
 820    u_char *p;
 821    if (tuple->TupleDataLen < 2)
 822        return -EINVAL;
 823    p = (u_char *)tuple->TupleData;
 824    f->func = p[0];
 825    f->sysinit = p[1];
 826    return 0;
 827}
 828
 829/*====================================================================*/
 830
 831static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
 832{
 833    u_char *p;
 834    int i;
 835    if (tuple->TupleDataLen < 1)
 836        return -EINVAL;
 837    p = (u_char *)tuple->TupleData;
 838    f->type = p[0];
 839    for (i = 1; i < tuple->TupleDataLen; i++)
 840        f->data[i-1] = p[i];
 841    return 0;
 842}
 843
 844/*====================================================================*/
 845
 846static int parse_config(tuple_t *tuple, cistpl_config_t *config)
 847{
 848    int rasz, rmsz, i;
 849    u_char *p;
 850
 851    p = (u_char *)tuple->TupleData;
 852    rasz = *p & 0x03;
 853    rmsz = (*p & 0x3c) >> 2;
 854    if (tuple->TupleDataLen < rasz+rmsz+4)
 855        return -EINVAL;
 856    config->last_idx = *(++p);
 857    p++;
 858    config->base = 0;
 859    for (i = 0; i <= rasz; i++)
 860        config->base += p[i] << (8*i);
 861    p += rasz+1;
 862    for (i = 0; i < 4; i++)
 863        config->rmask[i] = 0;
 864    for (i = 0; i <= rmsz; i++)
 865        config->rmask[i>>2] += p[i] << (8*(i%4));
 866    config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
 867    return 0;
 868}
 869
 870/*======================================================================
 871
 872    The following routines are all used to parse the nightmarish
 873    config table entries.
 874    
 875======================================================================*/
 876
 877static u_char *parse_power(u_char *p, u_char *q,
 878                           cistpl_power_t *pwr)
 879{
 880    int i;
 881    u_int scale;
 882
 883    if (p == q) return NULL;
 884    pwr->present = *p;
 885    pwr->flags = 0;
 886    p++;
 887    for (i = 0; i < 7; i++)
 888        if (pwr->present & (1<<i)) {
 889            if (p == q) return NULL;
 890            pwr->param[i] = POWER_CVT(*p);
 891            scale = POWER_SCALE(*p);
 892            while (*p & 0x80) {
 893                if (++p == q) return NULL;
 894                if ((*p & 0x7f) < 100)
 895                    pwr->param[i] += (*p & 0x7f) * scale / 100;
 896                else if (*p == 0x7d)
 897                    pwr->flags |= CISTPL_POWER_HIGHZ_OK;
 898                else if (*p == 0x7e)
 899                    pwr->param[i] = 0;
 900                else if (*p == 0x7f)
 901                    pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
 902                else
 903                    return NULL;
 904            }
 905            p++;
 906        }
 907    return p;
 908}
 909
 910/*====================================================================*/
 911
 912static u_char *parse_timing(u_char *p, u_char *q,
 913                            cistpl_timing_t *timing)
 914{
 915    u_char scale;
 916
 917    if (p == q) return NULL;
 918    scale = *p;
 919    if ((scale & 3) != 3) {
 920        if (++p == q) return NULL;
 921        timing->wait = SPEED_CVT(*p);
 922        timing->waitscale = exponent[scale & 3];
 923    } else
 924        timing->wait = 0;
 925    scale >>= 2;
 926    if ((scale & 7) != 7) {
 927        if (++p == q) return NULL;
 928        timing->ready = SPEED_CVT(*p);
 929        timing->rdyscale = exponent[scale & 7];
 930    } else
 931        timing->ready = 0;
 932    scale >>= 3;
 933    if (scale != 7) {
 934        if (++p == q) return NULL;
 935        timing->reserved = SPEED_CVT(*p);
 936        timing->rsvscale = exponent[scale];
 937    } else
 938        timing->reserved = 0;
 939    p++;
 940    return p;
 941}
 942
 943/*====================================================================*/
 944
 945static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
 946{
 947    int i, j, bsz, lsz;
 948
 949    if (p == q) return NULL;
 950    io->flags = *p;
 951
 952    if (!(*p & 0x80)) {
 953        io->nwin = 1;
 954        io->win[0].base = 0;
 955        io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
 956        return p+1;
 957    }
 958    
 959    if (++p == q) return NULL;
 960    io->nwin = (*p & 0x0f) + 1;
 961    bsz = (*p & 0x30) >> 4;
 962    if (bsz == 3) bsz++;
 963    lsz = (*p & 0xc0) >> 6;
 964    if (lsz == 3) lsz++;
 965    p++;
 966    
 967    for (i = 0; i < io->nwin; i++) {
 968        io->win[i].base = 0;
 969        io->win[i].len = 1;
 970        for (j = 0; j < bsz; j++, p++) {
 971            if (p == q) return NULL;
 972            io->win[i].base += *p << (j*8);
 973        }
 974        for (j = 0; j < lsz; j++, p++) {
 975            if (p == q) return NULL;
 976            io->win[i].len += *p << (j*8);
 977        }
 978    }
 979    return p;
 980}
 981
 982/*====================================================================*/
 983
 984static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
 985{
 986    int i, j, asz, lsz, has_ha;
 987    u_int len, ca, ha;
 988
 989    if (p == q) return NULL;
 990
 991    mem->nwin = (*p & 0x07) + 1;
 992    lsz = (*p & 0x18) >> 3;
 993    asz = (*p & 0x60) >> 5;
 994    has_ha = (*p & 0x80);
 995    if (++p == q) return NULL;
 996    
 997    for (i = 0; i < mem->nwin; i++) {
 998        len = ca = ha = 0;
 999        for (j = 0; j < lsz; j++, p++) {
1000            if (p == q) return NULL;
1001            len += *p << (j*8);
1002        }
1003        for (j = 0; j < asz; j++, p++) {
1004            if (p == q) return NULL;
1005            ca += *p << (j*8);
1006        }
1007        if (has_ha)
1008            for (j = 0; j < asz; j++, p++) {
1009                if (p == q) return NULL;
1010                ha += *p << (j*8);
1011            }
1012        mem->win[i].len = len << 8;
1013        mem->win[i].card_addr = ca << 8;
1014        mem->win[i].host_addr = ha << 8;
1015    }
1016    return p;
1017}
1018
1019/*====================================================================*/
1020
1021static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
1022{
1023    if (p == q)
1024            return NULL;
1025    irq->IRQInfo1 = *p; p++;
1026    if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
1027        if (p+2 > q)
1028                return NULL;
1029        irq->IRQInfo2 = (p[1]<<8) + p[0];
1030        p += 2;
1031    }
1032    return p;
1033}
1034
1035/*====================================================================*/
1036
1037static int parse_cftable_entry(tuple_t *tuple,
1038                               cistpl_cftable_entry_t *entry)
1039{
1040    u_char *p, *q, features;
1041
1042    p = tuple->TupleData;
1043    q = p + tuple->TupleDataLen;
1044    entry->index = *p & 0x3f;
1045    entry->flags = 0;
1046    if (*p & 0x40)
1047        entry->flags |= CISTPL_CFTABLE_DEFAULT;
1048    if (*p & 0x80) {
1049        if (++p == q)
1050                return -EINVAL;
1051        if (*p & 0x10)
1052            entry->flags |= CISTPL_CFTABLE_BVDS;
1053        if (*p & 0x20)
1054            entry->flags |= CISTPL_CFTABLE_WP;
1055        if (*p & 0x40)
1056            entry->flags |= CISTPL_CFTABLE_RDYBSY;
1057        if (*p & 0x80)
1058            entry->flags |= CISTPL_CFTABLE_MWAIT;
1059        entry->interface = *p & 0x0f;
1060    } else
1061        entry->interface = 0;
1062
1063    /* Process optional features */
1064    if (++p == q)
1065            return -EINVAL;
1066    features = *p; p++;
1067
1068    /* Power options */
1069    if ((features & 3) > 0) {
1070        p = parse_power(p, q, &entry->vcc);
1071        if (p == NULL)
1072                return -EINVAL;
1073    } else
1074        entry->vcc.present = 0;
1075    if ((features & 3) > 1) {
1076        p = parse_power(p, q, &entry->vpp1);
1077        if (p == NULL)
1078                return -EINVAL;
1079    } else
1080        entry->vpp1.present = 0;
1081    if ((features & 3) > 2) {
1082        p = parse_power(p, q, &entry->vpp2);
1083        if (p == NULL)
1084                return -EINVAL;
1085    } else
1086        entry->vpp2.present = 0;
1087
1088    /* Timing options */
1089    if (features & 0x04) {
1090        p = parse_timing(p, q, &entry->timing);
1091        if (p == NULL)
1092                return -EINVAL;
1093    } else {
1094        entry->timing.wait = 0;
1095        entry->timing.ready = 0;
1096        entry->timing.reserved = 0;
1097    }
1098    
1099    /* I/O window options */
1100    if (features & 0x08) {
1101        p = parse_io(p, q, &entry->io);
1102        if (p == NULL)
1103                return -EINVAL;
1104    } else
1105        entry->io.nwin = 0;
1106    
1107    /* Interrupt options */
1108    if (features & 0x10) {
1109        p = parse_irq(p, q, &entry->irq);
1110        if (p == NULL)
1111                return -EINVAL;
1112    } else
1113        entry->irq.IRQInfo1 = 0;
1114
1115    switch (features & 0x60) {
1116    case 0x00:
1117        entry->mem.nwin = 0;
1118        break;
1119    case 0x20:
1120        entry->mem.nwin = 1;
1121        entry->mem.win[0].len = get_unaligned_le16(p) << 8;
1122        entry->mem.win[0].card_addr = 0;
1123        entry->mem.win[0].host_addr = 0;
1124        p += 2;
1125        if (p > q)
1126                return -EINVAL;
1127        break;
1128    case 0x40:
1129        entry->mem.nwin = 1;
1130        entry->mem.win[0].len = get_unaligned_le16(p) << 8;
1131        entry->mem.win[0].card_addr = get_unaligned_le16(p + 2) << 8;
1132        entry->mem.win[0].host_addr = 0;
1133        p += 4;
1134        if (p > q)
1135                return -EINVAL;
1136        break;
1137    case 0x60:
1138        p = parse_mem(p, q, &entry->mem);
1139        if (p == NULL)
1140                return -EINVAL;
1141        break;
1142    }
1143
1144    /* Misc features */
1145    if (features & 0x80) {
1146        if (p == q)
1147                return -EINVAL;
1148        entry->flags |= (*p << 8);
1149        while (*p & 0x80)
1150            if (++p == q)
1151                    return -EINVAL;
1152        p++;
1153    }
1154
1155    entry->subtuples = q-p;
1156    
1157    return 0;
1158}
1159
1160/*====================================================================*/
1161
1162#ifdef CONFIG_CARDBUS
1163
1164static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
1165{
1166    u_char *p;
1167    if (tuple->TupleDataLen < 6)
1168        return -EINVAL;
1169    p = (u_char *)tuple->TupleData;
1170    bar->attr = *p;
1171    p += 2;
1172    bar->size = get_unaligned_le32(p);
1173    return 0;
1174}
1175
1176static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
1177{
1178    u_char *p;
1179    
1180    p = (u_char *)tuple->TupleData;
1181    if ((*p != 3) || (tuple->TupleDataLen < 6))
1182        return -EINVAL;
1183    config->last_idx = *(++p);
1184    p++;
1185    config->base = get_unaligned_le32(p);
1186    config->subtuples = tuple->TupleDataLen - 6;
1187    return 0;
1188}
1189
1190static int parse_cftable_entry_cb(tuple_t *tuple,
1191                                  cistpl_cftable_entry_cb_t *entry)
1192{
1193    u_char *p, *q, features;
1194
1195    p = tuple->TupleData;
1196    q = p + tuple->TupleDataLen;
1197    entry->index = *p & 0x3f;
1198    entry->flags = 0;
1199    if (*p & 0x40)
1200        entry->flags |= CISTPL_CFTABLE_DEFAULT;
1201
1202    /* Process optional features */
1203    if (++p == q)
1204            return -EINVAL;
1205    features = *p; p++;
1206
1207    /* Power options */
1208    if ((features & 3) > 0) {
1209        p = parse_power(p, q, &entry->vcc);
1210        if (p == NULL)
1211                return -EINVAL;
1212    } else
1213        entry->vcc.present = 0;
1214    if ((features & 3) > 1) {
1215        p = parse_power(p, q, &entry->vpp1);
1216        if (p == NULL)
1217                return -EINVAL;
1218    } else
1219        entry->vpp1.present = 0;
1220    if ((features & 3) > 2) {
1221        p = parse_power(p, q, &entry->vpp2);
1222        if (p == NULL)
1223                return -EINVAL;
1224    } else
1225        entry->vpp2.present = 0;
1226
1227    /* I/O window options */
1228    if (features & 0x08) {
1229        if (p == q)
1230                return -EINVAL;
1231        entry->io = *p; p++;
1232    } else
1233        entry->io = 0;
1234    
1235    /* Interrupt options */
1236    if (features & 0x10) {
1237        p = parse_irq(p, q, &entry->irq);
1238        if (p == NULL)
1239                return -EINVAL;
1240    } else
1241        entry->irq.IRQInfo1 = 0;
1242
1243    if (features & 0x20) {
1244        if (p == q)
1245                return -EINVAL;
1246        entry->mem = *p; p++;
1247    } else
1248        entry->mem = 0;
1249
1250    /* Misc features */
1251    if (features & 0x80) {
1252        if (p == q)
1253                return -EINVAL;
1254        entry->flags |= (*p << 8);
1255        if (*p & 0x80) {
1256            if (++p == q)
1257                    return -EINVAL;
1258            entry->flags |= (*p << 16);
1259        }
1260        while (*p & 0x80)
1261            if (++p == q)
1262                    return -EINVAL;
1263        p++;
1264    }
1265
1266    entry->subtuples = q-p;
1267    
1268    return 0;
1269}
1270
1271#endif
1272
1273/*====================================================================*/
1274
1275static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
1276{
1277    u_char *p, *q;
1278    int n;
1279
1280    p = (u_char *)tuple->TupleData;
1281    q = p + tuple->TupleDataLen;
1282
1283    for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
1284        if (p > q-6) break;
1285        geo->geo[n].buswidth = p[0];
1286        geo->geo[n].erase_block = 1 << (p[1]-1);
1287        geo->geo[n].read_block  = 1 << (p[2]-1);
1288        geo->geo[n].write_block = 1 << (p[3]-1);
1289        geo->geo[n].partition   = 1 << (p[4]-1);
1290        geo->geo[n].interleave  = 1 << (p[5]-1);
1291        p += 6;
1292    }
1293    geo->ngeo = n;
1294    return 0;
1295}
1296
1297/*====================================================================*/
1298
1299static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
1300{
1301    u_char *p, *q;
1302
1303    if (tuple->TupleDataLen < 10)
1304        return -EINVAL;
1305    
1306    p = tuple->TupleData;
1307    q = p + tuple->TupleDataLen;
1308
1309    v2->vers = p[0];
1310    v2->comply = p[1];
1311    v2->dindex = get_unaligned_le16(p +2 );
1312    v2->vspec8 = p[6];
1313    v2->vspec9 = p[7];
1314    v2->nhdr = p[8];
1315    p += 9;
1316    return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
1317}
1318
1319/*====================================================================*/
1320
1321static int parse_org(tuple_t *tuple, cistpl_org_t *org)
1322{
1323    u_char *p, *q;
1324    int i;
1325    
1326    p = tuple->TupleData;
1327    q = p + tuple->TupleDataLen;
1328    if (p == q)
1329            return -EINVAL;
1330    org->data_org = *p;
1331    if (++p == q)
1332            return -EINVAL;
1333    for (i = 0; i < 30; i++) {
1334        org->desc[i] = *p;
1335        if (*p == '\0') break;
1336        if (++p == q)
1337                return -EINVAL;
1338    }
1339    return 0;
1340}
1341
1342/*====================================================================*/
1343
1344static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
1345{
1346    u_char *p;
1347
1348    if (tuple->TupleDataLen < 10)
1349        return -EINVAL;
1350
1351    p = tuple->TupleData;
1352
1353    fmt->type = p[0];
1354    fmt->edc = p[1];
1355    fmt->offset = get_unaligned_le32(p + 2);
1356    fmt->length = get_unaligned_le32(p + 6);
1357
1358    return 0;
1359}
1360
1361/*====================================================================*/
1362
1363int pcmcia_parse_tuple(tuple_t *tuple, cisparse_t *parse)
1364{
1365    int ret = 0;
1366    
1367    if (tuple->TupleDataLen > tuple->TupleDataMax)
1368        return -EINVAL;
1369    switch (tuple->TupleCode) {
1370    case CISTPL_DEVICE:
1371    case CISTPL_DEVICE_A:
1372        ret = parse_device(tuple, &parse->device);
1373        break;
1374#ifdef CONFIG_CARDBUS
1375    case CISTPL_BAR:
1376        ret = parse_bar(tuple, &parse->bar);
1377        break;
1378    case CISTPL_CONFIG_CB:
1379        ret = parse_config_cb(tuple, &parse->config);
1380        break;
1381    case CISTPL_CFTABLE_ENTRY_CB:
1382        ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
1383        break;
1384#endif
1385    case CISTPL_CHECKSUM:
1386        ret = parse_checksum(tuple, &parse->checksum);
1387        break;
1388    case CISTPL_LONGLINK_A:
1389    case CISTPL_LONGLINK_C:
1390        ret = parse_longlink(tuple, &parse->longlink);
1391        break;
1392    case CISTPL_LONGLINK_MFC:
1393        ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
1394        break;
1395    case CISTPL_VERS_1:
1396        ret = parse_vers_1(tuple, &parse->version_1);
1397        break;
1398    case CISTPL_ALTSTR:
1399        ret = parse_altstr(tuple, &parse->altstr);
1400        break;
1401    case CISTPL_JEDEC_A:
1402    case CISTPL_JEDEC_C:
1403        ret = parse_jedec(tuple, &parse->jedec);
1404        break;
1405    case CISTPL_MANFID:
1406        ret = parse_manfid(tuple, &parse->manfid);
1407        break;
1408    case CISTPL_FUNCID:
1409        ret = parse_funcid(tuple, &parse->funcid);
1410        break;
1411    case CISTPL_FUNCE:
1412        ret = parse_funce(tuple, &parse->funce);
1413        break;
1414    case CISTPL_CONFIG:
1415        ret = parse_config(tuple, &parse->config);
1416        break;
1417    case CISTPL_CFTABLE_ENTRY:
1418        ret = parse_cftable_entry(tuple, &parse->cftable_entry);
1419        break;
1420    case CISTPL_DEVICE_GEO:
1421    case CISTPL_DEVICE_GEO_A:
1422        ret = parse_device_geo(tuple, &parse->device_geo);
1423        break;
1424    case CISTPL_VERS_2:
1425        ret = parse_vers_2(tuple, &parse->vers_2);
1426        break;
1427    case CISTPL_ORG:
1428        ret = parse_org(tuple, &parse->org);
1429        break;
1430    case CISTPL_FORMAT:
1431    case CISTPL_FORMAT_A:
1432        ret = parse_format(tuple, &parse->format);
1433        break;
1434    case CISTPL_NO_LINK:
1435    case CISTPL_LINKTARGET:
1436        ret = 0;
1437        break;
1438    default:
1439        ret = -EINVAL;
1440        break;
1441    }
1442    if (ret)
1443            __cs_dbg(0, "parse_tuple failed %d\n", ret);
1444    return ret;
1445}
1446EXPORT_SYMBOL(pcmcia_parse_tuple);
1447
1448/*======================================================================
1449
1450    This is used internally by Card Services to look up CIS stuff.
1451    
1452======================================================================*/
1453
1454int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t code, void *parse)
1455{
1456    tuple_t tuple;
1457    cisdata_t *buf;
1458    int ret;
1459
1460    buf = kmalloc(256, GFP_KERNEL);
1461    if (buf == NULL) {
1462            dev_printk(KERN_WARNING, &s->dev, "no memory to read tuple\n");
1463            return -ENOMEM;
1464    }
1465    tuple.DesiredTuple = code;
1466    tuple.Attributes = 0;
1467    if (function == BIND_FN_ALL)
1468            tuple.Attributes = TUPLE_RETURN_COMMON;
1469    ret = pccard_get_first_tuple(s, function, &tuple);
1470    if (ret != 0)
1471            goto done;
1472    tuple.TupleData = buf;
1473    tuple.TupleOffset = 0;
1474    tuple.TupleDataMax = 255;
1475    ret = pccard_get_tuple_data(s, &tuple);
1476    if (ret != 0)
1477            goto done;
1478    ret = pcmcia_parse_tuple(&tuple, parse);
1479done:
1480    kfree(buf);
1481    return ret;
1482}
1483EXPORT_SYMBOL(pccard_read_tuple);
1484
1485/*======================================================================
1486
1487    This tries to determine if a card has a sensible CIS.  It returns
1488    the number of tuples in the CIS, or 0 if the CIS looks bad.  The
1489    checks include making sure several critical tuples are present and
1490    valid; seeing if the total number of tuples is reasonable; and
1491    looking for tuples that use reserved codes.
1492    
1493======================================================================*/
1494
1495int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
1496{
1497    tuple_t *tuple;
1498    cisparse_t *p;
1499    unsigned int count = 0;
1500    int ret, reserved, dev_ok = 0, ident_ok = 0;
1501
1502    if (!s)
1503        return -EINVAL;
1504
1505    tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
1506    if (tuple == NULL) {
1507            dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
1508            return -ENOMEM;
1509    }
1510    p = kmalloc(sizeof(*p), GFP_KERNEL);
1511    if (p == NULL) {
1512            kfree(tuple);
1513            dev_printk(KERN_WARNING, &s->dev, "no memory to validate CIS\n");
1514            return -ENOMEM;
1515    }
1516
1517    count = reserved = 0;
1518    tuple->DesiredTuple = RETURN_FIRST_TUPLE;
1519    tuple->Attributes = TUPLE_RETURN_COMMON;
1520    ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
1521    if (ret != 0)
1522        goto done;
1523
1524    /* First tuple should be DEVICE; we should really have either that
1525       or a CFTABLE_ENTRY of some sort */
1526    if ((tuple->TupleCode == CISTPL_DEVICE) ||
1527        (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) ||
1528        (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
1529        dev_ok++;
1530
1531    /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
1532       tuple, for card identification.  Certain old D-Link and Linksys
1533       cards have only a broken VERS_2 tuple; hence the bogus test. */
1534    if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) ||
1535        (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) ||
1536        (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC))
1537        ident_ok++;
1538
1539    if (!dev_ok && !ident_ok)
1540        goto done;
1541
1542    for (count = 1; count < MAX_TUPLES; count++) {
1543        ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple);
1544        if (ret != 0)
1545                break;
1546        if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
1547            ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
1548            ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
1549            reserved++;
1550    }
1551    if ((count == MAX_TUPLES) || (reserved > 5) ||
1552        ((!dev_ok || !ident_ok) && (count > 10)))
1553        count = 0;
1554
1555done:
1556    if (info)
1557            *info = count;
1558    kfree(tuple);
1559    kfree(p);
1560    return 0;
1561}
1562EXPORT_SYMBOL(pccard_validate_cis);
1563