1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2000,2001 Jonathan Chen All rights reserved.
5 * Copyright (c) 2005-2008 M. Warner Losh <imp@FreeBSD.org>
6 *
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD$");
32
33/*
34 * CIS Handling for the Cardbus Bus
35 */
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#include <sys/endian.h>
47
48#include <sys/pciio.h>
49#include <dev/pci/pcivar.h>
50#include <dev/pci/pcireg.h>
51
52#include <dev/pccard/pccardvar.h>
53#include <dev/pccard/pccard_cis.h>
54
55#include <dev/cardbus/cardbusreg.h>
56#include <dev/cardbus/cardbusvar.h>
57#include <dev/cardbus/cardbus_cis.h>
58
59extern int cardbus_cis_debug;
60
61#define	DPRINTF(a) if (cardbus_cis_debug) printf a
62#define	DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
63
64#define CIS_CONFIG_SPACE	(struct resource *)~0UL
65
66static int decode_tuple_generic(device_t cbdev, device_t child, int id,
67    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
68    struct tuple_callbacks *info, void *);
69static int decode_tuple_linktarget(device_t cbdev, device_t child, int id,
70    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
71    struct tuple_callbacks *info, void *);
72static int decode_tuple_vers_1(device_t cbdev, device_t child, int id,
73    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
74    struct tuple_callbacks *info, void *);
75static int decode_tuple_funcid(device_t cbdev, device_t child, int id,
76    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
77    struct tuple_callbacks *info, void *);
78static int decode_tuple_manfid(device_t cbdev, device_t child, int id,
79    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
80    struct tuple_callbacks *info, void *);
81static int decode_tuple_funce(device_t cbdev, device_t child, int id,
82    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
83    struct tuple_callbacks *info, void *);
84static int decode_tuple_bar(device_t cbdev, device_t child, int id,
85    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
86    struct tuple_callbacks *info, void *);
87static int decode_tuple_unhandled(device_t cbdev, device_t child, int id,
88    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
89    struct tuple_callbacks *info, void *);
90static int decode_tuple_end(device_t cbdev, device_t child, int id,
91    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
92    struct tuple_callbacks *info, void *);
93
94static int	cardbus_read_tuple_conf(device_t cbdev, device_t child,
95		    uint32_t start, uint32_t *off, int *tupleid, int *len,
96		    uint8_t *tupledata);
97static int	cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
98		    uint32_t start, uint32_t *off, int *tupleid, int *len,
99		    uint8_t *tupledata);
100static int	cardbus_read_tuple(device_t cbdev, device_t child,
101		    struct resource *res, uint32_t start, uint32_t *off,
102		    int *tupleid, int *len, uint8_t *tupledata);
103static void	cardbus_read_tuple_finish(device_t cbdev, device_t child,
104		    int rid, struct resource *res);
105static struct resource	*cardbus_read_tuple_init(device_t cbdev, device_t child,
106		    uint32_t *start, int *rid);
107static int	decode_tuple(device_t cbdev, device_t child, int tupleid,
108		    int len, uint8_t *tupledata, uint32_t start,
109		    uint32_t *off, struct tuple_callbacks *callbacks,
110		    void *);
111#define	MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
112
113static 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/*
127 * Handler functions for various CIS tuples
128 */
129
130static int
131decode_tuple_generic(device_t cbdev, device_t child, int id,
132    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
133    struct tuple_callbacks *info, void *argp)
134{
135	int i;
136
137	if (cardbus_cis_debug) {
138		if (info)
139			printf("TUPLE: %s [%d]:", info->name, len);
140		else
141			printf("TUPLE: Unknown(0x%02x) [%d]:", id, len);
142
143		for (i = 0; i < len; i++) {
144			if (i % 0x10 == 0 && len > 0x10)
145				printf("\n       0x%02x:", i);
146			printf(" %02x", tupledata[i]);
147		}
148		printf("\n");
149	}
150	return (0);
151}
152
153static int
154decode_tuple_linktarget(device_t cbdev, device_t child, int id,
155    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
156    struct tuple_callbacks *info, void *argp)
157{
158	int i;
159
160	if (cardbus_cis_debug) {
161		printf("TUPLE: %s [%d]:", info->name, len);
162
163		for (i = 0; i < len; i++) {
164			if (i % 0x10 == 0 && len > 0x10)
165				printf("\n       0x%02x:", i);
166			printf(" %02x", tupledata[i]);
167		}
168		printf("\n");
169	}
170	if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
171	    tupledata[2] != 'S') {
172		printf("Invalid data for CIS Link Target!\n");
173		decode_tuple_generic(cbdev, child, id, len, tupledata,
174		    start, off, info, argp);
175		return (EINVAL);
176	}
177	return (0);
178}
179
180static int
181decode_tuple_vers_1(device_t cbdev, device_t child, int id,
182    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
183    struct tuple_callbacks *info, void *argp)
184{
185	int i;
186
187	if (cardbus_cis_debug) {
188		printf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
189		printf("Product name: ");
190		for (i = 2; i < len; i++) {
191			if (tupledata[i] == '\0')
192				printf(" | ");
193			else if (tupledata[i] == 0xff)
194				break;
195			else
196				printf("%c", tupledata[i]);
197		}
198		printf("\n");
199	}
200	return (0);
201}
202
203static int
204decode_tuple_funcid(device_t cbdev, device_t child, int id,
205    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
206    struct tuple_callbacks *info, void *argp)
207{
208	struct cardbus_devinfo *dinfo = device_get_ivars(child);
209	int numnames = nitems(funcnames);
210	int i;
211
212	if (cardbus_cis_debug) {
213		printf("Functions: ");
214		for (i = 0; i < len; i++) {
215			if (tupledata[i] < numnames)
216				printf("%s", funcnames[tupledata[i]]);
217			else
218				printf("Unknown(%d)", tupledata[i]);
219			if (i < len - 1)
220				printf(", ");
221		}
222		printf("\n");
223	}
224	if (len > 0)
225		dinfo->funcid = tupledata[0];		/* use first in list */
226	return (0);
227}
228
229static int
230decode_tuple_manfid(device_t cbdev, device_t child, int id,
231    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
232    struct tuple_callbacks *info, void *argp)
233{
234	struct cardbus_devinfo *dinfo = device_get_ivars(child);
235	int i;
236
237	if (cardbus_cis_debug) {
238		printf("Manufacturer ID: ");
239		for (i = 0; i < len; i++)
240			printf("%02x", tupledata[i]);
241		printf("\n");
242	}
243
244	if (len == 5) {
245		dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
246		dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
247	}
248	return (0);
249}
250
251static int
252decode_tuple_funce(device_t cbdev, device_t child, int id,
253    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
254    struct tuple_callbacks *info, void *argp)
255{
256	struct cardbus_devinfo *dinfo = device_get_ivars(child);
257	int type, i;
258
259	if (cardbus_cis_debug) {
260		printf("Function Extension: ");
261		for (i = 0; i < len; i++)
262			printf("%02x", tupledata[i]);
263		printf("\n");
264	}
265	if (len < 2)			/* too short */
266		return (0);
267	type = tupledata[0];		/* XXX <32 always? */
268	switch (dinfo->funcid) {
269	case PCCARD_FUNCTION_NETWORK:
270		switch (type) {
271		case PCCARD_TPLFE_TYPE_LAN_NID:
272			if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) {
273				/* ignore, warning? */
274				return (0);
275			}
276			bcopy(tupledata + 2, dinfo->funce.lan.nid,
277			    tupledata[1]);
278			break;
279		}
280		dinfo->fepresent |= 1<<type;
281		break;
282	}
283	return (0);
284}
285
286static int
287decode_tuple_bar(device_t cbdev, device_t child, int id,
288    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
289    struct tuple_callbacks *info, void *argp)
290{
291	struct cardbus_devinfo *dinfo = device_get_ivars(child);
292	int type;
293	uint8_t reg;
294	uint32_t bar;
295
296	if (len != 6) {
297		device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
298		return (EINVAL);
299	}
300
301	reg = *tupledata;
302	len = le32toh(*(uint32_t*)(tupledata + 2));
303	if (reg & TPL_BAR_REG_AS)
304		type = SYS_RES_IOPORT;
305	else
306		type = SYS_RES_MEMORY;
307
308	bar = reg & TPL_BAR_REG_ASI_MASK;
309	if (bar == 0) {
310		device_printf(cbdev, "Invalid BAR type 0 in CIS\n");
311		return (EINVAL);	/* XXX Return an error? */
312	} else if (bar == 7) {
313		/* XXX Should we try to map in Option ROMs? */
314		return (0);
315	}
316
317	/* Convert from BAR type to BAR offset */
318	bar = PCIR_BAR(bar - 1);
319
320	if (type == SYS_RES_MEMORY) {
321		if (reg & TPL_BAR_REG_PREFETCHABLE)
322			dinfo->mprefetchable |= (1 << PCI_RID2BAR(bar));
323		/*
324		 * The PC Card spec says we're only supposed to honor this
325		 * hint when the cardbus bridge is a child of pci0 (the main
326		 * bus).  The PC Card spec seems to indicate that this should
327		 * only be done on x86 based machines, which suggests that on
328		 * non-x86 machines the addresses can be anywhere.  Since the
329		 * hardware can do it on non-x86 machines, it should be able
330		 * to do it on x86 machines too.  Therefore, we can and should
331		 * ignore this hint.  Furthermore, the PC Card spec recommends
332		 * always allocating memory above 1MB, contradicting the other
333		 * part of the PC Card spec, it seems.  We make note of it,
334		 * but otherwise don't use this information.
335		 *
336		 * Some Realtek cards have this set in their CIS, but fail
337		 * to actually work when mapped this way, and experience
338		 * has shown ignoring this big to be a wise choice.
339		 *
340		 * XXX We should cite chapter and verse for standard refs.
341		 */
342		if (reg & TPL_BAR_REG_BELOW1MB)
343			dinfo->mbelow1mb |= (1 << PCI_RID2BAR(bar));
344	}
345
346	return (0);
347}
348
349static int
350decode_tuple_unhandled(device_t cbdev, device_t child, int id,
351    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
352    struct tuple_callbacks *info, void *argp)
353{
354	/* Make this message suck less XXX */
355	printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
356	return (EINVAL);
357}
358
359static int
360decode_tuple_end(device_t cbdev, device_t child, int id,
361    int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
362    struct tuple_callbacks *info, void *argp)
363{
364	if (cardbus_cis_debug)
365		printf("CIS reading done\n");
366	return (0);
367}
368
369/*
370 * Functions to read the a tuple from the card
371 */
372
373/*
374 * Read CIS bytes out of the config space.  We have to read it 4 bytes at a
375 * time and do the usual mask and shift to return the bytes.  The standard
376 * defines the byte order to be little endian.  pci_read_config converts it to
377 * host byte order.  This is why we have no endian conversion functions: the
378 * shifts wind up being endian neutral.  This is also why we avoid the obvious
379 * memcpy optimization.
380 */
381static int
382cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start,
383    uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
384{
385	int i, j;
386	uint32_t e;
387	uint32_t loc;
388
389	loc = start + *off;
390
391	e = pci_read_config(child, loc & ~0x3, 4);
392	e >>= 8 * (loc & 0x3);
393	*len = 0;
394	for (i = loc, j = -2; j < *len; j++, i++) {
395		if ((i & 0x3) == 0)
396			e = pci_read_config(child, i, 4);
397		if (j == -2)
398			*tupleid = 0xff & e;
399		else if (j == -1)
400			*len = 0xff & e;
401		else
402			tupledata[j] = 0xff & e;
403		e >>= 8;
404	}
405	*off += *len + 2;
406	return (0);
407}
408
409/*
410 * Read the CIS data out of memory.  We indirect through the bus space
411 * routines to ensure proper byte ordering conversions when necessary.
412 */
413static int
414cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start,
415    uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
416{
417	int ret;
418
419	*tupleid = bus_read_1(res, start + *off);
420	*len = bus_read_1(res, start + *off + 1);
421	bus_read_region_1(res, *off + start + 2, tupledata, *len);
422	ret = 0;
423	*off += *len + 2;
424	return (ret);
425}
426
427static int
428cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
429    uint32_t start, uint32_t *off, int *tupleid, int *len,
430    uint8_t *tupledata)
431{
432	if (res == CIS_CONFIG_SPACE)
433		return (cardbus_read_tuple_conf(cbdev, child, start, off,
434		    tupleid, len, tupledata));
435	return (cardbus_read_tuple_mem(cbdev, res, start, off, tupleid, len,
436	    tupledata));
437}
438
439static void
440cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
441    struct resource *res)
442{
443	if (res != CIS_CONFIG_SPACE) {
444		bus_release_resource(child, SYS_RES_MEMORY, rid, res);
445		bus_delete_resource(child, SYS_RES_MEMORY, rid);
446	}
447}
448
449static struct resource *
450cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
451    int *rid)
452{
453	struct resource *res;
454	uint32_t space;
455
456	space = *start & PCIM_CIS_ASI_MASK;
457	switch (space) {
458	case PCIM_CIS_ASI_CONFIG:
459		DEVPRINTF((cbdev, "CIS in PCI config space\n"));
460		/* CIS in PCI config space need no initialization */
461		return (CIS_CONFIG_SPACE);
462	case PCIM_CIS_ASI_BAR0:
463	case PCIM_CIS_ASI_BAR1:
464	case PCIM_CIS_ASI_BAR2:
465	case PCIM_CIS_ASI_BAR3:
466	case PCIM_CIS_ASI_BAR4:
467	case PCIM_CIS_ASI_BAR5:
468		*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
469		DEVPRINTF((cbdev, "CIS in BAR %#x\n", *rid));
470		break;
471	case PCIM_CIS_ASI_ROM:
472		*rid = PCIR_BIOS;
473		DEVPRINTF((cbdev, "CIS in option rom\n"));
474		break;
475	default:
476		device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
477		    space);
478		return (NULL);
479	}
480
481	/* allocate the memory space to read CIS */
482	res = bus_alloc_resource_any(child, SYS_RES_MEMORY, rid,
483	    rman_make_alignment_flags(4096) | RF_ACTIVE);
484	if (res == NULL) {
485		device_printf(cbdev, "Unable to allocate resource "
486		    "to read CIS.\n");
487		return (NULL);
488	}
489	DEVPRINTF((cbdev, "CIS Mapped to %#jx\n",
490	    rman_get_start(res)));
491
492	/* Flip to the right ROM image if CIS is in ROM */
493	if (space == PCIM_CIS_ASI_ROM) {
494		uint32_t imagesize;
495		uint32_t imagebase = 0;
496		uint32_t pcidata;
497		uint16_t romsig;
498		int romnum = 0;
499		int imagenum;
500
501		imagenum = (*start & PCIM_CIS_ROM_MASK) >> 28;
502		for (romnum = 0;; romnum++) {
503			romsig = bus_read_2(res,
504			    imagebase + CARDBUS_EXROM_SIGNATURE);
505			if (romsig != 0xaa55) {
506				device_printf(cbdev, "Bad header in rom %d: "
507				    "[%x] %04x\n", romnum, imagebase +
508				    CARDBUS_EXROM_SIGNATURE, romsig);
509				cardbus_read_tuple_finish(cbdev, child, *rid,
510				    res);
511				*rid = 0;
512				return (NULL);
513			}
514
515			/*
516			 * If this was the Option ROM image that we were
517			 * looking for, then we are done.
518			 */
519			if (romnum == imagenum)
520				break;
521
522			/* Find out where the next Option ROM image is */
523			pcidata = imagebase + bus_read_2(res,
524			    imagebase + CARDBUS_EXROM_DATA_PTR);
525			imagesize = bus_read_2(res,
526			    pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
527
528			if (imagesize == 0) {
529				/*
530				 * XXX some ROMs seem to have this as zero,
531				 * can we assume this means 1 block?
532				 */
533				device_printf(cbdev, "Warning, size of Option "
534				    "ROM image %d is 0 bytes, assuming 512 "
535				    "bytes.\n", romnum);
536				imagesize = 1;
537			}
538
539			/* Image size is in 512 byte units */
540			imagesize <<= 9;
541
542			if ((bus_read_1(res, pcidata +
543			    CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
544				device_printf(cbdev, "Cannot find CIS in "
545				    "Option ROM\n");
546				cardbus_read_tuple_finish(cbdev, child, *rid,
547				    res);
548				*rid = 0;
549				return (NULL);
550			}
551			imagebase += imagesize;
552		}
553		*start = imagebase + (*start & PCIM_CIS_ADDR_MASK);
554	} else {
555		*start = *start & PCIM_CIS_ADDR_MASK;
556	}
557	DEVPRINTF((cbdev, "CIS offset is %#x\n", *start));
558
559	return (res);
560}
561
562/*
563 * Dispatch the right handler function per tuple
564 */
565
566static int
567decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
568    uint8_t *tupledata, uint32_t start, uint32_t *off,
569    struct tuple_callbacks *callbacks, void *argp)
570{
571	int i;
572	for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
573		if (tupleid == callbacks[i].id)
574			return (callbacks[i].func(cbdev, child, tupleid, len,
575			    tupledata, start, off, &callbacks[i], argp));
576	}
577	return (callbacks[i].func(cbdev, child, tupleid, len,
578	    tupledata, start, off, NULL, argp));
579}
580
581int
582cardbus_parse_cis(device_t cbdev, device_t child,
583    struct tuple_callbacks *callbacks, void *argp)
584{
585	uint8_t *tupledata;
586	int tupleid = CISTPL_NULL;
587	int len;
588	int expect_linktarget;
589	uint32_t start, off;
590	struct resource *res;
591	int rid;
592
593	tupledata = malloc(MAXTUPLESIZE, M_DEVBUF, M_WAITOK | M_ZERO);
594	expect_linktarget = TRUE;
595	if ((start = pci_read_config(child, PCIR_CIS, 4)) == 0) {
596		DEVPRINTF((cbdev, "Warning: CIS pointer is 0: (no CIS)\n"));
597		free(tupledata, M_DEVBUF);
598		return (0);
599	}
600	DEVPRINTF((cbdev, "CIS pointer is %#x\n", start));
601	off = 0;
602	res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
603	if (res == NULL) {
604		device_printf(cbdev, "Unable to allocate resources for CIS\n");
605		free(tupledata, M_DEVBUF);
606		return (ENXIO);
607	}
608
609	do {
610		if (cardbus_read_tuple(cbdev, child, res, start, &off,
611		    &tupleid, &len, tupledata) != 0) {
612			device_printf(cbdev, "Failed to read CIS.\n");
613			cardbus_read_tuple_finish(cbdev, child, rid, res);
614			free(tupledata, M_DEVBUF);
615			return (ENXIO);
616		}
617
618		if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
619			device_printf(cbdev, "Expecting link target, got 0x%x\n",
620			    tupleid);
621			cardbus_read_tuple_finish(cbdev, child, rid, res);
622			free(tupledata, M_DEVBUF);
623			return (EINVAL);
624		}
625		expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
626		    tupledata, start, &off, callbacks, argp);
627		if (expect_linktarget != 0) {
628			device_printf(cbdev, "Parsing failed with %d\n",
629			    expect_linktarget);
630			cardbus_read_tuple_finish(cbdev, child, rid, res);
631			free(tupledata, M_DEVBUF);
632			return (expect_linktarget);
633		}
634	} while (tupleid != CISTPL_END);
635	cardbus_read_tuple_finish(cbdev, child, rid, res);
636	free(tupledata, M_DEVBUF);
637	return (0);
638}
639
640int
641cardbus_do_cis(device_t cbdev, device_t child)
642{
643	struct tuple_callbacks init_callbacks[] = {
644		MAKETUPLE(LONGLINK_CB,		unhandled),
645		MAKETUPLE(INDIRECT,		unhandled),
646		MAKETUPLE(LONGLINK_MFC,		unhandled),
647		MAKETUPLE(BAR,			bar),
648		MAKETUPLE(LONGLINK_A,		unhandled),
649		MAKETUPLE(LONGLINK_C,		unhandled),
650		MAKETUPLE(LINKTARGET,		linktarget),
651		MAKETUPLE(VERS_1,		vers_1),
652		MAKETUPLE(MANFID,		manfid),
653		MAKETUPLE(FUNCID,		funcid),
654		MAKETUPLE(FUNCE,		funce),
655		MAKETUPLE(END,			end),
656		MAKETUPLE(GENERIC,		generic),
657	};
658
659	return (cardbus_parse_cis(cbdev, child, init_callbacks, NULL));
660}
661