xref: /freebsd/sys/dev/cardbus/cardbus_cis.c (revision 6f39832c711187f3351bf796bc4bf74bf292f7dc)
1 /*
2  * Copyright (c) 2000,2001 Jonathan Chen.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions, and the following disclaimer,
10  *    without modification, immediately at the beginning of the file.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30 
31 /*
32  * CIS Handling for the Cardbus Bus
33  */
34 
35 #define CARDBUS_DEBUG
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 
42 #include <sys/bus.h>
43 #include <machine/bus.h>
44 #include <machine/resource.h>
45 #include <sys/rman.h>
46 
47 #include <pci/pcivar.h>
48 
49 #include <dev/cardbus/cardbusreg.h>
50 #include <dev/cardbus/cardbus_cis.h>
51 
52 #include "card_if.h"
53 
54 #if defined CARDBUS_DEBUG
55 #define STATIC
56 #define DPRINTF(a) printf a
57 #define DEVPRINTF(x) device_printf x
58 #else
59 #define STATIC static
60 #define DPRINTF(a)
61 #define DEVPRINTF(x)
62 #endif
63 
64 #if !defined(lint)
65 static const char rcsid[] =
66   "$FreeBSD$";
67 #endif
68 
69 struct tuple_callbacks;
70 
71 static int cardbus_read_tuple_conf(device_t dev, device_t child,
72 				   u_int32_t *start, u_int32_t *off,
73 				   int *tupleid, int *len, u_int8_t *tupledata);
74 static int cardbus_read_tuple_exrom(device_t dev, struct resource *mem,
75 				    u_int32_t *start, u_int32_t *off,
76 				    int *tupleid, int *len, u_int8_t *tupledata);
77 static int cardbus_read_tuple_mem(device_t dev, device_t child, u_int32_t *start,
78 				  u_int32_t *off, int *tupleid, int *len,
79 				  u_int8_t *tupledata);
80 static int cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start,
81 			      u_int32_t *off, int *tupleid, int *len,
82 			      u_int8_t *tupledata);
83 static int decode_tuple(device_t dev, device_t child, int tupleid, int len,
84 			u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,
85 			struct tuple_callbacks *callbacks);
86 static int cardbus_parse_cis(device_t dev, device_t child,
87 			     struct tuple_callbacks *callbacks);
88 
89 #define DECODE_PARAMS							\
90 		(device_t dev, device_t child, int id, int len,		\
91 		 u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,	\
92 		 struct tuple_callbacks *info)
93 #define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME DECODE_PARAMS
94 DECODE_PROTOTYPE(generic);
95 DECODE_PROTOTYPE(nothing);
96 DECODE_PROTOTYPE(copy);
97 DECODE_PROTOTYPE(bar);
98 DECODE_PROTOTYPE(linktarget);
99 DECODE_PROTOTYPE(vers_1);
100 DECODE_PROTOTYPE(manfid);
101 DECODE_PROTOTYPE(funcid);
102 DECODE_PROTOTYPE(funce);
103 DECODE_PROTOTYPE(end);
104 DECODE_PROTOTYPE(unhandled);
105 
106 struct tuple_callbacks {
107 	int id;
108 	char* name;
109 	int (*func) DECODE_PARAMS;
110 };
111 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
112 
113 static char* funcnames[] = {
114 	"Multi-Functioned",
115 	"Memory",
116 	"Serial Port",
117 	"Parallel Port",
118 	"Fixed Disk",
119 	"Video Adaptor",
120 	"Network Adaptor",
121 	"AIMS",
122 	"SCSI",
123 	"Security"
124 };
125 
126 static struct cis_tupleinfo* cisread_buf;
127 static int ncisread_buf;
128 
129 DECODE_PROTOTYPE(generic)
130 {
131 #ifdef CARDBUS_DEBUG
132 	int i;
133 
134 	if (info)
135 		printf ("TUPLE: %s [%d]:", info->name, len);
136 	else
137 		printf ("TUPLE: Unknown(0x%02x) [%d]:", id, len);
138 
139 	for (i = 0; i < len; i++) {
140 		if (i % 0x10 == 0 && len > 0x10)
141 			printf ("\n       0x%02x:", i);
142 		printf (" %02x", tupledata[i]);
143 	}
144 	printf ("\n");
145 #endif
146 	return 0;
147 }
148 
149 DECODE_PROTOTYPE(nothing)
150 {
151 	return 0;
152 }
153 
154 DECODE_PROTOTYPE(copy)
155 {
156 	struct cis_tupleinfo* tmpbuf;
157 
158 	tmpbuf = malloc(sizeof(struct cis_tupleinfo)*(ncisread_buf+1),
159 			M_DEVBUF, M_WAITOK);
160 	if (ncisread_buf > 0) {
161 		memcpy(tmpbuf, cisread_buf,
162 		       sizeof(struct cis_tupleinfo)*ncisread_buf);
163 		free(cisread_buf, M_DEVBUF);
164 	}
165 	cisread_buf = tmpbuf;
166 
167 	cisread_buf[ncisread_buf].id = id;
168 	cisread_buf[ncisread_buf].len = len;
169 	cisread_buf[ncisread_buf].data = malloc(len, M_DEVBUF, M_WAITOK);
170 	memcpy (cisread_buf[ncisread_buf].data, tupledata, len);
171 	ncisread_buf++;
172 	return 0;
173 }
174 
175 DECODE_PROTOTYPE(linktarget)
176 {
177 #ifdef CARDBUS_DEBUG
178 	int i;
179 
180 	printf ("TUPLE: %s [%d]:", info->name, len);
181 
182 	for (i = 0; i < len; i++) {
183 		if (i % 0x10 == 0 && len > 0x10)
184 			printf ("\n       0x%02x:", i);
185 		printf (" %02x", tupledata[i]);
186 	}
187 	printf ("\n");
188 #endif
189 	if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
190 	    tupledata[2] != 'S') {
191 		printf("Invalid data for CIS Link Target!\n");
192 		decode_tuple_generic(dev, child, id, len, tupledata,
193 				     start, off, info);
194 		return EINVAL;
195 	}
196 	return 0;
197 }
198 
199 DECODE_PROTOTYPE(vers_1)
200 {
201 	int i;
202 	printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
203 	printf("Product name: ");
204 	for (i = 2; i < len; i++) {
205 		if (tupledata[i] == '\0')
206 			printf (" | ");
207 		else if (tupledata[i] == 0xff)
208 			break;
209 		else
210 			printf("%c", tupledata[i]);
211 	}
212 	printf("\n");
213 	return 0;
214 }
215 
216 DECODE_PROTOTYPE(funcid)
217 {
218 	int i;
219 	int numnames = sizeof(funcnames)/sizeof(funcnames[0]);
220 
221 	printf("Functions: ");
222 	for(i = 0; i < len; i++) {
223 		if (tupledata[i] < numnames)
224 			printf ("%s", funcnames[tupledata[i]]);
225 		else
226 			printf ("Unknown(%d)", tupledata[i]);
227 		if (i < len-1) printf(", ");
228 	}
229 	printf ("\n");
230 	return 0;
231 }
232 
233 DECODE_PROTOTYPE(manfid)
234 {
235 	int i;
236 	printf ("Manufacturer ID: ");
237 	for (i = 0; i < len; i++)
238 		printf("%02x", tupledata[i]);
239 	printf("\n");
240 	return 0;
241 }
242 
243 DECODE_PROTOTYPE(funce)
244 {
245 	int i;
246 	printf ("Function Extension: ");
247 	for (i = 0; i < len; i++)
248 		printf("%02x", tupledata[i]);
249 	printf("\n");
250 	return 0;
251 }
252 
253 DECODE_PROTOTYPE(bar)
254 {
255 	if (len != 6) {
256 		printf ("*** ERROR *** BAR length not 6 (%d)\n", len);
257 		return EINVAL;
258 	} else {
259 		int type;
260 		int reg;
261 		u_int32_t bar;
262 		u_int32_t len;
263 		struct resource *res;
264 
265 		reg = *(u_int16_t*)tupledata;
266 		len = *(u_int32_t*)(tupledata+2);
267 		if (reg & TPL_BAR_REG_AS) {
268 			type = SYS_RES_IOPORT;
269 		} else {
270 			type = SYS_RES_MEMORY;
271 		}
272 		bar = (reg & TPL_BAR_REG_ASI_MASK) - 1;
273 		if (bar < 0 || bar > 5 || (type == SYS_RES_IOPORT && bar == 5)) {
274 			device_printf(dev, "Invalid BAR number: %02x(%02x)\n",
275 				      reg, bar);
276 			return 0;
277 		}
278 		bar = CARDBUS_BASE0_REG + bar * 4;
279 		DEVPRINTF((dev, "Opening BAR: type=%s, bar=%02x, len=%04x\n",
280 			   (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len));
281 		res = bus_generic_alloc_resource(child, child, type, &bar, 0,
282 			 ~0, len, rman_make_alignment_flags(len) | RF_ACTIVE);
283 		if (res == NULL) {
284 			device_printf(dev, "Cannot allocate BAR %02x\n", bar);
285 		}
286 	}
287 	return 0;
288 }
289 
290 DECODE_PROTOTYPE(unhandled)
291 {
292 	printf ("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
293 	return -1;
294 }
295 
296 DECODE_PROTOTYPE(end)
297 {
298 	printf("CIS reading done\n");
299 	return 0;
300 }
301 
302 static int
303 cardbus_read_tuple_conf(device_t dev, device_t child, u_int32_t *start,
304 			 u_int32_t *off, int *tupleid, int *len,
305 			 u_int8_t *tupledata)
306 {
307 	int i, j;
308 	u_int32_t e;
309 	u_int32_t loc;
310 
311 	loc = CARDBUS_CIS_ADDR(*start) + *off;
312 
313 	e = pci_read_config(child, loc - loc%4, 4);
314 	for (j = loc % 4; j>0; j--)
315 		e >>= 8;
316 	*len = 0;
317 	for (i = loc, j = -2; j < *len; j++, i++) {
318 		if (i % 4 == 0)
319 			e = pci_read_config(child, i, 4);
320 		if (j == -2)
321 			*tupleid = 0xff & e;
322 		else if (j == -1)
323 			*len = 0xff & e;
324 		else
325 			tupledata[j] = 0xff & e;
326 		e >>= 8;
327 	}
328 	*off += *len+2;
329 	return 0;
330 }
331 
332 
333 static int
334 cardbus_read_tuple_exrom(device_t dev, struct resource *mem, u_int32_t *start,
335 			 u_int32_t *off, int *tupleid, int *len,
336 			 u_int8_t *tupledata)
337 {
338 #define READROM(rom, type, offset)				       \
339 	(*((u_int ## type ##_t *)(((unsigned char*)rom) + offset)))
340 
341 	int romnum = 0;
342 	unsigned char *data;
343 	u_int32_t imagesize;
344 	unsigned char *image;
345 	int imagenum;
346 
347 	image = (unsigned char*)rman_get_virtual(mem);
348 	imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
349 	do {
350 		if (READROM(image, 16, CARDBUS_EXROM_SIGNATURE) != 0xaa55) {
351 			device_printf (dev, "Bad header in rom %d: %04x\n",
352 				       romnum, *(u_int16_t*)(image +
353 				       CARDBUS_EXROM_SIGNATURE));
354 			return ENXIO;
355 		}
356 		data = image + READROM(image, 16, CARDBUS_EXROM_DATA_PTR);
357 		imagesize = READROM(data, 16, CARDBUS_EXROM_DATA_IMAGE_LENGTH);
358 
359 		if (imagesize == 0) {
360 			/*
361 			 * XXX some ROMs seem to have this as zero,
362 			 * can we assume this means 1 block?
363 			 */
364 			imagesize = 1;
365 		}
366 		imagesize <<= 9;
367 
368 		if (imagenum == romnum) {
369 			image += CARDBUS_CIS_ADDR(*start) + *off;
370 			*tupleid = image[0];
371 			*len = image[1];
372 			memcpy(tupledata, image+2, *len);
373 			*off += *len+2;
374 			return 0;
375 		}
376 		image += imagesize;
377 		romnum++;
378 	} while ((READROM(data, 8, CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0);
379 	device_printf(dev, "Cannot read CIS: Not enough images of rom\n");
380 	return ENOENT;
381 #undef READROM
382 }
383 
384 static int
385 cardbus_read_tuple_mem(device_t dev, device_t child, u_int32_t *start,
386 		       u_int32_t *off, int *tupleid, int *len,
387 		       u_int8_t *tupledata)
388 {
389 	struct resource *mem;
390 	int rid;
391 	int ret;
392 
393 	if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
394 		rid = CARDBUS_ROM_REG;
395 	} else {
396 		rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
397 	}
398 
399 	mem = bus_alloc_resource(child, SYS_RES_MEMORY, &rid, 0, ~0,
400 				 1, RF_ACTIVE);
401 	if (mem == NULL) {
402 		device_printf(dev, "Failed to get memory for CIS reading\n");
403 		return ENOMEM;
404 	}
405 
406 	if(CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
407 		ret = cardbus_read_tuple_exrom(dev, mem, start, off, tupleid,
408 					       len, tupledata);
409 	} else {
410 		/* XXX byte order? */
411 		unsigned char* ptr;
412 		ptr = (unsigned char*)rman_get_virtual(mem)
413 			+ CARDBUS_CIS_ADDR(*start) + *off;
414 		*tupleid = ptr[0];
415 		*len = ptr[1];
416 		memcpy(tupledata, ptr+2, *len);
417 		ret = 0;
418 		*off += *len+2;
419 	}
420 	bus_release_resource(child, SYS_RES_MEMORY, rid, mem);
421 	return ret;
422 }
423 
424 static int
425 cardbus_read_tuple(device_t dev, device_t child, u_int32_t *start,
426 		   u_int32_t *off, int *tupleid, int *len,
427 		   u_int8_t *tupledata)
428 {
429 	switch(CARDBUS_CIS_SPACE(*start)) {
430 	case CARDBUS_CIS_ASI_TUPLE:
431 		return cardbus_read_tuple_conf(dev, child, start, off,
432 					       tupleid, len, tupledata);
433 	case CARDBUS_CIS_ASI_BAR0:
434 	case CARDBUS_CIS_ASI_BAR1:
435 	case CARDBUS_CIS_ASI_BAR2:
436 	case CARDBUS_CIS_ASI_BAR3:
437 	case CARDBUS_CIS_ASI_BAR4:
438 	case CARDBUS_CIS_ASI_BAR5:
439 	case CARDBUS_CIS_ASI_ROM:
440 		return cardbus_read_tuple_mem(dev, child, start, off,
441 					      tupleid, len, tupledata);
442 	default:
443 		device_printf(dev, "Unable to read CIS: Unknown space: %d\n",
444 			      CARDBUS_CIS_SPACE(*start));
445 		return EINVAL;
446 	}
447 }
448 
449 static int
450 decode_tuple(device_t dev, device_t child, int tupleid, int len,
451 	     u_int8_t *tupledata, u_int32_t *start, u_int32_t *off,
452 	     struct tuple_callbacks *callbacks)
453 {
454 	int i;
455 	for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
456 		if (tupleid == callbacks[i].id)
457 			return callbacks[i].func(dev, child, tupleid, len,
458 						tupledata, start, off,
459 						&callbacks[i]);
460 	}
461 
462 	if (tupleid < CISTPL_CUSTOMSTART) {
463 		device_printf(dev, "Undefined tuple encountered, CIS parsing terminated\n");
464 		return EINVAL;
465 	}
466 	return callbacks[i].func(dev, child, tupleid, len,
467 				 tupledata, start, off,
468 				 NULL);
469 }
470 
471 static int
472 cardbus_parse_cis(device_t dev, device_t child,
473 		  struct tuple_callbacks *callbacks)
474 {
475 	u_int8_t tupledata[MAXTUPLESIZE];
476 	int tupleid;
477 	int len;
478 	int expect_linktarget;
479 	u_int32_t start, off;
480 
481 	bzero(tupledata, MAXTUPLESIZE);
482 	expect_linktarget = TRUE;
483 	start = pci_read_config(child, CARDBUS_CIS_REG, 4);
484 	off = 0;
485 	do {
486 		cardbus_read_tuple(dev, child, &start, &off, &tupleid, &len,
487 				   tupledata);
488 
489 		if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
490 			device_printf(dev, "Expecting link target, got 0x%x\n",
491 				      tupleid);
492 			return EINVAL;
493 		}
494 		expect_linktarget = decode_tuple(dev, child, tupleid, len,
495 						 tupledata, &start, &off,
496 						 callbacks);
497 		if (expect_linktarget != 0)
498 			return expect_linktarget;
499 	} while (tupleid != CISTPL_END);
500 	return 0;
501 }
502 
503 int
504 cardbus_cis_read(device_t dev, device_t child, u_int8_t id,
505 		     struct cis_tupleinfo** buff, int* nret)
506 {
507 	struct tuple_callbacks cisread_callbacks[] = {
508 		MAKETUPLE(NULL,			nothing),
509 		/* first entry will be overwritten */
510 		MAKETUPLE(NULL,			nothing),
511 		MAKETUPLE(DEVICE,		nothing),
512 		MAKETUPLE(LONG_LINK_CB,		unhandled),
513 		MAKETUPLE(INDIRECT,		unhandled),
514 		MAKETUPLE(CONFIG_CB,		nothing),
515 		MAKETUPLE(CFTABLE_ENTRY_CB,	nothing),
516 		MAKETUPLE(LONGLINK_MFC,		unhandled),
517 		MAKETUPLE(BAR,			nothing),
518 		MAKETUPLE(PWR_MGMNT,		nothing),
519 		MAKETUPLE(EXTDEVICE,		nothing),
520 		MAKETUPLE(CHECKSUM,		nothing),
521 		MAKETUPLE(LONGLINK_A,		unhandled),
522 		MAKETUPLE(LONGLINK_C,		unhandled),
523 		MAKETUPLE(LINKTARGET,		nothing),
524 		MAKETUPLE(NO_LINK,		nothing),
525 		MAKETUPLE(VERS_1,		nothing),
526 		MAKETUPLE(ALTSTR,		nothing),
527 		MAKETUPLE(DEVICE_A,		nothing),
528 		MAKETUPLE(JEDEC_C,		nothing),
529 		MAKETUPLE(JEDEC_A,		nothing),
530 		MAKETUPLE(CONFIG,		nothing),
531 		MAKETUPLE(CFTABLE_ENTRY,	nothing),
532 		MAKETUPLE(DEVICE_OC,		nothing),
533 		MAKETUPLE(DEVICE_OA,		nothing),
534 		MAKETUPLE(DEVICE_GEO,		nothing),
535 		MAKETUPLE(DEVICE_GEO_A,		nothing),
536 		MAKETUPLE(MANFID,		nothing),
537 		MAKETUPLE(FUNCID,		nothing),
538 		MAKETUPLE(FUNCE,		nothing),
539 		MAKETUPLE(SWIL,			nothing),
540 		MAKETUPLE(VERS_2,		nothing),
541 		MAKETUPLE(FORMAT,		nothing),
542 		MAKETUPLE(GEOMETRY,		nothing),
543 		MAKETUPLE(BYTEORDER,		nothing),
544 		MAKETUPLE(DATE,			nothing),
545 		MAKETUPLE(BATTERY,		nothing),
546 		MAKETUPLE(ORG,			nothing),
547 		MAKETUPLE(END,			end),
548 		MAKETUPLE(GENERIC,		nothing),
549 	};
550 	int ret;
551 
552 	cisread_callbacks[0].id = id;
553 	cisread_callbacks[0].name = "COPY";
554 	cisread_callbacks[0].func = decode_tuple_copy;
555 	ncisread_buf = 0;
556 	cisread_buf = NULL;
557 	ret = cardbus_parse_cis(dev, child, cisread_callbacks);
558 
559 	*buff = cisread_buf;
560 	*nret = ncisread_buf;
561 	return ret;
562 }
563 
564 void
565 cardbus_cis_free(device_t dev, struct cis_tupleinfo *buff, int* nret)
566 {
567 	int i;
568 	for (i = 0; i < *nret; i++)
569 		free(buff[i].data, M_DEVBUF);
570 	if (*nret > 0)
571 		free(buff, M_DEVBUF);
572 }
573 
574 int
575 cardbus_do_cis(device_t dev, device_t child)
576 {
577 	struct tuple_callbacks init_callbacks[] = {
578 		MAKETUPLE(NULL,			generic),
579 		MAKETUPLE(DEVICE,		generic),
580 		MAKETUPLE(LONG_LINK_CB,		unhandled),
581 		MAKETUPLE(INDIRECT,		unhandled),
582 		MAKETUPLE(CONFIG_CB,		generic),
583 		MAKETUPLE(CFTABLE_ENTRY_CB,	generic),
584 		MAKETUPLE(LONGLINK_MFC,		unhandled),
585 		MAKETUPLE(BAR,			bar),
586 		MAKETUPLE(PWR_MGMNT,		generic),
587 		MAKETUPLE(EXTDEVICE,		generic),
588 		MAKETUPLE(CHECKSUM,		generic),
589 		MAKETUPLE(LONGLINK_A,		unhandled),
590 		MAKETUPLE(LONGLINK_C,		unhandled),
591 		MAKETUPLE(LINKTARGET,		linktarget),
592 		MAKETUPLE(NO_LINK,		generic),
593 		MAKETUPLE(VERS_1,		vers_1),
594 		MAKETUPLE(ALTSTR,		generic),
595 		MAKETUPLE(DEVICE_A,		generic),
596 		MAKETUPLE(JEDEC_C,		generic),
597 		MAKETUPLE(JEDEC_A,		generic),
598 		MAKETUPLE(CONFIG,		generic),
599 		MAKETUPLE(CFTABLE_ENTRY,	generic),
600 		MAKETUPLE(DEVICE_OC,		generic),
601 		MAKETUPLE(DEVICE_OA,		generic),
602 		MAKETUPLE(DEVICE_GEO,		generic),
603 		MAKETUPLE(DEVICE_GEO_A,		generic),
604 		MAKETUPLE(MANFID,		manfid),
605 		MAKETUPLE(FUNCID,		funcid),
606 		MAKETUPLE(FUNCE,		funce),
607 		MAKETUPLE(SWIL,			generic),
608 		MAKETUPLE(VERS_2,		generic),
609 		MAKETUPLE(FORMAT,		generic),
610 		MAKETUPLE(GEOMETRY,		generic),
611 		MAKETUPLE(BYTEORDER,		generic),
612 		MAKETUPLE(DATE,			generic),
613 		MAKETUPLE(BATTERY,		generic),
614 		MAKETUPLE(ORG,			generic),
615 		MAKETUPLE(END,			end),
616 		MAKETUPLE(GENERIC,		generic),
617 	};
618 	return cardbus_parse_cis(dev, child, init_callbacks);
619 }
620