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