dsynth - Make dummy /usr/packages directory for pkg compatibility
[dragonfly.git] / sys / dev / pccard / cardbus / cardbus_cis.c
blob976fe341bb1e3cd4369b7205a5d6367b855454f0
1 /*-
2 * Copyright (c) 2000,2001 Jonathan Chen.
3 * All rights reserved.
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.
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.
26 * $FreeBSD: src/sys/dev/cardbus/cardbus_cis.c,v 1.50 2005/02/20 20:36:16 imp Exp $
30 * CIS Handling for the Cardbus Bus
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/malloc.h>
38 #include <sys/bus.h>
39 #include <sys/rman.h>
40 #include <sys/endian.h>
42 #include <sys/pciio.h>
43 #include <bus/pci/pcivar.h>
44 #include <bus/pci/pcireg.h>
46 #include <bus/pccard/pccardvar.h>
47 #include <bus/pccard/pccard_cis.h>
49 #include <dev/pccard/cardbus/cardbusreg.h>
50 #include <dev/pccard/cardbus/cardbusvar.h>
51 #include <dev/pccard/cardbus/cardbus_cis.h>
53 extern int cardbus_cis_debug;
55 #define DPRINTF(a) if (cardbus_cis_debug) kprintf a
56 #define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
58 struct tuple_callbacks;
60 typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
61 uint8_t *tupledata, uint32_t start, uint32_t *off,
62 struct tuple_callbacks *info);
64 struct tuple_callbacks {
65 int id;
66 char *name;
67 tuple_cb *func;
70 static int decode_tuple_generic(device_t cbdev, device_t child, int id,
71 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
72 struct tuple_callbacks *info);
73 static int decode_tuple_linktarget(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_vers_1(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_funcid(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_manfid(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_funce(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_bar(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_unhandled(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_end(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);
98 static int cardbus_read_tuple_conf(device_t cbdev, device_t child,
99 uint32_t start, uint32_t *off, int *tupleid, int *len,
100 uint8_t *tupledata);
101 static int cardbus_read_tuple_mem(device_t cbdev, struct resource *res,
102 uint32_t start, uint32_t *off, int *tupleid, int *len,
103 uint8_t *tupledata);
104 static int cardbus_read_tuple(device_t cbdev, device_t child,
105 struct resource *res, uint32_t start, uint32_t *off,
106 int *tupleid, int *len, uint8_t *tupledata);
107 static void cardbus_read_tuple_finish(device_t cbdev, device_t child,
108 int rid, struct resource *res);
109 static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child,
110 uint32_t *start, int *rid);
111 static int decode_tuple(device_t cbdev, device_t child, int tupleid,
112 int len, uint8_t *tupledata, uint32_t start,
113 uint32_t *off, struct tuple_callbacks *callbacks);
114 static int cardbus_parse_cis(device_t cbdev, device_t child,
115 struct tuple_callbacks *callbacks);
117 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
119 static char *funcnames[] = {
120 "Multi-Functioned",
121 "Memory",
122 "Serial Port",
123 "Parallel Port",
124 "Fixed Disk",
125 "Video Adaptor",
126 "Network Adaptor",
127 "AIMS",
128 "SCSI",
129 "Security"
133 * Handler functions for various CIS tuples
136 static int
137 decode_tuple_generic(device_t cbdev, device_t child, int id,
138 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
139 struct tuple_callbacks *info)
141 int i;
143 if (cardbus_cis_debug) {
144 if (info)
145 kprintf("TUPLE: %s [%d]:", info->name, len);
146 else
147 kprintf("TUPLE: Unknown(0x%02x) [%d]:", id, len);
149 for (i = 0; i < len; i++) {
150 if (i % 0x10 == 0 && len > 0x10)
151 kprintf("\n 0x%02x:", i);
152 kprintf(" %02x", tupledata[i]);
154 kprintf("\n");
156 return (0);
159 static int
160 decode_tuple_linktarget(device_t cbdev, device_t child, int id,
161 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
162 struct tuple_callbacks *info)
164 int i;
166 if (cardbus_cis_debug) {
167 kprintf("TUPLE: %s [%d]:", info->name, len);
169 for (i = 0; i < len; i++) {
170 if (i % 0x10 == 0 && len > 0x10)
171 kprintf("\n 0x%02x:", i);
172 kprintf(" %02x", tupledata[i]);
174 kprintf("\n");
176 if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' ||
177 tupledata[2] != 'S') {
178 kprintf("Invalid data for CIS Link Target!\n");
179 decode_tuple_generic(cbdev, child, id, len, tupledata,
180 start, off, info);
181 return (EINVAL);
183 return (0);
186 static int
187 decode_tuple_vers_1(device_t cbdev, device_t child, int id,
188 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
189 struct tuple_callbacks *info)
191 int i;
193 if (cardbus_cis_debug) {
194 kprintf("Product version: %d.%d\n", tupledata[0], tupledata[1]);
195 kprintf("Product name: ");
196 for (i = 2; i < len; i++) {
197 if (tupledata[i] == '\0')
198 kprintf(" | ");
199 else if (tupledata[i] == 0xff)
200 break;
201 else
202 kprintf("%c", tupledata[i]);
204 kprintf("\n");
206 return (0);
209 static int
210 decode_tuple_funcid(device_t cbdev, device_t child, int id,
211 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
212 struct tuple_callbacks *info)
214 struct cardbus_devinfo *dinfo = device_get_ivars(child);
215 int numnames = NELEM(funcnames);
216 int i;
218 if (cardbus_cis_debug) {
219 kprintf("Functions: ");
220 for (i = 0; i < len; i++) {
221 if (tupledata[i] < numnames)
222 kprintf("%s", funcnames[tupledata[i]]);
223 else
224 kprintf("Unknown(%d)", tupledata[i]);
225 if (i < len-1)
226 kprintf(", ");
228 kprintf("\n");
230 if (len > 0)
231 dinfo->funcid = tupledata[0]; /* use first in list */
232 return (0);
235 static int
236 decode_tuple_manfid(device_t cbdev, device_t child, int id,
237 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
238 struct tuple_callbacks *info)
240 struct cardbus_devinfo *dinfo = device_get_ivars(child);
241 int i;
243 if (cardbus_cis_debug) {
244 kprintf("Manufacturer ID: ");
245 for (i = 0; i < len; i++)
246 kprintf("%02x", tupledata[i]);
247 kprintf("\n");
250 if (len == 5) {
251 dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
252 dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
254 return (0);
257 static int
258 decode_tuple_funce(device_t cbdev, device_t child, int id,
259 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
260 struct tuple_callbacks *info)
262 struct cardbus_devinfo *dinfo = device_get_ivars(child);
263 int type, i;
265 if (cardbus_cis_debug) {
266 kprintf("Function Extension: ");
267 for (i = 0; i < len; i++)
268 kprintf("%02x", tupledata[i]);
269 kprintf("\n");
271 if (len < 2) /* too short */
272 return (0);
273 type = tupledata[0]; /* XXX <32 always? */
274 switch (dinfo->funcid) {
275 case PCCARD_FUNCTION_NETWORK:
276 switch (type) {
277 case PCCARD_TPLFE_TYPE_LAN_NID:
278 if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) {
279 /* ignore, warning? */
280 return (0);
282 bcopy(tupledata + 2, dinfo->funce.lan.nid,
283 tupledata[1]);
284 break;
286 dinfo->fepresent |= 1<<type;
287 break;
289 return (0);
292 static int
293 decode_tuple_bar(device_t cbdev, device_t child, int id,
294 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
295 struct tuple_callbacks *info)
297 struct cardbus_devinfo *dinfo = device_get_ivars(child);
298 int type;
299 uint8_t reg;
300 uint32_t bar, pci_bar;
302 if (len != 6) {
303 device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
304 return (EINVAL);
307 reg = *tupledata;
308 len = le32toh(*(uint32_t*)(tupledata + 2));
309 if (reg & TPL_BAR_REG_AS) {
310 type = SYS_RES_IOPORT;
311 } else {
312 type = SYS_RES_MEMORY;
315 bar = reg & TPL_BAR_REG_ASI_MASK;
316 if (bar == 0) {
317 device_printf(cbdev, "Invalid BAR type 0 in CIS\n");
318 return (EINVAL); /* XXX Return an error? */
319 } else if (bar == 7) {
320 /* XXX Should we try to map in Option ROMs? */
321 return (0);
324 /* Convert from BAR type to BAR offset */
325 bar = CARDBUS_BASE0_REG + (bar - 1) * 4;
327 if (type == SYS_RES_MEMORY) {
328 if (reg & TPL_BAR_REG_PREFETCHABLE)
329 dinfo->mprefetchable |= BARBIT(bar);
330 #if 0
332 * XXX: It appears from a careful reading of the spec
333 * that we're not supposed to honor this when the bridge
334 * is not on the main system bus. PCI spec doesn't appear
335 * to allow for memory ranges not listed in the bridge's
336 * decode range to be decoded. The PC Card spec seems to
337 * indicate that this should only be done on x86 based
338 * machines, which seems to imply that on non-x86 machines
339 * the adddresses can be anywhere. This further implies that
340 * since the hardware can do it on non-x86 machines, it should
341 * be able to do it on x86 machines. Therefore, we can and
342 * should ignore this hint. Furthermore, the PC Card spec
343 * recommends always allocating memory above 1MB, contradicting
344 * the other part of the PC Card spec.
346 * NetBSD ignores this bit, but it also ignores the
347 * prefetchable bit too, so that's not an indication of
348 * correctness.
350 if (reg & TPL_BAR_REG_BELOW1MB)
351 dinfo->mbelow1mb |= BARBIT(bar);
352 #endif
356 * Sanity check the BAR length reported in the CIS with the length
357 * encoded in the PCI BAR. The latter seems to be more reliable.
358 * XXX - This probably belongs elsewhere.
360 pci_write_config(child, bar, 0xffffffff, 4);
361 pci_bar = pci_read_config(child, bar, 4);
362 if ((pci_bar != 0x0) && (pci_bar != 0xffffffff)) {
363 if (type == SYS_RES_MEMORY) {
364 pci_bar &= ~0xf;
365 } else {
366 pci_bar &= ~0x3;
368 len = 1 << (ffs(pci_bar) - 1);
371 DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x%s%s\n",
372 (type == SYS_RES_MEMORY) ? "MEM" : "IO", bar, len,
373 (type == SYS_RES_MEMORY && dinfo->mprefetchable & BARBIT(bar)) ?
374 " (Prefetchable)" : "", type == SYS_RES_MEMORY ?
375 ((dinfo->mbelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "") : ""));
377 resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len, -1);
380 * Mark the appropriate bit in the PCI command register so that
381 * device drivers will know which type of BARs can be used.
383 pci_enable_io(child, type);
384 return (0);
387 static int
388 decode_tuple_unhandled(device_t cbdev, device_t child, int id,
389 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
390 struct tuple_callbacks *info)
392 /* Make this message suck less XXX */
393 kprintf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
394 return (-1);
397 static int
398 decode_tuple_end(device_t cbdev, device_t child, int id,
399 int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
400 struct tuple_callbacks *info)
402 if (cardbus_cis_debug)
403 kprintf("CIS reading done\n");
404 return (0);
408 * Functions to read the a tuple from the card
411 static int
412 cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start,
413 uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
415 int i, j;
416 uint32_t e;
417 uint32_t loc;
419 loc = start + *off;
421 e = pci_read_config(child, loc - loc % 4, 4);
422 for (j = loc % 4; j > 0; j--)
423 e >>= 8;
424 *len = 0;
425 for (i = loc, j = -2; j < *len; j++, i++) {
426 if (i % 4 == 0)
427 e = pci_read_config(child, i, 4);
428 if (j == -2)
429 *tupleid = 0xff & e;
430 else if (j == -1)
431 *len = 0xff & e;
432 else
433 tupledata[j] = 0xff & e;
434 e >>= 8;
436 *off += *len + 2;
437 return (0);
440 static int
441 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start,
442 uint32_t *off, int *tupleid, int *len, uint8_t *tupledata)
444 bus_space_tag_t bt;
445 bus_space_handle_t bh;
446 int ret;
448 bt = rman_get_bustag(res);
449 bh = rman_get_bushandle(res);
451 *tupleid = bus_space_read_1(bt, bh, start + *off);
452 *len = bus_space_read_1(bt, bh, start + *off + 1);
453 bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len);
454 ret = 0;
455 *off += *len + 2;
456 return (ret);
459 static int
460 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res,
461 uint32_t start, uint32_t *off, int *tupleid, int *len,
462 uint8_t *tupledata)
464 if (res == (struct resource*)~0UL) {
465 return (cardbus_read_tuple_conf(cbdev, child, start, off,
466 tupleid, len, tupledata));
467 } else {
468 return (cardbus_read_tuple_mem(cbdev, res, start, off,
469 tupleid, len, tupledata));
473 static void
474 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
475 struct resource *res)
477 if (res != (struct resource*)~0UL) {
478 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res);
479 pci_write_config(child, rid, 0, 4);
480 PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY);
484 static struct resource *
485 cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
486 int *rid)
488 uint32_t testval;
489 uint32_t size;
490 struct resource *res;
492 switch (CARDBUS_CIS_SPACE(*start)) {
493 case CARDBUS_CIS_ASI_TUPLE:
494 /* CIS in PCI config space need no initialization */
495 return ((struct resource*)~0UL);
496 case CARDBUS_CIS_ASI_BAR0:
497 case CARDBUS_CIS_ASI_BAR1:
498 case CARDBUS_CIS_ASI_BAR2:
499 case CARDBUS_CIS_ASI_BAR3:
500 case CARDBUS_CIS_ASI_BAR4:
501 case CARDBUS_CIS_ASI_BAR5:
502 *rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4;
503 break;
504 case CARDBUS_CIS_ASI_ROM:
505 *rid = CARDBUS_ROM_REG;
506 #if 0
508 * This mask doesn't contain the bit that actually enables
509 * the Option ROM.
511 pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4);
512 #endif
513 break;
514 default:
515 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
516 CARDBUS_CIS_SPACE(*start));
517 return (NULL);
520 /* figure out how much space we need */
521 pci_write_config(child, *rid, 0xffffffff, 4);
522 testval = pci_read_config(child, *rid, 4);
525 * This bit has a different meaning depending if we are dealing
526 * with a normal BAR or an Option ROM BAR.
528 if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) {
529 device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
530 return (NULL);
533 size = CARDBUS_MAPREG_MEM_SIZE(testval);
534 /* XXX Is this some kind of hack? */
535 if (size < 4096)
536 size = 4096;
537 /* allocate the memory space to read CIS */
538 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size,
539 rman_make_alignment_flags(size) | RF_ACTIVE);
540 if (res == NULL) {
541 device_printf(cbdev, "Unable to allocate resource "
542 "to read CIS.\n");
543 return (NULL);
545 pci_write_config(child, *rid,
546 rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
547 CARDBUS_ROM_ENABLE : 0),
549 PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
551 /* Flip to the right ROM image if CIS is in ROM */
552 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) {
553 bus_space_tag_t bt;
554 bus_space_handle_t bh;
555 uint32_t imagesize;
556 uint32_t imagebase = 0;
557 uint32_t pcidata;
558 uint16_t romsig;
559 int romnum = 0;
560 int imagenum;
562 bt = rman_get_bustag(res);
563 bh = rman_get_bushandle(res);
565 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start);
566 for (romnum = 0;; romnum++) {
567 romsig = bus_space_read_2(bt, bh,
568 imagebase + CARDBUS_EXROM_SIGNATURE);
569 if (romsig != 0xaa55) {
570 device_printf(cbdev, "Bad header in rom %d: "
571 "[%x] %04x\n", romnum, imagebase +
572 CARDBUS_EXROM_SIGNATURE, romsig);
573 bus_release_resource(cbdev, SYS_RES_MEMORY,
574 *rid, res);
575 *rid = 0;
576 return (NULL);
580 * If this was the Option ROM image that we were
581 * looking for, then we are done.
583 if (romnum == imagenum)
584 break;
586 /* Find out where the next Option ROM image is */
587 pcidata = imagebase + bus_space_read_2(bt, bh,
588 imagebase + CARDBUS_EXROM_DATA_PTR);
589 imagesize = bus_space_read_2(bt, bh,
590 pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH);
592 if (imagesize == 0) {
594 * XXX some ROMs seem to have this as zero,
595 * can we assume this means 1 block?
597 device_printf(cbdev, "Warning, size of Option "
598 "ROM image %d is 0 bytes, assuming 512 "
599 "bytes.\n", romnum);
600 imagesize = 1;
603 /* Image size is in 512 byte units */
604 imagesize <<= 9;
606 if ((bus_space_read_1(bt, bh, pcidata +
607 CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) {
608 device_printf(cbdev, "Cannot find CIS in "
609 "Option ROM\n");
610 bus_release_resource(cbdev, SYS_RES_MEMORY,
611 *rid, res);
612 *rid = 0;
613 return (NULL);
615 imagebase += imagesize;
617 *start = imagebase + CARDBUS_CIS_ADDR(*start);
618 } else {
619 *start = CARDBUS_CIS_ADDR(*start);
622 return (res);
626 * Dispatch the right handler function per tuple
629 static int
630 decode_tuple(device_t cbdev, device_t child, int tupleid, int len,
631 uint8_t *tupledata, uint32_t start, uint32_t *off,
632 struct tuple_callbacks *callbacks)
634 int i;
635 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) {
636 if (tupleid == callbacks[i].id)
637 return (callbacks[i].func(cbdev, child, tupleid, len,
638 tupledata, start, off, &callbacks[i]));
640 return (callbacks[i].func(cbdev, child, tupleid, len,
641 tupledata, start, off, NULL));
644 static int
645 cardbus_parse_cis(device_t cbdev, device_t child,
646 struct tuple_callbacks *callbacks)
648 uint8_t tupledata[MAXTUPLESIZE];
649 int tupleid = CISTPL_NULL;
650 int len;
651 int expect_linktarget;
652 uint32_t start, off;
653 struct resource *res;
654 int rid;
656 bzero(tupledata, MAXTUPLESIZE);
657 expect_linktarget = TRUE;
658 if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0) {
659 if (bootverbose)
660 device_printf(cbdev, "CIS pointer is 0!\n");
661 return (ENXIO);
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);
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);
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);
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);
692 } while (tupleid != CISTPL_END);
693 cardbus_read_tuple_finish(cbdev, child, rid, res);
694 return (0);
698 cardbus_do_cis(device_t cbdev, device_t child)
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),
717 ret = cardbus_parse_cis(cbdev, child, init_callbacks);
718 if (ret < 0)
719 return (ret);
720 return 0;