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