1 /*======================================================================
3 PCMCIA Card Information Structure parser
5 cistpl.c 1.74 1999/11/08 20:47:02
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dhinds@pcmcia.sourceforge.org>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU 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.
32 ======================================================================*/
34 #define __NO_VERSION__
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>
45 #include <linux/sched.h>
46 #include <linux/pci.h>
47 #include <linux/ioport.h>
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/cistpl.h>
56 #include "cs_internal.h"
59 static const u_char mantissa
[] = {
60 10, 12, 13, 15, 20, 25, 30, 35,
61 40, 45, 50, 55, 60, 70, 80, 90
64 static const u_int exponent
[] = {
65 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
68 /* Convert an extended speed byte to a time in nanoseconds */
69 #define SPEED_CVT(v) \
70 (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
71 /* Convert a power byte to a current in 0.1 microamps */
72 #define POWER_CVT(v) \
73 (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
74 #define POWER_SCALE(v) (exponent[(v)&7])
76 /* Upper limit on reasonable # of tuples */
77 #define MAX_TUPLES 200
79 /*======================================================================
81 Low-level functions to read and write CIS memory. I think the
82 write routine is only useful for writing one-byte registers.
84 ======================================================================*/
86 void read_cis_mem(socket_info_t
*s
, int attr
, u_int addr
,
89 pccard_mem_map
*mem
= &s
->cis_mem
;
93 DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr
, addr
, len
);
94 if (setup_cis_mem(s
) != 0) {
95 memset(ptr
, 0xff, len
);
98 mem
->flags
|= MAP_ACTIVE
; mem
->flags
&= ~MAP_ATTRIB
;
99 if (attr
) { mem
->flags
|= MAP_ATTRIB
; inc
++; addr
*= 2; }
100 sys
= s
->cis_virt
+ (addr
& (s
->cap
.map_size
-1));
101 mem
->card_start
= addr
& ~(s
->cap
.map_size
-1);
103 for (; len
> 0; sys
= s
->cis_virt
) {
104 s
->ss_entry(s
->sock
, SS_SetMemMap
, mem
);
105 DEBUG(3, "cs: %#2.2x %#2.2x %#2.2x %#2.2x %#2.2x ...\n",
106 bus_readb(s
->cap
.bus
, sys
),
107 bus_readb(s
->cap
.bus
, sys
+inc
),
108 bus_readb(s
->cap
.bus
, sys
+2*inc
),
109 bus_readb(s
->cap
.bus
, sys
+3*inc
),
110 bus_readb(s
->cap
.bus
, sys
+4*inc
));
111 for ( ; len
> 0; len
--, ((u_char
*)ptr
)++, sys
+= inc
) {
112 if (sys
== s
->cis_virt
+s
->cap
.map_size
) break;
113 *(u_char
*)ptr
= bus_readb(s
->cap
.bus
, sys
);
115 mem
->card_start
+= s
->cap
.map_size
;
119 void write_cis_mem(socket_info_t
*s
, int attr
, u_int addr
,
120 u_int len
, void *ptr
)
122 pccard_mem_map
*mem
= &s
->cis_mem
;
126 DEBUG(3, "cs: write_cis_mem(%d, %#x, %u)\n", attr
, addr
, len
);
127 if (setup_cis_mem(s
) != 0) return;
128 mem
->flags
&= ~MAP_ATTRIB
;
129 if (attr
) { mem
->flags
|= MAP_ATTRIB
; inc
++; addr
*= 2; }
130 sys
= s
->cis_virt
+ (addr
& (s
->cap
.map_size
-1));
131 mem
->card_start
= addr
& ~(s
->cap
.map_size
-1);
133 for (; len
> 0; sys
= s
->cis_virt
) {
134 s
->ss_entry(s
->sock
, SS_SetMemMap
, mem
);
135 for ( ; len
> 0; len
--, ((u_char
*)ptr
)++, sys
+= inc
) {
136 if (sys
== s
->cis_virt
+s
->cap
.map_size
) break;
137 bus_writeb(s
->cap
.bus
, *(u_char
*)ptr
, sys
);
139 mem
->card_start
+= s
->cap
.map_size
;
143 /*======================================================================
145 This is tricky... when we set up CIS memory, we try to validate
146 the memory window space allocations.
148 ======================================================================*/
150 /* Scratch pointer to the socket we use for validation */
151 static socket_info_t
*vs
= NULL
;
153 /* Validation function for cards with a valid CIS */
154 static int cis_readable(u_long base
)
156 cisinfo_t info1
, info2
;
158 vs
->cis_mem
.sys_start
= base
;
159 vs
->cis_mem
.sys_stop
= base
+vs
->cap
.map_size
-1;
160 vs
->cis_virt
= bus_ioremap(vs
->cap
.bus
, base
, vs
->cap
.map_size
);
161 ret
= pcmcia_validate_cis(vs
->clients
, &info1
);
162 /* invalidate mapping and CIS cache */
163 bus_iounmap(vs
->cap
.bus
, vs
->cis_virt
); vs
->cis_used
= 0;
164 if ((ret
!= 0) || (info1
.Chains
== 0))
166 vs
->cis_mem
.sys_start
= base
+vs
->cap
.map_size
;
167 vs
->cis_mem
.sys_stop
= base
+2*vs
->cap
.map_size
-1;
168 vs
->cis_virt
= bus_ioremap(vs
->cap
.bus
, base
+vs
->cap
.map_size
,
170 ret
= pcmcia_validate_cis(vs
->clients
, &info2
);
171 bus_iounmap(vs
->cap
.bus
, vs
->cis_virt
); vs
->cis_used
= 0;
172 return ((ret
== 0) && (info1
.Chains
== info2
.Chains
));
175 /* Validation function for simple memory cards */
176 static int checksum(u_long base
)
179 vs
->cis_mem
.sys_start
= base
;
180 vs
->cis_mem
.sys_stop
= base
+vs
->cap
.map_size
-1;
181 vs
->cis_virt
= bus_ioremap(vs
->cap
.bus
, base
, vs
->cap
.map_size
);
182 vs
->cis_mem
.card_start
= 0;
183 vs
->cis_mem
.flags
= MAP_ACTIVE
;
184 vs
->ss_entry(vs
->sock
, SS_SetMemMap
, &vs
->cis_mem
);
185 /* Don't bother checking every word... */
187 for (i
= 0; i
< vs
->cap
.map_size
; i
+= 44) {
188 d
= bus_readl(vs
->cap
.bus
, vs
->cis_virt
+i
);
191 bus_iounmap(vs
->cap
.bus
, vs
->cis_virt
);
192 return (b
== -1) ? -1 : (a
>>1);
195 static int checksum_match(u_long base
)
197 int a
= checksum(base
), b
= checksum(base
+vs
->cap
.map_size
);
198 return ((a
== b
) && (a
>= 0));
201 int setup_cis_mem(socket_info_t
*s
)
203 if (s
->cis_mem
.sys_start
== 0) {
204 int low
= !(s
->cap
.features
& SS_CAP_PAGE_REGS
);
206 validate_mem(cis_readable
, checksum_match
, low
);
207 s
->cis_mem
.sys_start
= 0;
209 if (find_mem_region(&s
->cis_mem
.sys_start
, s
->cap
.map_size
,
210 s
->cap
.map_size
, low
, "card services")) {
211 printk(KERN_NOTICE
"cs: unable to map card memory!\n");
212 return CS_OUT_OF_RESOURCE
;
214 s
->cis_mem
.sys_stop
= s
->cis_mem
.sys_start
+s
->cap
.map_size
-1;
215 s
->cis_mem
.flags
|= MAP_ACTIVE
;
216 s
->cis_virt
= bus_ioremap(s
->cap
.bus
, s
->cis_mem
.sys_start
,
222 void release_cis_mem(socket_info_t
*s
)
224 if (s
->cis_mem
.sys_start
!= 0) {
225 s
->cis_mem
.flags
&= ~MAP_ACTIVE
;
226 s
->ss_entry(s
->sock
, SS_SetMemMap
, &s
->cis_mem
);
227 release_mem_region(s
->cis_mem
.sys_start
, s
->cap
.map_size
);
228 bus_iounmap(s
->cap
.bus
, s
->cis_virt
);
229 s
->cis_mem
.sys_start
= 0;
233 /*======================================================================
235 This is a wrapper around read_cis_mem, with the same interface,
236 but which caches information, for cards whose CIS may not be
237 readable all the time.
239 ======================================================================*/
241 static void read_cis_cache(socket_info_t
*s
, int attr
, u_int addr
,
242 u_int len
, void *ptr
)
248 if (s
->fake_cis_len
> addr
+len
)
249 memcpy(ptr
, s
->fake_cis
+addr
, len
);
251 memset(ptr
, 0xff, len
);
254 caddr
= s
->cis_cache
;
255 for (i
= 0; i
< s
->cis_used
; i
++) {
256 if ((s
->cis_table
[i
].addr
== addr
) &&
257 (s
->cis_table
[i
].len
== len
) &&
258 (s
->cis_table
[i
].attr
== attr
)) break;
259 caddr
+= s
->cis_table
[i
].len
;
261 if (i
< s
->cis_used
) {
262 memcpy(ptr
, caddr
, len
);
265 #ifdef CONFIG_CARDBUS
266 if (s
->state
& SOCKET_CARDBUS
)
267 read_cb_mem(s
, 0, attr
, addr
, len
, ptr
);
270 read_cis_mem(s
, attr
, addr
, len
, ptr
);
271 /* Copy data into the cache, if there is room */
272 if ((i
< MAX_CIS_TABLE
) &&
273 (caddr
+len
< s
->cis_cache
+MAX_CIS_DATA
)) {
274 s
->cis_table
[i
].addr
= addr
;
275 s
->cis_table
[i
].len
= len
;
276 s
->cis_table
[i
].attr
= attr
;
278 memcpy(caddr
, ptr
, len
);
282 /*======================================================================
284 This verifies if the CIS of a card matches what is in the CIS
287 ======================================================================*/
289 int verify_cis_cache(socket_info_t
*s
)
291 char buf
[256], *caddr
;
294 caddr
= s
->cis_cache
;
295 for (i
= 0; i
< s
->cis_used
; i
++) {
296 #ifdef CONFIG_CARDBUS
297 if (s
->state
& SOCKET_CARDBUS
)
298 read_cb_mem(s
, 0, s
->cis_table
[i
].attr
, s
->cis_table
[i
].addr
,
299 s
->cis_table
[i
].len
, buf
);
302 read_cis_mem(s
, s
->cis_table
[i
].attr
, s
->cis_table
[i
].addr
,
303 s
->cis_table
[i
].len
, buf
);
304 if (memcmp(buf
, caddr
, s
->cis_table
[i
].len
) != 0)
306 caddr
+= s
->cis_table
[i
].len
;
308 return (i
< s
->cis_used
);
311 /*======================================================================
313 For really bad cards, we provide a facility for uploading a
316 ======================================================================*/
318 int pcmcia_replace_cis(client_handle_t handle
, cisdump_t
*cis
)
321 if (CHECK_HANDLE(handle
))
322 return CS_BAD_HANDLE
;
324 if (s
->fake_cis
!= NULL
) {
328 if (cis
->Length
> CISTPL_MAX_CIS_SIZE
)
330 s
->fake_cis
= kmalloc(cis
->Length
, GFP_KERNEL
);
331 if (s
->fake_cis
== NULL
)
332 return CS_OUT_OF_RESOURCE
;
333 s
->fake_cis_len
= cis
->Length
;
334 memcpy(s
->fake_cis
, cis
->Data
, cis
->Length
);
338 /*======================================================================
340 The high-level CIS tuple services
342 ======================================================================*/
344 typedef struct tuple_flags
{
351 #define LINK_SPACE(f) (((tuple_flags *)(&(f)))->link_space)
352 #define HAS_LINK(f) (((tuple_flags *)(&(f)))->has_link)
353 #define MFC_FN(f) (((tuple_flags *)(&(f)))->mfc_fn)
354 #define SPACE(f) (((tuple_flags *)(&(f)))->space)
356 int pcmcia_get_next_tuple(client_handle_t handle
, tuple_t
*tuple
);
358 int pcmcia_get_first_tuple(client_handle_t handle
, tuple_t
*tuple
)
361 if (CHECK_HANDLE(handle
))
362 return CS_BAD_HANDLE
;
364 if (!(s
->state
& SOCKET_PRESENT
))
366 tuple
->TupleLink
= tuple
->Flags
= 0;
367 #ifdef CONFIG_CARDBUS
368 if (s
->state
& SOCKET_CARDBUS
) {
370 pcibios_read_config_dword(s
->cap
.cardbus
, 0, 0x28, &ptr
);
371 tuple
->CISOffset
= ptr
& ~7;
372 SPACE(tuple
->Flags
) = (ptr
& 7);
376 /* Assume presence of a LONGLINK_C to address 0 */
377 tuple
->CISOffset
= tuple
->LinkOffset
= 0;
378 SPACE(tuple
->Flags
) = HAS_LINK(tuple
->Flags
) = 1;
380 if (!(s
->state
& SOCKET_CARDBUS
) && (s
->functions
> 1) &&
381 !(tuple
->Attributes
& TUPLE_RETURN_COMMON
)) {
382 cisdata_t req
= tuple
->DesiredTuple
;
383 tuple
->DesiredTuple
= CISTPL_LONGLINK_MFC
;
384 if (pcmcia_get_next_tuple(handle
, tuple
) == CS_SUCCESS
) {
385 tuple
->DesiredTuple
= CISTPL_LINKTARGET
;
386 if (pcmcia_get_next_tuple(handle
, tuple
) != CS_SUCCESS
)
387 return CS_NO_MORE_ITEMS
;
389 tuple
->CISOffset
= tuple
->TupleLink
= 0;
390 tuple
->DesiredTuple
= req
;
392 return pcmcia_get_next_tuple(handle
, tuple
);
395 static int follow_link(socket_info_t
*s
, tuple_t
*tuple
)
400 if (MFC_FN(tuple
->Flags
)) {
401 /* Get indirect link from the MFC tuple */
402 read_cis_cache(s
, LINK_SPACE(tuple
->Flags
),
403 tuple
->LinkOffset
, 5, link
);
404 ofs
= le32_to_cpu(*(u_int
*)(link
+1));
405 SPACE(tuple
->Flags
) = (link
[0] == CISTPL_MFC_ATTR
);
406 /* Move to the next indirect link */
407 tuple
->LinkOffset
+= 5;
408 MFC_FN(tuple
->Flags
)--;
409 } else if (HAS_LINK(tuple
->Flags
)) {
410 ofs
= tuple
->LinkOffset
;
411 SPACE(tuple
->Flags
) = LINK_SPACE(tuple
->Flags
);
412 HAS_LINK(tuple
->Flags
) = 0;
416 if (!(s
->state
& SOCKET_CARDBUS
) && SPACE(tuple
->Flags
)) {
417 /* This is ugly, but a common CIS error is to code the long
418 link offset incorrectly, so we check the right spot... */
419 read_cis_cache(s
, SPACE(tuple
->Flags
), ofs
, 5, link
);
420 if ((link
[0] == CISTPL_LINKTARGET
) && (link
[1] >= 3) &&
421 (strncmp(link
+2, "CIS", 3) == 0))
423 /* Then, we try the wrong spot... */
426 read_cis_cache(s
, SPACE(tuple
->Flags
), ofs
, 5, link
);
427 if ((link
[0] != CISTPL_LINKTARGET
) || (link
[1] < 3) ||
428 (strncmp(link
+2, "CIS", 3) != 0))
433 int pcmcia_get_next_tuple(client_handle_t handle
, tuple_t
*tuple
)
439 if (CHECK_HANDLE(handle
))
440 return CS_BAD_HANDLE
;
442 if (!(s
->state
& SOCKET_PRESENT
))
445 link
[1] = tuple
->TupleLink
;
446 ofs
= tuple
->CISOffset
+ tuple
->TupleLink
;
447 attr
= SPACE(tuple
->Flags
);
449 for (i
= 0; i
< MAX_TUPLES
; i
++) {
450 if (link
[1] == 0xff) {
451 link
[0] = CISTPL_END
;
453 read_cis_cache(s
, attr
, ofs
, 2, link
);
454 if (link
[0] == CISTPL_NULL
) {
459 /* End of chain? Follow long link if possible */
460 if (link
[0] == CISTPL_END
) {
461 if ((ofs
= follow_link(s
, tuple
)) < 0)
462 return CS_NO_MORE_ITEMS
;
463 attr
= SPACE(tuple
->Flags
);
464 read_cis_cache(s
, attr
, ofs
, 2, link
);
467 /* Is this a link tuple? Make a note of it */
468 if ((link
[0] == CISTPL_LONGLINK_A
) ||
469 (link
[0] == CISTPL_LONGLINK_C
) ||
470 (link
[0] == CISTPL_LONGLINK_MFC
) ||
471 (link
[0] == CISTPL_LINKTARGET
) ||
472 (link
[0] == CISTPL_NO_LINK
)) {
474 case CISTPL_LONGLINK_A
:
475 HAS_LINK(tuple
->Flags
) = 1;
476 LINK_SPACE(tuple
->Flags
) = 1;
477 read_cis_cache(s
, attr
, ofs
+2, 4, &tuple
->LinkOffset
);
479 case CISTPL_LONGLINK_C
:
480 HAS_LINK(tuple
->Flags
) = 1;
481 LINK_SPACE(tuple
->Flags
) = 0;
482 read_cis_cache(s
, attr
, ofs
+2, 4, &tuple
->LinkOffset
);
484 case CISTPL_LONGLINK_MFC
:
485 tuple
->LinkOffset
= ofs
+ 3;
486 LINK_SPACE(tuple
->Flags
) = attr
;
487 if (handle
->Function
== BIND_FN_ALL
) {
488 /* Follow all the MFC links */
489 read_cis_cache(s
, attr
, ofs
+2, 1, &tmp
);
490 MFC_FN(tuple
->Flags
) = tmp
;
492 /* Follow exactly one of the links */
493 MFC_FN(tuple
->Flags
) = 1;
494 tuple
->LinkOffset
+= handle
->Function
* 5;
498 HAS_LINK(tuple
->Flags
) = 0;
501 if ((tuple
->Attributes
& TUPLE_RETURN_LINK
) &&
502 (tuple
->DesiredTuple
== RETURN_FIRST_TUPLE
))
505 if (tuple
->DesiredTuple
== RETURN_FIRST_TUPLE
)
508 if (link
[0] == tuple
->DesiredTuple
)
512 if (i
== MAX_TUPLES
) {
513 DEBUG(1, "cs: overrun in pcmcia_get_next_tuple for socket %d\n",
515 return CS_NO_MORE_ITEMS
;
518 tuple
->TupleCode
= link
[0];
519 tuple
->TupleLink
= link
[1];
520 tuple
->CISOffset
= ofs
+ 2;
524 /*====================================================================*/
526 #define _MIN(a, b) (((a) < (b)) ? (a) : (b))
528 int pcmcia_get_tuple_data(client_handle_t handle
, tuple_t
*tuple
)
533 if (CHECK_HANDLE(handle
))
534 return CS_BAD_HANDLE
;
538 if (tuple
->TupleLink
< tuple
->TupleOffset
)
539 return CS_NO_MORE_ITEMS
;
540 len
= tuple
->TupleLink
- tuple
->TupleOffset
;
541 tuple
->TupleDataLen
= tuple
->TupleLink
;
544 read_cis_cache(s
, SPACE(tuple
->Flags
),
545 tuple
->CISOffset
+ tuple
->TupleOffset
,
546 _MIN(len
, tuple
->TupleDataMax
), tuple
->TupleData
);
550 /*======================================================================
552 Parsing routines for individual tuples
554 ======================================================================*/
556 static int parse_device(tuple_t
*tuple
, cistpl_device_t
*device
)
562 p
= (u_char
*)tuple
->TupleData
;
563 q
= p
+ tuple
->TupleDataLen
;
566 for (i
= 0; i
< CISTPL_MAX_DEVICES
; i
++) {
568 if (*p
== 0xff) break;
569 device
->dev
[i
].type
= (*p
>> 4);
570 device
->dev
[i
].wp
= (*p
& 0x08) ? 1 : 0;
572 case 0: device
->dev
[i
].speed
= 0; break;
573 case 1: device
->dev
[i
].speed
= 250; break;
574 case 2: device
->dev
[i
].speed
= 200; break;
575 case 3: device
->dev
[i
].speed
= 150; break;
576 case 4: device
->dev
[i
].speed
= 100; break;
578 if (++p
== q
) return CS_BAD_TUPLE
;
581 device
->dev
[i
].speed
= SPEED_CVT(*p
);
583 if (++p
== q
) return CS_BAD_TUPLE
;
589 if (++p
== q
) return CS_BAD_TUPLE
;
590 if (*p
== 0xff) break;
592 if (scale
== 7) return CS_BAD_TUPLE
;
593 device
->dev
[i
].size
= ((*p
>> 3) + 1) * (512 << (scale
*2));
601 /*====================================================================*/
603 static int parse_checksum(tuple_t
*tuple
, cistpl_checksum_t
*csum
)
606 if (tuple
->TupleDataLen
< 5)
608 p
= (u_char
*)tuple
->TupleData
;
609 csum
->addr
= tuple
->CISOffset
+(short)le16_to_cpu(*(u_short
*)p
)-2;
610 csum
->len
= le16_to_cpu(*(u_short
*)(p
+ 2));
615 /*====================================================================*/
617 static int parse_longlink(tuple_t
*tuple
, cistpl_longlink_t
*link
)
619 if (tuple
->TupleDataLen
< 4)
621 link
->addr
= le32_to_cpu(*(u_int
*)tuple
->TupleData
);
625 /*====================================================================*/
627 static int parse_longlink_mfc(tuple_t
*tuple
,
628 cistpl_longlink_mfc_t
*link
)
633 p
= (u_char
*)tuple
->TupleData
;
636 if (tuple
->TupleDataLen
<= link
->nfn
*5)
638 for (i
= 0; i
< link
->nfn
; i
++) {
639 link
->fn
[i
].space
= *p
; p
++;
640 link
->fn
[i
].addr
= le32_to_cpu(*(u_int
*)p
); p
+= 4;
645 /*====================================================================*/
647 static int parse_strings(u_char
*p
, u_char
*q
, int max
,
648 char *s
, u_char
*ofs
, u_char
*found
)
652 if (p
== q
) return CS_BAD_TUPLE
;
654 for (i
= 0; i
< max
; i
++) {
655 if (*p
== 0xff) break;
659 s
[j
++] = (*p
== 0xff) ? '\0' : *p
;
660 if ((*p
== '\0') || (*p
== 0xff)) break;
661 if (++p
== q
) return CS_BAD_TUPLE
;
663 if ((*p
== 0xff) || (++p
== q
)) break;
669 return (ns
== max
) ? CS_SUCCESS
: CS_BAD_TUPLE
;
673 /*====================================================================*/
675 static int parse_vers_1(tuple_t
*tuple
, cistpl_vers_1_t
*vers_1
)
679 p
= (u_char
*)tuple
->TupleData
;
680 q
= p
+ tuple
->TupleDataLen
;
682 vers_1
->major
= *p
; p
++;
683 vers_1
->minor
= *p
; p
++;
684 if (p
>= q
) return CS_BAD_TUPLE
;
686 return parse_strings(p
, q
, CISTPL_VERS_1_MAX_PROD_STRINGS
,
687 vers_1
->str
, vers_1
->ofs
, &vers_1
->ns
);
690 /*====================================================================*/
692 static int parse_altstr(tuple_t
*tuple
, cistpl_altstr_t
*altstr
)
696 p
= (u_char
*)tuple
->TupleData
;
697 q
= p
+ tuple
->TupleDataLen
;
699 return parse_strings(p
, q
, CISTPL_MAX_ALTSTR_STRINGS
,
700 altstr
->str
, altstr
->ofs
, &altstr
->ns
);
703 /*====================================================================*/
705 static int parse_jedec(tuple_t
*tuple
, cistpl_jedec_t
*jedec
)
710 p
= (u_char
*)tuple
->TupleData
;
711 q
= p
+ tuple
->TupleDataLen
;
713 for (nid
= 0; nid
< CISTPL_MAX_DEVICES
; nid
++) {
715 jedec
->id
[nid
].mfr
= p
[0];
716 jedec
->id
[nid
].info
= p
[1];
723 /*====================================================================*/
725 static int parse_manfid(tuple_t
*tuple
, cistpl_manfid_t
*m
)
728 if (tuple
->TupleDataLen
< 4)
730 p
= (u_short
*)tuple
->TupleData
;
731 m
->manf
= le16_to_cpu(p
[0]);
732 m
->card
= le16_to_cpu(p
[1]);
736 /*====================================================================*/
738 static int parse_funcid(tuple_t
*tuple
, cistpl_funcid_t
*f
)
741 if (tuple
->TupleDataLen
< 2)
743 p
= (u_char
*)tuple
->TupleData
;
749 /*====================================================================*/
751 static int parse_funce(tuple_t
*tuple
, cistpl_funce_t
*f
)
755 if (tuple
->TupleDataLen
< 1)
757 p
= (u_char
*)tuple
->TupleData
;
759 for (i
= 1; i
< tuple
->TupleDataLen
; i
++)
764 /*====================================================================*/
766 static int parse_config(tuple_t
*tuple
, cistpl_config_t
*config
)
771 p
= (u_char
*)tuple
->TupleData
;
773 rmsz
= (*p
& 0x3c) >> 2;
774 if (tuple
->TupleDataLen
< rasz
+rmsz
+4)
776 config
->last_idx
= *(++p
);
779 for (i
= 0; i
<= rasz
; i
++)
780 config
->base
+= p
[i
] << (8*i
);
782 for (i
= 0; i
< 4; i
++)
783 config
->rmask
[i
] = 0;
784 for (i
= 0; i
<= rmsz
; i
++)
785 config
->rmask
[i
>>2] += p
[i
] << (8*(i
%4));
786 config
->subtuples
= tuple
->TupleDataLen
- (rasz
+rmsz
+4);
790 /*======================================================================
792 The following routines are all used to parse the nightmarish
793 config table entries.
795 ======================================================================*/
797 static u_char
*parse_power(u_char
*p
, u_char
*q
,
803 if (p
== q
) return NULL
;
807 for (i
= 0; i
< 7; i
++)
808 if (pwr
->present
& (1<<i
)) {
809 if (p
== q
) return NULL
;
810 pwr
->param
[i
] = POWER_CVT(*p
);
811 scale
= POWER_SCALE(*p
);
813 if (++p
== q
) return NULL
;
814 if ((*p
& 0x7f) < 100)
815 pwr
->param
[i
] += (*p
& 0x7f) * scale
/ 100;
817 pwr
->flags
|= CISTPL_POWER_HIGHZ_OK
;
821 pwr
->flags
|= CISTPL_POWER_HIGHZ_REQ
;
830 /*====================================================================*/
832 static u_char
*parse_timing(u_char
*p
, u_char
*q
,
833 cistpl_timing_t
*timing
)
837 if (p
== q
) return NULL
;
839 if ((scale
& 3) != 3) {
840 if (++p
== q
) return NULL
;
841 timing
->wait
= SPEED_CVT(*p
);
842 timing
->waitscale
= exponent
[scale
& 3];
846 if ((scale
& 7) != 7) {
847 if (++p
== q
) return NULL
;
848 timing
->ready
= SPEED_CVT(*p
);
849 timing
->rdyscale
= exponent
[scale
& 7];
854 if (++p
== q
) return NULL
;
855 timing
->reserved
= SPEED_CVT(*p
);
856 timing
->rsvscale
= exponent
[scale
];
858 timing
->reserved
= 0;
863 /*====================================================================*/
865 static u_char
*parse_io(u_char
*p
, u_char
*q
, cistpl_io_t
*io
)
869 if (p
== q
) return NULL
;
875 io
->win
[0].len
= (1 << (io
->flags
& CISTPL_IO_LINES_MASK
));
879 if (++p
== q
) return NULL
;
880 io
->nwin
= (*p
& 0x0f) + 1;
881 bsz
= (*p
& 0x30) >> 4;
883 lsz
= (*p
& 0xc0) >> 6;
887 for (i
= 0; i
< io
->nwin
; i
++) {
890 for (j
= 0; j
< bsz
; j
++, p
++) {
891 if (p
== q
) return NULL
;
892 io
->win
[i
].base
+= *p
<< (j
*8);
894 for (j
= 0; j
< lsz
; j
++, p
++) {
895 if (p
== q
) return NULL
;
896 io
->win
[i
].len
+= *p
<< (j
*8);
902 /*====================================================================*/
904 static u_char
*parse_mem(u_char
*p
, u_char
*q
, cistpl_mem_t
*mem
)
906 int i
, j
, asz
, lsz
, has_ha
;
909 if (p
== q
) return NULL
;
911 mem
->nwin
= (*p
& 0x07) + 1;
912 lsz
= (*p
& 0x18) >> 3;
913 asz
= (*p
& 0x60) >> 5;
914 has_ha
= (*p
& 0x80);
915 if (++p
== q
) return NULL
;
917 for (i
= 0; i
< mem
->nwin
; i
++) {
919 for (j
= 0; j
< lsz
; j
++, p
++) {
920 if (p
== q
) return NULL
;
923 for (j
= 0; j
< asz
; j
++, p
++) {
924 if (p
== q
) return NULL
;
928 for (j
= 0; j
< asz
; j
++, p
++) {
929 if (p
== q
) return NULL
;
932 mem
->win
[i
].len
= len
<< 8;
933 mem
->win
[i
].card_addr
= ca
<< 8;
934 mem
->win
[i
].host_addr
= ha
<< 8;
939 /*====================================================================*/
941 static u_char
*parse_irq(u_char
*p
, u_char
*q
, cistpl_irq_t
*irq
)
943 if (p
== q
) return NULL
;
944 irq
->IRQInfo1
= *p
; p
++;
945 if (irq
->IRQInfo1
& IRQ_INFO2_VALID
) {
946 if (p
+2 > q
) return NULL
;
947 irq
->IRQInfo2
= (p
[1]<<8) + p
[0];
953 /*====================================================================*/
955 static int parse_cftable_entry(tuple_t
*tuple
,
956 cistpl_cftable_entry_t
*entry
)
958 u_char
*p
, *q
, features
;
960 p
= tuple
->TupleData
;
961 q
= p
+ tuple
->TupleDataLen
;
962 entry
->index
= *p
& 0x3f;
965 entry
->flags
|= CISTPL_CFTABLE_DEFAULT
;
967 if (++p
== q
) return CS_BAD_TUPLE
;
969 entry
->flags
|= CISTPL_CFTABLE_BVDS
;
971 entry
->flags
|= CISTPL_CFTABLE_WP
;
973 entry
->flags
|= CISTPL_CFTABLE_RDYBSY
;
975 entry
->flags
|= CISTPL_CFTABLE_MWAIT
;
976 entry
->interface
= *p
& 0x0f;
978 entry
->interface
= 0;
980 /* Process optional features */
981 if (++p
== q
) return CS_BAD_TUPLE
;
985 if ((features
& 3) > 0) {
986 p
= parse_power(p
, q
, &entry
->vcc
);
987 if (p
== NULL
) return CS_BAD_TUPLE
;
989 entry
->vcc
.present
= 0;
990 if ((features
& 3) > 1) {
991 p
= parse_power(p
, q
, &entry
->vpp1
);
992 if (p
== NULL
) return CS_BAD_TUPLE
;
994 entry
->vpp1
.present
= 0;
995 if ((features
& 3) > 2) {
996 p
= parse_power(p
, q
, &entry
->vpp2
);
997 if (p
== NULL
) return CS_BAD_TUPLE
;
999 entry
->vpp2
.present
= 0;
1001 /* Timing options */
1002 if (features
& 0x04) {
1003 p
= parse_timing(p
, q
, &entry
->timing
);
1004 if (p
== NULL
) return CS_BAD_TUPLE
;
1006 entry
->timing
.wait
= 0;
1007 entry
->timing
.ready
= 0;
1008 entry
->timing
.reserved
= 0;
1011 /* I/O window options */
1012 if (features
& 0x08) {
1013 p
= parse_io(p
, q
, &entry
->io
);
1014 if (p
== NULL
) return CS_BAD_TUPLE
;
1018 /* Interrupt options */
1019 if (features
& 0x10) {
1020 p
= parse_irq(p
, q
, &entry
->irq
);
1021 if (p
== NULL
) return CS_BAD_TUPLE
;
1023 entry
->irq
.IRQInfo1
= 0;
1025 switch (features
& 0x60) {
1027 entry
->mem
.nwin
= 0;
1030 entry
->mem
.nwin
= 1;
1031 entry
->mem
.win
[0].len
= le16_to_cpu(*(u_short
*)p
) << 8;
1032 entry
->mem
.win
[0].card_addr
= 0;
1033 entry
->mem
.win
[0].host_addr
= 0;
1035 if (p
> q
) return CS_BAD_TUPLE
;
1038 entry
->mem
.nwin
= 1;
1039 entry
->mem
.win
[0].len
= le16_to_cpu(*(u_short
*)p
) << 8;
1040 entry
->mem
.win
[0].card_addr
=
1041 le16_to_cpu(*(u_short
*)(p
+2)) << 8;
1042 entry
->mem
.win
[0].host_addr
= 0;
1044 if (p
> q
) return CS_BAD_TUPLE
;
1047 p
= parse_mem(p
, q
, &entry
->mem
);
1048 if (p
== NULL
) return CS_BAD_TUPLE
;
1053 if (features
& 0x80) {
1054 if (p
== q
) return CS_BAD_TUPLE
;
1055 entry
->flags
|= (*p
<< 8);
1057 if (++p
== q
) return CS_BAD_TUPLE
;
1061 entry
->subtuples
= q
-p
;
1066 /*====================================================================*/
1068 #ifdef CONFIG_CARDBUS
1070 static int parse_bar(tuple_t
*tuple
, cistpl_bar_t
*bar
)
1073 if (tuple
->TupleDataLen
< 6)
1074 return CS_BAD_TUPLE
;
1075 p
= (u_char
*)tuple
->TupleData
;
1078 bar
->size
= le32_to_cpu(*(u_int
*)p
);
1082 static int parse_config_cb(tuple_t
*tuple
, cistpl_config_t
*config
)
1086 p
= (u_char
*)tuple
->TupleData
;
1087 if ((*p
!= 3) || (tuple
->TupleDataLen
< 6))
1088 return CS_BAD_TUPLE
;
1089 config
->last_idx
= *(++p
);
1091 config
->base
= le32_to_cpu(*(u_int
*)p
);
1092 config
->subtuples
= tuple
->TupleDataLen
- 6;
1096 static int parse_cftable_entry_cb(tuple_t
*tuple
,
1097 cistpl_cftable_entry_cb_t
*entry
)
1099 u_char
*p
, *q
, features
;
1101 p
= tuple
->TupleData
;
1102 q
= p
+ tuple
->TupleDataLen
;
1103 entry
->index
= *p
& 0x3f;
1106 entry
->flags
|= CISTPL_CFTABLE_DEFAULT
;
1108 /* Process optional features */
1109 if (++p
== q
) return CS_BAD_TUPLE
;
1113 if ((features
& 3) > 0) {
1114 p
= parse_power(p
, q
, &entry
->vcc
);
1115 if (p
== NULL
) return CS_BAD_TUPLE
;
1117 entry
->vcc
.present
= 0;
1118 if ((features
& 3) > 1) {
1119 p
= parse_power(p
, q
, &entry
->vpp1
);
1120 if (p
== NULL
) return CS_BAD_TUPLE
;
1122 entry
->vpp1
.present
= 0;
1123 if ((features
& 3) > 2) {
1124 p
= parse_power(p
, q
, &entry
->vpp2
);
1125 if (p
== NULL
) return CS_BAD_TUPLE
;
1127 entry
->vpp2
.present
= 0;
1129 /* I/O window options */
1130 if (features
& 0x08) {
1131 if (p
== q
) return CS_BAD_TUPLE
;
1132 entry
->io
= *p
; p
++;
1136 /* Interrupt options */
1137 if (features
& 0x10) {
1138 p
= parse_irq(p
, q
, &entry
->irq
);
1139 if (p
== NULL
) return CS_BAD_TUPLE
;
1141 entry
->irq
.IRQInfo1
= 0;
1143 if (features
& 0x20) {
1144 if (p
== q
) return CS_BAD_TUPLE
;
1145 entry
->mem
= *p
; p
++;
1150 if (features
& 0x80) {
1151 if (p
== q
) return CS_BAD_TUPLE
;
1152 entry
->flags
|= (*p
<< 8);
1154 if (++p
== q
) return CS_BAD_TUPLE
;
1155 entry
->flags
|= (*p
<< 16);
1158 if (++p
== q
) return CS_BAD_TUPLE
;
1162 entry
->subtuples
= q
-p
;
1169 /*====================================================================*/
1171 static int parse_device_geo(tuple_t
*tuple
, cistpl_device_geo_t
*geo
)
1176 p
= (u_char
*)tuple
->TupleData
;
1177 q
= p
+ tuple
->TupleDataLen
;
1179 for (n
= 0; n
< CISTPL_MAX_DEVICES
; n
++) {
1181 geo
->geo
[n
].buswidth
= p
[0];
1182 geo
->geo
[n
].erase_block
= 1 << (p
[1]-1);
1183 geo
->geo
[n
].read_block
= 1 << (p
[2]-1);
1184 geo
->geo
[n
].write_block
= 1 << (p
[3]-1);
1185 geo
->geo
[n
].partition
= 1 << (p
[4]-1);
1186 geo
->geo
[n
].interleave
= 1 << (p
[5]-1);
1193 /*====================================================================*/
1195 static int parse_vers_2(tuple_t
*tuple
, cistpl_vers_2_t
*v2
)
1199 if (tuple
->TupleDataLen
< 10)
1200 return CS_BAD_TUPLE
;
1202 p
= tuple
->TupleData
;
1203 q
= p
+ tuple
->TupleDataLen
;
1207 v2
->dindex
= le16_to_cpu(*(u_short
*)(p
+2));
1212 return parse_strings(p
, q
, 2, v2
->str
, &v2
->vendor
, NULL
);
1215 /*====================================================================*/
1217 static int parse_org(tuple_t
*tuple
, cistpl_org_t
*org
)
1222 p
= tuple
->TupleData
;
1223 q
= p
+ tuple
->TupleDataLen
;
1224 if (p
== q
) return CS_BAD_TUPLE
;
1226 if (++p
== q
) return CS_BAD_TUPLE
;
1227 for (i
= 0; i
< 30; i
++) {
1229 if (*p
== '\0') break;
1230 if (++p
== q
) return CS_BAD_TUPLE
;
1235 /*====================================================================*/
1237 int pcmcia_parse_tuple(client_handle_t handle
, tuple_t
*tuple
, cisparse_t
*parse
)
1239 int ret
= CS_SUCCESS
;
1241 if (tuple
->TupleDataLen
> tuple
->TupleDataMax
)
1242 return CS_BAD_TUPLE
;
1243 switch (tuple
->TupleCode
) {
1245 case CISTPL_DEVICE_A
:
1246 ret
= parse_device(tuple
, &parse
->device
);
1248 #ifdef CONFIG_CARDBUS
1250 ret
= parse_bar(tuple
, &parse
->bar
);
1252 case CISTPL_CONFIG_CB
:
1253 ret
= parse_config_cb(tuple
, &parse
->config
);
1255 case CISTPL_CFTABLE_ENTRY_CB
:
1256 ret
= parse_cftable_entry_cb(tuple
, &parse
->cftable_entry_cb
);
1259 case CISTPL_CHECKSUM
:
1260 ret
= parse_checksum(tuple
, &parse
->checksum
);
1262 case CISTPL_LONGLINK_A
:
1263 case CISTPL_LONGLINK_C
:
1264 ret
= parse_longlink(tuple
, &parse
->longlink
);
1266 case CISTPL_LONGLINK_MFC
:
1267 ret
= parse_longlink_mfc(tuple
, &parse
->longlink_mfc
);
1270 ret
= parse_vers_1(tuple
, &parse
->version_1
);
1273 ret
= parse_altstr(tuple
, &parse
->altstr
);
1275 case CISTPL_JEDEC_A
:
1276 case CISTPL_JEDEC_C
:
1277 ret
= parse_jedec(tuple
, &parse
->jedec
);
1280 ret
= parse_manfid(tuple
, &parse
->manfid
);
1283 ret
= parse_funcid(tuple
, &parse
->funcid
);
1286 ret
= parse_funce(tuple
, &parse
->funce
);
1289 ret
= parse_config(tuple
, &parse
->config
);
1291 case CISTPL_CFTABLE_ENTRY
:
1292 ret
= parse_cftable_entry(tuple
, &parse
->cftable_entry
);
1294 case CISTPL_DEVICE_GEO
:
1295 case CISTPL_DEVICE_GEO_A
:
1296 ret
= parse_device_geo(tuple
, &parse
->device_geo
);
1299 ret
= parse_vers_2(tuple
, &parse
->vers_2
);
1302 ret
= parse_org(tuple
, &parse
->org
);
1304 case CISTPL_NO_LINK
:
1305 case CISTPL_LINKTARGET
:
1309 ret
= CS_UNSUPPORTED_FUNCTION
;
1315 /*======================================================================
1317 This is used internally by Card Services to look up CIS stuff.
1319 ======================================================================*/
1321 int read_tuple(client_handle_t handle
, cisdata_t code
, void *parse
)
1327 tuple
.DesiredTuple
= code
;
1328 tuple
.Attributes
= TUPLE_RETURN_COMMON
;
1329 ret
= pcmcia_get_first_tuple(handle
, &tuple
);
1330 if (ret
!= CS_SUCCESS
) return ret
;
1331 tuple
.TupleData
= buf
;
1332 tuple
.TupleOffset
= 0;
1333 tuple
.TupleDataMax
= sizeof(buf
);
1334 ret
= pcmcia_get_tuple_data(handle
, &tuple
);
1335 if (ret
!= CS_SUCCESS
) return ret
;
1336 ret
= pcmcia_parse_tuple(handle
, &tuple
, parse
);
1340 /*======================================================================
1342 This tries to determine if a card has a sensible CIS. It returns
1343 the number of tuples in the CIS, or 0 if the CIS looks bad. The
1344 checks include making sure several critical tuples are present and
1345 valid; seeing if the total number of tuples is reasonable; and
1346 looking for tuples that use reserved codes.
1348 ======================================================================*/
1350 int pcmcia_validate_cis(client_handle_t handle
, cisinfo_t
*info
)
1354 int ret
, reserved
, errors
;
1356 if (CHECK_HANDLE(handle
))
1357 return CS_BAD_HANDLE
;
1359 info
->Chains
= reserved
= errors
= 0;
1360 tuple
.DesiredTuple
= RETURN_FIRST_TUPLE
;
1361 tuple
.Attributes
= TUPLE_RETURN_COMMON
;
1362 ret
= pcmcia_get_first_tuple(handle
, &tuple
);
1363 if (ret
!= CS_SUCCESS
)
1366 /* First tuple should be DEVICE */
1367 if (tuple
.TupleCode
!= CISTPL_DEVICE
)
1369 /* All cards should have a MANFID tuple */
1370 if (read_tuple(handle
, CISTPL_MANFID
, &p
) != CS_SUCCESS
)
1372 /* All cards should have either a VERS_1 or a VERS_2 tuple. But
1373 at worst, we'll accept a CFTABLE_ENTRY that parses. */
1374 if ((read_tuple(handle
, CISTPL_VERS_1
, &p
) != CS_SUCCESS
) &&
1375 (read_tuple(handle
, CISTPL_VERS_2
, &p
) != CS_SUCCESS
) &&
1376 (read_tuple(handle
, CISTPL_CFTABLE_ENTRY
, &p
) != CS_SUCCESS
) &&
1377 (read_tuple(handle
, CISTPL_CFTABLE_ENTRY_CB
, &p
) != CS_SUCCESS
))
1382 for (info
->Chains
= 1; info
->Chains
< MAX_TUPLES
; info
->Chains
++) {
1383 ret
= pcmcia_get_next_tuple(handle
, &tuple
);
1384 if (ret
!= CS_SUCCESS
) break;
1385 if (((tuple
.TupleCode
> 0x23) && (tuple
.TupleCode
< 0x40)) ||
1386 ((tuple
.TupleCode
> 0x47) && (tuple
.TupleCode
< 0x80)) ||
1387 ((tuple
.TupleCode
> 0x90) && (tuple
.TupleCode
< 0xff)))
1390 if ((info
->Chains
== MAX_TUPLES
) || (reserved
> 5))