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