Root/drivers/pcmcia/cistpl.c

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

Archive Download this file



interactive