xref: /freebsd/sys/dev/cardbus/cardbus_cis.c (revision 6af83ee0d2941d18880b6aaa2b4facd1d30c6106)
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  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29 
30 /*
31  * CIS Handling for the Cardbus Bus
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 
39 #include <sys/bus.h>
40 #include <machine/bus.h>
41 #include <machine/resource.h>
42 #include <sys/rman.h>
43 #include <sys/endian.h>
44 
45 #include <sys/pciio.h>
46 #include <dev/pci/pcivar.h>
47 #include <dev/pci/pcireg.h>
48 
49 #include <dev/pccard/pccardvar.h>
50 #include <dev/pccard/pccard_cis.h>
51 
52 #include <dev/cardbus/cardbusreg.h>
53 #include <dev/cardbus/cardbusvar.h>
54 #include <dev/cardbus/cardbus_cis.h>
55 
56 extern int cardbus_cis_debug;
57 
58 #define	DPRINTF(a) if (cardbus_cis_debug) printf a
59 #define	DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
60 
61 struct tuple_callbacks;
62 
63 typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
64 		 uint8_t *tupledata, uint32_t start, uint32_t *off,
65 		 struct tuple_callbacks *info);
66 
67 struct tuple_callbacks {
68 	int	id;
69 	char	*name;
70 	tuple_cb *func;
71 };
72 
73 static int decode_tuple_generic(device_t cbdev, device_t child, int id,
74     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
75     struct tuple_callbacks *info);
76 static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
77     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
78     struct tuple_callbacks *info);
79 static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
80     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
81     struct tuple_callbacks *info);
82 static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
83     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
84     struct tuple_callbacks *info);
85 static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
86     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
87     struct tuple_callbacks *info);
88 static int decode_tuple_funce(device_t cbdev, device_t child, int id,
89     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
90     struct tuple_callbacks *info);
91 static int decode_tuple_bar(device_t cbdev, device_t child, int id,
92     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
93     struct tuple_callbacks *info);
94 static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
95     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
96     struct tuple_callbacks *info);
97 static int decode_tuple_end(device_t cbdev, device_t child, int id,
98     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
99     struct tuple_callbacks *info);
100 
101 static int	cardbus_read_tuple_conf(device_t cbdev, device_t child,
102 		    uint32_t start, uint32_t *off, int *tupleid, int *len,
103 		    uint8_t *tupledata);
104 static int	cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
105 		    uint32_t start, uint32_t *off, int *tupleid, int *len,
106 		    uint8_t *tupledata);
107 static int	cardbus_read_tuple(device_t cbdev, device_t child,
108 		    struct resource *res, uint32_t start, uint32_t *off,
109 		    int *tupleid, int *len, uint8_t *tupledata);
110 static void	cardbus_read_tuple_finish(device_t cbdev, device_t child,
111 		    int rid, struct resource *res);
112 static struct resource	*cardbus_read_tuple_init(device_t cbdev, device_t child,
113 		    uint32_t *start, int *rid);
114 static int	decode_tuple(device_t cbdev, device_t child, int tupleid,
115 		    int len, uint8_t *tupledata, uint32_t start,
116 		    uint32_t *off, struct tuple_callbacks *callbacks);
117 static int	cardbus_parse_cis(device_t cbdev, device_t child,
118 		    struct tuple_callbacks *callbacks);
119 
120 #define	MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
121 
122 static char *funcnames[] = {
123 	"Multi-Functioned",
124 	"Memory",
125 	"Serial Port",
126 	"Parallel Port",
127 	"Fixed Disk",
128 	"Video Adaptor",
129 	"Network Adaptor",
130 	"AIMS",
131 	"SCSI",
132 	"Security"
133 };
134 
135 /*
136  * Handler functions for various CIS tuples
137  */
138 
139 static int
140 decode_tuple_generic(device_t cbdev, device_t child, int id,
141     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
142     struct tuple_callbacks *info)
143 {
144 	int i;
145 
146 	if (cardbus_cis_debug) {
147 		if (info)
148 			printf("TUPLE: %s [%d]:", info->name, len);
149 		else
150 			printf("TUPLE: Unknown(0x%02x) [%d]:", id, len);
151 
152 		for (i = 0; i < len; i++) {
153 			if (i % 0x10 == 0 && len > 0x10)
154 				printf("\n       0x%02x:", i);
155 			printf(" %02x", tupledata[i]);
156 		}
157 		printf("\n");
158 	}
159 	return (0);
160 }
161 
162 static int
163 decode_tuple_linktarget(device_t cbdev, device_t child, int id,
164     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
165     struct tuple_callbacks *info)
166 {
167 	int i;
168 
169 	if (cardbus_cis_debug) {
170 		printf("TUPLE: %s [%d]:", info->name, len);
171 
172 		for (i = 0; i < len; i++) {
173 			if (i % 0x10 == 0 && len > 0x10)
174 				printf("\n       0x%02x:", i);
175 			printf(" %02x", tupledata[i]);
176 		}
177 		printf("\n");
178 	}
179 	if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
180 	    tupledata[2] != 'S') {
181 		printf("Invalid data for CIS Link Target!\n");
182 		decode_tuple_generic(cbdev, child, id, len, tupledata,
183 		    start, off, info);
184 		return (EINVAL);
185 	}
186 	return (0);
187 }
188 
189 static int
190 decode_tuple_vers_1(device_t cbdev, device_t child, int id,
191     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
192     struct tuple_callbacks *info)
193 {
194 	int i;
195 
196 	if (cardbus_cis_debug) {
197 		printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
198 		printf("Product name: ");
199 		for (i = 2; i < len; i++) {
200 			if (tupledata[i] == '\0')
201 				printf(" | ");
202 			else if (tupledata[i] == 0xff)
203 				break;
204 			else
205 				printf("%c", tupledata[i]);
206 		}
207 		printf("\n");
208 	}
209 	return (0);
210 }
211 
212 static int
213 decode_tuple_funcid(device_t cbdev, device_t child, int id,
214     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
215     struct tuple_callbacks *info)
216 {
217 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
218 	int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
219 	int i;
220 
221 	if (cardbus_cis_debug) {
222 		printf("Functions: ");
223 		for (i = 0; i < len; i++) {
224 			if (tupledata[i] < numnames)
225 				printf("%s", funcnames[tupledata[i]]);
226 			else
227 				printf("Unknown(%d)", tupledata[i]);
228 			if (i < len-1)
229 				printf(", ");
230 		}
231 		printf("\n");
232 	}
233 	if (len > 0)
234 		dinfo->funcid = tupledata[0];		/* use first in list */
235 	return (0);
236 }
237 
238 static int
239 decode_tuple_manfid(device_t cbdev, device_t child, int id,
240     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
241     struct tuple_callbacks *info)
242 {
243 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
244 	int i;
245 
246 	if (cardbus_cis_debug) {
247 		printf("Manufacturer ID: ");
248 		for (i = 0; i < len; i++)
249 			printf("%02x", tupledata[i]);
250 		printf("\n");
251 	}
252 
253 	if (len == 5) {
254 		dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
255 		dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
256 	}
257 	return (0);
258 }
259 
260 static int
261 decode_tuple_funce(device_t cbdev, device_t child, int id,
262     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
263     struct tuple_callbacks *info)
264 {
265 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
266 	int type, i;
267 
268 	if (cardbus_cis_debug) {
269 		printf("Function Extension: ");
270 		for (i = 0; i < len; i++)
271 			printf("%02x", tupledata[i]);
272 		printf("\n");
273 	}
274 	if (len < 2)			/* too short */
275 		return (0);
276 	type = tupledata[0];		/* XXX <32 always? */
277 	switch (dinfo->funcid) {
278 	case PCCARD_FUNCTION_NETWORK:
279 		switch (type) {
280 		case PCCARD_TPLFE_TYPE_LAN_NID:
281 			if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) {
282 				/* ignore, warning? */
283 				return (0);
284 			}
285 			bcopy(tupledata + 2, dinfo->funce.lan.nid,
286 			    tupledata[1]);
287 			break;
288 		}
289 		dinfo->fepresent |= 1<<type;
290 		break;
291 	}
292 	return (0);
293 }
294 
295 static int
296 decode_tuple_bar(device_t cbdev, device_t child, int id,
297     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
298     struct tuple_callbacks *info)
299 {
300 	struct cardbus_devinfo *dinfo = device_get_ivars(child);
301 	int type;
302 	uint8_t reg;
303 	uint32_t bar, pci_bar;
304 
305 	if (len != 6) {
306 		device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
307 		return (EINVAL);
308 	}
309 
310 	reg = *tupledata;
311 	len = le32toh(*(uint32_t*)(tupledata + 2));
312 	if (reg & TPL_BAR_REG_AS) {
313 		type = SYS_RES_IOPORT;
314 	} else {
315 		type = SYS_RES_MEMORY;
316 	}
317 
318 	bar = reg & TPL_BAR_REG_ASI_MASK;
319 	if (bar == 0) {
320 		device_printf(cbdev, "Invalid BAR type 0 in CIS\n");
321 		return (EINVAL);	/* XXX Return an error? */
322 	} else if (bar == 7) {
323 		/* XXX Should we try to map in Option ROMs? */
324 		return (0);
325 	}
326 
327 	/* Convert from BAR type to BAR offset */
328 	bar = CARDBUS_BASE0_REG + (bar - 1) * 4;
329 
330 	if (type == SYS_RES_MEMORY) {
331 		if (reg & TPL_BAR_REG_PREFETCHABLE)
332 			dinfo->mprefetchable |= BARBIT(bar);
333 #if 0
334 		/*
335 		 * XXX: It appears from a careful reading of the spec
336 		 * that we're not supposed to honor this when the bridge
337 		 * is not on the main system bus.  PCI spec doesn't appear
338 		 * to allow for memory ranges not listed in the bridge's
339 		 * decode range to be decoded.  The PC Card spec seems to
340 		 * indicate that this should only be done on x86 based
341 		 * machines, which seems to imply that on non-x86 machines
342 		 * the adddresses can be anywhere.  This further implies that
343 		 * since the hardware can do it on non-x86 machines, it should
344 		 * be able to do it on x86 machines.  Therefore, we can and
345 		 * should ignore this hint.  Furthermore, the PC Card spec
346 		 * recommends always allocating memory above 1MB, contradicting
347 		 * the other part of the PC Card spec.
348 		 *
349 		 * NetBSD ignores this bit, but it also ignores the
350 		 * prefetchable bit too, so that's not an indication of
351 		 * correctness.
352 		 */
353 		if (reg & TPL_BAR_REG_BELOW1MB)
354 			dinfo->mbelow1mb |= BARBIT(bar);
355 #endif
356 	}
357 
358 	/*
359 	 * Sanity check the BAR length reported in the CIS with the length
360 	 * encoded in the PCI BAR.  The latter seems to be more reliable.
361 	 * XXX - This probably belongs elsewhere.
362 	 */
363 	pci_write_config(child, bar, 0xffffffff, 4);
364 	pci_bar = pci_read_config(child, bar, 4);
365 	if ((pci_bar != 0x0) && (pci_bar != 0xffffffff)) {
366 		if (type == SYS_RES_MEMORY) {
367 			pci_bar &= ~0xf;
368 		} else {
369 			pci_bar &= ~0x3;
370 		}
371 		len = 1 << (ffs(pci_bar) - 1);
372 	}
373 
374 	DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x%s%s\n",
375 	    (type == SYS_RES_MEMORY) ? "MEM" : "IO", bar, len,
376 	    (type == SYS_RES_MEMORY && dinfo->mprefetchable & BARBIT(bar)) ?
377 	    " (Prefetchable)" : "", type == SYS_RES_MEMORY ?
378 	    ((dinfo->mbelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "") : ""));
379 
380 	resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len);
381 
382 	/*
383 	 * Mark the appropriate bit in the PCI command register so that
384 	 * device drivers will know which type of BARs can be used.
385 	 */
386 	pci_enable_io(child, type);
387 	return (0);
388 }
389 
390 static int
391 decode_tuple_unhandled(device_t cbdev, device_t child, int id,
392     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
393     struct tuple_callbacks *info)
394 {
395 	/* Make this message suck less XXX */
396 	printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
397 	return (-1);
398 }
399 
400 static int
401 decode_tuple_end(device_t cbdev, device_t child, int id,
402     int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
403     struct tuple_callbacks *info)
404 {
405 	if (cardbus_cis_debug) {
406 		printf("CIS reading done\n");
407 	}
408 	return (0);
409 }
410 
411 /*
412  * Functions to read the a tuple from the card
413  */
414 
415 static int
416 cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start,
417     uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
418 {
419 	int i, j;
420 	uint32_t e;
421 	uint32_t loc;
422 
423 	loc = start + *off;
424 
425 	e = pci_read_config(child, loc - loc % 4, 4);
426 	for (j = loc % 4; j > 0; j--)
427 		e >>= 8;
428 	*len = 0;
429 	for (i = loc, j = -2; j < *len; j++, i++) {
430 		if (i % 4 == 0)
431 			e = pci_read_config(child, i, 4);
432 		if (j == -2)
433 			*tupleid = 0xff & e;
434 		else if (j == -1)
435 			*len = 0xff & e;
436 		else
437 			tupledata[j] = 0xff & e;
438 		e >>= 8;
439 	}
440 	*off += *len + 2;
441 	return (0);
442 }
443 
444 static int
445 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start,
446     uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
447 {
448 	bus_space_tag_t bt;
449 	bus_space_handle_t bh;
450 	int ret;
451 
452 	bt = rman_get_bustag(res);
453 	bh = rman_get_bushandle(res);
454 
455 	*tupleid = bus_space_read_1(bt, bh, start + *off);
456 	*len = bus_space_read_1(bt, bh, start + *off + 1);
457 	bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len);
458 	ret = 0;
459 	*off += *len + 2;
460 	return (ret);
461 }
462 
463 static int
464 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
465     uint32_t start, uint32_t *off, int *tupleid, int *len,
466     uint8_t *tupledata)
467 {
468 	if (res == (struct resource*)~0UL) {
469 		return (cardbus_read_tuple_conf(cbdev, child, start, off,
470 		    tupleid, len, tupledata));
471 	} else {
472 		return (cardbus_read_tuple_mem(cbdev, res, start, off,
473 		    tupleid, len, tupledata));
474 	}
475 }
476 
477 static void
478 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
479     struct resource *res)
480 {
481 	if (res != (struct resource*)~0UL) {
482 		bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
483 		pci_write_config(child, rid, 0, 4);
484 		PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
485 	}
486 }
487 
488 static struct resource *
489 cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
490     int *rid)
491 {
492 	uint32_t testval;
493 	uint32_t size;
494 	struct resource *res;
495 
496 	switch (CARDBUS_CIS_SPACE(*start)) {
497 	case CARDBUS_CIS_ASI_TUPLE:
498 		/* CIS in PCI config space need no initialization */
499 		return ((struct resource*)~0UL);
500 	case CARDBUS_CIS_ASI_BAR0:
501 	case CARDBUS_CIS_ASI_BAR1:
502 	case CARDBUS_CIS_ASI_BAR2:
503 	case CARDBUS_CIS_ASI_BAR3:
504 	case CARDBUS_CIS_ASI_BAR4:
505 	case CARDBUS_CIS_ASI_BAR5:
506 		*rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
507 		break;
508 	case CARDBUS_CIS_ASI_ROM:
509 		*rid = CARDBUS_ROM_REG;
510 #if 0
511 		/*
512 		 * This mask doesn't contain the bit that actually enables
513 		 * the Option ROM.
514 		 */
515 		pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4);
516 #endif
517 		break;
518 	default:
519 		device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
520 		    CARDBUS_CIS_SPACE(*start));
521 		return (NULL);
522 	}
523 
524 	/* figure out how much space we need */
525 	pci_write_config(child, *rid, 0xffffffff, 4);
526 	testval = pci_read_config(child, *rid, 4);
527 
528 	/*
529 	 * This bit has a different meaning depending if we are dealing
530 	 * with a normal BAR or an Option ROM BAR.
531 	 */
532 	if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) {
533 		device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
534 		return (NULL);
535 	}
536 
537 	size = CARDBUS_MAPREG_MEM_SIZE(testval);
538 	/* XXX Is this some kind of hack? */
539 	if (size < 4096)
540 		size = 4096;
541 	/* allocate the memory space to read CIS */
542 	res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
543 	    rman_make_alignment_flags(size) | RF_ACTIVE);
544 	if (res == NULL) {
545 		device_printf(cbdev, "Unable to allocate resource "
546 		    "to read CIS.\n");
547 		return (NULL);
548 	}
549 	pci_write_config(child, *rid,
550 	    rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
551 		CARDBUS_ROM_ENABLE : 0),
552 	    4);
553 	PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
554 
555 	/* Flip to the right ROM image if CIS is in ROM */
556 	if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
557 		bus_space_tag_t bt;
558 		bus_space_handle_t bh;
559 		uint32_t imagesize;
560 		uint32_t imagebase = 0;
561 		uint32_t pcidata;
562 		uint16_t romsig;
563 		int romnum = 0;
564 		int imagenum;
565 
566 		bt = rman_get_bustag(res);
567 		bh = rman_get_bushandle(res);
568 
569 		imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
570 		for (romnum = 0;; romnum++) {
571 			romsig = bus_space_read_2(bt, bh,
572 			    imagebase + CARDBUS_EXROM_SIGNATURE);
573 			if (romsig != 0xaa55) {
574 				device_printf(cbdev, "Bad header in rom %d: "
575 				    "[%x] %04x\n", romnum, imagebase +
576 				    CARDBUS_EXROM_SIGNATURE, romsig);
577 				bus_release_resource(cbdev, SYS_RES_MEMORY,
578 				    *rid, res);
579 				*rid = 0;
580 				return (NULL);
581 			}
582 
583 			/*
584 			 * If this was the Option ROM image that we were
585 			 * looking for, then we are done.
586 			 */
587 			if (romnum == imagenum)
588 				break;
589 
590 			/* Find out where the next Option ROM image is */
591 			pcidata = imagebase + bus_space_read_2(bt, bh,
592 			    imagebase + CARDBUS_EXROM_DATA_PTR);
593 			imagesize = bus_space_read_2(bt, bh,
594 			    pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
595 
596 			if (imagesize == 0) {
597 				/*
598 				 * XXX some ROMs seem to have this as zero,
599 				 * can we assume this means 1 block?
600 				 */
601 				device_printf(cbdev, "Warning, size of Option "
602 				    "ROM image %d is 0 bytes, assuming 512 "
603 				    "bytes.\n", romnum);
604 				imagesize = 1;
605 			}
606 
607 			/* Image size is in 512 byte units */
608 			imagesize <<= 9;
609 
610 			if ((bus_space_read_1(bt, bh, pcidata +
611 			    CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
612 				device_printf(cbdev, "Cannot find CIS in "
613 				    "Option ROM\n");
614 				bus_release_resource(cbdev, SYS_RES_MEMORY,
615 				    *rid, res);
616 				*rid = 0;
617 				return (NULL);
618 			}
619 			imagebase += imagesize;
620 		}
621 		*start = imagebase + CARDBUS_CIS_ADDR(*start);
622 	} else {
623 		*start = CARDBUS_CIS_ADDR(*start);
624 	}
625 
626 	return (res);
627 }
628 
629 /*
630  * Dispatch the right handler function per tuple
631  */
632 
633 static int
634 decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
635     uint8_t *tupledata, uint32_t start, uint32_t *off,
636     struct tuple_callbacks *callbacks)
637 {
638 	int i;
639 	for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
640 		if (tupleid == callbacks[i].id)
641 			return (callbacks[i].func(cbdev, child, tupleid, len,
642 			    tupledata, start, off, &callbacks[i]));
643 	}
644 	return (callbacks[i].func(cbdev, child, tupleid, len,
645 	    tupledata, start, off, NULL));
646 }
647 
648 static int
649 cardbus_parse_cis(device_t cbdev, device_t child,
650     struct tuple_callbacks *callbacks)
651 {
652 	uint8_t tupledata[MAXTUPLESIZE];
653 	int tupleid;
654 	int len;
655 	int expect_linktarget;
656 	uint32_t start, off;
657 	struct resource *res;
658 	int rid;
659 
660 	bzero(tupledata, MAXTUPLESIZE);
661 	expect_linktarget = TRUE;
662 	if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0)
663 		return (ENXIO);
664 	off = 0;
665 	res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
666 	if (res == NULL)
667 		return (ENXIO);
668 
669 	do {
670 		if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
671 		    &tupleid, &len, tupledata)) {
672 			device_printf(cbdev, "Failed to read CIS.\n");
673 			cardbus_read_tuple_finish(cbdev, child, rid, res);
674 			return (ENXIO);
675 		}
676 
677 		if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
678 			device_printf(cbdev, "Expecting link target, got 0x%x\n",
679 			    tupleid);
680 			cardbus_read_tuple_finish(cbdev, child, rid, res);
681 			return (EINVAL);
682 		}
683 		expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
684 		    tupledata, start, &off, callbacks);
685 		if (expect_linktarget != 0) {
686 			cardbus_read_tuple_finish(cbdev, child, rid, res);
687 			return (expect_linktarget);
688 		}
689 	} while (tupleid != CISTPL_END);
690 	cardbus_read_tuple_finish(cbdev, child, rid, res);
691 	return (0);
692 }
693 
694 int
695 cardbus_do_cis(device_t cbdev, device_t child)
696 {
697 	int ret;
698 	struct tuple_callbacks init_callbacks[] = {
699 		MAKETUPLE(LONGLINK_CB,		unhandled),
700 		MAKETUPLE(INDIRECT,		unhandled),
701 		MAKETUPLE(LONGLINK_MFC,		unhandled),
702 		MAKETUPLE(BAR,			bar),
703 		MAKETUPLE(LONGLINK_A,		unhandled),
704 		MAKETUPLE(LONGLINK_C,		unhandled),
705 		MAKETUPLE(LINKTARGET,		linktarget),
706 		MAKETUPLE(VERS_1,		vers_1),
707 		MAKETUPLE(MANFID,		manfid),
708 		MAKETUPLE(FUNCID,		funcid),
709 		MAKETUPLE(FUNCE,		funce),
710 		MAKETUPLE(END,			end),
711 		MAKETUPLE(GENERIC,		generic),
712 	};
713 
714 	ret = cardbus_parse_cis(cbdev, child, init_callbacks);
715 	if (ret < 0)
716 		return (ret);
717 	return 0;
718 }
719