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 struct tuple_callbacks; 62 63 typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len, 64 uint8_t *tupledata, uint32_t start, uint32_t *off, 65 struct tuple_callbacks *info); 66 67 struct tuple_callbacks { 68 int id; 69 char *name; 70 tuple_cb *func; 71 }; 72 73 static int decode_tuple_generic(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); 76 static int decode_tuple_linktarget(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); 79 static int decode_tuple_vers_1(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); 82 static int decode_tuple_funcid(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); 85 static int decode_tuple_manfid(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); 88 static int decode_tuple_funce(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); 91 static int decode_tuple_bar(device_t cbdev, device_t child, int id, 92 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 93 struct tuple_callbacks *info); 94 static int decode_tuple_unhandled(device_t cbdev, device_t child, int id, 95 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 96 struct tuple_callbacks *info); 97 static int decode_tuple_end(device_t cbdev, device_t child, int id, 98 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 99 struct tuple_callbacks *info); 100 101 static int cardbus_read_tuple_conf(device_t cbdev, device_t child, 102 uint32_t start, uint32_t *off, int *tupleid, int *len, 103 uint8_t *tupledata); 104 static int cardbus_read_tuple_mem(device_t cbdev, struct resource *res, 105 uint32_t start, uint32_t *off, int *tupleid, int *len, 106 uint8_t *tupledata); 107 static int cardbus_read_tuple(device_t cbdev, device_t child, 108 struct resource *res, uint32_t start, uint32_t *off, 109 int *tupleid, int *len, uint8_t *tupledata); 110 static void cardbus_read_tuple_finish(device_t cbdev, device_t child, 111 int rid, struct resource *res); 112 static struct resource *cardbus_read_tuple_init(device_t cbdev, device_t child, 113 uint32_t *start, int *rid); 114 static int decode_tuple(device_t cbdev, device_t child, int tupleid, 115 int len, uint8_t *tupledata, uint32_t start, 116 uint32_t *off, struct tuple_callbacks *callbacks); 117 static int cardbus_parse_cis(device_t cbdev, device_t child, 118 struct tuple_callbacks *callbacks); 119 120 #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 121 122 static char *funcnames[] = { 123 "Multi-Functioned", 124 "Memory", 125 "Serial Port", 126 "Parallel Port", 127 "Fixed Disk", 128 "Video Adaptor", 129 "Network Adaptor", 130 "AIMS", 131 "SCSI", 132 "Security" 133 }; 134 135 /* 136 * Handler functions for various CIS tuples 137 */ 138 139 static int 140 decode_tuple_generic(device_t cbdev, device_t child, int id, 141 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 142 struct tuple_callbacks *info) 143 { 144 int i; 145 146 if (cardbus_cis_debug) { 147 if (info) 148 printf("TUPLE: %s [%d]:", info->name, len); 149 else 150 printf("TUPLE: Unknown(0x%02x) [%d]:", id, len); 151 152 for (i = 0; i < len; i++) { 153 if (i % 0x10 == 0 && len > 0x10) 154 printf("\n 0x%02x:", i); 155 printf(" %02x", tupledata[i]); 156 } 157 printf("\n"); 158 } 159 return (0); 160 } 161 162 static int 163 decode_tuple_linktarget(device_t cbdev, device_t child, int id, 164 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 165 struct tuple_callbacks *info) 166 { 167 int i; 168 169 if (cardbus_cis_debug) { 170 printf("TUPLE: %s [%d]:", info->name, len); 171 172 for (i = 0; i < len; i++) { 173 if (i % 0x10 == 0 && len > 0x10) 174 printf("\n 0x%02x:", i); 175 printf(" %02x", tupledata[i]); 176 } 177 printf("\n"); 178 } 179 if (len != 3 || tupledata[0] != 'C' || tupledata[1] != 'I' || 180 tupledata[2] != 'S') { 181 printf("Invalid data for CIS Link Target!\n"); 182 decode_tuple_generic(cbdev, child, id, len, tupledata, 183 start, off, info); 184 return (EINVAL); 185 } 186 return (0); 187 } 188 189 static int 190 decode_tuple_vers_1(device_t cbdev, device_t child, int id, 191 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 192 struct tuple_callbacks *info) 193 { 194 int i; 195 196 if (cardbus_cis_debug) { 197 printf("Product version: %d.%d\n", tupledata[0], tupledata[1]); 198 printf("Product name: "); 199 for (i = 2; i < len; i++) { 200 if (tupledata[i] == '\0') 201 printf(" | "); 202 else if (tupledata[i] == 0xff) 203 break; 204 else 205 printf("%c", tupledata[i]); 206 } 207 printf("\n"); 208 } 209 return (0); 210 } 211 212 static int 213 decode_tuple_funcid(device_t cbdev, device_t child, int id, 214 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 215 struct tuple_callbacks *info) 216 { 217 struct cardbus_devinfo *dinfo = device_get_ivars(child); 218 int numnames = sizeof(funcnames) / sizeof(funcnames[0]); 219 int i; 220 221 if (cardbus_cis_debug) { 222 printf("Functions: "); 223 for (i = 0; i < len; i++) { 224 if (tupledata[i] < numnames) 225 printf("%s", funcnames[tupledata[i]]); 226 else 227 printf("Unknown(%d)", tupledata[i]); 228 if (i < len-1) 229 printf(", "); 230 } 231 printf("\n"); 232 } 233 if (len > 0) 234 dinfo->funcid = tupledata[0]; /* use first in list */ 235 return (0); 236 } 237 238 static int 239 decode_tuple_manfid(device_t cbdev, device_t child, int id, 240 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 241 struct tuple_callbacks *info) 242 { 243 struct cardbus_devinfo *dinfo = device_get_ivars(child); 244 int i; 245 246 if (cardbus_cis_debug) { 247 printf("Manufacturer ID: "); 248 for (i = 0; i < len; i++) 249 printf("%02x", tupledata[i]); 250 printf("\n"); 251 } 252 253 if (len == 5) { 254 dinfo->mfrid = tupledata[1] | (tupledata[2] << 8); 255 dinfo->prodid = tupledata[3] | (tupledata[4] << 8); 256 } 257 return (0); 258 } 259 260 static int 261 decode_tuple_funce(device_t cbdev, device_t child, int id, 262 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 263 struct tuple_callbacks *info) 264 { 265 struct cardbus_devinfo *dinfo = device_get_ivars(child); 266 int type, i; 267 268 if (cardbus_cis_debug) { 269 printf("Function Extension: "); 270 for (i = 0; i < len; i++) 271 printf("%02x", tupledata[i]); 272 printf("\n"); 273 } 274 if (len < 2) /* too short */ 275 return (0); 276 type = tupledata[0]; /* XXX <32 always? */ 277 switch (dinfo->funcid) { 278 case PCCARD_FUNCTION_NETWORK: 279 switch (type) { 280 case PCCARD_TPLFE_TYPE_LAN_NID: 281 if (tupledata[1] > sizeof(dinfo->funce.lan.nid)) { 282 /* ignore, warning? */ 283 return (0); 284 } 285 bcopy(tupledata + 2, dinfo->funce.lan.nid, 286 tupledata[1]); 287 break; 288 } 289 dinfo->fepresent |= 1<<type; 290 break; 291 } 292 return (0); 293 } 294 295 static int 296 decode_tuple_bar(device_t cbdev, device_t child, int id, 297 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 298 struct tuple_callbacks *info) 299 { 300 struct cardbus_devinfo *dinfo = device_get_ivars(child); 301 int type; 302 uint8_t reg; 303 uint32_t bar, pci_bar; 304 305 if (len != 6) { 306 device_printf(cbdev, "CIS BAR length not 6 (%d)\n", len); 307 return (EINVAL); 308 } 309 310 reg = *tupledata; 311 len = le32toh(*(uint32_t*)(tupledata + 2)); 312 if (reg & TPL_BAR_REG_AS) { 313 type = SYS_RES_IOPORT; 314 } else { 315 type = SYS_RES_MEMORY; 316 } 317 318 bar = reg & TPL_BAR_REG_ASI_MASK; 319 if (bar == 0) { 320 device_printf(cbdev, "Invalid BAR type 0 in CIS\n"); 321 return (EINVAL); /* XXX Return an error? */ 322 } else if (bar == 7) { 323 /* XXX Should we try to map in Option ROMs? */ 324 return (0); 325 } 326 327 /* Convert from BAR type to BAR offset */ 328 bar = CARDBUS_BASE0_REG + (bar - 1) * 4; 329 330 if (type == SYS_RES_MEMORY) { 331 if (reg & TPL_BAR_REG_PREFETCHABLE) 332 dinfo->mprefetchable |= BARBIT(bar); 333 #if 0 334 /* 335 * XXX: It appears from a careful reading of the spec 336 * that we're not supposed to honor this when the bridge 337 * is not on the main system bus. PCI spec doesn't appear 338 * to allow for memory ranges not listed in the bridge's 339 * decode range to be decoded. The PC Card spec seems to 340 * indicate that this should only be done on x86 based 341 * machines, which seems to imply that on non-x86 machines 342 * the adddresses can be anywhere. This further implies that 343 * since the hardware can do it on non-x86 machines, it should 344 * be able to do it on x86 machines. Therefore, we can and 345 * should ignore this hint. Furthermore, the PC Card spec 346 * recommends always allocating memory above 1MB, contradicting 347 * the other part of the PC Card spec. 348 * 349 * NetBSD ignores this bit, but it also ignores the 350 * prefetchable bit too, so that's not an indication of 351 * correctness. 352 */ 353 if (reg & TPL_BAR_REG_BELOW1MB) 354 dinfo->mbelow1mb |= BARBIT(bar); 355 #endif 356 } 357 358 /* 359 * Sanity check the BAR length reported in the CIS with the length 360 * encoded in the PCI BAR. The latter seems to be more reliable. 361 * XXX - This probably belongs elsewhere. 362 */ 363 pci_write_config(child, bar, 0xffffffff, 4); 364 pci_bar = pci_read_config(child, bar, 4); 365 if ((pci_bar != 0x0) && (pci_bar != 0xffffffff)) { 366 if (type == SYS_RES_MEMORY) { 367 pci_bar &= ~0xf; 368 } else { 369 pci_bar &= ~0x3; 370 } 371 len = 1 << (ffs(pci_bar) - 1); 372 } 373 374 DEVPRINTF((cbdev, "Opening BAR: type=%s, bar=%02x, len=%04x%s%s\n", 375 (type == SYS_RES_MEMORY) ? "MEM" : "IO", bar, len, 376 (type == SYS_RES_MEMORY && dinfo->mprefetchable & BARBIT(bar)) ? 377 " (Prefetchable)" : "", type == SYS_RES_MEMORY ? 378 ((dinfo->mbelow1mb & BARBIT(bar)) ? " (Below 1Mb)" : "") : "")); 379 380 resource_list_add(&dinfo->pci.resources, type, bar, 0UL, ~0UL, len); 381 382 /* 383 * Mark the appropriate bit in the PCI command register so that 384 * device drivers will know which type of BARs can be used. 385 */ 386 pci_enable_io(child, type); 387 return (0); 388 } 389 390 static int 391 decode_tuple_unhandled(device_t cbdev, device_t child, int id, 392 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 393 struct tuple_callbacks *info) 394 { 395 /* Make this message suck less XXX */ 396 printf("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len); 397 return (-1); 398 } 399 400 static int 401 decode_tuple_end(device_t cbdev, device_t child, int id, 402 int len, uint8_t *tupledata, uint32_t start, uint32_t *off, 403 struct tuple_callbacks *info) 404 { 405 if (cardbus_cis_debug) { 406 printf("CIS reading done\n"); 407 } 408 return (0); 409 } 410 411 /* 412 * Functions to read the a tuple from the card 413 */ 414 415 static int 416 cardbus_read_tuple_conf(device_t cbdev, device_t child, uint32_t start, 417 uint32_t *off, int *tupleid, int *len, uint8_t *tupledata) 418 { 419 int i, j; 420 uint32_t e; 421 uint32_t loc; 422 423 loc = start + *off; 424 425 e = pci_read_config(child, loc - loc % 4, 4); 426 for (j = loc % 4; j > 0; j--) 427 e >>= 8; 428 *len = 0; 429 for (i = loc, j = -2; j < *len; j++, i++) { 430 if (i % 4 == 0) 431 e = pci_read_config(child, i, 4); 432 if (j == -2) 433 *tupleid = 0xff & e; 434 else if (j == -1) 435 *len = 0xff & e; 436 else 437 tupledata[j] = 0xff & e; 438 e >>= 8; 439 } 440 *off += *len + 2; 441 return (0); 442 } 443 444 static int 445 cardbus_read_tuple_mem(device_t cbdev, struct resource *res, uint32_t start, 446 uint32_t *off, int *tupleid, int *len, uint8_t *tupledata) 447 { 448 bus_space_tag_t bt; 449 bus_space_handle_t bh; 450 int ret; 451 452 bt = rman_get_bustag(res); 453 bh = rman_get_bushandle(res); 454 455 *tupleid = bus_space_read_1(bt, bh, start + *off); 456 *len = bus_space_read_1(bt, bh, start + *off + 1); 457 bus_space_read_region_1(bt, bh, *off + start + 2, tupledata, *len); 458 ret = 0; 459 *off += *len + 2; 460 return (ret); 461 } 462 463 static int 464 cardbus_read_tuple(device_t cbdev, device_t child, struct resource *res, 465 uint32_t start, uint32_t *off, int *tupleid, int *len, 466 uint8_t *tupledata) 467 { 468 if (res == (struct resource*)~0UL) { 469 return (cardbus_read_tuple_conf(cbdev, child, start, off, 470 tupleid, len, tupledata)); 471 } else { 472 return (cardbus_read_tuple_mem(cbdev, res, start, off, 473 tupleid, len, tupledata)); 474 } 475 } 476 477 static void 478 cardbus_read_tuple_finish(device_t cbdev, device_t child, int rid, 479 struct resource *res) 480 { 481 if (res != (struct resource*)~0UL) { 482 bus_release_resource(cbdev, SYS_RES_MEMORY, rid, res); 483 pci_write_config(child, rid, 0, 4); 484 PCI_DISABLE_IO(cbdev, child, SYS_RES_MEMORY); 485 } 486 } 487 488 static struct resource * 489 cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start, 490 int *rid) 491 { 492 uint32_t testval; 493 uint32_t size; 494 struct resource *res; 495 496 switch (CARDBUS_CIS_SPACE(*start)) { 497 case CARDBUS_CIS_ASI_TUPLE: 498 /* CIS in PCI config space need no initialization */ 499 return ((struct resource*)~0UL); 500 case CARDBUS_CIS_ASI_BAR0: 501 case CARDBUS_CIS_ASI_BAR1: 502 case CARDBUS_CIS_ASI_BAR2: 503 case CARDBUS_CIS_ASI_BAR3: 504 case CARDBUS_CIS_ASI_BAR4: 505 case CARDBUS_CIS_ASI_BAR5: 506 *rid = CARDBUS_BASE0_REG + (CARDBUS_CIS_SPACE(*start) - 1) * 4; 507 break; 508 case CARDBUS_CIS_ASI_ROM: 509 *rid = CARDBUS_ROM_REG; 510 #if 0 511 /* 512 * This mask doesn't contain the bit that actually enables 513 * the Option ROM. 514 */ 515 pci_write_config(child, *rid, CARDBUS_ROM_ADDRMASK, 4); 516 #endif 517 break; 518 default: 519 device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n", 520 CARDBUS_CIS_SPACE(*start)); 521 return (NULL); 522 } 523 524 /* figure out how much space we need */ 525 pci_write_config(child, *rid, 0xffffffff, 4); 526 testval = pci_read_config(child, *rid, 4); 527 528 /* 529 * This bit has a different meaning depending if we are dealing 530 * with a normal BAR or an Option ROM BAR. 531 */ 532 if (((testval & 0x1) == 0x1) && (*rid != CARDBUS_ROM_REG)) { 533 device_printf(cbdev, "CIS Space is IO, expecting memory.\n"); 534 return (NULL); 535 } 536 537 size = CARDBUS_MAPREG_MEM_SIZE(testval); 538 /* XXX Is this some kind of hack? */ 539 if (size < 4096) 540 size = 4096; 541 /* allocate the memory space to read CIS */ 542 res = bus_alloc_resource(cbdev, SYS_RES_MEMORY, rid, 0, ~0, size, 543 rman_make_alignment_flags(size) | RF_ACTIVE); 544 if (res == NULL) { 545 device_printf(cbdev, "Unable to allocate resource " 546 "to read CIS.\n"); 547 return (NULL); 548 } 549 pci_write_config(child, *rid, 550 rman_get_start(res) | ((*rid == CARDBUS_ROM_REG)? 551 CARDBUS_ROM_ENABLE : 0), 552 4); 553 PCI_ENABLE_IO(cbdev, child, SYS_RES_MEMORY); 554 555 /* Flip to the right ROM image if CIS is in ROM */ 556 if (CARDBUS_CIS_SPACE(*start) == CARDBUS_CIS_ASI_ROM) { 557 bus_space_tag_t bt; 558 bus_space_handle_t bh; 559 uint32_t imagesize; 560 uint32_t imagebase = 0; 561 uint32_t pcidata; 562 uint16_t romsig; 563 int romnum = 0; 564 int imagenum; 565 566 bt = rman_get_bustag(res); 567 bh = rman_get_bushandle(res); 568 569 imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(*start); 570 for (romnum = 0;; romnum++) { 571 romsig = bus_space_read_2(bt, bh, 572 imagebase + CARDBUS_EXROM_SIGNATURE); 573 if (romsig != 0xaa55) { 574 device_printf(cbdev, "Bad header in rom %d: " 575 "[%x] %04x\n", romnum, imagebase + 576 CARDBUS_EXROM_SIGNATURE, romsig); 577 bus_release_resource(cbdev, SYS_RES_MEMORY, 578 *rid, res); 579 *rid = 0; 580 return (NULL); 581 } 582 583 /* 584 * If this was the Option ROM image that we were 585 * looking for, then we are done. 586 */ 587 if (romnum == imagenum) 588 break; 589 590 /* Find out where the next Option ROM image is */ 591 pcidata = imagebase + bus_space_read_2(bt, bh, 592 imagebase + CARDBUS_EXROM_DATA_PTR); 593 imagesize = bus_space_read_2(bt, bh, 594 pcidata + CARDBUS_EXROM_DATA_IMAGE_LENGTH); 595 596 if (imagesize == 0) { 597 /* 598 * XXX some ROMs seem to have this as zero, 599 * can we assume this means 1 block? 600 */ 601 device_printf(cbdev, "Warning, size of Option " 602 "ROM image %d is 0 bytes, assuming 512 " 603 "bytes.\n", romnum); 604 imagesize = 1; 605 } 606 607 /* Image size is in 512 byte units */ 608 imagesize <<= 9; 609 610 if ((bus_space_read_1(bt, bh, pcidata + 611 CARDBUS_EXROM_DATA_INDICATOR) & 0x80) != 0) { 612 device_printf(cbdev, "Cannot find CIS in " 613 "Option ROM\n"); 614 bus_release_resource(cbdev, SYS_RES_MEMORY, 615 *rid, res); 616 *rid = 0; 617 return (NULL); 618 } 619 imagebase += imagesize; 620 } 621 *start = imagebase + CARDBUS_CIS_ADDR(*start); 622 } else { 623 *start = CARDBUS_CIS_ADDR(*start); 624 } 625 626 return (res); 627 } 628 629 /* 630 * Dispatch the right handler function per tuple 631 */ 632 633 static int 634 decode_tuple(device_t cbdev, device_t child, int tupleid, int len, 635 uint8_t *tupledata, uint32_t start, uint32_t *off, 636 struct tuple_callbacks *callbacks) 637 { 638 int i; 639 for (i = 0; callbacks[i].id != CISTPL_GENERIC; i++) { 640 if (tupleid == callbacks[i].id) 641 return (callbacks[i].func(cbdev, child, tupleid, len, 642 tupledata, start, off, &callbacks[i])); 643 } 644 return (callbacks[i].func(cbdev, child, tupleid, len, 645 tupledata, start, off, NULL)); 646 } 647 648 static int 649 cardbus_parse_cis(device_t cbdev, device_t child, 650 struct tuple_callbacks *callbacks) 651 { 652 uint8_t tupledata[MAXTUPLESIZE]; 653 int tupleid; 654 int len; 655 int expect_linktarget; 656 uint32_t start, off; 657 struct resource *res; 658 int rid; 659 660 bzero(tupledata, MAXTUPLESIZE); 661 expect_linktarget = TRUE; 662 if ((start = pci_read_config(child, CARDBUS_CIS_REG, 4)) == 0) 663 return (ENXIO); 664 off = 0; 665 res = cardbus_read_tuple_init(cbdev, child, &start, &rid); 666 if (res == NULL) 667 return (ENXIO); 668 669 do { 670 if (0 != cardbus_read_tuple(cbdev, child, res, start, &off, 671 &tupleid, &len, tupledata)) { 672 device_printf(cbdev, "Failed to read CIS.\n"); 673 cardbus_read_tuple_finish(cbdev, child, rid, res); 674 return (ENXIO); 675 } 676 677 if (expect_linktarget && tupleid != CISTPL_LINKTARGET) { 678 device_printf(cbdev, "Expecting link target, got 0x%x\n", 679 tupleid); 680 cardbus_read_tuple_finish(cbdev, child, rid, res); 681 return (EINVAL); 682 } 683 expect_linktarget = decode_tuple(cbdev, child, tupleid, len, 684 tupledata, start, &off, callbacks); 685 if (expect_linktarget != 0) { 686 cardbus_read_tuple_finish(cbdev, child, rid, res); 687 return (expect_linktarget); 688 } 689 } while (tupleid != CISTPL_END); 690 cardbus_read_tuple_finish(cbdev, child, rid, res); 691 return (0); 692 } 693 694 int 695 cardbus_do_cis(device_t cbdev, device_t child) 696 { 697 int ret; 698 struct tuple_callbacks init_callbacks[] = { 699 MAKETUPLE(LONGLINK_CB, unhandled), 700 MAKETUPLE(INDIRECT, unhandled), 701 MAKETUPLE(LONGLINK_MFC, unhandled), 702 MAKETUPLE(BAR, bar), 703 MAKETUPLE(LONGLINK_A, unhandled), 704 MAKETUPLE(LONGLINK_C, unhandled), 705 MAKETUPLE(LINKTARGET, linktarget), 706 MAKETUPLE(VERS_1, vers_1), 707 MAKETUPLE(MANFID, manfid), 708 MAKETUPLE(FUNCID, funcid), 709 MAKETUPLE(FUNCE, funce), 710 MAKETUPLE(END, end), 711 MAKETUPLE(GENERIC, generic), 712 }; 713 714 ret = cardbus_parse_cis(cbdev, child, init_callbacks); 715 if (ret < 0) 716 return (ret); 717 return 0; 718 } 719