~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/pcmcia/cistpl.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.