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