Bug Summary

File:obj-scan-build/../linux/pcmcia-cs/modules/cistpl.c
Location:line 143, column 2
Description:The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage

Annotated Source Code

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 <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 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
60static const u_char mantissa[] = {
61 10, 12, 13, 15, 20, 25, 30, 35,
62 40, 45, 50, 55, 60, 70, 80, 90
63};
64
65static 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)(mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10
)
\
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)(mantissa[((v)>>3)&15] * exponent[(v)&7] / 10) \
74 (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
75#define POWER_SCALE(v)(exponent[(v)&7]) (exponent[(v)&7])
76
77/* Upper limit on reasonable # of tuples */
78#define MAX_TUPLES200 200
79
80/*====================================================================*/
81
82/* Parameters that can be set with 'insmod' */
83
84#define INT_MODULE_PARM(n, v)static int n = v; static int n = v; MODULE_PARM(n, "i")
85
86INT_MODULE_PARM(cis_width, 0)static int 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_ATTR1 1
97#define IS_INDIRECT8 8
98
99static int setup_cis_mem(socket_info_t *s);
100
101static 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_MAP0x0008) {
105 if (s->cis_virt)
106 bus_iounmap(s->cap.bus, s->cis_virt)(((long)s->cis_virt<0x100000)?0:vfree ((void*)s->cis_virt
))
;
107 s->cis_virt = bus_ioremap(s->cap.bus, mem->sys_start,ioremap(mem->sys_start,s->cap.map_size)
108 s->cap.map_size)ioremap(mem->sys_start,s->cap.map_size);
109 }
110}
111
112int 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;
5
Variable 'sys' declared without an initial value
117
118 DEBUG(3, "cs: read_cis_mem(%d, %#x, %u)\n", attr, addr, len)do { if (pc_debug>(3)) printk("<7>" "cs: read_cis_mem(%d, %#x, %u)\n"
, attr, addr, len); } while (0)
;
119 if (setup_cis_mem(s) != 0) {
6
Taking false branch
120 memset(ptr, 0xff, len)(__builtin_constant_p(0xff) ? (__builtin_constant_p((len)) ? __constant_c_and_count_memset
(((ptr)),((0x01010101UL*(unsigned char)(0xff))),((len))) : __constant_c_memset
(((ptr)),((0x01010101UL*(unsigned char)(0xff))),((len)))) : (
__builtin_constant_p((len)) ? __memset_generic((((ptr))),(((0xff
))),(((len)))) : __memset_generic(((ptr)),((0xff)),((len)))))
;
121 return -1;
122 }
123 mem->flags = MAP_ACTIVE0x01 | ((cis_width) ? MAP_16BIT0x02 : 0);
7
Assuming 'cis_width' is 0
8
'?' condition is false
124
125 if (attr & IS_INDIRECT8) {
9
Taking false branch
126 /* Indirect accesses use a bunch of special registers at fixed
127 locations in common memory */
128 u_char flags = ICTRL0_COMMON0x01|ICTRL0_AUTOINC0x02|ICTRL0_BYTEGRAN0x04;
129 if (attr & IS_ATTR1) { addr *= 2; flags = ICTRL0_AUTOINC0x02; }
130 mem->card_start = 0; mem->flags = MAP_ACTIVE0x01;
131 set_cis_map(s, mem);
132 sys = s->cis_virt;
133 bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0)((*(volatile unsigned char *) (sys+0x02)) = (flags));
134 bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0)((*(volatile unsigned char *) (sys+0x04)) = (addr & 0xff)
)
;
135 bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1)((*(volatile unsigned char *) (sys+0x05)) = ((addr>>8) &
0xff))
;
136 bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2)((*(volatile unsigned char *) (sys+0x06)) = ((addr>>16)
& 0xff))
;
137 bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3)((*(volatile unsigned char *) (sys+0x07)) = ((addr>>24)
& 0xff))
;
138 for ( ; len > 0; len--, buf++)
139 *buf = bus_readb(s->cap.bus, sys+CISREG_IDATA0)(*(volatile unsigned char *) (sys+0x08));
140 } else {
141 u_int inc = 1;
142 if (attr) { mem->flags |= MAP_ATTRIB0x20; inc++; addr *= 2; }
10
Assuming 'attr' is 0
11
Taking false branch
143 sys += (addr & (s->cap.map_size-1));
12
The left expression of the compound assignment is an uninitialized value. The computed value will also be garbage
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)(*(volatile unsigned char *) (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",do { if (pc_debug>(3)) printk("<7>" "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n"
, *(u_char *)(ptr+0), *(u_char *)(ptr+1), *(u_char *)(ptr+2),
*(u_char *)(ptr+3)); } while (0)
157 *(u_char *)(ptr+0), *(u_char *)(ptr+1),do { if (pc_debug>(3)) printk("<7>" "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n"
, *(u_char *)(ptr+0), *(u_char *)(ptr+1), *(u_char *)(ptr+2),
*(u_char *)(ptr+3)); } while (0)
158 *(u_char *)(ptr+2), *(u_char *)(ptr+3))do { if (pc_debug>(3)) printk("<7>" "cs: %#2.2x %#2.2x %#2.2x %#2.2x ...\n"
, *(u_char *)(ptr+0), *(u_char *)(ptr+1), *(u_char *)(ptr+2),
*(u_char *)(ptr+3)); } while (0)
;
159 return 0;
160}
161
162void 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)do { if (pc_debug>(3)) printk("<7>" "cs: write_cis_mem(%d, %#x, %u)\n"
, attr, addr, len); } while (0)
;
169 if (setup_cis_mem(s) != 0) return;
170 mem->flags = MAP_ACTIVE0x01 | ((cis_width) ? MAP_16BIT0x02 : 0);
171
172 if (attr & IS_INDIRECT8) {
173 /* Indirect accesses use a bunch of special registers at fixed
174 locations in common memory */
175 u_char flags = ICTRL0_COMMON0x01|ICTRL0_AUTOINC0x02|ICTRL0_BYTEGRAN0x04;
176 if (attr & IS_ATTR1) { addr *= 2; flags = ICTRL0_AUTOINC0x02; }
177 mem->card_start = 0; mem->flags = MAP_ACTIVE0x01;
178 set_cis_map(s, mem);
179 sys = s->cis_virt;
180 bus_writeb(s->cap.bus, flags, sys+CISREG_ICTRL0)((*(volatile unsigned char *) (sys+0x02)) = (flags));
181 bus_writeb(s->cap.bus, addr & 0xff, sys+CISREG_IADDR0)((*(volatile unsigned char *) (sys+0x04)) = (addr & 0xff)
)
;
182 bus_writeb(s->cap.bus, (addr>>8) & 0xff, sys+CISREG_IADDR1)((*(volatile unsigned char *) (sys+0x05)) = ((addr>>8) &
0xff))
;
183 bus_writeb(s->cap.bus, (addr>>16) & 0xff, sys+CISREG_IADDR2)((*(volatile unsigned char *) (sys+0x06)) = ((addr>>16)
& 0xff))
;
184 bus_writeb(s->cap.bus, (addr>>24) & 0xff, sys+CISREG_IADDR3)((*(volatile unsigned char *) (sys+0x07)) = ((addr>>24)
& 0xff))
;
185 for ( ; len > 0; len--, buf++)
186 bus_writeb(s->cap.bus, *buf, sys+CISREG_IDATA0)((*(volatile unsigned char *) (sys+0x08)) = (*buf));
187 } else {
188 int inc = 1;
189 if (attr & IS_ATTR1) { mem->flags |= MAP_ATTRIB0x20; 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)((*(volatile unsigned char *) (sys)) = (*buf));
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 */
212static socket_info_t *vs = NULL((void *) 0);
213
214/* Validation function for cards with a valid CIS */
215static 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)ioremap(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)(((long)vs->cis_virt<0x100000)?0:vfree ((void*)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,ioremap(base+vs->cap.map_size,vs->cap.map_size)
230 vs->cap.map_size)ioremap(base+vs->cap.map_size,vs->cap.map_size);
231 ret = validate_cis(vs->clients, &info2);
232 bus_iounmap(vs->cap.bus, vs->cis_virt)(((long)vs->cis_virt<0x100000)?0:vfree ((void*)vs->cis_virt
))
; vs->cis_used = 0;
233 return ((ret == 0) && (info1.Chains == info2.Chains));
234}
235
236/* Validation function for simple memory cards */
237static 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)ioremap(base,vs->cap.map_size);
243 vs->cis_mem.card_start = 0;
244 vs->cis_mem.flags = MAP_ACTIVE0x01;
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)(*(volatile unsigned int *) (vs->cis_virt+i));
250 a += d; b &= d;
251 }
252 bus_iounmap(vs->cap.bus, vs->cis_virt)(((long)vs->cis_virt<0x100000)?0:vfree ((void*)vs->cis_virt
))
;
253 return (b == -1) ? -1 : (a>>1);
254}
255
256static 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
262static int setup_cis_mem(socket_info_t *s)
263{
264 if (!(s->cap.features & SS_CAP_STATIC_MAP0x0008) &&
265 (s->cis_mem.sys_start == 0)) {
266 int low = !(s->cap.features & SS_CAP_PAGE_REGS0x0001);
267 vs = s;
268 validate_mem(cis_readable, checksum_match, low);
269 s->cis_mem.sys_start = 0;
270 vs = NULL((void *) 0);
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"<5>" "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,ioremap(s->cis_mem.sys_start,s->cap.map_size)
278 s->cap.map_size)ioremap(s->cis_mem.sys_start,s->cap.map_size);
279 }
280 return 0;
281}
282
283void release_cis_mem(socket_info_t *s)
284{
285 if (s->cis_mem.sys_start != 0) {
286 s->cis_mem.flags &= ~MAP_ACTIVE0x01;
287 s->ss_entry(s->sock, SS_SetMemMap, &s->cis_mem);
288 if (!(s->cap.features & SS_CAP_STATIC_MAP0x0008))
289 release_mem_region(s->cis_mem.sys_start, s->cap.map_size);
290 bus_iounmap(s->cap.bus, s->cis_virt)(((long)s->cis_virt<0x100000)?0:vfree ((void*)s->cis_virt
))
;
291 s->cis_mem.sys_start = 0;
292 s->cis_virt = NULL((void *) 0);
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
304static 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)(__builtin_constant_p(len) ? __constant_memcpy((ptr),(s->fake_cis
+addr),(len)) : __memcpy((ptr),(s->fake_cis+addr),(len)))
;
313 else
314 memset(ptr, 0xff, len)(__builtin_constant_p(0xff) ? (__builtin_constant_p((len)) ? __constant_c_and_count_memset
(((ptr)),((0x01010101UL*(unsigned char)(0xff))),((len))) : __constant_c_memset
(((ptr)),((0x01010101UL*(unsigned char)(0xff))),((len)))) : (
__builtin_constant_p((len)) ? __memset_generic((((ptr))),(((0xff
))),(((len)))) : __memset_generic(((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)(__builtin_constant_p(len) ? __constant_memcpy((ptr),(caddr),
(len)) : __memcpy((ptr),(caddr),(len)))
;
326 return;
327 }
328#ifdef CONFIG_CARDBUS
329 if (s->state & SOCKET_CARDBUS0x8000)
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_TABLE64) &&
336 (caddr+len < s->cis_cache+MAX_CIS_DATA512)) {
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)(__builtin_constant_p(len) ? __constant_memcpy((caddr),(ptr),
(len)) : __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
352int verify_cis_cache(socket_info_t *s)
353{
354 char *buf, *caddr;
355 int i;
356
357 buf = kmalloclinux_kmalloc(256, GFP_KERNEL0x03);
358 if (buf == NULL((void *) 0))
1
Assuming 'buf' is not equal to null
2
Taking false branch
359 return -1;
360 caddr = s->cis_cache;
361 for (i = 0; i < s->cis_used; i++) {
3
Loop condition is true. Entering loop body
362#ifdef CONFIG_CARDBUS
363 if (s->state & SOCKET_CARDBUS0x8000)
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,
4
Calling 'read_cis_mem'
369 s->cis_table[i].len, buf);
370 if (memcmp__builtin_memcmp(buf, caddr, s->cis_table[i].len) != 0)
371 break;
372 caddr += s->cis_table[i].len;
373 }
374 kfreelinux_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
385int replace_cis(client_handle_t handle, cisdump_t *cis)
386{
387 socket_info_t *s;
388 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
389 return CS_BAD_HANDLE0x21;
390 s = SOCKET(handle)(socket_table[(handle)->Socket]);
391 if (s->fake_cis != NULL((void *) 0)) {
392 kfreelinux_kfree(s->fake_cis);
393 s->fake_cis = NULL((void *) 0);
394 }
395 if (cis->Length > CISTPL_MAX_CIS_SIZE0x200)
396 return CS_BAD_SIZE0x0a;
397 s->fake_cis = kmalloclinux_kmalloc(cis->Length, GFP_KERNEL0x03);
398 if (s->fake_cis == NULL((void *) 0))
399 return CS_OUT_OF_RESOURCE0x20;
400 s->fake_cis_len = cis->Length;
401 memcpy(s->fake_cis, cis->Data, cis->Length)(__builtin_constant_p(cis->Length) ? __constant_memcpy((s->
fake_cis),(cis->Data),(cis->Length)) : __memcpy((s->
fake_cis),(cis->Data),(cis->Length)))
;
402 return CS_SUCCESS0x00;
403}
404
405/*======================================================================
406
407 The high-level CIS tuple services
408
409======================================================================*/
410
411typedef 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) (((tuple_flags *)(&(f)))->link_space)
419#define HAS_LINK(f)(((tuple_flags *)(&(f)))->has_link) (((tuple_flags *)(&(f)))->has_link)
420#define MFC_FN(f)(((tuple_flags *)(&(f)))->mfc_fn) (((tuple_flags *)(&(f)))->mfc_fn)
421#define SPACE(f)(((tuple_flags *)(&(f)))->space) (((tuple_flags *)(&(f)))->space)
422
423int get_next_tuple(client_handle_t handle, tuple_t *tuple);
424
425int get_first_tuple(client_handle_t handle, tuple_t *tuple)
426{
427 socket_info_t *s;
428 if (CHECK_HANDLE(handle)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
429 return CS_BAD_HANDLE0x21;
430 s = SOCKET(handle)(socket_table[(handle)->Socket]);
431 if (!(s->state & SOCKET_PRESENT0x0008))
432 return CS_NO_CARD0x14;
433 tuple->TupleLink = tuple->Flags = 0;
434#ifdef CONFIG_CARDBUS
435 if (s->state & SOCKET_CARDBUS0x8000) {
436 u_int ptr;
437 pcibios_read_config_dword(s->cap.cardbus, 0, 0x28, &ptr);
438 tuple->CISOffset = ptr & ~7;
439 SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space) = (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)(((tuple_flags *)(&(tuple->Flags)))->space) = HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link) = 1;
446 }
447 if (!(s->state & SOCKET_CARDBUS0x8000) && (s->functions > 1) &&
448 !(tuple->Attributes & TUPLE_RETURN_COMMON0x02)) {
449 cisdata_t req = tuple->DesiredTuple;
450 tuple->DesiredTuple = CISTPL_LONGLINK_MFC0x06;
451 if (get_next_tuple(handle, tuple) == CS_SUCCESS0x00) {
452 tuple->DesiredTuple = CISTPL_LINKTARGET0x13;
453 if (get_next_tuple(handle, tuple) != CS_SUCCESS0x00)
454 return CS_NO_MORE_ITEMS0x1f;
455 } else
456 tuple->CISOffset = tuple->TupleLink = 0;
457 tuple->DesiredTuple = req;
458 }
459 return get_next_tuple(handle, tuple);
460}
461
462static 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)(((tuple_flags *)(&(tuple->Flags)))->mfc_fn)) {
468 /* Get indirect link from the MFC tuple */
469 read_cis_cache(s, LINK_SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->link_space),
470 tuple->LinkOffset, 5, link);
471 ofs = le32_to_cpu(*(u_int *)(link+1))(*(u_int *)(link+1));
472 SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space) = (link[0] == CISTPL_MFC_ATTR0x00);
473 /* Move to the next indirect link */
474 tuple->LinkOffset += 5;
475 MFC_FN(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->mfc_fn)--;
476 } else if (HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link)) {
477 ofs = tuple->LinkOffset;
478 SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space) = LINK_SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->link_space);
479 HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link) = 0;
480 } else {
481 return -1;
482 }
483 if (!(s->state & SOCKET_CARDBUS0x8000) && SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space)) {
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)(((tuple_flags *)(&(tuple->Flags)))->space), ofs, 5, link);
487 if ((link[0] == CISTPL_LINKTARGET0x13) && (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)(((tuple_flags *)(&(tuple->Flags)))->space), ofs, 5, link);
494 if ((link[0] != CISTPL_LINKTARGET0x13) || (link[1] < 3) ||
495 (strncmp(link+2, "CIS", 3) != 0))
496 return -1;
497 return ofs;
498}
499
500int 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
507 return CS_BAD_HANDLE0x21;
508 s = SOCKET(handle)(socket_table[(handle)->Socket]);
509 if (!(s->state & SOCKET_PRESENT0x0008))
510 return CS_NO_CARD0x14;
511
512 link[1] = tuple->TupleLink;
513 ofs = tuple->CISOffset + tuple->TupleLink;
514 attr = SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space);
515
516 for (i = 0; i < MAX_TUPLES200; i++) {
517 if (link[1] == 0xff) {
518 link[0] = CISTPL_END0xff;
519 } else {
520 read_cis_cache(s, attr, ofs, 2, link);
521 if (link[0] == CISTPL_NULL0x00) {
522 ofs++; continue;
523 }
524 }
525
526 /* End of chain? Follow long link if possible */
527 if (link[0] == CISTPL_END0xff) {
528 if ((ofs = follow_link(s, tuple)) < 0)
529 return CS_NO_MORE_ITEMS0x1f;
530 attr = SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space);
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_A0x11) ||
536 (link[0] == CISTPL_LONGLINK_C0x12) ||
537 (link[0] == CISTPL_LONGLINK_MFC0x06) ||
538 (link[0] == CISTPL_LINKTARGET0x13) ||
539 (link[0] == CISTPL_INDIRECT0x03) ||
540 (link[0] == CISTPL_NO_LINK0x14)) {
541 switch (link[0]) {
542 case CISTPL_LONGLINK_A0x11:
543 HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link) = 1;
544 LINK_SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->link_space) = attr | IS_ATTR1;
545 read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
546 break;
547 case CISTPL_LONGLINK_C0x12:
548 HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link) = 1;
549 LINK_SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->link_space) = attr & ~IS_ATTR1;
550 read_cis_cache(s, attr, ofs+2, 4, &tuple->LinkOffset);
551 break;
552 case CISTPL_INDIRECT0x03:
553 HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link) = 1;
554 LINK_SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->link_space) = IS_ATTR1 | IS_INDIRECT8;
555 tuple->LinkOffset = 0;
556 break;
557 case CISTPL_LONGLINK_MFC0x06:
558 tuple->LinkOffset = ofs + 3;
559 LINK_SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->link_space) = attr;
560 if (handle->Function == BIND_FN_ALL0xff) {
561 /* Follow all the MFC links */
562 read_cis_cache(s, attr, ofs+2, 1, &tmp);
563 MFC_FN(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->mfc_fn) = tmp;
564 } else {
565 /* Follow exactly one of the links */
566 MFC_FN(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->mfc_fn) = 1;
567 tuple->LinkOffset += handle->Function * 5;
568 }
569 break;
570 case CISTPL_NO_LINK0x14:
571 HAS_LINK(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->has_link) = 0;
572 break;
573 }
574 if ((tuple->Attributes & TUPLE_RETURN_LINK0x01) &&
575 (tuple->DesiredTuple == RETURN_FIRST_TUPLE0xff))
576 break;
577 } else
578 if (tuple->DesiredTuple == RETURN_FIRST_TUPLE0xff)
579 break;
580
581 if (link[0] == tuple->DesiredTuple)
582 break;
583 ofs += link[1] + 2;
584 }
585 if (i == MAX_TUPLES200) {
586 DEBUG(1, "cs: overrun in get_next_tuple for socket %d\n",do { if (pc_debug>(1)) printk("<7>" "cs: overrun in get_next_tuple for socket %d\n"
, handle->Socket); } while (0)
587 handle->Socket)do { if (pc_debug>(1)) printk("<7>" "cs: overrun in get_next_tuple for socket %d\n"
, handle->Socket); } while (0)
;
588 return CS_NO_MORE_ITEMS0x1f;
589 }
590
591 tuple->TupleCode = link[0];
592 tuple->TupleLink = link[1];
593 tuple->CISOffset = ofs + 2;
594 return CS_SUCCESS0x00;
595}
596
597/*====================================================================*/
598
599#define _MIN(a, b)(((a) < (b)) ? (a) : (b)) (((a) < (b)) ? (a) : (b))
600
601int 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
607 return CS_BAD_HANDLE0x21;
608
609 s = SOCKET(handle)(socket_table[(handle)->Socket]);
610
611 if (tuple->TupleLink < tuple->TupleOffset)
612 return CS_NO_MORE_ITEMS0x1f;
613 len = tuple->TupleLink - tuple->TupleOffset;
614 tuple->TupleDataLen = tuple->TupleLink;
615 if (len == 0)
616 return CS_SUCCESS0x00;
617 read_cis_cache(s, SPACE(tuple->Flags)(((tuple_flags *)(&(tuple->Flags)))->space),
618 tuple->CISOffset + tuple->TupleOffset,
619 _MIN(len, tuple->TupleDataMax)(((len) < (tuple->TupleDataMax)) ? (len) : (tuple->TupleDataMax
))
, tuple->TupleData);
620 return CS_SUCCESS0x00;
621}
622
623/*======================================================================
624
625 Parsing routines for individual tuples
626
627======================================================================*/
628
629static 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_DEVICES4; 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_TUPLE0x40;
652 device->dev[i].speed = SPEED_CVT(*p)(mantissa[(((*p)>>3)&15)-1] * exponent[(*p)&7] /
10)
;
653 while (*p & 0x80)
654 if (++p == q) return CS_BAD_TUPLE0x40;
655 break;
656 default:
657 return CS_BAD_TUPLE0x40;
658 }
659
660 if (++p == q) return CS_BAD_TUPLE0x40;
661 if (*p == 0xff) break;
662 scale = *p & 7;
663 if (scale == 7) return CS_BAD_TUPLE0x40;
664 device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
665 device->ndev++;
666 if (++p == q) break;
667 }
668
669 return CS_SUCCESS0x00;
670}
671
672/*====================================================================*/
673
674static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
675{
676 u_char *p;
677 if (tuple->TupleDataLen < 5)
678 return CS_BAD_TUPLE0x40;
679 p = (u_char *)tuple->TupleData;
680 csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)(*(u_short *)p)-2;
681 csum->len = le16_to_cpu(*(u_short *)(p + 2))(*(u_short *)(p + 2));
682 csum->sum = *(p+4);
683 return CS_SUCCESS0x00;
684}
685
686/*====================================================================*/
687
688static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
689{
690 if (tuple->TupleDataLen < 4)
691 return CS_BAD_TUPLE0x40;
692 link->addr = le32_to_cpu(*(u_int *)tuple->TupleData)(*(u_int *)tuple->TupleData);
693 return CS_SUCCESS0x00;
694}
695
696/*====================================================================*/
697
698static 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_TUPLE0x40;
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)(*(u_int *)p); p += 4;
712 }
713 return CS_SUCCESS0x00;
714}
715
716/*====================================================================*/
717
718static 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_TUPLE0x40;
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_TUPLE0x40;
733 }
734 if ((*p == 0xff) || (++p == q)) break;
735 }
736 if (found) {
737 *found = ns;
738 return CS_SUCCESS0x00;
739 } else {
740 return (ns == max) ? CS_SUCCESS0x00 : CS_BAD_TUPLE0x40;
741 }
742}
743
744/*====================================================================*/
745
746static 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_TUPLE0x40;
756
757 return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS4,
758 vers_1->str, vers_1->ofs, &vers_1->ns);
759}
760
761/*====================================================================*/
762
763static 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_STRINGS4,
771 altstr->str, altstr->ofs, &altstr->ns);
772}
773
774/*====================================================================*/
775
776static 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_DEVICES4; 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_SUCCESS0x00;
792}
793
794/*====================================================================*/
795
796static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
797{
798 u_short *p;
799 if (tuple->TupleDataLen < 4)
800 return CS_BAD_TUPLE0x40;
801 p = (u_short *)tuple->TupleData;
802 m->manf = le16_to_cpu(p[0])(p[0]);
803 m->card = le16_to_cpu(p[1])(p[1]);
804 return CS_SUCCESS0x00;
805}
806
807/*====================================================================*/
808
809static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
810{
811 u_char *p;
812 if (tuple->TupleDataLen < 2)
813 return CS_BAD_TUPLE0x40;
814 p = (u_char *)tuple->TupleData;
815 f->func = p[0];
816 f->sysinit = p[1];
817 return CS_SUCCESS0x00;
818}
819
820/*====================================================================*/
821
822static 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_TUPLE0x40;
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_SUCCESS0x00;
833}
834
835/*====================================================================*/
836
837static 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_TUPLE0x40;
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_SUCCESS0x00;
859}
860
861/*======================================================================
862
863 The following routines are all used to parse the nightmarish
864 config table entries.
865
866======================================================================*/
867
868static 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((void *) 0);
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((void *) 0);
881 pwr->param[i] = POWER_CVT(*p)(mantissa[((*p)>>3)&15] * exponent[(*p)&7] / 10
)
;
882 scale = POWER_SCALE(*p)(exponent[(*p)&7]);
883 while (*p & 0x80) {
884 if (++p == q) return NULL((void *) 0);
885 if ((*p & 0x7f) < 100)
886 pwr->param[i] += (*p & 0x7f) * scale / 100;
887 else if (*p == 0x7d)
888 pwr->flags |= CISTPL_POWER_HIGHZ_OK0x01;
889 else if (*p == 0x7e)
890 pwr->param[i] = 0;
891 else if (*p == 0x7f)
892 pwr->flags |= CISTPL_POWER_HIGHZ_REQ0x02;
893 else
894 return NULL((void *) 0);
895 }
896 p++;
897 }
898 return p;
899}
900
901/*====================================================================*/
902
903static 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((void *) 0);
909 scale = *p;
910 if ((scale & 3) != 3) {
911 if (++p == q) return NULL((void *) 0);
912 timing->wait = SPEED_CVT(*p)(mantissa[(((*p)>>3)&15)-1] * exponent[(*p)&7] /
10)
;
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((void *) 0);
919 timing->ready = SPEED_CVT(*p)(mantissa[(((*p)>>3)&15)-1] * exponent[(*p)&7] /
10)
;
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((void *) 0);
926 timing->reserved = SPEED_CVT(*p)(mantissa[(((*p)>>3)&15)-1] * exponent[(*p)&7] /
10)
;
927 timing->rsvscale = exponent[scale];
928 } else
929 timing->reserved = 0;
930 p++;
931 return p;
932}
933
934/*====================================================================*/
935
936static 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((void *) 0);
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_MASK0x1f));
947 return p+1;
948 }
949
950 if (++p == q) return NULL((void *) 0);
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((void *) 0);
963 io->win[i].base += *p << (j*8);
964 }
965 for (j = 0; j < lsz; j++, p++) {
966 if (p == q) return NULL((void *) 0);
967 io->win[i].len += *p << (j*8);
968 }
969 }
970 return p;
971}
972
973/*====================================================================*/
974
975static 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((void *) 0);
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((void *) 0);
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((void *) 0);
992 len += *p << (j*8);
993 }
994 for (j = 0; j < asz; j++, p++) {
995 if (p == q) return NULL((void *) 0);
996 ca += *p << (j*8);
997 }
998 if (has_ha)
999 for (j = 0; j < asz; j++, p++) {
1000 if (p == q) return NULL((void *) 0);
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
1012static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
1013{
1014 if (p == q) return NULL((void *) 0);
1015 irq->IRQInfo1 = *p; p++;
1016 if (irq->IRQInfo1 & IRQ_INFO2_VALID0x10) {
1017 if (p+2 > q) return NULL((void *) 0);
1018 irq->IRQInfo2 = (p[1]<<8) + p[0];
1019 p += 2;
1020 }
1021 return p;
1022}
1023
1024/*====================================================================*/
1025
1026static 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_DEFAULT0x0001;
1037 if (*p & 0x80) {
1038 if (++p == q) return CS_BAD_TUPLE0x40;
1039 if (*p & 0x10)
1040 entry->flags |= CISTPL_CFTABLE_BVDS0x0002;
1041 if (*p & 0x20)
1042 entry->flags |= CISTPL_CFTABLE_WP0x0004;
1043 if (*p & 0x40)
1044 entry->flags |= CISTPL_CFTABLE_RDYBSY0x0008;
1045 if (*p & 0x80)
1046 entry->flags |= CISTPL_CFTABLE_MWAIT0x0010;
1047 entry->interface = *p & 0x0f;
1048 } else
1049 entry->interface = 0;
1050
1051 /* Process optional features */
1052 if (++p == q) return CS_BAD_TUPLE0x40;
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((void *) 0)) return CS_BAD_TUPLE0x40;
1059 } else
1060 entry->vcc.present = 0;
1061 if ((features & 3) > 1) {
1062 p = parse_power(p, q, &entry->vpp1);
1063 if (p == NULL((void *) 0)) return CS_BAD_TUPLE0x40;
1064 } else
1065 entry->vpp1.present = 0;
1066 if ((features & 3) > 2) {
1067 p = parse_power(p, q, &entry->vpp2);
1068 if (p == NULL((void *) 0)) return CS_BAD_TUPLE0x40;
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((void *) 0)) return CS_BAD_TUPLE0x40;
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((void *) 0)) return CS_BAD_TUPLE0x40;
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((void *) 0)) return CS_BAD_TUPLE0x40;
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)(*(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_TUPLE0x40;
1107 break;
1108 case 0x40:
1109 entry->mem.nwin = 1;
1110 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p)(*(u_short *)p) << 8;
1111 entry->mem.win[0].card_addr =
1112 le16_to_cpu(*(u_short *)(p+2))(*(u_short *)(p+2)) << 8;
1113 entry->mem.win[0].host_addr = 0;
1114 p += 4;
1115 if (p > q) return CS_BAD_TUPLE0x40;
1116 break;
1117 case 0x60:
1118 p = parse_mem(p, q, &entry->mem);
1119 if (p == NULL((void *) 0)) return CS_BAD_TUPLE0x40;
1120 break;
1121 }
1122
1123 /* Misc features */
1124 if (features & 0x80) {
1125 if (p == q) return CS_BAD_TUPLE0x40;
1126 entry->flags |= (*p << 8);
1127 while (*p & 0x80)
1128 if (++p == q) return CS_BAD_TUPLE0x40;
1129 p++;
1130 }
1131
1132 entry->subtuples = q-p;
1133
1134 return CS_SUCCESS0x00;
1135}
1136
1137/*====================================================================*/
1138
1139#ifdef CONFIG_CARDBUS
1140
1141static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
1142{
1143 u_char *p;
1144 if (tuple->TupleDataLen < 6)
1145 return CS_BAD_TUPLE0x40;
1146 p = (u_char *)tuple->TupleData;
1147 bar->attr = *p;
1148 p += 2;
1149 bar->size = le32_to_cpu(*(u_int *)p)(*(u_int *)p);
1150 return CS_SUCCESS0x00;
1151}
1152
1153static 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_TUPLE0x40;
1160 config->last_idx = *(++p);
1161 p++;
1162 config->base = le32_to_cpu(*(u_int *)p)(*(u_int *)p);
1163 config->subtuples = tuple->TupleDataLen - 6;
1164 return CS_SUCCESS0x00;
1165}
1166
1167static 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_DEFAULT0x0001;
1178
1179 /* Process optional features */
1180 if (++p == q) return CS_BAD_TUPLE0x40;
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((void *) 0)) return CS_BAD_TUPLE0x40;
1187 } else
1188 entry->vcc.present = 0;
1189 if ((features & 3) > 1) {
1190 p = parse_power(p, q, &entry->vpp1);
1191 if (p == NULL((void *) 0)) return CS_BAD_TUPLE0x40;
1192 } else
1193 entry->vpp1.present = 0;
1194 if ((features & 3) > 2) {
1195 p = parse_power(p, q, &entry->vpp2);
1196 if (p == NULL((void *) 0)) return CS_BAD_TUPLE0x40;
1197 } else
1198 entry->vpp2.present = 0;
1199
1200 /* I/O window options */
1201 if (features & 0x08) {
1202 if (p == q) return CS_BAD_TUPLE0x40;
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((void *) 0)) return CS_BAD_TUPLE0x40;
1211 } else
1212 entry->irq.IRQInfo1 = 0;
1213
1214 if (features & 0x20) {
1215 if (p == q) return CS_BAD_TUPLE0x40;
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_TUPLE0x40;
1223 entry->flags |= (*p << 8);
1224 if (*p & 0x80) {
1225 if (++p == q) return CS_BAD_TUPLE0x40;
1226 entry->flags |= (*p << 16);
1227 }
1228 while (*p & 0x80)
1229 if (++p == q) return CS_BAD_TUPLE0x40;
1230 p++;
1231 }
1232
1233 entry->subtuples = q-p;
1234
1235 return CS_SUCCESS0x00;
1236}
1237
1238#endif
1239
1240/*====================================================================*/
1241
1242static 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_DEVICES4; 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_SUCCESS0x00;
1262}
1263
1264/*====================================================================*/
1265
1266static 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_TUPLE0x40;
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))(*(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((void *) 0));
1284}
1285
1286/*====================================================================*/
1287
1288static 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_TUPLE0x40;
1296 org->data_org = *p;
1297 if (++p == q) return CS_BAD_TUPLE0x40;
1298 for (i = 0; i < 30; i++) {
1299 org->desc[i] = *p;
1300 if (*p == '\0') break;
1301 if (++p == q) return CS_BAD_TUPLE0x40;
1302 }
1303 return CS_SUCCESS0x00;
1304}
1305
1306/*====================================================================*/
1307
1308static 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_TUPLE0x40;
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))(*(u_int *)(p+2));
1320 fmt->length = le32_to_cpu(*(u_int *)(p+6))(*(u_int *)(p+6));
1321
1322 return CS_SUCCESS0x00;
1323}
1324
1325/*====================================================================*/
1326
1327int parse_tuple(client_handle_t handle, tuple_t *tuple, cisparse_t *parse)
1328{
1329 int ret = CS_SUCCESS0x00;
1330
1331 if (tuple->TupleDataLen > tuple->TupleDataMax)
1332 return CS_BAD_TUPLE0x40;
1333 switch (tuple->TupleCode) {
1334 case CISTPL_DEVICE0x01:
1335 case CISTPL_DEVICE_A0x17:
1336 ret = parse_device(tuple, &parse->device);
1337 break;
1338#ifdef CONFIG_CARDBUS
1339 case CISTPL_BAR0x07:
1340 ret = parse_bar(tuple, &parse->bar);
1341 break;
1342 case CISTPL_CONFIG_CB0x04:
1343 ret = parse_config_cb(tuple, &parse->config);
1344 break;
1345 case CISTPL_CFTABLE_ENTRY_CB0x05:
1346 ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
1347 break;
1348#endif
1349 case CISTPL_CHECKSUM0x10:
1350 ret = parse_checksum(tuple, &parse->checksum);
1351 break;
1352 case CISTPL_LONGLINK_A0x11:
1353 case CISTPL_LONGLINK_C0x12:
1354 ret = parse_longlink(tuple, &parse->longlink);
1355 break;
1356 case CISTPL_LONGLINK_MFC0x06:
1357 ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
1358 break;
1359 case CISTPL_VERS_10x15:
1360 ret = parse_vers_1(tuple, &parse->version_1);
1361 break;
1362 case CISTPL_ALTSTR0x16:
1363 ret = parse_altstr(tuple, &parse->altstr);
1364 break;
1365 case CISTPL_JEDEC_A0x19:
1366 case CISTPL_JEDEC_C0x18:
1367 ret = parse_jedec(tuple, &parse->jedec);
1368 break;
1369 case CISTPL_MANFID0x20:
1370 ret = parse_manfid(tuple, &parse->manfid);
1371 break;
1372 case CISTPL_FUNCID0x21:
1373 ret = parse_funcid(tuple, &parse->funcid);
1374 break;
1375 case CISTPL_FUNCE0x22:
1376 ret = parse_funce(tuple, &parse->funce);
1377 break;
1378 case CISTPL_CONFIG0x1a:
1379 ret = parse_config(tuple, &parse->config);
1380 break;
1381 case CISTPL_CFTABLE_ENTRY0x1b:
1382 ret = parse_cftable_entry(tuple, &parse->cftable_entry);
1383 break;
1384 case CISTPL_DEVICE_GEO0x1e:
1385 case CISTPL_DEVICE_GEO_A0x1f:
1386 ret = parse_device_geo(tuple, &parse->device_geo);
1387 break;
1388 case CISTPL_VERS_20x40:
1389 ret = parse_vers_2(tuple, &parse->vers_2);
1390 break;
1391 case CISTPL_ORG0x46:
1392 ret = parse_org(tuple, &parse->org);
1393 break;
1394 case CISTPL_FORMAT0x41:
1395 case CISTPL_FORMAT_A0x47:
1396 ret = parse_format(tuple, &parse->format);
1397 break;
1398 case CISTPL_NO_LINK0x14:
1399 case CISTPL_LINKTARGET0x13:
1400 ret = CS_SUCCESS0x00;
1401 break;
1402 default:
1403 ret = CS_UNSUPPORTED_FUNCTION0x15;
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
1415int 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 = kmalloclinux_kmalloc(255, GFP_KERNEL0x03);
1422 if (buf == NULL((void *) 0))
1423 return CS_OUT_OF_RESOURCE0x20;
1424 tuple.DesiredTuple = code;
1425 tuple.Attributes = TUPLE_RETURN_COMMON0x02;
1426 ret = CardServices(GetFirstTuple, handle, &tuple, NULL((void *) 0));
1427 if (ret != CS_SUCCESS0x00) goto done;
1428 tuple.TupleData = buf;
1429 tuple.TupleOffset = 0;
1430 tuple.TupleDataMax = 255;
1431 ret = CardServices(GetTupleData, handle, &tuple, NULL((void *) 0));
1432 if (ret != CS_SUCCESS0x00) goto done;
1433 ret = CardServices(ParseTuple, handle, &tuple, parse);
1434done:
1435 kfreelinux_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
1449int 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)(((handle) == ((void *) 0)) || ((handle)->client_magic != 0x51E6
))
)
1456 return CS_BAD_HANDLE0x21;
1457 p = kmalloclinux_kmalloc(sizeof(*p), GFP_KERNEL0x03);
1458 if (p == NULL((void *) 0))
1459 return CS_OUT_OF_RESOURCE0x20;
1460
1461 info->Chains = reserved = 0;
1462 tuple.DesiredTuple = RETURN_FIRST_TUPLE0xff;
1463 tuple.Attributes = TUPLE_RETURN_COMMON0x02;
1464 ret = get_first_tuple(handle, &tuple);
1465 if (ret != CS_SUCCESS0x00)
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_DEVICE0x01) ||
1471 (read_tuple(handle, CISTPL_CFTABLE_ENTRY0x1b, p) == CS_SUCCESS0x00) ||
1472 (read_tuple(handle, CISTPL_CFTABLE_ENTRY_CB0x05, p) == CS_SUCCESS0x00))
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_MANFID0x20, p) == CS_SUCCESS0x00) ||
1479 (read_tuple(handle, CISTPL_VERS_10x15, p) == CS_SUCCESS0x00) ||
1480 (read_tuple(handle, CISTPL_VERS_20x40, p) != CS_NO_MORE_ITEMS0x1f))
1481 ident_ok++;
1482
1483 if (!dev_ok && !ident_ok)
1484 goto done;
1485
1486 for (info->Chains = 1; info->Chains < MAX_TUPLES200; info->Chains++) {
1487 ret = get_next_tuple(handle, &tuple);
1488 if (ret != CS_SUCCESS0x00) 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_TUPLES200) || (reserved > 5) ||
1495 ((!dev_ok || !ident_ok) && (info->Chains > 10)))
1496 info->Chains = 0;
1497
1498done:
1499 kfreelinux_kfree(p);
1500 return CS_SUCCESS0x00;
1501}
1502