pccard_cis.c revision 58581
1/* $NetBSD: pcmcia_cis.c,v 1.10 1998/12/29 09:03:15 marc Exp $ */ 2/* $FreeBSD: head/sys/dev/pccard/pccard_cis.c 58581 2000-03-26 07:01:52Z imp $ */ 3 4/* 5 * Copyright (c) 1997 Marc Horowitz. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Marc Horowitz. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/malloc.h> 36#include <sys/module.h> 37#include <sys/kernel.h> 38#include <sys/queue.h> 39#include <sys/types.h> 40 41#include <sys/bus.h> 42#include <machine/bus.h> 43#include <sys/rman.h> 44#include <machine/resource.h> 45 46#include <dev/pccard/pccardreg.h> 47#include <dev/pccard/pccardchip.h> 48#include <dev/pccard/pccardvar.h> 49 50#ifdef PCCARDCISDEBUG 51int pccardcis_debug = 0; 52#define DPRINTF(arg) if (pccardcis_debug) printf arg 53#define DEVPRINTF(arg) if (pccardcis_debug) device_printf arg 54#else 55#define DPRINTF(arg) 56#define DEVPRINTF(arg) 57#endif 58 59#define PCCARD_CIS_SIZE 1024 60 61struct cis_state { 62 int count; 63 int gotmfc; 64 struct pccard_config_entry temp_cfe; 65 struct pccard_config_entry *default_cfe; 66 struct pccard_card *card; 67 struct pccard_function *pf; 68}; 69 70int pccard_parse_cis_tuple(struct pccard_tuple *, void *); 71 72void 73pccard_read_cis(struct pccard_softc *sc) 74{ 75 struct cis_state state; 76 77 state.count = 0; 78 state.gotmfc = 0; 79 80 state.card = &sc->card; 81 82 state.card->error = 0; 83 state.card->cis1_major = -1; 84 state.card->cis1_minor = -1; 85 state.card->cis1_info[0] = NULL; 86 state.card->cis1_info[1] = NULL; 87 state.card->cis1_info[2] = NULL; 88 state.card->cis1_info[3] = NULL; 89 state.card->manufacturer = PCCARD_VENDOR_INVALID; 90 state.card->product = PCCARD_PRODUCT_INVALID; 91 STAILQ_INIT(&state.card->pf_head); 92 93 state.pf = NULL; 94 95 if (pccard_scan_cis((struct device *)sc, pccard_parse_cis_tuple, 96 &state) == -1) 97 state.card->error++; 98} 99 100int 101pccard_scan_cis(device_t dev, int (*fct)(struct pccard_tuple *, void *), 102 void *arg) 103{ 104 struct resource *res; 105 int rid; 106 struct pccard_tuple tuple; 107 int longlink_present; 108 int longlink_common; 109 u_long longlink_addr; 110 int mfc_count; 111 int mfc_index; 112 struct { 113 int common; 114 u_long addr; 115 } mfc[256 / 5]; 116 int ret; 117 118 ret = 0; 119 120 /* allocate some memory */ 121 122 rid = 0; 123 res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 124 PCCARD_CIS_SIZE, RF_ACTIVE /* | RF_PCCARD_ATTR */); 125 if (res == NULL) { 126#ifdef DIAGNOSTIC 127 device_printf(dev, "can't alloc memory to read attributes\n"); 128#endif 129 return -1; 130 } 131 tuple.memt = rman_get_bustag(res); 132 tuple.memh = rman_get_bushandle(res); 133 134 DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh)); 135 136 tuple.mult = 2; 137 138 longlink_present = 1; 139 longlink_common = 1; 140 longlink_addr = 0; 141 142 mfc_count = 0; 143 mfc_index = 0; 144 145 DEVPRINTF((dev, "CIS tuple chain:\n")); 146 147 while (1) { 148 while (1) { 149 /* get the tuple code */ 150 151 tuple.code = pccard_cis_read_1(&tuple, tuple.ptr); 152 153 /* two special-case tuples */ 154 155 if (tuple.code == PCCARD_CISTPL_NULL) { 156 DPRINTF(("CISTPL_NONE\n 00\n")); 157 tuple.ptr++; 158 continue; 159 } else if (tuple.code == PCCARD_CISTPL_END) { 160 DPRINTF(("CISTPL_END\n ff\n")); 161 /* Call the function for the END tuple, since 162 the CIS semantics depend on it */ 163 if ((*fct) (&tuple, arg)) { 164 ret = 1; 165 goto done; 166 } 167 tuple.ptr++; 168 break; 169 } 170 /* now all the normal tuples */ 171 172 tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1); 173 switch (tuple.code) { 174 case PCCARD_CISTPL_LONGLINK_A: 175 case PCCARD_CISTPL_LONGLINK_C: 176 if (tuple.length < 4) { 177 DPRINTF(("CISTPL_LONGLINK_%s too " 178 "short %d\n", 179 longlink_common ? "C" : "A", 180 tuple.length)); 181 break; 182 } 183 longlink_present = 1; 184 longlink_common = (tuple.code == 185 PCCARD_CISTPL_LONGLINK_C) ? 1 : 0; 186 longlink_addr = pccard_tuple_read_4(&tuple, 0); 187 DPRINTF(("CISTPL_LONGLINK_%s %lx\n", 188 longlink_common ? "C" : "A", 189 longlink_addr)); 190 break; 191 case PCCARD_CISTPL_NO_LINK: 192 longlink_present = 0; 193 DPRINTF(("CISTPL_NO_LINK\n")); 194 break; 195 case PCCARD_CISTPL_CHECKSUM: 196 if (tuple.length < 5) { 197 DPRINTF(("CISTPL_CHECKSUM too " 198 "short %d\n", tuple.length)); 199 break; 200 } { 201 int16_t offset; 202 u_long addr, length; 203 u_int cksum, sum; 204 int i; 205 206 *((u_int16_t *) & offset) = 207 pccard_tuple_read_2(&tuple, 0); 208 length = pccard_tuple_read_2(&tuple, 2); 209 cksum = pccard_tuple_read_1(&tuple, 4); 210 211 addr = tuple.ptr + offset; 212 213 DPRINTF(("CISTPL_CHECKSUM addr=%lx " 214 "len=%lx cksum=%x", 215 addr, length, cksum)); 216 217 /* 218 * XXX do more work to deal with 219 * distant regions 220 */ 221 if ((addr >= PCCARD_CIS_SIZE) || 222 ((addr + length) < 0) || 223 ((addr + length) >= 224 PCCARD_CIS_SIZE)) { 225 DPRINTF((" skipped, " 226 "too distant\n")); 227 break; 228 } 229 sum = 0; 230 for (i = 0; i < length; i++) 231 sum += 232 bus_space_read_1(tuple.memt, 233 tuple.memh, 234 addr + tuple.mult * i); 235 if (cksum != (sum & 0xff)) { 236 DPRINTF((" failed sum=%x\n", 237 sum)); 238 device_printf(dev, 239 "CIS checksum failed\n"); 240#if 0 241 /* 242 * XXX Some working cards have 243 * XXX bad checksums!! 244 */ 245 ret = -1; 246#endif 247 } else { 248 DPRINTF((" ok\n")); 249 } 250 } 251 break; 252 case PCCARD_CISTPL_LONGLINK_MFC: 253 if (tuple.length < 1) { 254 DPRINTF(("CISTPL_LONGLINK_MFC too " 255 "short %d\n", tuple.length)); 256 break; 257 } 258 /* 259 * this is kind of ad hoc, as I don't have 260 * any real documentation 261 */ 262 { 263 int i; 264 265 mfc_count = 266 pccard_tuple_read_1(&tuple, 0); 267 DPRINTF(("CISTPL_LONGLINK_MFC %d", 268 mfc_count)); 269 for (i = 0; i < mfc_count; i++) { 270 mfc[i].common = 271 (pccard_tuple_read_1(&tuple, 272 1 + 5 * i) == 273 PCCARD_MFC_MEM_COMMON) ? 274 1 : 0; 275 mfc[i].addr = 276 pccard_tuple_read_4(&tuple, 277 1 + 5 * i + 1); 278 DPRINTF((" %s:%lx", 279 mfc[i].common ? "common" : 280 "attr", mfc[i].addr)); 281 } 282 DPRINTF(("\n")); 283 } 284 /* 285 * for LONGLINK_MFC, fall through to the 286 * function. This tuple has structural and 287 * semantic content. 288 */ 289 default: 290 { 291 if ((*fct) (&tuple, arg)) { 292 ret = 1; 293 goto done; 294 } 295 } 296 break; 297 } /* switch */ 298#ifdef PCCARDCISDEBUG 299 /* print the tuple */ 300 { 301 int i; 302 303 DPRINTF((" %02x %02x", tuple.code, 304 tuple.length)); 305 306 for (i = 0; i < tuple.length; i++) { 307 DPRINTF((" %02x", 308 pccard_tuple_read_1(&tuple, i))); 309 if ((i % 16) == 13) 310 DPRINTF(("\n")); 311 } 312 if ((i % 16) != 14) 313 DPRINTF(("\n")); 314 } 315#endif 316 /* skip to the next tuple */ 317 tuple.ptr += 2 + tuple.length; 318 } 319 320#ifdef XXX /* I'm not up to this tonight, need to implement new API */ 321 /* to deal with moving windows and such. At least that's */ 322 /* what it appears at this instant */ 323 324 /* 325 * the chain is done. Clean up and move onto the next one, 326 * if any. The loop is here in the case that there is an MFC 327 * card with no longlink (which defaults to existing, == 0). 328 * In general, this means that if one pointer fails, it will 329 * try the next one, instead of just bailing. 330 */ 331 332 while (1) { 333 pccard_chip_mem_unmap(pct, pch, window); 334 335 if (longlink_present) { 336 /* 337 * if the longlink is to attribute memory, 338 * then it is unindexed. That is, if the 339 * link value is 0x100, then the actual 340 * memory address is 0x200. This means that 341 * we need to multiply by 2 before calling 342 * mem_map, and then divide the resulting ptr 343 * by 2 after. 344 */ 345 346 if (!longlink_common) 347 longlink_addr *= 2; 348 349 pccard_chip_mem_map(pct, pch, longlink_common ? 350 PCCARD_MEM_COMMON : PCCARD_MEM_ATTR, 351 longlink_addr, PCCARD_CIS_SIZE, 352 &pcmh, &tuple.ptr, &window); 353 354 if (!longlink_common) 355 tuple.ptr /= 2; 356 DPRINTF(("cis mem map %x\n", 357 (unsigned int) tuple.memh)); 358 tuple.mult = longlink_common ? 1 : 2; 359 longlink_present = 0; 360 longlink_common = 1; 361 longlink_addr = 0; 362 } else if (mfc_count && (mfc_index < mfc_count)) { 363 if (!mfc[mfc_index].common) 364 mfc[mfc_index].addr *= 2; 365 366 pccard_chip_mem_map(pct, pch, 367 mfc[mfc_index].common ? 368 PCCARD_MEM_COMMON : PCCARD_MEM_ATTR, 369 mfc[mfc_index].addr, PCCARD_CIS_SIZE, 370 &pcmh, &tuple.ptr, &window); 371 372 if (!mfc[mfc_index].common) 373 tuple.ptr /= 2; 374 DPRINTF(("cis mem map %x\n", 375 (unsigned int) tuple.memh)); 376 /* set parse state, and point at the next one */ 377 378 tuple.mult = mfc[mfc_index].common ? 1 : 2; 379 380 mfc_index++; 381 } else { 382 goto done; 383 } 384 385 /* make sure that the link is valid */ 386 tuple.code = pccard_cis_read_1(&tuple, tuple.ptr); 387 if (tuple.code != PCCARD_CISTPL_LINKTARGET) { 388 DPRINTF(("CISTPL_LINKTARGET expected, " 389 "code %02x observed\n", tuple.code)); 390 continue; 391 } 392 tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1); 393 if (tuple.length < 3) { 394 DPRINTF(("CISTPL_LINKTARGET too short %d\n", 395 tuple.length)); 396 continue; 397 } 398 if ((pccard_tuple_read_1(&tuple, 0) != 'C') || 399 (pccard_tuple_read_1(&tuple, 1) != 'I') || 400 (pccard_tuple_read_1(&tuple, 2) != 'S')) { 401 DPRINTF(("CISTPL_LINKTARGET magic " 402 "%02x%02x%02x incorrect\n", 403 pccard_tuple_read_1(&tuple, 0), 404 pccard_tuple_read_1(&tuple, 1), 405 pccard_tuple_read_1(&tuple, 2))); 406 continue; 407 } 408 tuple.ptr += 2 + tuple.length; 409 410 break; 411 } 412#endif /* XXX */ 413 } 414 415done: 416 bus_release_resource(dev, SYS_RES_MEMORY, rid, res); 417 418 return (ret); 419} 420 421/* XXX this is incredibly verbose. Not sure what trt is */ 422 423void 424pccard_print_cis(device_t dev) 425{ 426 struct pccard_softc *sc = (struct pccard_softc *) device_get_softc(dev); 427 struct pccard_card *card = &sc->card; 428 struct pccard_function *pf; 429 struct pccard_config_entry *cfe; 430 int i; 431 432 device_printf(dev, "CIS version "); 433 if (card->cis1_major == 4) { 434 if (card->cis1_minor == 0) 435 printf("PCCARD 1.0\n"); 436 else if (card->cis1_minor == 1) 437 printf("PCCARD 2.0 or 2.1\n"); 438 } else if (card->cis1_major >= 5) 439 printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor); 440 else 441 printf("unknown (major=%d, minor=%d)\n", 442 card->cis1_major, card->cis1_minor); 443 444 device_printf(dev, "CIS info: "); 445 for (i = 0; i < 4; i++) { 446 if (card->cis1_info[i] == NULL) 447 break; 448 if (i) 449 printf(", "); 450 printf("%s", card->cis1_info[i]); 451 } 452 printf("\n"); 453 454 device_printf(dev, "Manufacturer code 0x%x, product 0x%x\n", 455 card->manufacturer, card->product); 456 457 STAILQ_FOREACH(pf, &card->pf_head, pf_list) { 458 device_printf(dev, "function %d: ", pf->number); 459 460 switch (pf->function) { 461 case PCCARD_FUNCTION_UNSPEC: 462 printf("unspecified"); 463 break; 464 case PCCARD_FUNCTION_MULTIFUNCTION: 465 printf("multi-function"); 466 break; 467 case PCCARD_FUNCTION_MEMORY: 468 printf("memory"); 469 break; 470 case PCCARD_FUNCTION_SERIAL: 471 printf("serial port"); 472 break; 473 case PCCARD_FUNCTION_PARALLEL: 474 printf("parallel port"); 475 break; 476 case PCCARD_FUNCTION_DISK: 477 printf("fixed disk"); 478 break; 479 case PCCARD_FUNCTION_VIDEO: 480 printf("video adapter"); 481 break; 482 case PCCARD_FUNCTION_NETWORK: 483 printf("network adapter"); 484 break; 485 case PCCARD_FUNCTION_AIMS: 486 printf("auto incrementing mass storage"); 487 break; 488 case PCCARD_FUNCTION_SCSI: 489 printf("SCSI bridge"); 490 break; 491 case PCCARD_FUNCTION_SECURITY: 492 printf("Security services"); 493 break; 494 case PCCARD_FUNCTION_INSTRUMENT: 495 printf("Instrument"); 496 break; 497 default: 498 printf("unknown (%d)", pf->function); 499 break; 500 } 501 502 printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask); 503 504 STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) { 505 device_printf(dev, "function %d, config table entry " 506 "%d: ", pf->number, cfe->number); 507 508 switch (cfe->iftype) { 509 case PCCARD_IFTYPE_MEMORY: 510 printf("memory card"); 511 break; 512 case PCCARD_IFTYPE_IO: 513 printf("I/O card"); 514 break; 515 default: 516 printf("card type unknown"); 517 break; 518 } 519 520 printf("; irq mask %x", cfe->irqmask); 521 522 if (cfe->num_iospace) { 523 printf("; iomask %lx, iospace", cfe->iomask); 524 525 for (i = 0; i < cfe->num_iospace; i++) { 526 printf(" %lx", cfe->iospace[i].start); 527 if (cfe->iospace[i].length) 528 printf("-%lx", 529 cfe->iospace[i].start + 530 cfe->iospace[i].length - 1); 531 } 532 } 533 if (cfe->num_memspace) { 534 printf("; memspace"); 535 536 for (i = 0; i < cfe->num_memspace; i++) { 537 printf(" %lx", 538 cfe->memspace[i].cardaddr); 539 if (cfe->memspace[i].length) 540 printf("-%lx", 541 cfe->memspace[i].cardaddr + 542 cfe->memspace[i].length - 1); 543 if (cfe->memspace[i].hostaddr) 544 printf("@%lx", 545 cfe->memspace[i].hostaddr); 546 } 547 } 548 if (cfe->maxtwins) 549 printf("; maxtwins %d", cfe->maxtwins); 550 551 printf(";"); 552 553 if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED) 554 printf(" mwait_required"); 555 if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE) 556 printf(" rdybsy_active"); 557 if (cfe->flags & PCCARD_CFE_WP_ACTIVE) 558 printf(" wp_active"); 559 if (cfe->flags & PCCARD_CFE_BVD_ACTIVE) 560 printf(" bvd_active"); 561 if (cfe->flags & PCCARD_CFE_IO8) 562 printf(" io8"); 563 if (cfe->flags & PCCARD_CFE_IO16) 564 printf(" io16"); 565 if (cfe->flags & PCCARD_CFE_IRQSHARE) 566 printf(" irqshare"); 567 if (cfe->flags & PCCARD_CFE_IRQPULSE) 568 printf(" irqpulse"); 569 if (cfe->flags & PCCARD_CFE_IRQLEVEL) 570 printf(" irqlevel"); 571 if (cfe->flags & PCCARD_CFE_POWERDOWN) 572 printf(" powerdown"); 573 if (cfe->flags & PCCARD_CFE_READONLY) 574 printf(" readonly"); 575 if (cfe->flags & PCCARD_CFE_AUDIO) 576 printf(" audio"); 577 578 printf("\n"); 579 } 580 } 581 582 if (card->error) 583 device_printf(dev, "%d errors found while parsing CIS\n", 584 card->error); 585} 586 587int 588pccard_parse_cis_tuple(struct pccard_tuple *tuple, void *arg) 589{ 590 /* most of these are educated guesses */ 591 static struct pccard_config_entry init_cfe = { 592 -1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE | 593 PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY, 594 }; 595 596 struct cis_state *state = arg; 597 598 switch (tuple->code) { 599 case PCCARD_CISTPL_END: 600 /* if we've seen a LONGLINK_MFC, and this is the first 601 * END after it, reset the function list. 602 * 603 * XXX This might also be the right place to start a 604 * new function, but that assumes that a function 605 * definition never crosses any longlink, and I'm not 606 * sure about that. This is probably safe for MFC 607 * cards, but what we have now isn't broken, so I'd 608 * rather not change it. 609 */ 610 if (state->gotmfc == 1) { 611 struct pccard_function *pf, *pfnext; 612 613 for (pf = STAILQ_FIRST(&state->card->pf_head); 614 pf != NULL; pf = pfnext) { 615 pfnext = STAILQ_NEXT(pf, pf_list); 616 free(pf, M_DEVBUF); 617 } 618 619 STAILQ_INIT(&state->card->pf_head); 620 621 state->count = 0; 622 state->gotmfc = 2; 623 state->pf = NULL; 624 } 625 break; 626 case PCCARD_CISTPL_LONGLINK_MFC: 627 /* 628 * this tuple's structure was dealt with in scan_cis. here, 629 * record the fact that the MFC tuple was seen, so that 630 * functions declared before the MFC link can be cleaned 631 * up. 632 */ 633 state->gotmfc = 1; 634 break; 635#ifdef PCCARDCISDEBUG 636 case PCCARD_CISTPL_DEVICE: 637 case PCCARD_CISTPL_DEVICE_A: 638 { 639 u_int reg, dtype, dspeed; 640 641 reg = pccard_tuple_read_1(tuple, 0); 642 dtype = reg & PCCARD_DTYPE_MASK; 643 dspeed = reg & PCCARD_DSPEED_MASK; 644 645 DPRINTF(("CISTPL_DEVICE%s type=", 646 (tuple->code == PCCARD_CISTPL_DEVICE) ? "" : "_A")); 647 switch (dtype) { 648 case PCCARD_DTYPE_NULL: 649 DPRINTF(("null")); 650 break; 651 case PCCARD_DTYPE_ROM: 652 DPRINTF(("rom")); 653 break; 654 case PCCARD_DTYPE_OTPROM: 655 DPRINTF(("otprom")); 656 break; 657 case PCCARD_DTYPE_EPROM: 658 DPRINTF(("eprom")); 659 break; 660 case PCCARD_DTYPE_EEPROM: 661 DPRINTF(("eeprom")); 662 break; 663 case PCCARD_DTYPE_FLASH: 664 DPRINTF(("flash")); 665 break; 666 case PCCARD_DTYPE_SRAM: 667 DPRINTF(("sram")); 668 break; 669 case PCCARD_DTYPE_DRAM: 670 DPRINTF(("dram")); 671 break; 672 case PCCARD_DTYPE_FUNCSPEC: 673 DPRINTF(("funcspec")); 674 break; 675 case PCCARD_DTYPE_EXTEND: 676 DPRINTF(("extend")); 677 break; 678 default: 679 DPRINTF(("reserved")); 680 break; 681 } 682 DPRINTF((" speed=")); 683 switch (dspeed) { 684 case PCCARD_DSPEED_NULL: 685 DPRINTF(("null")); 686 break; 687 case PCCARD_DSPEED_250NS: 688 DPRINTF(("250ns")); 689 break; 690 case PCCARD_DSPEED_200NS: 691 DPRINTF(("200ns")); 692 break; 693 case PCCARD_DSPEED_150NS: 694 DPRINTF(("150ns")); 695 break; 696 case PCCARD_DSPEED_100NS: 697 DPRINTF(("100ns")); 698 break; 699 case PCCARD_DSPEED_EXT: 700 DPRINTF(("ext")); 701 break; 702 default: 703 DPRINTF(("reserved")); 704 break; 705 } 706 } 707 DPRINTF(("\n")); 708 break; 709#endif 710 case PCCARD_CISTPL_VERS_1: 711 if (tuple->length < 6) { 712 DPRINTF(("CISTPL_VERS_1 too short %d\n", 713 tuple->length)); 714 break; 715 } { 716 int start, i, ch, count; 717 718 state->card->cis1_major = pccard_tuple_read_1(tuple, 0); 719 state->card->cis1_minor = pccard_tuple_read_1(tuple, 1); 720 721 for (count = 0, start = 0, i = 0; 722 (count < 4) && ((i + 4) < 256); i++) { 723 ch = pccard_tuple_read_1(tuple, 2 + i); 724 if (ch == 0xff) 725 break; 726 state->card->cis1_info_buf[i] = ch; 727 if (ch == 0) { 728 state->card->cis1_info[count] = 729 state->card->cis1_info_buf + start; 730 start = i + 1; 731 count++; 732 } 733 } 734 DPRINTF(("CISTPL_VERS_1\n")); 735 } 736 break; 737 case PCCARD_CISTPL_MANFID: 738 if (tuple->length < 4) { 739 DPRINTF(("CISTPL_MANFID too short %d\n", 740 tuple->length)); 741 break; 742 } 743 state->card->manufacturer = pccard_tuple_read_2(tuple, 0); 744 state->card->product = pccard_tuple_read_2(tuple, 2); 745 DPRINTF(("CISTPL_MANFID\n")); 746 break; 747 case PCCARD_CISTPL_FUNCID: 748 if (tuple->length < 1) { 749 DPRINTF(("CISTPL_FUNCID too short %d\n", 750 tuple->length)); 751 break; 752 } 753 if ((state->pf == NULL) || (state->gotmfc == 2)) { 754 state->pf = malloc(sizeof(*state->pf), M_DEVBUF, 755 M_NOWAIT); 756 bzero(state->pf, sizeof(*state->pf)); 757 state->pf->number = state->count++; 758 state->pf->last_config_index = -1; 759 STAILQ_INIT(&state->pf->cfe_head); 760 761 STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf, 762 pf_list); 763 } 764 state->pf->function = pccard_tuple_read_1(tuple, 0); 765 766 DPRINTF(("CISTPL_FUNCID\n")); 767 break; 768 case PCCARD_CISTPL_CONFIG: 769 if (tuple->length < 3) { 770 DPRINTF(("CISTPL_CONFIG too short %d\n", 771 tuple->length)); 772 break; 773 } { 774 u_int reg, rasz, rmsz, rfsz; 775 int i; 776 777 reg = pccard_tuple_read_1(tuple, 0); 778 rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >> 779 PCCARD_TPCC_RASZ_SHIFT); 780 rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >> 781 PCCARD_TPCC_RMSZ_SHIFT); 782 rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >> 783 PCCARD_TPCC_RFSZ_SHIFT); 784 785 if (tuple->length < (rasz + rmsz + rfsz)) { 786 DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too " 787 "short %d\n", rasz, rmsz, rfsz, 788 tuple->length)); 789 break; 790 } 791 if (state->pf == NULL) { 792 state->pf = malloc(sizeof(*state->pf), 793 M_DEVBUF, M_NOWAIT); 794 bzero(state->pf, sizeof(*state->pf)); 795 state->pf->number = state->count++; 796 state->pf->last_config_index = -1; 797 STAILQ_INIT(&state->pf->cfe_head); 798 799 STAILQ_INSERT_TAIL(&state->card->pf_head, 800 state->pf, pf_list); 801 802 state->pf->function = PCCARD_FUNCTION_UNSPEC; 803 } 804 state->pf->last_config_index = 805 pccard_tuple_read_1(tuple, 1); 806 807 state->pf->ccr_base = 0; 808 for (i = 0; i < rasz; i++) 809 state->pf->ccr_base |= 810 ((pccard_tuple_read_1(tuple, 2 + i)) << 811 (i * 8)); 812 813 state->pf->ccr_mask = 0; 814 for (i = 0; i < rmsz; i++) 815 state->pf->ccr_mask |= 816 ((pccard_tuple_read_1(tuple, 817 2 + rasz + i)) << (i * 8)); 818 819 /* skip the reserved area and subtuples */ 820 821 /* reset the default cfe for each cfe list */ 822 state->temp_cfe = init_cfe; 823 state->default_cfe = &state->temp_cfe; 824 } 825 DPRINTF(("CISTPL_CONFIG\n")); 826 break; 827 case PCCARD_CISTPL_CFTABLE_ENTRY: 828 { 829 int idx, i, j; 830 u_int reg, reg2; 831 u_int intface, def, num; 832 u_int power, timing, iospace, irq, memspace, misc; 833 struct pccard_config_entry *cfe; 834 835 idx = 0; 836 837 reg = pccard_tuple_read_1(tuple, idx); 838 idx++; 839 intface = reg & PCCARD_TPCE_INDX_INTFACE; 840 def = reg & PCCARD_TPCE_INDX_DEFAULT; 841 num = reg & PCCARD_TPCE_INDX_NUM_MASK; 842 843 /* 844 * this is a little messy. Some cards have only a 845 * cfentry with the default bit set. So, as we go 846 * through the list, we add new indexes to the queue, 847 * and keep a pointer to the last one with the 848 * default bit set. if we see a record with the same 849 * index, as the default, we stash the default and 850 * replace the queue entry. otherwise, we just add 851 * new entries to the queue, pointing the default ptr 852 * at them if the default bit is set. if we get to 853 * the end with the default pointer pointing at a 854 * record which hasn't had a matching index, that's 855 * ok; it just becomes a cfentry like any other. 856 */ 857 858 /* 859 * if the index in the cis differs from the default 860 * cis, create new entry in the queue and start it 861 * with the current default 862 */ 863 if (num != state->default_cfe->number) { 864 cfe = (struct pccard_config_entry *) 865 malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT); 866 867 *cfe = *state->default_cfe; 868 869 STAILQ_INSERT_TAIL(&state->pf->cfe_head, 870 cfe, cfe_list); 871 872 cfe->number = num; 873 874 /* 875 * if the default bit is set in the cis, then 876 * point the new default at whatever is being 877 * filled in 878 */ 879 if (def) 880 state->default_cfe = cfe; 881 } else { 882 /* 883 * the cis index matches the default index, 884 * fill in the default cfentry. It is 885 * assumed that the cfdefault index is in the 886 * queue. For it to be otherwise, the cis 887 * index would have to be -1 (initial 888 * condition) which is not possible, or there 889 * would have to be a preceding cis entry 890 * which had the same cis index and had the 891 * default bit unset. Neither condition 892 * should happen. If it does, this cfentry 893 * is lost (written into temp space), which 894 * is an acceptable failure mode. 895 */ 896 897 cfe = state->default_cfe; 898 899 /* 900 * if the cis entry does not have the default 901 * bit set, copy the default out of the way 902 * first. 903 */ 904 if (!def) { 905 state->temp_cfe = *state->default_cfe; 906 state->default_cfe = &state->temp_cfe; 907 } 908 } 909 910 if (intface) { 911 reg = pccard_tuple_read_1(tuple, idx); 912 idx++; 913 if (reg & PCCARD_TPCE_IF_MWAIT) 914 cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED; 915 if (reg & PCCARD_TPCE_IF_RDYBSY) 916 cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE; 917 if (reg & PCCARD_TPCE_IF_WP) 918 cfe->flags |= PCCARD_CFE_WP_ACTIVE; 919 if (reg & PCCARD_TPCE_IF_BVD) 920 cfe->flags |= PCCARD_CFE_BVD_ACTIVE; 921 cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE; 922 } 923 reg = pccard_tuple_read_1(tuple, idx); 924 idx++; 925 926 power = reg & PCCARD_TPCE_FS_POWER_MASK; 927 timing = reg & PCCARD_TPCE_FS_TIMING; 928 iospace = reg & PCCARD_TPCE_FS_IOSPACE; 929 irq = reg & PCCARD_TPCE_FS_IRQ; 930 memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK; 931 misc = reg & PCCARD_TPCE_FS_MISC; 932 933 if (power) { 934 /* skip over power, don't save */ 935 /* for each parameter selection byte */ 936 for (i = 0; i < power; i++) { 937 reg = pccard_tuple_read_1(tuple, idx); 938 idx++; 939 /* for each bit */ 940 for (j = 0; j < 7; j++) { 941 /* if the bit is set */ 942 if ((reg >> j) & 0x01) { 943 /* skip over bytes */ 944 do { 945 reg2 = pccard_tuple_read_1(tuple, idx); 946 idx++; 947 /* 948 * until 949 * non-extensi 950 * on byte 951 */ 952 } while (reg2 & 0x80); 953 } 954 } 955 } 956 } 957 if (timing) { 958 /* skip over timing, don't save */ 959 reg = pccard_tuple_read_1(tuple, idx); 960 idx++; 961 962 if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) != 963 PCCARD_TPCE_TD_RESERVED_MASK) 964 idx++; 965 if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) != 966 PCCARD_TPCE_TD_RDYBSY_MASK) 967 idx++; 968 if ((reg & PCCARD_TPCE_TD_WAIT_MASK) != 969 PCCARD_TPCE_TD_WAIT_MASK) 970 idx++; 971 } 972 if (iospace) { 973 if (tuple->length <= idx) { 974 DPRINTF(("ran out of space before TCPE_IO\n")); 975 goto abort_cfe; 976 } 977 978 reg = pccard_tuple_read_1(tuple, idx); 979 idx++; 980 981 if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT) 982 cfe->flags |= PCCARD_CFE_IO8; 983 if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT) 984 cfe->flags |= PCCARD_CFE_IO16; 985 cfe->iomask = 986 reg & PCCARD_TPCE_IO_IOADDRLINES_MASK; 987 988 if (reg & PCCARD_TPCE_IO_HASRANGE) { 989 reg = pccard_tuple_read_1(tuple, idx); 990 idx++; 991 992 cfe->num_iospace = 1 + (reg & 993 PCCARD_TPCE_IO_RANGE_COUNT); 994 995 if (cfe->num_iospace > 996 (sizeof(cfe->iospace) / 997 sizeof(cfe->iospace[0]))) { 998 DPRINTF(("too many io " 999 "spaces %d", 1000 cfe->num_iospace)); 1001 state->card->error++; 1002 break; 1003 } 1004 for (i = 0; i < cfe->num_iospace; i++) { 1005 switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) { 1006 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE: 1007 cfe->iospace[i].start = 1008 pccard_tuple_read_1(tuple, idx); 1009 idx++; 1010 break; 1011 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO: 1012 cfe->iospace[i].start = 1013 pccard_tuple_read_2(tuple, idx); 1014 idx += 2; 1015 break; 1016 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR: 1017 cfe->iospace[i].start = 1018 pccard_tuple_read_4(tuple, idx); 1019 idx += 4; 1020 break; 1021 } 1022 switch (reg & 1023 PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) { 1024 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE: 1025 cfe->iospace[i].length = 1026 pccard_tuple_read_1(tuple, idx); 1027 idx++; 1028 break; 1029 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO: 1030 cfe->iospace[i].length = 1031 pccard_tuple_read_2(tuple, idx); 1032 idx += 2; 1033 break; 1034 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR: 1035 cfe->iospace[i].length = 1036 pccard_tuple_read_4(tuple, idx); 1037 idx += 4; 1038 break; 1039 } 1040 cfe->iospace[i].length++; 1041 } 1042 } else { 1043 cfe->num_iospace = 1; 1044 cfe->iospace[0].start = 0; 1045 cfe->iospace[0].length = 1046 (1 << cfe->iomask); 1047 } 1048 } 1049 if (irq) { 1050 if (tuple->length <= idx) { 1051 DPRINTF(("ran out of space before TCPE_IR\n")); 1052 goto abort_cfe; 1053 } 1054 1055 reg = pccard_tuple_read_1(tuple, idx); 1056 idx++; 1057 1058 if (reg & PCCARD_TPCE_IR_SHARE) 1059 cfe->flags |= PCCARD_CFE_IRQSHARE; 1060 if (reg & PCCARD_TPCE_IR_PULSE) 1061 cfe->flags |= PCCARD_CFE_IRQPULSE; 1062 if (reg & PCCARD_TPCE_IR_LEVEL) 1063 cfe->flags |= PCCARD_CFE_IRQLEVEL; 1064 1065 if (reg & PCCARD_TPCE_IR_HASMASK) { 1066 /* 1067 * it's legal to ignore the 1068 * special-interrupt bits, so I will 1069 */ 1070 1071 cfe->irqmask = 1072 pccard_tuple_read_2(tuple, idx); 1073 idx += 2; 1074 } else { 1075 cfe->irqmask = 1076 (1 << (reg & PCCARD_TPCE_IR_IRQ)); 1077 } 1078 } 1079 if (memspace) { 1080 if (tuple->length <= idx) { 1081 DPRINTF(("ran out of space before TCPE_MS\n")); 1082 goto abort_cfe; 1083 } 1084 1085 if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) { 1086 cfe->num_memspace = 0; 1087 } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) { 1088 cfe->num_memspace = 1; 1089 cfe->memspace[0].length = 256 * 1090 pccard_tuple_read_2(tuple, idx); 1091 idx += 2; 1092 cfe->memspace[0].cardaddr = 0; 1093 cfe->memspace[0].hostaddr = 0; 1094 } else if (memspace == 1095 PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) { 1096 cfe->num_memspace = 1; 1097 cfe->memspace[0].length = 256 * 1098 pccard_tuple_read_2(tuple, idx); 1099 idx += 2; 1100 cfe->memspace[0].cardaddr = 256 * 1101 pccard_tuple_read_2(tuple, idx); 1102 idx += 2; 1103 cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr; 1104 } else { 1105 int lengthsize; 1106 int cardaddrsize; 1107 int hostaddrsize; 1108 1109 reg = pccard_tuple_read_1(tuple, idx); 1110 idx++; 1111 1112 cfe->num_memspace = (reg & 1113 PCCARD_TPCE_MS_COUNT) + 1; 1114 1115 if (cfe->num_memspace > 1116 (sizeof(cfe->memspace) / 1117 sizeof(cfe->memspace[0]))) { 1118 DPRINTF(("too many mem " 1119 "spaces %d", 1120 cfe->num_memspace)); 1121 state->card->error++; 1122 break; 1123 } 1124 lengthsize = 1125 ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >> 1126 PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT); 1127 cardaddrsize = 1128 ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >> 1129 PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT); 1130 hostaddrsize = 1131 (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0; 1132 1133 if (lengthsize == 0) { 1134 DPRINTF(("cfe memspace " 1135 "lengthsize == 0")); 1136 state->card->error++; 1137 } 1138 for (i = 0; i < cfe->num_memspace; i++) { 1139 if (lengthsize) { 1140 cfe->memspace[i].length = 1141 256 * pccard_tuple_read_n(tuple, lengthsize, 1142 idx); 1143 idx += lengthsize; 1144 } else { 1145 cfe->memspace[i].length = 0; 1146 } 1147 if (cfe->memspace[i].length == 0) { 1148 DPRINTF(("cfe->memspace[%d].length == 0", 1149 i)); 1150 state->card->error++; 1151 } 1152 if (cardaddrsize) { 1153 cfe->memspace[i].cardaddr = 1154 256 * pccard_tuple_read_n(tuple, cardaddrsize, 1155 idx); 1156 idx += cardaddrsize; 1157 } else { 1158 cfe->memspace[i].cardaddr = 0; 1159 } 1160 if (hostaddrsize) { 1161 cfe->memspace[i].hostaddr = 1162 256 * pccard_tuple_read_n(tuple, hostaddrsize, 1163 idx); 1164 idx += hostaddrsize; 1165 } else { 1166 cfe->memspace[i].hostaddr = 0; 1167 } 1168 } 1169 } 1170 } 1171 if (misc) { 1172 if (tuple->length <= idx) { 1173 DPRINTF(("ran out of space before TCPE_MI\n")); 1174 goto abort_cfe; 1175 } 1176 1177 reg = pccard_tuple_read_1(tuple, idx); 1178 idx++; 1179 1180 if (reg & PCCARD_TPCE_MI_PWRDOWN) 1181 cfe->flags = PCCARD_CFE_POWERDOWN; 1182 if (reg & PCCARD_TPCE_MI_READONLY) 1183 cfe->flags = PCCARD_CFE_READONLY; 1184 if (reg & PCCARD_TPCE_MI_AUDIO) 1185 cfe->flags = PCCARD_CFE_AUDIO; 1186 cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS; 1187 1188 while (reg & PCCARD_TPCE_MI_EXT) { 1189 reg = pccard_tuple_read_1(tuple, idx); 1190 idx++; 1191 } 1192 } 1193 /* skip all the subtuples */ 1194 } 1195 1196 abort_cfe: 1197 DPRINTF(("CISTPL_CFTABLE_ENTRY\n")); 1198 break; 1199 default: 1200 DPRINTF(("unhandled CISTPL %x\n", tuple->code)); 1201 break; 1202 } 1203 1204 return (0); 1205} 1206