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
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.