OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [pcmcia/] [cistpl.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.