Nuke unused macro and comment
[dragonfly.git] / sys / dev / pccard / cardbus / cardbus_cis.c
blob0e210b513bfdb0f02af20928c4f58a16a0f9f0db
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 $
27 * $DragonFly: src/sys/dev/pccard/cardbus/cardbus_cis.c,v 1.8 2008/01/11 10:53:46 sephe Exp $
31 * CIS Handling for the Cardbus Bus
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
39 #include <sys/bus.h>
40 #include <sys/rman.h>
41 #include <sys/endian.h>
43 #include <sys/pciio.h>
44 #include <bus/pci/pcivar.h>
45 #include <bus/pci/pcireg.h>
47 #include <bus/pccard/pccardvar.h>
48 #include <bus/pccard/pccard_cis.h>
50 #include <dev/pccard/cardbus/cardbusreg.h>
51 #include <dev/pccard/cardbus/cardbusvar.h>
52 #include <dev/pccard/cardbus/cardbus_cis.h>
54 extern int cardbus_cis_debug;
56 #define DPRINTF(a) if (cardbus_cis_debug) kprintf a
57 #define DEVPRINTF(x) if (cardbus_cis_debug) device_printf x
59 struct tuple_callbacks;
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);
65 struct tuple_callbacks {
66 int id;
67 char *name;
68 tuple_cb *func;
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);
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);
118 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC }
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"
134 * Handler functions for various CIS tuples
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)
142 int i;
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);
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]);
155 kprintf("\n");
157 return (0);
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)
165 int i;
167 if (cardbus_cis_debug) {
168 kprintf("TUPLE: %s [%d]:", info->name, len);
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]);
175 kprintf("\n");
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);
184 return (0);
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)
192 int i;
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]);
205 kprintf("\n");
207 return (0);
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)
215 struct cardbus_devinfo *dinfo = device_get_ivars(child);
216 int numnames = sizeof(funcnames) / sizeof(funcnames[0]);
217 int i;
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(", ");
229 kprintf("\n");
231 if (len > 0)
232 dinfo->funcid = tupledata[0]; /* use first in list */
233 return (0);
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)
241 struct cardbus_devinfo *dinfo = device_get_ivars(child);
242 int i;
244 if (cardbus_cis_debug) {
245 kprintf("Manufacturer ID: ");
246 for (i = 0; i < len; i++)
247 kprintf("%02x", tupledata[i]);
248 kprintf("\n");
251 if (len == 5) {
252 dinfo->mfrid = tupledata[1] | (tupledata[2] << 8);
253 dinfo->prodid = tupledata[3] | (tupledata[4] << 8);
255 return (0);
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)
263 struct cardbus_devinfo *dinfo = device_get_ivars(child);
264 int type, i;
266 if (cardbus_cis_debug) {
267 kprintf("Function Extension: ");
268 for (i = 0; i < len; i++)
269 kprintf("%02x", tupledata[i]);
270 kprintf("\n");
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);
283 bcopy(tupledata + 2, dinfo->funce.lan.nid,
284 tupledata[1]);
285 break;
287 dinfo->fepresent |= 1<<type;
288 break;
290 return (0);
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)
298 struct cardbus_devinfo *dinfo = device_get_ivars(child);
299 int type;
300 uint8_t reg;
301 uint32_t bar, pci_bar;
303 if (len != 6) {
304 device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len);
305 return (EINVAL);
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;
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);
325 /* Convert from BAR type to BAR offset */
326 bar = CARDBUS_BASE0_REG + (bar - 1) * 4;
328 if (type == SYS_RES_MEMORY) {
329 if (reg & TPL_BAR_REG_PREFETCHABLE)
330 dinfo->mprefetchable |= BARBIT(bar);
331 #if 0
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.
347 * NetBSD ignores this bit, but it also ignores the
348 * prefetchable bit too, so that's not an indication of
349 * correctness.
351 if (reg & TPL_BAR_REG_BELOW1MB)
352 dinfo->mbelow1mb |= BARBIT(bar);
353 #endif
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.
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;
369 len = 1 << (ffs(pci_bar) - 1);
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)" : "") : ""));
378 resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len);
381 * Mark the appropriate bit in the PCI command register so that
382 * device drivers will know which type of BARs can be used.
384 pci_enable_io(child, type);
385 return (0);
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)
393 /* Make this message suck less XXX */
394 kprintf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len);
395 return (-1);
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)
403 if (cardbus_cis_debug)
404 kprintf("CIS reading done\n");
405 return (0);
409 * Functions to read the a tuple from the card
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)
416 int i, j;
417 uint32_t e;
418 uint32_t loc;
420 loc = start + *off;
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;
437 *off += *len + 2;
438 return (0);
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)
445 bus_space_tag_t bt;
446 bus_space_handle_t bh;
447 int ret;
449 bt = rman_get_bustag(res);
450 bh = rman_get_bushandle(res);
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);
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)
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));
474 static void
475 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid,
476 struct resource *res)
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);
485 static struct resource *
486 cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
487 int *rid)
489 uint32_t testval;
490 uint32_t size;
491 struct resource *res;
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
509 * This mask doesn't contain the bit that actually enables
510 * the Option ROM.
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);
521 /* figure out how much space we need */
522 pci_write_config(child, *rid, 0xffffffff, 4);
523 testval = pci_read_config(child, *rid, 4);
526 * This bit has a different meaning depending if we are dealing
527 * with a normal BAR or an Option ROM BAR.
529 if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) {
530 device_printf(cbdev, "CIS Space is IO, expecting memory.\n");
531 return (NULL);
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);
546 pci_write_config(child, *rid,
547 rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)?
548 CARDBUS_ROM_ENABLE : 0),
550 PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY);
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;
563 bt = rman_get_bustag(res);
564 bh = rman_get_bushandle(res);
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);
581 * If this was the Option ROM image that we were
582 * looking for, then we are done.
584 if (romnum == imagenum)
585 break;
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);
593 if (imagesize == 0) {
595 * XXX some ROMs seem to have this as zero,
596 * can we assume this means 1 block?
598 device_printf(cbdev, "Warning, size of Option "
599 "ROM image %d is 0 bytes, assuming 512 "
600 "bytes.\n", romnum);
601 imagesize = 1;
604 /* Image size is in 512 byte units */
605 imagesize <<= 9;
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);
616 imagebase += imagesize;
618 *start = imagebase + CARDBUS_CIS_ADDR(*start);
619 } else {
620 *start = CARDBUS_CIS_ADDR(*start);
623 return (res);
627 * Dispatch the right handler function per tuple
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)
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]));
641 return (callbacks[i].func(cbdev, child, tupleid, len,
642 tupledata, start, off, NULL));
645 static int
646 cardbus_parse_cis(device_t cbdev, device_t child,
647 struct tuple_callbacks *callbacks)
649 uint8_t tupledata[MAXTUPLESIZE];
650 int tupleid = CISTPL_NULL;
651 int len;
652 int expect_linktarget;
653 uint32_t start, off;
654 struct resource *res;
655 int rid;
657 bzero(tupledata, MAXTUPLESIZE);
658 expect_linktarget = TRUE;
659 if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0) {
660 if (bootverbose)
661 device_printf(cbdev, "CIS pointer is 0!\n");
662 return (ENXIO);
664 off = 0;
665 res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
666 if (res == NULL) {
667 device_printf(cbdev, "Unable to allocate resources for CIS\n");
668 return (ENXIO);
671 do {
672 if (0 != cardbus_read_tuple(cbdev, child, res, start, &off,
673 &tupleid, &len, tupledata)) {
674 device_printf(cbdev, "Failed to read CIS.\n");
675 cardbus_read_tuple_finish(cbdev, child, rid, res);
676 return (ENXIO);
679 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) {
680 device_printf(cbdev, "Expecting link target, got 0x%x\n",
681 tupleid);
682 cardbus_read_tuple_finish(cbdev, child, rid, res);
683 return (EINVAL);
685 expect_linktarget = decode_tuple(cbdev, child, tupleid, len,
686 tupledata, start, &off, callbacks);
687 if (expect_linktarget != 0) {
688 device_printf(cbdev, "Parsing failed with %d\n",
689 expect_linktarget);
690 cardbus_read_tuple_finish(cbdev, child, rid, res);
691 return (expect_linktarget);
693 } while (tupleid != CISTPL_END);
694 cardbus_read_tuple_finish(cbdev, child, rid, res);
695 return (0);
699 cardbus_do_cis(device_t cbdev, device_t child)
701 int ret;
702 struct tuple_callbacks init_callbacks[] = {
703 MAKETUPLE(LONGLINK_CB, unhandled),
704 MAKETUPLE(INDIRECT, unhandled),
705 MAKETUPLE(LONGLINK_MFC, unhandled),
706 MAKETUPLE(BAR, bar),
707 MAKETUPLE(LONGLINK_A, unhandled),
708 MAKETUPLE(LONGLINK_C, unhandled),
709 MAKETUPLE(LINKTARGET, linktarget),
710 MAKETUPLE(VERS_1, vers_1),
711 MAKETUPLE(MANFID, manfid),
712 MAKETUPLE(FUNCID, funcid),
713 MAKETUPLE(FUNCE, funce),
714 MAKETUPLE(END, end),
715 MAKETUPLE(GENERIC, generic),
718 ret = cardbus_parse_cis(cbdev, child, init_callbacks);
719 if (ret < 0)
720 return (ret);
721 return 0;