1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 59 extern 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 66 static 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 *); 69 static 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 *); 72 static 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 *); 75 static 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 *); 78 static 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 *); 81 static 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 *); 84 static 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 *); 87 static 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 *); 90 static 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 94 static 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); 97 static 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); 100 static 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); 103 static void cardbus_read_tuple_finish(device_t cbdev, device_t child, 104 int rid, struct resource *res); 105 static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child, 106 uint32_t *start, int *rid); 107 static 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 113 static 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 130 static int 131 decode_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 153 static int 154 decode_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 180 static int 181 decode_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 203 static int 204 decode_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 229 static int 230 decode_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 251 static int 252 decode_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 286 static int 287 decode_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 349 static int 350 decode_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 359 static int 360 decode_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 */ 381 static int 382 cardbus_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 */ 413 static int 414 cardbus_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 427 static int 428 cardbus_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 439 static void 440 cardbus_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 449 static struct resource * 450 cardbus_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 566 static int 567 decode_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 581 int 582 cardbus_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 640 int 641 cardbus_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