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