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