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