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

Archive Download this file



interactive