initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / pcmcia / cistpl.c
blob317ca50a3db3b86e9729820237916cfe6fd3f4cd
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/moduleparam.h>
37 #include <linux/kernel.h>
38 #include <linux/string.h>
39 #include <linux/major.h>
40 #include <linux/errno.h>
41 #include <linux/timer.h>
42 #include <linux/slab.h>
43 #include <linux/mm.h>
44 #include <linux/sched.h>
45 #include <linux/pci.h>
46 #include <linux/ioport.h>
47 #include <asm/io.h>
48 #include <asm/byteorder.h>
50 #include <pcmcia/cs_types.h>
51 #include <pcmcia/ss.h>
52 #include <pcmcia/cs.h>
53 #include <pcmcia/bulkmem.h>
54 #include <pcmcia/cisreg.h>
55 #include <pcmcia/cistpl.h>
56 #include "cs_internal.h"
58 static const u_char mantissa[] = {
59 10, 12, 13, 15, 20, 25, 30, 35,
60 40, 45, 50, 55, 60, 70, 80, 90
63 static const u_int exponent[] = {
64 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
67 /* Convert an extended speed byte to a time in nanoseconds */
68 #define SPEED_CVT(v) \
69 (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
70 /* Convert a power byte to a current in 0.1 microamps */
71 #define POWER_CVT(v) \
72 (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
73 #define POWER_SCALE(v) (exponent[(v)&7])
75 /* Upper limit on reasonable # of tuples */
76 #define MAX_TUPLES 200
78 /*====================================================================*/
80 /* Parameters that can be set with 'insmod' */
82 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
84 INT_MODULE_PARM(cis_width, 0); /* 16-bit CIS? */
86 void release_cis_mem(struct pcmcia_socket *s)
88 if (s->cis_mem.flags & MAP_ACTIVE) {
89 s->cis_mem.flags &= ~MAP_ACTIVE;
90 s->ops->set_mem_map(s, &s->cis_mem);
91 if (s->cis_mem.res) {
92 release_resource(s->cis_mem.res);
93 kfree(s->cis_mem.res);
94 s->cis_mem.res = NULL;
96 iounmap(s->cis_virt);
97 s->cis_virt = NULL;
102 * Map the card memory at "card_offset" into virtual space.
103 * If flags & MAP_ATTRIB, map the attribute space, otherwise
104 * map the memory space.
106 static void __iomem *
107 set_cis_map(struct pcmcia_socket *s, unsigned int card_offset, unsigned int flags)
109 pccard_mem_map *mem = &s->cis_mem;
110 if (!(s->features & SS_CAP_STATIC_MAP) && mem->res == NULL) {
111 mem->res = find_mem_region(0, s->map_size, s->map_size, 0,
112 "card services", s);
113 if (mem->res == NULL) {
114 printk(KERN_NOTICE "cs: unable to map card memory!\n");
115 return NULL;
117 s->cis_virt = ioremap(mem->res->start, s->map_size);
119 mem->card_start = card_offset;
120 mem->flags = flags;
121 s->ops->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->static_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 void __iomem *sys, *end;
145 unsigned char *buf = ptr;
147 cs_dbg(s, 3, "read_cis_mem(%d, %#x, %u)\n", attr, addr, len);
149 if (attr & IS_INDIRECT) {
150 /* Indirect accesses use a bunch of special registers at fixed
151 locations in common memory */
152 u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
153 if (attr & IS_ATTR) {
154 addr *= 2;
155 flags = ICTRL0_AUTOINC;
158 sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
159 if (!sys) {
160 memset(ptr, 0xff, len);
161 return -1;
164 writeb(flags, sys+CISREG_ICTRL0);
165 writeb(addr & 0xff, sys+CISREG_IADDR0);
166 writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
167 writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
168 writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
169 for ( ; len > 0; len--, buf++)
170 *buf = readb(sys+CISREG_IDATA0);
171 } else {
172 u_int inc = 1, card_offset, flags;
174 flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
175 if (attr) {
176 flags |= MAP_ATTRIB;
177 inc++;
178 addr *= 2;
181 card_offset = addr & ~(s->map_size-1);
182 while (len) {
183 sys = set_cis_map(s, card_offset, flags);
184 if (!sys) {
185 memset(ptr, 0xff, len);
186 return -1;
188 end = sys + s->map_size;
189 sys = sys + (addr & (s->map_size-1));
190 for ( ; len > 0; len--, buf++, sys += inc) {
191 if (sys == end)
192 break;
193 *buf = readb(sys);
195 card_offset += s->map_size;
196 addr = 0;
199 cs_dbg(s, 3, " %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
200 *(u_char *)(ptr+0), *(u_char *)(ptr+1),
201 *(u_char *)(ptr+2), *(u_char *)(ptr+3));
202 return 0;
205 void write_cis_mem(struct pcmcia_socket *s, int attr, u_int addr,
206 u_int len, void *ptr)
208 void __iomem *sys, *end;
209 unsigned char *buf = ptr;
211 cs_dbg(s, 3, "write_cis_mem(%d, %#x, %u)\n", attr, addr, len);
213 if (attr & IS_INDIRECT) {
214 /* Indirect accesses use a bunch of special registers at fixed
215 locations in common memory */
216 u_char flags = ICTRL0_COMMON|ICTRL0_AUTOINC|ICTRL0_BYTEGRAN;
217 if (attr & IS_ATTR) {
218 addr *= 2;
219 flags = ICTRL0_AUTOINC;
222 sys = set_cis_map(s, 0, MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0));
223 if (!sys)
224 return; /* FIXME: Error */
226 writeb(flags, sys+CISREG_ICTRL0);
227 writeb(addr & 0xff, sys+CISREG_IADDR0);
228 writeb((addr>>8) & 0xff, sys+CISREG_IADDR1);
229 writeb((addr>>16) & 0xff, sys+CISREG_IADDR2);
230 writeb((addr>>24) & 0xff, sys+CISREG_IADDR3);
231 for ( ; len > 0; len--, buf++)
232 writeb(*buf, sys+CISREG_IDATA0);
233 } else {
234 u_int inc = 1, card_offset, flags;
236 flags = MAP_ACTIVE | ((cis_width) ? MAP_16BIT : 0);
237 if (attr & IS_ATTR) {
238 flags |= MAP_ATTRIB;
239 inc++;
240 addr *= 2;
243 card_offset = addr & ~(s->map_size-1);
244 while (len) {
245 sys = set_cis_map(s, card_offset, flags);
246 if (!sys)
247 return; /* FIXME: error */
249 end = sys + s->map_size;
250 sys = sys + (addr & (s->map_size-1));
251 for ( ; len > 0; len--, buf++, sys += inc) {
252 if (sys == end)
253 break;
254 writeb(*buf, sys);
256 card_offset += s->map_size;
257 addr = 0;
262 /*======================================================================
264 This is a wrapper around read_cis_mem, with the same interface,
265 but which caches information, for cards whose CIS may not be
266 readable all the time.
268 ======================================================================*/
270 static void read_cis_cache(struct pcmcia_socket *s, int attr, u_int addr,
271 u_int len, void *ptr)
273 struct cis_cache_entry *cis;
274 int ret;
276 if (s->fake_cis) {
277 if (s->fake_cis_len > addr+len)
278 memcpy(ptr, s->fake_cis+addr, len);
279 else
280 memset(ptr, 0xff, len);
281 return;
284 list_for_each_entry(cis, &s->cis_cache, node) {
285 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
286 memcpy(ptr, cis->cache, len);
287 return;
291 #ifdef CONFIG_CARDBUS
292 if (s->state & SOCKET_CARDBUS)
293 ret = read_cb_mem(s, attr, addr, len, ptr);
294 else
295 #endif
296 ret = read_cis_mem(s, attr, addr, len, ptr);
298 if (ret == 0) {
299 /* Copy data into the cache */
300 cis = kmalloc(sizeof(struct cis_cache_entry) + len, GFP_KERNEL);
301 if (cis) {
302 cis->addr = addr;
303 cis->len = len;
304 cis->attr = attr;
305 memcpy(cis->cache, ptr, len);
306 list_add(&cis->node, &s->cis_cache);
311 static void
312 remove_cis_cache(struct pcmcia_socket *s, int attr, u_int addr, u_int len)
314 struct cis_cache_entry *cis;
316 list_for_each_entry(cis, &s->cis_cache, node)
317 if (cis->addr == addr && cis->len == len && cis->attr == attr) {
318 list_del(&cis->node);
319 kfree(cis);
320 break;
324 void destroy_cis_cache(struct pcmcia_socket *s)
326 struct list_head *l, *n;
328 list_for_each_safe(l, n, &s->cis_cache) {
329 struct cis_cache_entry *cis = list_entry(l, struct cis_cache_entry, node);
331 list_del(&cis->node);
332 kfree(cis);
336 /*======================================================================
338 This verifies if the CIS of a card matches what is in the CIS
339 cache.
341 ======================================================================*/
343 int verify_cis_cache(struct pcmcia_socket *s)
345 struct cis_cache_entry *cis;
346 char *buf;
348 buf = kmalloc(256, GFP_KERNEL);
349 if (buf == NULL)
350 return -1;
351 list_for_each_entry(cis, &s->cis_cache, node) {
352 int len = cis->len;
354 if (len > 256)
355 len = 256;
356 #ifdef CONFIG_CARDBUS
357 if (s->state & SOCKET_CARDBUS)
358 read_cb_mem(s, cis->attr, cis->addr, len, buf);
359 else
360 #endif
361 read_cis_mem(s, cis->attr, cis->addr, len, buf);
363 if (memcmp(buf, cis->cache, len) != 0) {
364 kfree(buf);
365 return -1;
368 kfree(buf);
369 return 0;
372 /*======================================================================
374 For really bad cards, we provide a facility for uploading a
375 replacement CIS.
377 ======================================================================*/
379 int pcmcia_replace_cis(client_handle_t handle, cisdump_t *cis)
381 struct pcmcia_socket *s;
382 if (CHECK_HANDLE(handle))
383 return CS_BAD_HANDLE;
384 s = SOCKET(handle);
385 if (s->fake_cis != NULL) {
386 kfree(s->fake_cis);
387 s->fake_cis = NULL;
389 if (cis->Length > CISTPL_MAX_CIS_SIZE)
390 return CS_BAD_SIZE;
391 s->fake_cis = kmalloc(cis->Length, GFP_KERNEL);
392 if (s->fake_cis == NULL)
393 return CS_OUT_OF_RESOURCE;
394 s->fake_cis_len = cis->Length;
395 memcpy(s->fake_cis, cis->Data, cis->Length);
396 return CS_SUCCESS;
399 /*======================================================================
401 The high-level CIS tuple services
403 ======================================================================*/
405 typedef struct tuple_flags {
406 u_int link_space:4;
407 u_int has_link:1;
408 u_int mfc_fn:3;
409 u_int space:4;
410 } tuple_flags;
412 #define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
413 #define HAS_LINK(f) (((tuple_flags *)(&(f)))->has_link)
414 #define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn)
415 #define SPACE(f) (((tuple_flags *)(&(f)))->space)
417 int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple);
419 int pcmcia_get_first_tuple(client_handle_t handle, tuple_t *tuple)
421 struct pcmcia_socket *s;
422 if (CHECK_HANDLE(handle))
423 return CS_BAD_HANDLE;
424 s = SOCKET(handle);
425 if (!(s->state & SOCKET_PRESENT))
426 return CS_NO_CARD;
427 tuple->TupleLink = tuple->Flags = 0;
428 #ifdef CONFIG_CARDBUS
429 if (s->state & SOCKET_CARDBUS) {
430 struct pci_dev *dev = s->cb_dev;
431 u_int ptr;
432 pci_bus_read_config_dword(dev->subordinate, 0, PCI_CARDBUS_CIS, &ptr);
433 tuple->CISOffset = ptr & ~7;
434 SPACE(tuple->Flags) = (ptr & 7);
435 } else
436 #endif
438 /* Assume presence of a LONGLINK_C to address 0 */
439 tuple->CISOffset = tuple->LinkOffset = 0;
440 SPACE(tuple->Flags) = HAS_LINK(tuple->Flags) = 1;
442 if (!(s->state & SOCKET_CARDBUS) && (s->functions > 1) &&
443 !(tuple->Attributes & TUPLE_RETURN_COMMON)) {
444 cisdata_t req = tuple->DesiredTuple;
445 tuple->DesiredTuple = CISTPL_LONGLINK_MFC;
446 if (pcmcia_get_next_tuple(handle, tuple) == CS_SUCCESS) {
447 tuple->DesiredTuple = CISTPL_LINKTARGET;
448 if (pcmcia_get_next_tuple(handle, tuple) != CS_SUCCESS)
449 return CS_NO_MORE_ITEMS;
450 } else
451 tuple->CISOffset = tuple->TupleLink = 0;
452 tuple->DesiredTuple = req;
454 return pcmcia_get_next_tuple(handle, tuple);
457 static int follow_link(struct pcmcia_socket *s, tuple_t *tuple)
459 u_char link[5];
460 u_int ofs;
462 if (MFC_FN(tuple->Flags)) {
463 /* Get indirect link from the MFC tuple */
464 read_cis_cache(s, LINK_SPACE(tuple->Flags),
465 tuple->LinkOffset, 5, link);
466 ofs = le32_to_cpu(*(u_int *)(link+1));
467 SPACE(tuple->Flags) = (link[0] == CISTPL_MFC_ATTR);
468 /* Move to the next indirect link */
469 tuple->LinkOffset += 5;
470 MFC_FN(tuple->Flags)--;
471 } else if (HAS_LINK(tuple->Flags)) {
472 ofs = tuple->LinkOffset;
473 SPACE(tuple->Flags) = LINK_SPACE(tuple->Flags);
474 HAS_LINK(tuple->Flags) = 0;
475 } else {
476 return -1;
478 if (!(s->state & SOCKET_CARDBUS) && SPACE(tuple->Flags)) {
479 /* This is ugly, but a common CIS error is to code the long
480 link offset incorrectly, so we check the right spot... */
481 read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
482 if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
483 (strncmp(link+2, "CIS", 3) == 0))
484 return ofs;
485 remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
486 /* Then, we try the wrong spot... */
487 ofs = ofs >> 1;
489 read_cis_cache(s, SPACE(tuple->Flags), ofs, 5, link);
490 if ((link[0] == CISTPL_LINKTARGET) && (link[1] >= 3) &&
491 (strncmp(link+2, "CIS", 3) == 0))
492 return ofs;
493 remove_cis_cache(s, SPACE(tuple->Flags), ofs, 5);
494 return -1;
497 int pcmcia_get_next_tuple(client_handle_t handle, tuple_t *tuple)
499 struct pcmcia_socket *s;
500 u_char link[2], tmp;
501 int ofs, i, attr;
503 if (CHECK_HANDLE(handle))
504 return CS_BAD_HANDLE;
505 s = SOCKET(handle);
506 if (!(s->state & SOCKET_PRESENT))
507 return CS_NO_CARD;
509 link[1] = tuple->TupleLink;
510 ofs = tuple->CISOffset + tuple->TupleLink;
511 attr = SPACE(tuple->Flags);
513 for (i = 0; i < MAX_TUPLES; i++) {
514 if (link[1] == 0xff) {
515 link[0] = CISTPL_END;
516 } else {
517 read_cis_cache(s, attr, ofs, 2, link);
518 if (link[0] == CISTPL_NULL) {
519 ofs++; continue;
523 /* End of chain? Follow long link if possible */
524 if (link[0] == CISTPL_END) {
525 if ((ofs = follow_link(s, tuple)) < 0)
526 return CS_NO_MORE_ITEMS;
527 attr = SPACE(tuple->Flags);
528 read_cis_cache(s, attr, ofs, 2, link);
531 /* Is this a link tuple? Make a note of it */
532 if ((link[0] == CISTPL_LONGLINK_A) ||
533 (link[0] == CISTPL_LONGLINK_C) ||
534 (link[0] == CISTPL_LONGLINK_MFC) ||
535 (link[0] == CISTPL_LINKTARGET) ||
536 (link[0] == CISTPL_INDIRECT) ||
537 (link[0] == CISTPL_NO_LINK)) {
538 switch (link[0]) {
539 case CISTPL_LONGLINK_A:
540 HAS_LINK(tuple->Flags) = 1;
541 LINK_SPACE(tuple->Flags) = attr | IS_ATTR;
542 read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
543 break;
544 case CISTPL_LONGLINK_C:
545 HAS_LINK(tuple->Flags) = 1;
546 LINK_SPACE(tuple->Flags) = attr & ~IS_ATTR;
547 read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
548 break;
549 case CISTPL_INDIRECT:
550 HAS_LINK(tuple->Flags) = 1;
551 LINK_SPACE(tuple->Flags) = IS_ATTR | IS_INDIRECT;
552 tuple->LinkOffset = 0;
553 break;
554 case CISTPL_LONGLINK_MFC:
555 tuple->LinkOffset = ofs + 3;
556 LINK_SPACE(tuple->Flags) = attr;
557 if (handle->Function == BIND_FN_ALL) {
558 /* Follow all the MFC links */
559 read_cis_cache(s, attr, ofs+2, 1, &tmp);
560 MFC_FN(tuple->Flags) = tmp;
561 } else {
562 /* Follow exactly one of the links */
563 MFC_FN(tuple->Flags) = 1;
564 tuple->LinkOffset += handle->Function * 5;
566 break;
567 case CISTPL_NO_LINK:
568 HAS_LINK(tuple->Flags) = 0;
569 break;
571 if ((tuple->Attributes & TUPLE_RETURN_LINK) &&
572 (tuple->DesiredTuple == RETURN_FIRST_TUPLE))
573 break;
574 } else
575 if (tuple->DesiredTuple == RETURN_FIRST_TUPLE)
576 break;
578 if (link[0] == tuple->DesiredTuple)
579 break;
580 ofs += link[1] + 2;
582 if (i == MAX_TUPLES) {
583 cs_dbg(s, 1, "cs: overrun in pcmcia_get_next_tuple\n");
584 return CS_NO_MORE_ITEMS;
587 tuple->TupleCode = link[0];
588 tuple->TupleLink = link[1];
589 tuple->CISOffset = ofs + 2;
590 return CS_SUCCESS;
593 /*====================================================================*/
595 #define _MIN(a, b) (((a) < (b)) ? (a) : (b))
597 int pcmcia_get_tuple_data(client_handle_t handle, tuple_t *tuple)
599 struct pcmcia_socket *s;
600 u_int len;
602 if (CHECK_HANDLE(handle))
603 return CS_BAD_HANDLE;
605 s = SOCKET(handle);
607 if (tuple->TupleLink < tuple->TupleOffset)
608 return CS_NO_MORE_ITEMS;
609 len = tuple->TupleLink - tuple->TupleOffset;
610 tuple->TupleDataLen = tuple->TupleLink;
611 if (len == 0)
612 return CS_SUCCESS;
613 read_cis_cache(s, SPACE(tuple->Flags),
614 tuple->CISOffset + tuple->TupleOffset,
615 _MIN(len, tuple->TupleDataMax), tuple->TupleData);
616 return CS_SUCCESS;
619 /*======================================================================
621 Parsing routines for individual tuples
623 ======================================================================*/
625 static int parse_device(tuple_t *tuple, cistpl_device_t *device)
627 int i;
628 u_char scale;
629 u_char *p, *q;
631 p = (u_char *)tuple->TupleData;
632 q = p + tuple->TupleDataLen;
634 device->ndev = 0;
635 for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
637 if (*p == 0xff) break;
638 device->dev[i].type = (*p >> 4);
639 device->dev[i].wp = (*p & 0x08) ? 1 : 0;
640 switch (*p & 0x07) {
641 case 0: device->dev[i].speed = 0; break;
642 case 1: device->dev[i].speed = 250; break;
643 case 2: device->dev[i].speed = 200; break;
644 case 3: device->dev[i].speed = 150; break;
645 case 4: device->dev[i].speed = 100; break;
646 case 7:
647 if (++p == q) return CS_BAD_TUPLE;
648 device->dev[i].speed = SPEED_CVT(*p);
649 while (*p & 0x80)
650 if (++p == q) return CS_BAD_TUPLE;
651 break;
652 default:
653 return CS_BAD_TUPLE;
656 if (++p == q) return CS_BAD_TUPLE;
657 if (*p == 0xff) break;
658 scale = *p & 7;
659 if (scale == 7) return CS_BAD_TUPLE;
660 device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
661 device->ndev++;
662 if (++p == q) break;
665 return CS_SUCCESS;
668 /*====================================================================*/
670 static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
672 u_char *p;
673 if (tuple->TupleDataLen < 5)
674 return CS_BAD_TUPLE;
675 p = (u_char *)tuple->TupleData;
676 csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
677 csum->len = le16_to_cpu(*(u_short *)(p + 2));
678 csum->sum = *(p+4);
679 return CS_SUCCESS;
682 /*====================================================================*/
684 static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
686 if (tuple->TupleDataLen < 4)
687 return CS_BAD_TUPLE;
688 link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
689 return CS_SUCCESS;
692 /*====================================================================*/
694 static int parse_longlink_mfc(tuple_t *tuple,
695 cistpl_longlink_mfc_t *link)
697 u_char *p;
698 int i;
700 p = (u_char *)tuple->TupleData;
702 link->nfn = *p; p++;
703 if (tuple->TupleDataLen <= link->nfn*5)
704 return CS_BAD_TUPLE;
705 for (i = 0; i < link->nfn; i++) {
706 link->fn[i].space = *p; p++;
707 link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
709 return CS_SUCCESS;
712 /*====================================================================*/
714 static int parse_strings(u_char *p, u_char *q, int max,
715 char *s, u_char *ofs, u_char *found)
717 int i, j, ns;
719 if (p == q) return CS_BAD_TUPLE;
720 ns = 0; j = 0;
721 for (i = 0; i < max; i++) {
722 if (*p == 0xff) break;
723 ofs[i] = j;
724 ns++;
725 for (;;) {
726 s[j++] = (*p == 0xff) ? '\0' : *p;
727 if ((*p == '\0') || (*p == 0xff)) break;
728 if (++p == q) return CS_BAD_TUPLE;
730 if ((*p == 0xff) || (++p == q)) break;
732 if (found) {
733 *found = ns;
734 return CS_SUCCESS;
735 } else {
736 return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
740 /*====================================================================*/
742 static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
744 u_char *p, *q;
746 p = (u_char *)tuple->TupleData;
747 q = p + tuple->TupleDataLen;
749 vers_1->major = *p; p++;
750 vers_1->minor = *p; p++;
751 if (p >= q) return CS_BAD_TUPLE;
753 return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
754 vers_1->str, vers_1->ofs, &vers_1->ns);
757 /*====================================================================*/
759 static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
761 u_char *p, *q;
763 p = (u_char *)tuple->TupleData;
764 q = p + tuple->TupleDataLen;
766 return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
767 altstr->str, altstr->ofs, &altstr->ns);
770 /*====================================================================*/
772 static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
774 u_char *p, *q;
775 int nid;
777 p = (u_char *)tuple->TupleData;
778 q = p + tuple->TupleDataLen;
780 for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
781 if (p > q-2) break;
782 jedec->id[nid].mfr = p[0];
783 jedec->id[nid].info = p[1];
784 p += 2;
786 jedec->nid = nid;
787 return CS_SUCCESS;
790 /*====================================================================*/
792 static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
794 u_short *p;
795 if (tuple->TupleDataLen < 4)
796 return CS_BAD_TUPLE;
797 p = (u_short *)tuple->TupleData;
798 m->manf = le16_to_cpu(p[0]);
799 m->card = le16_to_cpu(p[1]);
800 return CS_SUCCESS;
803 /*====================================================================*/
805 static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
807 u_char *p;
808 if (tuple->TupleDataLen < 2)
809 return CS_BAD_TUPLE;
810 p = (u_char *)tuple->TupleData;
811 f->func = p[0];
812 f->sysinit = p[1];
813 return CS_SUCCESS;
816 /*====================================================================*/
818 static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
820 u_char *p;
821 int i;
822 if (tuple->TupleDataLen < 1)
823 return CS_BAD_TUPLE;
824 p = (u_char *)tuple->TupleData;
825 f->type = p[0];
826 for (i = 1; i < tuple->TupleDataLen; i++)
827 f->data[i-1] = p[i];
828 return CS_SUCCESS;
831 /*====================================================================*/
833 static int parse_config(tuple_t *tuple, cistpl_config_t *config)
835 int rasz, rmsz, i;
836 u_char *p;
838 p = (u_char *)tuple->TupleData;
839 rasz = *p & 0x03;
840 rmsz = (*p & 0x3c) >> 2;
841 if (tuple->TupleDataLen < rasz+rmsz+4)
842 return CS_BAD_TUPLE;
843 config->last_idx = *(++p);
844 p++;
845 config->base = 0;
846 for (i = 0; i <= rasz; i++)
847 config->base += p[i] << (8*i);
848 p += rasz+1;
849 for (i = 0; i < 4; i++)
850 config->rmask[i] = 0;
851 for (i = 0; i <= rmsz; i++)
852 config->rmask[i>>2] += p[i] << (8*(i%4));
853 config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
854 return CS_SUCCESS;
857 /*======================================================================
859 The following routines are all used to parse the nightmarish
860 config table entries.
862 ======================================================================*/
864 static u_char *parse_power(u_char *p, u_char *q,
865 cistpl_power_t *pwr)
867 int i;
868 u_int scale;
870 if (p == q) return NULL;
871 pwr->present = *p;
872 pwr->flags = 0;
873 p++;
874 for (i = 0; i < 7; i++)
875 if (pwr->present & (1<<i)) {
876 if (p == q) return NULL;
877 pwr->param[i] = POWER_CVT(*p);
878 scale = POWER_SCALE(*p);
879 while (*p & 0x80) {
880 if (++p == q) return NULL;
881 if ((*p & 0x7f) < 100)
882 pwr->param[i] += (*p & 0x7f) * scale / 100;
883 else if (*p == 0x7d)
884 pwr->flags |= CISTPL_POWER_HIGHZ_OK;
885 else if (*p == 0x7e)
886 pwr->param[i] = 0;
887 else if (*p == 0x7f)
888 pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
889 else
890 return NULL;
892 p++;
894 return p;
897 /*====================================================================*/
899 static u_char *parse_timing(u_char *p, u_char *q,
900 cistpl_timing_t *timing)
902 u_char scale;
904 if (p == q) return NULL;
905 scale = *p;
906 if ((scale & 3) != 3) {
907 if (++p == q) return NULL;
908 timing->wait = SPEED_CVT(*p);
909 timing->waitscale = exponent[scale & 3];
910 } else
911 timing->wait = 0;
912 scale >>= 2;
913 if ((scale & 7) != 7) {
914 if (++p == q) return NULL;
915 timing->ready = SPEED_CVT(*p);
916 timing->rdyscale = exponent[scale & 7];
917 } else
918 timing->ready = 0;
919 scale >>= 3;
920 if (scale != 7) {
921 if (++p == q) return NULL;
922 timing->reserved = SPEED_CVT(*p);
923 timing->rsvscale = exponent[scale];
924 } else
925 timing->reserved = 0;
926 p++;
927 return p;
930 /*====================================================================*/
932 static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
934 int i, j, bsz, lsz;
936 if (p == q) return NULL;
937 io->flags = *p;
939 if (!(*p & 0x80)) {
940 io->nwin = 1;
941 io->win[0].base = 0;
942 io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
943 return p+1;
946 if (++p == q) return NULL;
947 io->nwin = (*p & 0x0f) + 1;
948 bsz = (*p & 0x30) >> 4;
949 if (bsz == 3) bsz++;
950 lsz = (*p & 0xc0) >> 6;
951 if (lsz == 3) lsz++;
952 p++;
954 for (i = 0; i < io->nwin; i++) {
955 io->win[i].base = 0;
956 io->win[i].len = 1;
957 for (j = 0; j < bsz; j++, p++) {
958 if (p == q) return NULL;
959 io->win[i].base += *p << (j*8);
961 for (j = 0; j < lsz; j++, p++) {
962 if (p == q) return NULL;
963 io->win[i].len += *p << (j*8);
966 return p;
969 /*====================================================================*/
971 static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
973 int i, j, asz, lsz, has_ha;
974 u_int len, ca, ha;
976 if (p == q) return NULL;
978 mem->nwin = (*p & 0x07) + 1;
979 lsz = (*p & 0x18) >> 3;
980 asz = (*p & 0x60) >> 5;
981 has_ha = (*p & 0x80);
982 if (++p == q) return NULL;
984 for (i = 0; i < mem->nwin; i++) {
985 len = ca = ha = 0;
986 for (j = 0; j < lsz; j++, p++) {
987 if (p == q) return NULL;
988 len += *p << (j*8);
990 for (j = 0; j < asz; j++, p++) {
991 if (p == q) return NULL;
992 ca += *p << (j*8);
994 if (has_ha)
995 for (j = 0; j < asz; j++, p++) {
996 if (p == q) return NULL;
997 ha += *p << (j*8);
999 mem->win[i].len = len << 8;
1000 mem->win[i].card_addr = ca << 8;
1001 mem->win[i].host_addr = ha << 8;
1003 return p;
1006 /*====================================================================*/
1008 static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
1010 if (p == q) return NULL;
1011 irq->IRQInfo1 = *p; p++;
1012 if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
1013 if (p+2 > q) return NULL;
1014 irq->IRQInfo2 = (p[1]<<8) + p[0];
1015 p += 2;
1017 return p;
1020 /*====================================================================*/
1022 static int parse_cftable_entry(tuple_t *tuple,
1023 cistpl_cftable_entry_t *entry)
1025 u_char *p, *q, features;
1027 p = tuple->TupleData;
1028 q = p + tuple->TupleDataLen;
1029 entry->index = *p & 0x3f;
1030 entry->flags = 0;
1031 if (*p & 0x40)
1032 entry->flags |= CISTPL_CFTABLE_DEFAULT;
1033 if (*p & 0x80) {
1034 if (++p == q) return CS_BAD_TUPLE;
1035 if (*p & 0x10)
1036 entry->flags |= CISTPL_CFTABLE_BVDS;
1037 if (*p & 0x20)
1038 entry->flags |= CISTPL_CFTABLE_WP;
1039 if (*p & 0x40)
1040 entry->flags |= CISTPL_CFTABLE_RDYBSY;
1041 if (*p & 0x80)
1042 entry->flags |= CISTPL_CFTABLE_MWAIT;
1043 entry->interface = *p & 0x0f;
1044 } else
1045 entry->interface = 0;
1047 /* Process optional features */
1048 if (++p == q) return CS_BAD_TUPLE;
1049 features = *p; p++;
1051 /* Power options */
1052 if ((features & 3) > 0) {
1053 p = parse_power(p, q, &entry->vcc);
1054 if (p == NULL) return CS_BAD_TUPLE;
1055 } else
1056 entry->vcc.present = 0;
1057 if ((features & 3) > 1) {
1058 p = parse_power(p, q, &entry->vpp1);
1059 if (p == NULL) return CS_BAD_TUPLE;
1060 } else
1061 entry->vpp1.present = 0;
1062 if ((features & 3) > 2) {
1063 p = parse_power(p, q, &entry->vpp2);
1064 if (p == NULL) return CS_BAD_TUPLE;
1065 } else
1066 entry->vpp2.present = 0;
1068 /* Timing options */
1069 if (features & 0x04) {
1070 p = parse_timing(p, q, &entry->timing);
1071 if (p == NULL) return CS_BAD_TUPLE;
1072 } else {
1073 entry->timing.wait = 0;
1074 entry->timing.ready = 0;
1075 entry->timing.reserved = 0;
1078 /* I/O window options */
1079 if (features & 0x08) {
1080 p = parse_io(p, q, &entry->io);
1081 if (p == NULL) return CS_BAD_TUPLE;
1082 } else
1083 entry->io.nwin = 0;
1085 /* Interrupt options */
1086 if (features & 0x10) {
1087 p = parse_irq(p, q, &entry->irq);
1088 if (p == NULL) return CS_BAD_TUPLE;
1089 } else
1090 entry->irq.IRQInfo1 = 0;
1092 switch (features & 0x60) {
1093 case 0x00:
1094 entry->mem.nwin = 0;
1095 break;
1096 case 0x20:
1097 entry->mem.nwin = 1;
1098 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
1099 entry->mem.win[0].card_addr = 0;
1100 entry->mem.win[0].host_addr = 0;
1101 p += 2;
1102 if (p > q) return CS_BAD_TUPLE;
1103 break;
1104 case 0x40:
1105 entry->mem.nwin = 1;
1106 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
1107 entry->mem.win[0].card_addr =
1108 le16_to_cpu(*(u_short *)(p+2)) << 8;
1109 entry->mem.win[0].host_addr = 0;
1110 p += 4;
1111 if (p > q) return CS_BAD_TUPLE;
1112 break;
1113 case 0x60:
1114 p = parse_mem(p, q, &entry->mem);
1115 if (p == NULL) return CS_BAD_TUPLE;
1116 break;
1119 /* Misc features */
1120 if (features & 0x80) {
1121 if (p == q) return CS_BAD_TUPLE;
1122 entry->flags |= (*p << 8);
1123 while (*p & 0x80)
1124 if (++p == q) return CS_BAD_TUPLE;
1125 p++;
1128 entry->subtuples = q-p;
1130 return CS_SUCCESS;
1133 /*====================================================================*/
1135 #ifdef CONFIG_CARDBUS
1137 static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
1139 u_char *p;
1140 if (tuple->TupleDataLen < 6)
1141 return CS_BAD_TUPLE;
1142 p = (u_char *)tuple->TupleData;
1143 bar->attr = *p;
1144 p += 2;
1145 bar->size = le32_to_cpu(*(u_int *)p);
1146 return CS_SUCCESS;
1149 static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
1151 u_char *p;
1153 p = (u_char *)tuple->TupleData;
1154 if ((*p != 3) || (tuple->TupleDataLen < 6))
1155 return CS_BAD_TUPLE;
1156 config->last_idx = *(++p);
1157 p++;
1158 config->base = le32_to_cpu(*(u_int *)p);
1159 config->subtuples = tuple->TupleDataLen - 6;
1160 return CS_SUCCESS;
1163 static int parse_cftable_entry_cb(tuple_t *tuple,
1164 cistpl_cftable_entry_cb_t *entry)
1166 u_char *p, *q, features;
1168 p = tuple->TupleData;
1169 q = p + tuple->TupleDataLen;
1170 entry->index = *p & 0x3f;
1171 entry->flags = 0;
1172 if (*p & 0x40)
1173 entry->flags |= CISTPL_CFTABLE_DEFAULT;
1175 /* Process optional features */
1176 if (++p == q) return CS_BAD_TUPLE;
1177 features = *p; p++;
1179 /* Power options */
1180 if ((features & 3) > 0) {
1181 p = parse_power(p, q, &entry->vcc);
1182 if (p == NULL) return CS_BAD_TUPLE;
1183 } else
1184 entry->vcc.present = 0;
1185 if ((features & 3) > 1) {
1186 p = parse_power(p, q, &entry->vpp1);
1187 if (p == NULL) return CS_BAD_TUPLE;
1188 } else
1189 entry->vpp1.present = 0;
1190 if ((features & 3) > 2) {
1191 p = parse_power(p, q, &entry->vpp2);
1192 if (p == NULL) return CS_BAD_TUPLE;
1193 } else
1194 entry->vpp2.present = 0;
1196 /* I/O window options */
1197 if (features & 0x08) {
1198 if (p == q) return CS_BAD_TUPLE;
1199 entry->io = *p; p++;
1200 } else
1201 entry->io = 0;
1203 /* Interrupt options */
1204 if (features & 0x10) {
1205 p = parse_irq(p, q, &entry->irq);
1206 if (p == NULL) return CS_BAD_TUPLE;
1207 } else
1208 entry->irq.IRQInfo1 = 0;
1210 if (features & 0x20) {
1211 if (p == q) return CS_BAD_TUPLE;
1212 entry->mem = *p; p++;
1213 } else
1214 entry->mem = 0;
1216 /* Misc features */
1217 if (features & 0x80) {
1218 if (p == q) return CS_BAD_TUPLE;
1219 entry->flags |= (*p << 8);
1220 if (*p & 0x80) {
1221 if (++p == q) return CS_BAD_TUPLE;
1222 entry->flags |= (*p << 16);
1224 while (*p & 0x80)
1225 if (++p == q) return CS_BAD_TUPLE;
1226 p++;
1229 entry->subtuples = q-p;
1231 return CS_SUCCESS;
1234 #endif
1236 /*====================================================================*/
1238 static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
1240 u_char *p, *q;
1241 int n;
1243 p = (u_char *)tuple->TupleData;
1244 q = p + tuple->TupleDataLen;
1246 for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
1247 if (p > q-6) break;
1248 geo->geo[n].buswidth = p[0];
1249 geo->geo[n].erase_block = 1 << (p[1]-1);
1250 geo->geo[n].read_block = 1 << (p[2]-1);
1251 geo->geo[n].write_block = 1 << (p[3]-1);
1252 geo->geo[n].partition = 1 << (p[4]-1);
1253 geo->geo[n].interleave = 1 << (p[5]-1);
1254 p += 6;
1256 geo->ngeo = n;
1257 return CS_SUCCESS;
1260 /*====================================================================*/
1262 static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
1264 u_char *p, *q;
1266 if (tuple->TupleDataLen < 10)
1267 return CS_BAD_TUPLE;
1269 p = tuple->TupleData;
1270 q = p + tuple->TupleDataLen;
1272 v2->vers = p[0];
1273 v2->comply = p[1];
1274 v2->dindex = le16_to_cpu(*(u_short *)(p+2));
1275 v2->vspec8 = p[6];
1276 v2->vspec9 = p[7];
1277 v2->nhdr = p[8];
1278 p += 9;
1279 return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
1282 /*====================================================================*/
1284 static int parse_org(tuple_t *tuple, cistpl_org_t *org)
1286 u_char *p, *q;
1287 int i;
1289 p = tuple->TupleData;
1290 q = p + tuple->TupleDataLen;
1291 if (p == q) return CS_BAD_TUPLE;
1292 org->data_org = *p;
1293 if (++p == q) return CS_BAD_TUPLE;
1294 for (i = 0; i < 30; i++) {
1295 org->desc[i] = *p;
1296 if (*p == '\0') break;
1297 if (++p == q) return CS_BAD_TUPLE;
1299 return CS_SUCCESS;
1302 /*====================================================================*/
1304 static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
1306 u_char *p;
1308 if (tuple->TupleDataLen < 10)
1309 return CS_BAD_TUPLE;
1311 p = tuple->TupleData;
1313 fmt->type = p[0];
1314 fmt->edc = p[1];
1315 fmt->offset = le32_to_cpu(*(u_int *)(p+2));
1316 fmt->length = le32_to_cpu(*(u_int *)(p+6));
1318 return CS_SUCCESS;
1321 /*====================================================================*/
1323 int pcmcia_parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
1325 int ret = CS_SUCCESS;
1327 if (tuple->TupleDataLen > tuple->TupleDataMax)
1328 return CS_BAD_TUPLE;
1329 switch (tuple->TupleCode) {
1330 case CISTPL_DEVICE:
1331 case CISTPL_DEVICE_A:
1332 ret = parse_device(tuple, &parse->device);
1333 break;
1334 #ifdef CONFIG_CARDBUS
1335 case CISTPL_BAR:
1336 ret = parse_bar(tuple, &parse->bar);
1337 break;
1338 case CISTPL_CONFIG_CB:
1339 ret = parse_config_cb(tuple, &parse->config);
1340 break;
1341 case CISTPL_CFTABLE_ENTRY_CB:
1342 ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
1343 break;
1344 #endif
1345 case CISTPL_CHECKSUM:
1346 ret = parse_checksum(tuple, &parse->checksum);
1347 break;
1348 case CISTPL_LONGLINK_A:
1349 case CISTPL_LONGLINK_C:
1350 ret = parse_longlink(tuple, &parse->longlink);
1351 break;
1352 case CISTPL_LONGLINK_MFC:
1353 ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
1354 break;
1355 case CISTPL_VERS_1:
1356 ret = parse_vers_1(tuple, &parse->version_1);
1357 break;
1358 case CISTPL_ALTSTR:
1359 ret = parse_altstr(tuple, &parse->altstr);
1360 break;
1361 case CISTPL_JEDEC_A:
1362 case CISTPL_JEDEC_C:
1363 ret = parse_jedec(tuple, &parse->jedec);
1364 break;
1365 case CISTPL_MANFID:
1366 ret = parse_manfid(tuple, &parse->manfid);
1367 break;
1368 case CISTPL_FUNCID:
1369 ret = parse_funcid(tuple, &parse->funcid);
1370 break;
1371 case CISTPL_FUNCE:
1372 ret = parse_funce(tuple, &parse->funce);
1373 break;
1374 case CISTPL_CONFIG:
1375 ret = parse_config(tuple, &parse->config);
1376 break;
1377 case CISTPL_CFTABLE_ENTRY:
1378 ret = parse_cftable_entry(tuple, &parse->cftable_entry);
1379 break;
1380 case CISTPL_DEVICE_GEO:
1381 case CISTPL_DEVICE_GEO_A:
1382 ret = parse_device_geo(tuple, &parse->device_geo);
1383 break;
1384 case CISTPL_VERS_2:
1385 ret = parse_vers_2(tuple, &parse->vers_2);
1386 break;
1387 case CISTPL_ORG:
1388 ret = parse_org(tuple, &parse->org);
1389 break;
1390 case CISTPL_FORMAT:
1391 case CISTPL_FORMAT_A:
1392 ret = parse_format(tuple, &parse->format);
1393 break;
1394 case CISTPL_NO_LINK:
1395 case CISTPL_LINKTARGET:
1396 ret = CS_SUCCESS;
1397 break;
1398 default:
1399 ret = CS_UNSUPPORTED_FUNCTION;
1400 break;
1402 return ret;
1405 /*======================================================================
1407 This is used internally by Card Services to look up CIS stuff.
1409 ======================================================================*/
1411 int read_tuple(client_handle_t handle, cisdata_t code, void *parse)
1413 tuple_t tuple;
1414 cisdata_t *buf;
1415 int ret;
1417 buf = kmalloc(256, GFP_KERNEL);
1418 if (buf == NULL)
1419 return CS_OUT_OF_RESOURCE;
1420 tuple.DesiredTuple = code;
1421 tuple.Attributes = TUPLE_RETURN_COMMON;
1422 ret = pcmcia_get_first_tuple(handle, &tuple);
1423 if (ret != CS_SUCCESS) goto done;
1424 tuple.TupleData = buf;
1425 tuple.TupleOffset = 0;
1426 tuple.TupleDataMax = 255;
1427 ret = pcmcia_get_tuple_data(handle, &tuple);
1428 if (ret != CS_SUCCESS) goto done;
1429 ret = pcmcia_parse_tuple(handle, &tuple, parse);
1430 done:
1431 kfree(buf);
1432 return ret;
1435 /*======================================================================
1437 This tries to determine if a card has a sensible CIS. It returns
1438 the number of tuples in the CIS, or 0 if the CIS looks bad. The
1439 checks include making sure several critical tuples are present and
1440 valid; seeing if the total number of tuples is reasonable; and
1441 looking for tuples that use reserved codes.
1443 ======================================================================*/
1445 int pcmcia_validate_cis(client_handle_t handle, cisinfo_t *info)
1447 tuple_t *tuple;
1448 cisparse_t *p;
1449 int ret, reserved, dev_ok = 0, ident_ok = 0;
1451 if (CHECK_HANDLE(handle))
1452 return CS_BAD_HANDLE;
1453 tuple = kmalloc(sizeof(*tuple), GFP_KERNEL);
1454 if (tuple == NULL)
1455 return CS_OUT_OF_RESOURCE;
1456 p = kmalloc(sizeof(*p), GFP_KERNEL);
1457 if (p == NULL) {
1458 kfree(tuple);
1459 return CS_OUT_OF_RESOURCE;
1462 info->Chains = reserved = 0;
1463 tuple->DesiredTuple = RETURN_FIRST_TUPLE;
1464 tuple->Attributes = TUPLE_RETURN_COMMON;
1465 ret = pcmcia_get_first_tuple(handle, tuple);
1466 if (ret != CS_SUCCESS)
1467 goto done;
1469 /* First tuple should be DEVICE; we should really have either that
1470 or a CFTABLE_ENTRY of some sort */
1471 if ((tuple->TupleCode == CISTPL_DEVICE) ||
1472 (read_tuple(handle, CISTPL_CFTABLE_ENTRY, p) == CS_SUCCESS) ||
1473 (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB, p) == CS_SUCCESS))
1474 dev_ok++;
1476 /* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
1477 tuple, for card identification. Certain old D-Link and Linksys
1478 cards have only a broken VERS_2 tuple; hence the bogus test. */
1479 if ((read_tuple(handle, CISTPL_MANFID, p) == CS_SUCCESS) ||
1480 (read_tuple(handle, CISTPL_VERS_1, p) == CS_SUCCESS) ||
1481 (read_tuple(handle, CISTPL_VERS_2, p) != CS_NO_MORE_ITEMS))
1482 ident_ok++;
1484 if (!dev_ok && !ident_ok)
1485 goto done;
1487 for (info->Chains = 1; info->Chains < MAX_TUPLES; info->Chains++) {
1488 ret = pcmcia_get_next_tuple(handle, tuple);
1489 if (ret != CS_SUCCESS) break;
1490 if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
1491 ((tuple->TupleCode > 0x47) && (tuple->TupleCode < 0x80)) ||
1492 ((tuple->TupleCode > 0x90) && (tuple->TupleCode < 0xff)))
1493 reserved++;
1495 if ((info->Chains == MAX_TUPLES) || (reserved > 5) ||
1496 ((!dev_ok || !ident_ok) && (info->Chains > 10)))
1497 info->Chains = 0;
1499 done:
1500 kfree(tuple);
1501 kfree(p);
1502 return CS_SUCCESS;