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