More meth updates.
[linux-2.6/linux-mips.git] / drivers / pcmcia / cistpl.c
blob3dfaa5bb58820736d2a187a10d350a6c4d7bee3d
1 /*======================================================================
3 PCMCIA Card Information Structure parser
5 cistpl.c 1.99 2002/10/24 06:11:48
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/
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.
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.
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.
32 ======================================================================*/
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/kernel.h>
37 #include <linux/string.h>
38 #include <linux/major.h>
39 #include <linux/errno.h>
40 #include <linux/timer.h>
41 #include <linux/slab.h>
42 #include <linux/mm.h>
43 #include <linux/sched.h>
44 #include <linux/pci.h>
45 #include <linux/ioport.h>
46 #include <asm/io.h>
47 #include <asm/byteorder.h>
49 #include <pcmcia/cs_types.h>
50 #include <pcmcia/ss.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/bulkmem.h>
53 #include <pcmcia/cisreg.h>
54 #include <pcmcia/cistpl.h>
55 #include "cs_internal.h"
57 static const u_char mantissa[] = {
58 10, 12, 13, 15, 20, 25, 30, 35,
59 40, 45, 50, 55, 60, 70, 80, 90
62 static const u_int exponent[] = {
63 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
66 /* Convert an extended speed byte to a time in nanoseconds */
67 #define SPEED_CVT(v) \
68 (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
69 /* Convert a power byte to a current in 0.1 microamps */
70 #define POWER_CVT(v) \
71 (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
72 #define POWER_SCALE(v) (exponent[(v)&7])
74 /* Upper limit on reasonable # of tuples */
75 #define MAX_TUPLES 200
77 /*====================================================================*/
79 /* Parameters that can be set with 'insmod' */
81 #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i")
83 INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
85 void release_cis_mem(struct pcmcia_socket *s)
87 if (s->cis_mem.sys_start != 0) {
88 s->cis_mem.flags &= ~MAP_ACTIVE;
89 s->ss_entry->set_mem_map(s, &s->cis_mem);
90 if (!(s->features & SS_CAP_STATIC_MAP))
91 release_mem_region(s->cis_mem.sys_start, s->map_size);
92 iounmap(s->cis_virt);
93 s->cis_mem.sys_start = 0;
94 s->cis_virt = NULL;
99 * Map the card memory at "card_offset" into virtual space.
100 * If flags & MAP_ATTRIB, map the attribute space, otherwise
101 * map the memory space.
103 static unsigned char *
104 set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
106 pccard_mem_map *mem = &s->cis_mem;
107 if (!(s->features & SS_CAP_STATIC_MAP) &&
108 mem->sys_start == 0) {
109 validate_mem(s);
110 mem->sys_start = 0;
111 if (find_mem_region(&mem->sys_start, s->map_size,
112 s->map_size, 0, "card services", s)) {
113 printk(KERN_NOTICE "cs: unable to map card memory!\n");
114 return NULL;
116 mem->sys_stop = mem->sys_start+s->map_size-1;
117 s->cis_virt = ioremap(mem->sys_start, s->map_size);
119 mem->card_start = card_offset;
120 mem->flags = flags;
121 s->ss_entry->set_mem_map(s, mem);
122 if (s->features & SS_CAP_STATIC_MAP) {
123 if (s->cis_virt)
124 iounmap(s->cis_virt);
125 s->cis_virt = ioremap(mem->sys_start, s->map_size);
127 return s->cis_virt;
130 /*======================================================================
132 Low-level functions to read and write CIS memory. I think the
133 write routine is only useful for writing one-byte registers.
135 ======================================================================*/
137 /* Bits in attr field */
138 #define IS_ATTR 1
139 #define IS_INDIRECT 8
141 int read_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
142 u_int len, void *ptr)
144 u_char *sys, *end, *buf = ptr;
146 DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
148 if (attr & IS_INDIRECT) {
149 /* Indirect accesses use a bunch of special registers at fixed
150 locations in common memory */
151 u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
152 if (attr & IS_ATTR) {
153 addr *= 2;
154 flags = ICTRL0_AUTOINC;
157 sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
158 if (!sys) {
159 memset(ptr, 0xff, len);
160 return -1;
163 writeb(flags, sys+CISREG_ICTRL0);
164 writeb(addr & 0xff, sys+CISREG_IADDR0);
165 writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
166 writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
167 writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
168 for ( ; len > 0; len--, buf++)
169 *buf = readb(sys+CISREG_IDATA0);
170 } else {
171 u_int inc = 1, card_offset, flags;
173 flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
174 if (attr) {
175 flags |= MAP_ATTRIB;
176 inc++;
177 addr *= 2;
180 card_offset = addr & ~(s->map_size-1);
181 while (len) {
182 sys = set_cis_map(s, card_offset, flags);
183 if (!sys) {
184 memset(ptr, 0xff, len);
185 return -1;
187 end = sys + s->map_size;
188 sys = sys + (addr & (s->map_size-1));
189 for ( ; len > 0; len--, buf++, sys += inc) {
190 if (sys == end)
191 break;
192 *buf = readb(sys);
194 card_offset += s->map_size;
195 addr = 0;
198 DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
199 *(u_char *)(ptr+0), *(u_char *)(ptr+1),
200 *(u_char *)(ptr+2), *(u_char *)(ptr+3));
201 return 0;
204 void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
205 u_int len, void *ptr)
207 u_char *sys, *end, *buf = ptr;
209 DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
211 if (attr & IS_INDIRECT) {
212 /* Indirect accesses use a bunch of special registers at fixed
213 locations in common memory */
214 u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
215 if (attr & IS_ATTR) {
216 addr *= 2;
217 flags = ICTRL0_AUTOINC;
220 sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
221 if (!sys)
222 return; /* FIXME: Error */
224 writeb(flags, sys+CISREG_ICTRL0);
225 writeb(addr & 0xff, sys+CISREG_IADDR0);
226 writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
227 writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
228 writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
229 for ( ; len > 0; len--, buf++)
230 writeb(*buf, sys+CISREG_IDATA0);
231 } else {
232 u_int inc = 1, card_offset, flags;
234 flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
235 if (attr & IS_ATTR) {
236 flags |= MAP_ATTRIB;
237 inc++;
238 addr *= 2;
241 card_offset = addr & ~(s->map_size-1);
242 while (len) {
243 sys = set_cis_map(s, card_offset, flags);
244 if (!sys)
245 return; /* FIXME: error */
247 end = sys + s->map_size;
248 sys = sys + (addr & (s->map_size-1));
249 for ( ; len > 0; len--, buf++, sys += inc) {
250 if (sys == end)
251 break;
252 writeb(*buf, sys);
254 card_offset += s->map_size;
255 addr = 0;
260 /*======================================================================
262 This is a wrapper around read_cis_mem, with the same interface,
263 but which caches information, for cards whose CIS may not be
264 readable all the time.
266 ======================================================================*/
268 static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
269 u_int len, void *ptr)
271 struct cis_cache_entry *cis;
272 int ret;
274 if (s->fake_cis) {
275 if (s->fake_cis_len > addr+len)
276 memcpy(ptr, s->fake_cis+addr, len);
277 else
278 memset(ptr, 0xff, len);
279 return;
282 list_for_each_entry(cis, &s->cis_cache, node) {
283 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
284 memcpy(ptr, cis->cache, len);
285 return;
289 #ifdef CONFIG_CARDBUS
290 if (s->state & SOCKET_CARDBUS)
291 ret = read_cb_mem(s, attr, addr, len, ptr);
292 else
293 #endif
294 ret = read_cis_mem(s, attr, addr, len, ptr);
296 /* Copy data into the cache */
297 cis = kmalloc(sizeof(struct cis_cache_entry) + len, GFP_KERNEL);
298 if (cis) {
299 cis->addr = addr;
300 cis->len = len;
301 cis->attr = attr;
302 memcpy(cis->cache, ptr, len);
303 list_add(&cis->node, &s->cis_cache);
307 static void
308 remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
310 struct cis_cache_entry *cis;
312 list_for_each_entry(cis, &s->cis_cache, node)
313 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
314 list_del(&cis->node);
315 kfree(cis);
316 break;
320 void destroy_cis_cache(struct pcmcia_socket *s)
322 struct list_head *l, *n;
324 list_for_each_safe(l, n, &s->cis_cache) {
325 struct cis_cache_entry *cis = list_entry(l, struct cis_cache_entry, node);
327 list_del(&cis->node);
328 kfree(cis);
332 /*======================================================================
334 This verifies if the CIS of a card matches what is in the CIS
335 cache.
337 ======================================================================*/
339 int verify_cis_cache(struct pcmcia_socket *s)
341 struct cis_cache_entry *cis;
342 char buf[256];
344 list_for_each_entry(cis, &s->cis_cache, node) {
345 int len = cis->len;
347 if (len > 256)
348 len = 256;
349 #ifdef CONFIG_CARDBUS
350 if (s->state & SOCKET_CARDBUS)
351 read_cb_mem(s, cis->attr, cis->addr, len, buf);
352 else
353 #endif
354 read_cis_mem(s, cis->attr, cis->addr, len, buf);
356 if (memcmp(buf, cis->cache, len) != 0)
357 return -1;
359 return 0;
362 /*======================================================================
364 For really bad cards, we provide a facility for uploading a
365 replacement CIS.
367 ======================================================================*/
369 int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis)
371 struct pcmcia_socket *s;
372 if (CHECK_HANDLE(handle))
373 return CS_BAD_HANDLE;
374 s = SOCKET(handle);
375 if (s->fake_cis != NULL) {
376 kfree(s->fake_cis);
377 s->fake_cis = NULL;
379 if (cis->Length > CISTPL_MAX_CIS_SIZE)
380 return CS_BAD_SIZE;
381 s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
382 if (s->fake_cis == NULL)
383 return CS_OUT_OF_RESOURCE;
384 s->fake_cis_len = cis->Length;
385 memcpy(s->fake_cis, cis->Data, cis->Length);
386 return CS_SUCCESS;
389 /*======================================================================
391 The high-level CIS tuple services
393 ======================================================================*/
395 typedef struct tuple_flags {
396 u_int link_space:4;
397 u_int has_link:1;
398 u_int mfc_fn:3;
399 u_int space:4;
400 } tuple_flags;
402 #define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
403 #define HAS_LINK(f) (((tuple_flags *)(&(f)))->has_link)
404 #define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn)
405 #define SPACE(f) (((tuple_flags *)(&(f)))->space)
407 int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
409 int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
411 struct pcmcia_socket *s;
412 if (CHECK_HANDLE(handle))
413 return CS_BAD_HANDLE;
414 s = SOCKET(handle);
415 if (!(s->state & SOCKET_PRESENT))
416 return CS_NO_CARD;
417 tuple->TupleLink = tuple->Flags = 0;
418 #ifdef CONFIG_CARDBUS
419 if (s->state & SOCKET_CARDBUS) {
420 struct pci_dev *dev = s->cb_dev;
421 u_int ptr;
422 pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr);
423 tuple->CISOffset = ptr & ~7;
424 SPACE(tuple->Flags) = (ptr & 7);
425 } else
426 #endif
428 /* Assume presence of a LONGLINK_C to address 0 */
429 tuple->CISOffset = tuple->LinkOffset = 0;
430 SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
432 if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
433 !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
434 cisdata_t req = tuple->DesiredTuple;
435 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
436 if (pcmcia_get_next_tuple(handle, tuple) == CS_SUCCESS) {
437 tuple->DesiredTuple = CISTPL_LINKTARGET;
438 if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
439 return CS_NO_MORE_ITEMS;
440 } else
441 tuple->CISOffset = tuple->TupleLink = 0;
442 tuple->DesiredTuple = req;
444 return pcmcia_get_next_tuple(handle, tuple);
447 static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
449 u_char link[5];
450 u_int ofs;
452 if (MFC_FN(tuple->Flags)) {
453 /* Get indirect link from the MFC tuple */
454 read_cis_cache(s, LINK_SPACE(tuple->Flags),
455 tuple->LinkOffset, 5, link);
456 ofs = le32_to_cpu(*(u_int *)(link+1));
457 SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
458 /* Move to the next indirect link */
459 tuple->LinkOffset += 5;
460 MFC_FN(tuple->Flags)--;
461 } else if (HAS_LINK(tuple->Flags)) {
462 ofs = tuple->LinkOffset;
463 SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
464 HAS_LINK(tuple->Flags) = 0;
465 } else {
466 return -1;
468 if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) {
469 /* This is ugly, but a common CIS error is to code the long
470 link offset incorrectly, so we check the right spot... */
471 read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
472 if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
473 (strncmp(link+2, "CIS", 3) == 0))
474 return ofs;
475 remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
476 /* Then, we try the wrong spot... */
477 ofs = ofs >> 1;
479 read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
480 if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
481 (strncmp(link+2, "CIS", 3) == 0))
482 return ofs;
483 remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
484 return -1;
487 int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
489 struct pcmcia_socket *s;
490 u_char link[2], tmp;
491 int ofs, i, attr;
493 if (CHECK_HANDLE(handle))
494 return CS_BAD_HANDLE;
495 s = SOCKET(handle);
496 if (!(s->state & SOCKET_PRESENT))
497 return CS_NO_CARD;
499 link[1] = tuple->TupleLink;
500 ofs = tuple->CISOffset + tuple->TupleLink;
501 attr = SPACE(tuple->Flags);
503 for (i = 0; i < MAX_TUPLES; i++) {
504 if (link[1] == 0xff) {
505 link[0] = CISTPL_END;
506 } else {
507 read_cis_cache(s, attr, ofs, 2, link);
508 if (link[0] == CISTPL_NULL) {
509 ofs++; continue;
513 /* End of chain? Follow long link if possible */
514 if (link[0] == CISTPL_END) {
515 if ((ofs = follow_link(s, tuple)) < 0)
516 return CS_NO_MORE_ITEMS;
517 attr = SPACE(tuple->Flags);
518 read_cis_cache(s, attr, ofs, 2, link);
521 /* Is this a link tuple? Make a note of it */
522 if ((link[0] == CISTPL_LONGLINK_A) ||
523 (link[0] == CISTPL_LONGLINK_C) ||
524 (link[0] == CISTPL_LONGLINK_MFC) ||
525 (link[0] == CISTPL_LINKTARGET) ||
526 (link[0] == CISTPL_INDIRECT) ||
527 (link[0] == CISTPL_NO_LINK)) {
528 switch (link[0]) {
529 case CISTPL_LONGLINK_A:
530 HAS_LINK(tuple->Flags) = 1;
531 LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
532 read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
533 break;
534 case CISTPL_LONGLINK_C:
535 HAS_LINK(tuple->Flags) = 1;
536 LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
537 read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
538 break;
539 case CISTPL_INDIRECT:
540 HAS_LINK(tuple->Flags) = 1;
541 LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
542 tuple->LinkOffset = 0;
543 break;
544 case CISTPL_LONGLINK_MFC:
545 tuple->LinkOffset = ofs + 3;
546 LINK_SPACE(tuple->Flags) = attr;
547 if (handle->Function == BIND_FN_ALL) {
548 /* Follow all the MFC links */
549 read_cis_cache(s, attr, ofs+2, 1, &tmp);
550 MFC_FN(tuple->Flags) = tmp;
551 } else {
552 /* Follow exactly one of the links */
553 MFC_FN(tuple->Flags) = 1;
554 tuple->LinkOffset += handle->Function * 5;
556 break;
557 case CISTPL_NO_LINK:
558 HAS_LINK(tuple->Flags) = 0;
559 break;
561 if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
562 (tuple->DesiredTuple == RETURN_FIRST_TUPLE))
563 break;
564 } else
565 if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
566 break;
568 if (link[0] == tuple->DesiredTuple)
569 break;
570 ofs += link[1] + 2;
572 if (i == MAX_TUPLES) {
573 DEBUG(1, "cs: overrun in pcmcia_get_next_tuple for socket %d\n",
574 handle->Socket);
575 return CS_NO_MORE_ITEMS;
578 tuple->TupleCode = link[0];
579 tuple->TupleLink = link[1];
580 tuple->CISOffset = ofs + 2;
581 return CS_SUCCESS;
584 /*====================================================================*/
586 #define _MIN(a, b) (((a) < (b)) ? (a) : (b))
588 int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple)
590 struct pcmcia_socket *s;
591 u_int len;
593 if (CHECK_HANDLE(handle))
594 return CS_BAD_HANDLE;
596 s = SOCKET(handle);
598 if (tuple->TupleLink < tuple->TupleOffset)
599 return CS_NO_MORE_ITEMS;
600 len = tuple->TupleLink - tuple->TupleOffset;
601 tuple->TupleDataLen = tuple->TupleLink;
602 if (len == 0)
603 return CS_SUCCESS;
604 read_cis_cache(s, SPACE(tuple->Flags),
605 tuple->CISOffset + tuple->TupleOffset,
606 _MIN(len, tuple->TupleDataMax), tuple->TupleData);
607 return CS_SUCCESS;
610 /*======================================================================
612 Parsing routines for individual tuples
614 ======================================================================*/
616 static int parse_device(tuple_t *tuple, cistpl_device_t *device)
618 int i;
619 u_char scale;
620 u_char *p, *q;
622 p = (u_char *)tuple->TupleData;
623 q = p + tuple->TupleDataLen;
625 device->ndev = 0;
626 for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
628 if (*p == 0xff) break;
629 device->dev[i].type = (*p >> 4);
630 device->dev[i].wp = (*p & 0x08) ? 1 : 0;
631 switch (*p & 0x07) {
632 case 0: device->dev[i].speed = 0; break;
633 case 1: device->dev[i].speed = 250; break;
634 case 2: device->dev[i].speed = 200; break;
635 case 3: device->dev[i].speed = 150; break;
636 case 4: device->dev[i].speed = 100; break;
637 case 7:
638 if (++p == q) return CS_BAD_TUPLE;
639 device->dev[i].speed = SPEED_CVT(*p);
640 while (*p & 0x80)
641 if (++p == q) return CS_BAD_TUPLE;
642 break;
643 default:
644 return CS_BAD_TUPLE;
647 if (++p == q) return CS_BAD_TUPLE;
648 if (*p == 0xff) break;
649 scale = *p & 7;
650 if (scale == 7) return CS_BAD_TUPLE;
651 device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
652 device->ndev++;
653 if (++p == q) break;
656 return CS_SUCCESS;
659 /*====================================================================*/
661 static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
663 u_char *p;
664 if (tuple->TupleDataLen < 5)
665 return CS_BAD_TUPLE;
666 p = (u_char *)tuple->TupleData;
667 csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
668 csum->len = le16_to_cpu(*(u_short *)(p + 2));
669 csum->sum = *(p+4);
670 return CS_SUCCESS;
673 /*====================================================================*/
675 static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
677 if (tuple->TupleDataLen < 4)
678 return CS_BAD_TUPLE;
679 link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
680 return CS_SUCCESS;
683 /*====================================================================*/
685 static int parse_longlink_mfc(tuple_t *tuple,
686 cistpl_longlink_mfc_t *link)
688 u_char *p;
689 int i;
691 p = (u_char *)tuple->TupleData;
693 link->nfn = *p; p++;
694 if (tuple->TupleDataLen <= link->nfn*5)
695 return CS_BAD_TUPLE;
696 for (i = 0; i < link->nfn; i++) {
697 link->fn[i].space = *p; p++;
698 link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
700 return CS_SUCCESS;
703 /*====================================================================*/
705 static int parse_strings(u_char *p, u_char *q, int max,
706 char *s, u_char *ofs, u_char *found)
708 int i, j, ns;
710 if (p == q) return CS_BAD_TUPLE;
711 ns = 0; j = 0;
712 for (i = 0; i < max; i++) {
713 if (*p == 0xff) break;
714 ofs[i] = j;
715 ns++;
716 for (;;) {
717 s[j++] = (*p == 0xff) ? '\0' : *p;
718 if ((*p == '\0') || (*p == 0xff)) break;
719 if (++p == q) return CS_BAD_TUPLE;
721 if ((*p == 0xff) || (++p == q)) break;
723 if (found) {
724 *found = ns;
725 return CS_SUCCESS;
726 } else {
727 return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
731 /*====================================================================*/
733 static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
735 u_char *p, *q;
737 p = (u_char *)tuple->TupleData;
738 q = p + tuple->TupleDataLen;
740 vers_1->major = *p; p++;
741 vers_1->minor = *p; p++;
742 if (p >= q) return CS_BAD_TUPLE;
744 return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
745 vers_1->str, vers_1->ofs, &vers_1->ns);
748 /*====================================================================*/
750 static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
752 u_char *p, *q;
754 p = (u_char *)tuple->TupleData;
755 q = p + tuple->TupleDataLen;
757 return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
758 altstr->str, altstr->ofs, &altstr->ns);
761 /*====================================================================*/
763 static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
765 u_char *p, *q;
766 int nid;
768 p = (u_char *)tuple->TupleData;
769 q = p + tuple->TupleDataLen;
771 for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
772 if (p > q-2) break;
773 jedec->id[nid].mfr = p[0];
774 jedec->id[nid].info = p[1];
775 p += 2;
777 jedec->nid = nid;
778 return CS_SUCCESS;
781 /*====================================================================*/
783 static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
785 u_short *p;
786 if (tuple->TupleDataLen < 4)
787 return CS_BAD_TUPLE;
788 p = (u_short *)tuple->TupleData;
789 m->manf = le16_to_cpu(p[0]);
790 m->card = le16_to_cpu(p[1]);
791 return CS_SUCCESS;
794 /*====================================================================*/
796 static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
798 u_char *p;
799 if (tuple->TupleDataLen < 2)
800 return CS_BAD_TUPLE;
801 p = (u_char *)tuple->TupleData;
802 f->func = p[0];
803 f->sysinit = p[1];
804 return CS_SUCCESS;
807 /*====================================================================*/
809 static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
811 u_char *p;
812 int i;
813 if (tuple->TupleDataLen < 1)
814 return CS_BAD_TUPLE;
815 p = (u_char *)tuple->TupleData;
816 f->type = p[0];
817 for (i = 1; i < tuple->TupleDataLen; i++)
818 f->data[i-1] = p[i];
819 return CS_SUCCESS;
822 /*====================================================================*/
824 static int parse_config(tuple_t *tuple, cistpl_config_t *config)
826 int rasz, rmsz, i;
827 u_char *p;
829 p = (u_char *)tuple->TupleData;
830 rasz = *p & 0x03;
831 rmsz = (*p & 0x3c) >> 2;
832 if (tuple->TupleDataLen < rasz+rmsz+4)
833 return CS_BAD_TUPLE;
834 config->last_idx = *(++p);
835 p++;
836 config->base = 0;
837 for (i = 0; i <= rasz; i++)
838 config->base += p[i] << (8*i);
839 p += rasz+1;
840 for (i = 0; i < 4; i++)
841 config->rmask[i] = 0;
842 for (i = 0; i <= rmsz; i++)
843 config->rmask[i>>2] += p[i] << (8*(i%4));
844 config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
845 return CS_SUCCESS;
848 /*======================================================================
850 The following routines are all used to parse the nightmarish
851 config table entries.
853 ======================================================================*/
855 static u_char *parse_power(u_char *p, u_char *q,
856 cistpl_power_t *pwr)
858 int i;
859 u_int scale;
861 if (p == q) return NULL;
862 pwr->present = *p;
863 pwr->flags = 0;
864 p++;
865 for (i = 0; i < 7; i++)
866 if (pwr->present & (1<<i)) {
867 if (p == q) return NULL;
868 pwr->param[i] = POWER_CVT(*p);
869 scale = POWER_SCALE(*p);
870 while (*p & 0x80) {
871 if (++p == q) return NULL;
872 if ((*p & 0x7f) < 100)
873 pwr->param[i] += (*p & 0x7f) * scale / 100;
874 else if (*p == 0x7d)
875 pwr->flags |= CISTPL_POWER_HIGHZ_OK;
876 else if (*p == 0x7e)
877 pwr->param[i] = 0;
878 else if (*p == 0x7f)
879 pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
880 else
881 return NULL;
883 p++;
885 return p;
888 /*====================================================================*/
890 static u_char *parse_timing(u_char *p, u_char *q,
891 cistpl_timing_t *timing)
893 u_char scale;
895 if (p == q) return NULL;
896 scale = *p;
897 if ((scale & 3) != 3) {
898 if (++p == q) return NULL;
899 timing->wait = SPEED_CVT(*p);
900 timing->waitscale = exponent[scale & 3];
901 } else
902 timing->wait = 0;
903 scale >>= 2;
904 if ((scale & 7) != 7) {
905 if (++p == q) return NULL;
906 timing->ready = SPEED_CVT(*p);
907 timing->rdyscale = exponent[scale & 7];
908 } else
909 timing->ready = 0;
910 scale >>= 3;
911 if (scale != 7) {
912 if (++p == q) return NULL;
913 timing->reserved = SPEED_CVT(*p);
914 timing->rsvscale = exponent[scale];
915 } else
916 timing->reserved = 0;
917 p++;
918 return p;
921 /*====================================================================*/
923 static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
925 int i, j, bsz, lsz;
927 if (p == q) return NULL;
928 io->flags = *p;
930 if (!(*p & 0x80)) {
931 io->nwin = 1;
932 io->win[0].base = 0;
933 io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
934 return p+1;
937 if (++p == q) return NULL;
938 io->nwin = (*p & 0x0f) + 1;
939 bsz = (*p & 0x30) >> 4;
940 if (bsz == 3) bsz++;
941 lsz = (*p & 0xc0) >> 6;
942 if (lsz == 3) lsz++;
943 p++;
945 for (i = 0; i < io->nwin; i++) {
946 io->win[i].base = 0;
947 io->win[i].len = 1;
948 for (j = 0; j < bsz; j++, p++) {
949 if (p == q) return NULL;
950 io->win[i].base += *p << (j*8);
952 for (j = 0; j < lsz; j++, p++) {
953 if (p == q) return NULL;
954 io->win[i].len += *p << (j*8);
957 return p;
960 /*====================================================================*/
962 static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
964 int i, j, asz, lsz, has_ha;
965 u_int len, ca, ha;
967 if (p == q) return NULL;
969 mem->nwin = (*p & 0x07) + 1;
970 lsz = (*p & 0x18) >> 3;
971 asz = (*p & 0x60) >> 5;
972 has_ha = (*p & 0x80);
973 if (++p == q) return NULL;
975 for (i = 0; i < mem->nwin; i++) {
976 len = ca = ha = 0;
977 for (j = 0; j < lsz; j++, p++) {
978 if (p == q) return NULL;
979 len += *p << (j*8);
981 for (j = 0; j < asz; j++, p++) {
982 if (p == q) return NULL;
983 ca += *p << (j*8);
985 if (has_ha)
986 for (j = 0; j < asz; j++, p++) {
987 if (p == q) return NULL;
988 ha += *p << (j*8);
990 mem->win[i].len = len << 8;
991 mem->win[i].card_addr = ca << 8;
992 mem->win[i].host_addr = ha << 8;
994 return p;
997 /*====================================================================*/
999 static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
1001 if (p == q) return NULL;
1002 irq->IRQInfo1 = *p; p++;
1003 if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
1004 if (p+2 > q) return NULL;
1005 irq->IRQInfo2 = (p[1]<<8) + p[0];
1006 p += 2;
1008 return p;
1011 /*====================================================================*/
1013 static int parse_cftable_entry(tuple_t *tuple,
1014 cistpl_cftable_entry_t *entry)
1016 u_char *p, *q, features;
1018 p = tuple->TupleData;
1019 q = p + tuple->TupleDataLen;
1020 entry->index = *p & 0x3f;
1021 entry->flags = 0;
1022 if (*p & 0x40)
1023 entry->flags |= CISTPL_CFTABLE_DEFAULT;
1024 if (*p & 0x80) {
1025 if (++p == q) return CS_BAD_TUPLE;
1026 if (*p & 0x10)
1027 entry->flags |= CISTPL_CFTABLE_BVDS;
1028 if (*p & 0x20)
1029 entry->flags |= CISTPL_CFTABLE_WP;
1030 if (*p & 0x40)
1031 entry->flags |= CISTPL_CFTABLE_RDYBSY;
1032 if (*p & 0x80)
1033 entry->flags |= CISTPL_CFTABLE_MWAIT;
1034 entry->interface = *p & 0x0f;
1035 } else
1036 entry->interface = 0;
1038 /* Process optional features */
1039 if (++p == q) return CS_BAD_TUPLE;
1040 features = *p; p++;
1042 /* Power options */
1043 if ((features & 3) > 0) {
1044 p = parse_power(p, q, &entry->vcc);
1045 if (p == NULL) return CS_BAD_TUPLE;
1046 } else
1047 entry->vcc.present = 0;
1048 if ((features & 3) > 1) {
1049 p = parse_power(p, q, &entry->vpp1);
1050 if (p == NULL) return CS_BAD_TUPLE;
1051 } else
1052 entry->vpp1.present = 0;
1053 if ((features & 3) > 2) {
1054 p = parse_power(p, q, &entry->vpp2);
1055 if (p == NULL) return CS_BAD_TUPLE;
1056 } else
1057 entry->vpp2.present = 0;
1059 /* Timing options */
1060 if (features & 0x04) {
1061 p = parse_timing(p, q, &entry->timing);
1062 if (p == NULL) return CS_BAD_TUPLE;
1063 } else {
1064 entry->timing.wait = 0;
1065 entry->timing.ready = 0;
1066 entry->timing.reserved = 0;
1069 /* I/O window options */
1070 if (features & 0x08) {
1071 p = parse_io(p, q, &entry->io);
1072 if (p == NULL) return CS_BAD_TUPLE;
1073 } else
1074 entry->io.nwin = 0;
1076 /* Interrupt options */
1077 if (features & 0x10) {
1078 p = parse_irq(p, q, &entry->irq);
1079 if (p == NULL) return CS_BAD_TUPLE;
1080 } else
1081 entry->irq.IRQInfo1 = 0;
1083 switch (features & 0x60) {
1084 case 0x00:
1085 entry->mem.nwin = 0;
1086 break;
1087 case 0x20:
1088 entry->mem.nwin = 1;
1089 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
1090 entry->mem.win[0].card_addr = 0;
1091 entry->mem.win[0].host_addr = 0;
1092 p += 2;
1093 if (p > q) return CS_BAD_TUPLE;
1094 break;
1095 case 0x40:
1096 entry->mem.nwin = 1;
1097 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
1098 entry->mem.win[0].card_addr =
1099 le16_to_cpu(*(u_short *)(p+2)) << 8;
1100 entry->mem.win[0].host_addr = 0;
1101 p += 4;
1102 if (p > q) return CS_BAD_TUPLE;
1103 break;
1104 case 0x60:
1105 p = parse_mem(p, q, &entry->mem);
1106 if (p == NULL) return CS_BAD_TUPLE;
1107 break;
1110 /* Misc features */
1111 if (features & 0x80) {
1112 if (p == q) return CS_BAD_TUPLE;
1113 entry->flags |= (*p << 8);
1114 while (*p & 0x80)
1115 if (++p == q) return CS_BAD_TUPLE;
1116 p++;
1119 entry->subtuples = q-p;
1121 return CS_SUCCESS;
1124 /*====================================================================*/
1126 #ifdef CONFIG_CARDBUS
1128 static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
1130 u_char *p;
1131 if (tuple->TupleDataLen < 6)
1132 return CS_BAD_TUPLE;
1133 p = (u_char *)tuple->TupleData;
1134 bar->attr = *p;
1135 p += 2;
1136 bar->size = le32_to_cpu(*(u_int *)p);
1137 return CS_SUCCESS;
1140 static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
1142 u_char *p;
1144 p = (u_char *)tuple->TupleData;
1145 if ((*p != 3) || (tuple->TupleDataLen < 6))
1146 return CS_BAD_TUPLE;
1147 config->last_idx = *(++p);
1148 p++;
1149 config->base = le32_to_cpu(*(u_int *)p);
1150 config->subtuples = tuple->TupleDataLen - 6;
1151 return CS_SUCCESS;
1154 static int parse_cftable_entry_cb(tuple_t *tuple,
1155 cistpl_cftable_entry_cb_t *entry)
1157 u_char *p, *q, features;
1159 p = tuple->TupleData;
1160 q = p + tuple->TupleDataLen;
1161 entry->index = *p & 0x3f;
1162 entry->flags = 0;
1163 if (*p & 0x40)
1164 entry->flags |= CISTPL_CFTABLE_DEFAULT;
1166 /* Process optional features */
1167 if (++p == q) return CS_BAD_TUPLE;
1168 features = *p; p++;
1170 /* Power options */
1171 if ((features & 3) > 0) {
1172 p = parse_power(p, q, &entry->vcc);
1173 if (p == NULL) return CS_BAD_TUPLE;
1174 } else
1175 entry->vcc.present = 0;
1176 if ((features & 3) > 1) {
1177 p = parse_power(p, q, &entry->vpp1);
1178 if (p == NULL) return CS_BAD_TUPLE;
1179 } else
1180 entry->vpp1.present = 0;
1181 if ((features & 3) > 2) {
1182 p = parse_power(p, q, &entry->vpp2);
1183 if (p == NULL) return CS_BAD_TUPLE;
1184 } else
1185 entry->vpp2.present = 0;
1187 /* I/O window options */
1188 if (features & 0x08) {
1189 if (p == q) return CS_BAD_TUPLE;
1190 entry->io = *p; p++;
1191 } else
1192 entry->io = 0;
1194 /* Interrupt options */
1195 if (features & 0x10) {
1196 p = parse_irq(p, q, &entry->irq);
1197 if (p == NULL) return CS_BAD_TUPLE;
1198 } else
1199 entry->irq.IRQInfo1 = 0;
1201 if (features & 0x20) {
1202 if (p == q) return CS_BAD_TUPLE;
1203 entry->mem = *p; p++;
1204 } else
1205 entry->mem = 0;
1207 /* Misc features */
1208 if (features & 0x80) {
1209 if (p == q) return CS_BAD_TUPLE;
1210 entry->flags |= (*p << 8);
1211 if (*p & 0x80) {
1212 if (++p == q) return CS_BAD_TUPLE;
1213 entry->flags |= (*p << 16);
1215 while (*p & 0x80)
1216 if (++p == q) return CS_BAD_TUPLE;
1217 p++;
1220 entry->subtuples = q-p;
1222 return CS_SUCCESS;
1225 #endif
1227 /*====================================================================*/
1229 static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
1231 u_char *p, *q;
1232 int n;
1234 p = (u_char *)tuple->TupleData;
1235 q = p + tuple->TupleDataLen;
1237 for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
1238 if (p > q-6) break;
1239 geo->geo[n].buswidth = p[0];
1240 geo->geo[n].erase_block = 1 << (p[1]-1);
1241 geo->geo[n].read_block = 1 << (p[2]-1);
1242 geo->geo[n].write_block = 1 << (p[3]-1);
1243 geo->geo[n].partition = 1 << (p[4]-1);
1244 geo->geo[n].interleave = 1 << (p[5]-1);
1245 p += 6;
1247 geo->ngeo = n;
1248 return CS_SUCCESS;
1251 /*====================================================================*/
1253 static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
1255 u_char *p, *q;
1257 if (tuple->TupleDataLen < 10)
1258 return CS_BAD_TUPLE;
1260 p = tuple->TupleData;
1261 q = p + tuple->TupleDataLen;
1263 v2->vers = p[0];
1264 v2->comply = p[1];
1265 v2->dindex = le16_to_cpu(*(u_short *)(p+2));
1266 v2->vspec8 = p[6];
1267 v2->vspec9 = p[7];
1268 v2->nhdr = p[8];
1269 p += 9;
1270 return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
1273 /*====================================================================*/
1275 static int parse_org(tuple_t *tuple, cistpl_org_t *org)
1277 u_char *p, *q;
1278 int i;
1280 p = tuple->TupleData;
1281 q = p + tuple->TupleDataLen;
1282 if (p == q) return CS_BAD_TUPLE;
1283 org->data_org = *p;
1284 if (++p == q) return CS_BAD_TUPLE;
1285 for (i = 0; i < 30; i++) {
1286 org->desc[i] = *p;
1287 if (*p == '\0') break;
1288 if (++p == q) return CS_BAD_TUPLE;
1290 return CS_SUCCESS;
1293 /*====================================================================*/
1295 static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
1297 u_char *p;
1299 if (tuple->TupleDataLen < 10)
1300 return CS_BAD_TUPLE;
1302 p = tuple->TupleData;
1304 fmt->type = p[0];
1305 fmt->edc = p[1];
1306 fmt->offset = le32_to_cpu(*(u_int *)(p+2));
1307 fmt->length = le32_to_cpu(*(u_int *)(p+6));
1309 return CS_SUCCESS;
1312 /*====================================================================*/
1314 int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
1316 int ret = CS_SUCCESS;
1318 if (tuple->TupleDataLen > tuple->TupleDataMax)
1319 return CS_BAD_TUPLE;
1320 switch (tuple->TupleCode) {
1321 case CISTPL_DEVICE:
1322 case CISTPL_DEVICE_A:
1323 ret = parse_device(tuple, &parse->device);
1324 break;
1325 #ifdef CONFIG_CARDBUS
1326 case CISTPL_BAR:
1327 ret = parse_bar(tuple, &parse->bar);
1328 break;
1329 case CISTPL_CONFIG_CB:
1330 ret = parse_config_cb(tuple, &parse->config);
1331 break;
1332 case CISTPL_CFTABLE_ENTRY_CB:
1333 ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
1334 break;
1335 #endif
1336 case CISTPL_CHECKSUM:
1337 ret = parse_checksum(tuple, &parse->checksum);
1338 break;
1339 case CISTPL_LONGLINK_A:
1340 case CISTPL_LONGLINK_C:
1341 ret = parse_longlink(tuple, &parse->longlink);
1342 break;
1343 case CISTPL_LONGLINK_MFC:
1344 ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
1345 break;
1346 case CISTPL_VERS_1:
1347 ret = parse_vers_1(tuple, &parse->version_1);
1348 break;
1349 case CISTPL_ALTSTR:
1350 ret = parse_altstr(tuple, &parse->altstr);
1351 break;
1352 case CISTPL_JEDEC_A:
1353 case CISTPL_JEDEC_C:
1354 ret = parse_jedec(tuple, &parse->jedec);
1355 break;
1356 case CISTPL_MANFID:
1357 ret = parse_manfid(tuple, &parse->manfid);
1358 break;
1359 case CISTPL_FUNCID:
1360 ret = parse_funcid(tuple, &parse->funcid);
1361 break;
1362 case CISTPL_FUNCE:
1363 ret = parse_funce(tuple, &parse->funce);
1364 break;
1365 case CISTPL_CONFIG:
1366 ret = parse_config(tuple, &parse->config);
1367 break;
1368 case CISTPL_CFTABLE_ENTRY:
1369 ret = parse_cftable_entry(tuple, &parse->cftable_entry);
1370 break;
1371 case CISTPL_DEVICE_GEO:
1372 case CISTPL_DEVICE_GEO_A:
1373 ret = parse_device_geo(tuple, &parse->device_geo);
1374 break;
1375 case CISTPL_VERS_2:
1376 ret = parse_vers_2(tuple, &parse->vers_2);
1377 break;
1378 case CISTPL_ORG:
1379 ret = parse_org(tuple, &parse->org);
1380 break;
1381 case CISTPL_FORMAT:
1382 case CISTPL_FORMAT_A:
1383 ret = parse_format(tuple, &parse->format);
1384 break;
1385 case CISTPL_NO_LINK:
1386 case CISTPL_LINKTARGET:
1387 ret = CS_SUCCESS;
1388 break;
1389 default:
1390 ret = CS_UNSUPPORTED_FUNCTION;
1391 break;
1393 return ret;
1396 /*======================================================================
1398 This is used internally by Card Services to look up CIS stuff.
1400 ======================================================================*/
1402 int read_tuple(client_handle_t handle, cisdata_t code, void *parse)
1404 tuple_t tuple;
1405 cisdata_t buf[255];
1406 int ret;
1408 tuple.DesiredTuple = code;
1409 tuple.Attributes = TUPLE_RETURN_COMMON;
1410 ret = pcmcia_get_first_tuple(handle, &tuple);
1411 if (ret != CS_SUCCESS) return ret;
1412 tuple.TupleData = buf;
1413 tuple.TupleOffset = 0;
1414 tuple.TupleDataMax = sizeof(buf);
1415 ret = pcmcia_get_tuple_data(handle, &tuple);
1416 if (ret != CS_SUCCESS) return ret;
1417 ret = pcmcia_parse_tuple(handle, &tuple, parse);
1418 return ret;
1421 /*======================================================================
1423 This tries to determine if a card has a sensible CIS. It returns
1424 the number of tuples in the CIS, or 0 if the CIS looks bad. The
1425 checks include making sure several critical tuples are present and
1426 valid; seeing if the total number of tuples is reasonable; and
1427 looking for tuples that use reserved codes.
1429 ======================================================================*/
1431 int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info)
1433 tuple_t tuple;
1434 cisparse_t p;
1435 int ret, reserved, dev_ok = 0, ident_ok = 0;
1437 if (CHECK_HANDLE(handle))
1438 return CS_BAD_HANDLE;
1440 info->Chains = reserved = 0;
1441 tuple.DesiredTuple = RETURN_FIRST_TUPLE;
1442 tuple.Attributes = TUPLE_RETURN_COMMON;
1443 ret = pcmcia_get_first_tuple(handle, &tuple);
1444 if (ret != CS_SUCCESS)
1445 return CS_SUCCESS;
1447 /* First tuple should be DEVICE; we should really have either that
1448 or a CFTABLE_ENTRY of some sort */
1449 if ((tuple.TupleCode == CISTPL_DEVICE) ||
1450 (read_tuple(handle, CISTPL_CFTABLE_ENTRY, &p) == CS_SUCCESS) ||
1451 (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, &p) == CS_SUCCESS))
1452 dev_ok++;
1454 /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
1455 tuple, for card identification. Certain old D-Link and Linksys
1456 cards have only a broken VERS_2 tuple; hence the bogus test. */
1457 if ((read_tuple(handle, CISTPL_MANFID, &p) == CS_SUCCESS) ||
1458 (read_tuple(handle, CISTPL_VERS_1, &p) == CS_SUCCESS) ||
1459 (read_tuple(handle, CISTPL_VERS_2, &p) != CS_NO_MORE_ITEMS))
1460 ident_ok++;
1462 if (!dev_ok && !ident_ok)
1463 return CS_SUCCESS;
1465 for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) {
1466 ret = pcmcia_get_next_tuple(handle, &tuple);
1467 if (ret != CS_SUCCESS) break;
1468 if (((tuple.TupleCode > 0x23) && (tuple.TupleCode < 0x40)) ||
1469 ((tuple.TupleCode > 0x47) && (tuple.TupleCode < 0x80)) ||
1470 ((tuple.TupleCode > 0x90) && (tuple.TupleCode < 0xff)))
1471 reserved++;
1473 if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
1474 ((!dev_ok || !ident_ok) && (info->Chains > 10)))
1475 info->Chains = 0;
1477 return CS_SUCCESS;