printcis.c revision 15175
1/* 2 * dump CIS tuples. 3 */ 4#include <stdio.h> 5#include <unistd.h> 6#include <stdlib.h> 7#include <string.h> 8#include <sys/ioctl.h> 9 10#include <pccard/card.h> 11#include <pccard/cis.h> 12 13#include "readcis.h" 14 15int dump_pwr_desc(unsigned char *); 16void print_ext_speed(unsigned char, int); 17void dump_device_desc(unsigned char *p, int len, char *type); 18void dump_info_v1(unsigned char *p, int len); 19void dump_config_map(struct tuple *tp); 20void dump_cis_config(struct tuple *tp); 21void dump_other_cond(unsigned char *p); 22void dump_func_ext(unsigned char *p, int len); 23 24void 25dumpcis(struct cis *cp) 26{ 27 struct tuple *tp; 28 struct tuple_list *tl; 29 int count = 0, sz, ad, i; 30 unsigned char *p; 31 32 for (tl = cp->tlist; tl; tl = tl->next) 33 for (tp = tl->tuples; tp; tp = tp->next) { 34 printf("Tuple #%d, code = 0x%x (%s), length = %d\n", 35 ++count, tp->code, tuple_name(tp->code), tp->length); 36 p = tp->data; 37 sz = tp->length; 38 ad = 0; 39 while (sz > 0) { 40 printf(" %03x: ", ad); 41 for (i = 0; i < ((sz < 16) ? sz : 16); i++) 42 printf(" %02x", p[i]); 43 printf("\n"); 44 sz -= 16; 45 p += 16; 46 ad += 16; 47 } 48 switch (tp->code) { 49 default: 50 break; 51 case CIS_MEM_COMMON: /* 0x01 */ 52 dump_device_desc(tp->data, tp->length, "Common"); 53 break; 54 case CIS_CHECKSUM: /* 0x10 */ 55 if (tp->length == 5) { 56 printf("\tChecksum from offset %d, length %d, value is 0x%x\n", 57 (short)((tp->data[1] << 8) | tp->data[0]), 58 (tp->data[3] << 8) | tp->data[2], 59 tp->data[4]); 60 } else 61 printf("\tIllegal length for checksum!\n"); 62 break; 63 case CIS_LONGLINK_A: /* 0x11 */ 64 printf("\tLong link to attribute memory, address 0x%x\n", 65 (tp->data[3] << 24) | 66 (tp->data[2] << 16) | 67 (tp->data[1] << 8) | 68 tp->data[0]); 69 break; 70 case CIS_LONGLINK_C: /* 0x12 */ 71 printf("\tLong link to common memory, address 0x%x\n", 72 (tp->data[3] << 24) | 73 (tp->data[2] << 16) | 74 (tp->data[1] << 8) | 75 tp->data[0]); 76 break; 77 break; 78 case CIS_INFO_V1: /* 0x15 */ 79 dump_info_v1(tp->data, tp->length); 80 break; 81 case CIS_ALTSTR: /* 0x16 */ 82 break; 83 case CIS_MEM_ATTR: /* 0x17 */ 84 dump_device_desc(tp->data, tp->length, "Attribute"); 85 break; 86 case CIS_JEDEC_C: /* 0x18 */ 87 break; 88 case CIS_JEDEC_A: /* 0x19 */ 89 break; 90 case CIS_CONF_MAP: /* 0x1A */ 91 dump_config_map(tp); 92 break; 93 case CIS_CONFIG: /* 0x1B */ 94 dump_cis_config(tp); 95 break; 96 case CIS_DEVICE_OC: /* 0x1C */ 97 dump_other_cond(tp->data); 98 break; 99 case CIS_DEVICE_OA: /* 0x1D */ 100 dump_other_cond(tp->data); 101 break; 102 case CIS_DEVICEGEO: /* 0x1E */ 103 break; 104 case CIS_DEVICEGEO_A: /* 0x1F */ 105 break; 106 case CIS_MANUF_ID: /* 0x20 */ 107 printf("\tPCMCIA ID = 0x%x, OEM ID = 0x%x\n", 108 (tp->data[1] << 8) | tp->data[0], 109 (tp->data[3] << 8) | tp->data[2]); 110 break; 111 case CIS_FUNC_ID: /* 0x21 */ 112 switch (tp->data[0]) { 113 default: 114 printf("\tUnknown function"); 115 break; 116 case 0: 117 printf("\tMultifunction card"); 118 break; 119 case 1: 120 printf("\tMemory card"); 121 break; 122 case 2: 123 printf("\tSerial port/modem"); 124 break; 125 case 3: 126 printf("\tParallel port"); 127 break; 128 case 4: 129 printf("\tFixed disk card"); 130 break; 131 case 5: 132 printf("\tVideo adapter"); 133 break; 134 case 6: 135 printf("\tNetwork/LAN adapter"); 136 break; 137 case 7: 138 printf("\tAIMS"); 139 break; 140 } 141 printf("%s%s\n", (tp->data[1] & 1) ? " - POST initialize" : "", 142 (tp->data[1] & 2) ? " - Card has ROM" : ""); 143 break; 144 case CIS_FUNC_EXT: /* 0x22 */ 145 dump_func_ext(tp->data, tp->length); 146 break; 147 case CIS_VERS_2: /* 0x40 */ 148 break; 149 } 150 } 151} 152 153/* 154 * Dump configuration map tuple. 155 */ 156void 157dump_config_map(struct tuple *tp) 158{ 159 unsigned char *p, x; 160 int rlen, mlen; 161 int i; 162 union { 163 unsigned long l; 164 unsigned char b[4]; 165 } u; 166 167 rlen = (tp->data[0] & 3) + 1; 168 mlen = ((tp->data[0] >> 2) & 3) + 1; 169 u.l = 0; 170 p = tp->data + 2; 171 for (i = 0; i < rlen; i++) 172 u.b[i] = *p++; 173 printf("\tReg len = %d, config register addr = 0x%lx, last config = 0x%x\n", 174 rlen, u.l, tp->data[1]); 175 if (mlen) 176 printf("\tRegisters: "); 177 for (i = 0; i < mlen; i++, p++) { 178 for (x = 0x1; x; x <<= 1) 179 printf("%c", x & *p ? 'X' : '-'); 180 printf(" "); 181 } 182 printf("\n"); 183} 184 185/* 186 * Dump a config entry. 187 */ 188void 189dump_cis_config(struct tuple *tp) 190{ 191 unsigned char *p, feat; 192 int i, j; 193 char c; 194 195 p = tp->data; 196 printf("\tConfig index = 0x%x%s\n", *p & 0x3F, 197 *p & 0x40 ? "(default)" : ""); 198 if (*p & 0x80) { 199 p++; 200 printf("\tInterface byte = 0x%x ", *p); 201 switch (*p & 0xF) { 202 default: 203 printf("(reserved)"); 204 break; 205 case 0: 206 printf("(memory)"); 207 break; 208 case 1: 209 printf("(I/O)"); 210 break; 211 case 4: 212 case 5: 213 case 6: 214 case 7: 215 case 8: 216 printf("(custom)"); 217 break; 218 } 219 c = ' '; 220 if (*p & 0x10) { 221 printf(" BVD1/2 active"); 222 c = ','; 223 } 224 if (*p & 0x20) { 225 printf("%c card WP active", c); /* Write protect */ 226 c = ','; 227 } 228 if (*p & 0x40) { 229 printf("%c +RDY/-BSY active", c); 230 c = ','; 231 } 232 if (*p & 0x80) 233 printf("%c wait signal supported", c); 234 printf("\n"); 235 } 236 p++; 237 feat = *p++; 238 switch (feat & 3) { 239 case 0: 240 break; 241 case 1: 242 printf("\tVcc pwr:\n"); 243 p += dump_pwr_desc(p); 244 break; 245 case 2: 246 printf("\tVcc pwr:\n"); 247 p += dump_pwr_desc(p); 248 printf("\tVpp pwr:\n"); 249 p += dump_pwr_desc(p); 250 break; 251 case 3: 252 printf("\tVcc pwr:\n"); 253 p += dump_pwr_desc(p); 254 printf("\tVpp1 pwr:\n"); 255 p += dump_pwr_desc(p); 256 printf("\tVpp2 pwr:\n"); 257 p += dump_pwr_desc(p); 258 break; 259 } 260 if (feat & 0x4) { 261 i = *p & 3; 262 j = (*p >> 2) & 7; 263 p++; 264 if (i != 3) { 265 printf("\tWait scale "); 266 print_ext_speed(*p, i); 267 while (*p & 0x80) 268 p++; 269 printf("\n"); 270 } 271 if (j != 7) { 272 printf("\tRDY/BSY scale "); 273 print_ext_speed(*p, j); 274 while (*p & 0x80) 275 p++; 276 printf("\n"); 277 } 278 } 279 if (feat & 0x8) { 280 if (*p & 0x1F) 281 printf("\tCard decodes %d address lines", *p & 0x1F); 282 else 283 printf("\tCard provides address decode"); 284 switch ((*p >> 5) & 3) { 285 case 0: 286 break; 287 case 1: 288 printf(", 8 Bit I/O only"); 289 break; 290 case 2: 291 printf(", limited 8/16 Bit I/O"); 292 break; 293 case 3: 294 printf(", full 8/16 Bit I/O"); 295 break; 296 } 297 printf("\n"); 298 if (*p & 0x80) { 299 p++; 300 c = *p++; 301 for (i = 0; i <= (c & 0xF); i++) { 302 printf("\t\tI/O address # %d: ", i + 1); 303 switch ((c >> 4) & 3) { 304 case 0: 305 break; 306 case 1: 307 printf("block start = 0x%x", *p++); 308 break; 309 case 2: 310 printf("block start = 0x%x", (p[1] << 8) | *p); 311 p += 2; 312 break; 313 case 3: 314 printf("block start = 0x%x", 315 (p[3] << 24) | (p[2] << 16) | 316 (p[1] << 8) | *p); 317 p += 4; 318 break; 319 } 320 switch ((c >> 6) & 3) { 321 case 0: 322 break; 323 case 1: 324 printf(" block length = 0x%x", *p++ + 1); 325 break; 326 case 2: 327 printf(" block length = 0x%x", ((p[1] << 8) | *p) + 1); 328 p += 2; 329 break; 330 case 3: 331 printf(" block length = 0x%x", 332 ((p[3] << 24) | (p[2] << 16) | 333 (p[1] << 8) | *p) + 1); 334 p += 4; 335 break; 336 } 337 printf("\n"); 338 } 339 } 340 } 341 342 /* IRQ descriptor */ 343 if (feat & 0x10) { 344 printf("\t\tIRQ modes:"); 345 c = ' '; 346 if (*p & 0x20) { 347 printf(" Level"); 348 c = ','; 349 } 350 if (*p & 0x40) { 351 printf("%c Pulse", c); 352 c = ','; 353 } 354 if (*p & 0x80) 355 printf("%c Shared", c); 356 printf("\n"); 357 if (*p & 0x10) { 358 i = p[0] | (p[1] << 8); 359 printf("\t\tIRQs: "); 360 if (*p & 1) 361 printf(" NMI"); 362 if (*p & 0x2) 363 printf(" IOCK"); 364 if (*p & 0x4) 365 printf(" BERR"); 366 if (*p & 0x8) 367 printf(" VEND"); 368 for (j = 0; j < 16; j++) 369 if (i & (1 << j)) 370 printf(" %d", j); 371 printf("\n"); 372 p += 3; 373 } else { 374 printf("\t\tIRQ level = %d\n", *p & 0xF); 375 p++; 376 } 377 } 378 switch ((feat >> 5) & 3) { 379 case 0: 380 break; 381 case 1: 382 printf("\tMemory space length = 0x%x\n", (p[1] << 8) | p[0]); 383 p += 2; 384 break; 385 case 2: 386 printf("\tMemory space address = 0x%x, length = 0x%x\n", 387 (p[3] << 8) | p[2], 388 (p[1] << 8) | p[0]); 389 p += 4; 390 break; 391 392 /* Memory descriptors. */ 393 case 3: 394 c = *p++; 395 for (i = 0; i <= (c & 7); i++) { 396 printf("\tMemory descriptor %d\n\t\t", i + 1); 397 switch ((c >> 3) & 3) { 398 case 0: 399 break; 400 case 1: 401 printf(" blk length = 0x%x00", *p++); 402 break; 403 case 2: 404 printf(" blk length = 0x%x00", (p[1] << 8) | *p); 405 p += 2; 406 break; 407 case 3: 408 printf(" blk length = 0x%x00", 409 (p[3] << 24) | (p[2] << 16) | 410 (p[1] << 8) | *p); 411 p += 4; 412 break; 413 } 414 switch ((c >> 5) & 3) { 415 case 0: 416 break; 417 case 1: 418 printf(" card addr = 0x%x00", *p++); 419 break; 420 case 2: 421 printf(" card addr = 0x%x00", (p[1] << 8) | *p); 422 p += 2; 423 break; 424 case 3: 425 printf(" card addr = 0x%x00", 426 (p[3] << 24) | (p[2] << 16) | 427 (p[1] << 8) | *p); 428 p += 4; 429 break; 430 } 431 if (c & 0x80) 432 switch ((c >> 5) & 3) { 433 case 0: 434 break; 435 case 1: 436 printf(" host addr = 0x%x00", *p++); 437 break; 438 case 2: 439 printf(" host addr = 0x%x00", (p[1] << 8) | *p); 440 p += 2; 441 break; 442 case 3: 443 printf(" host addr = 0x%x00", 444 (p[3] << 24) | (p[2] << 16) | 445 (p[1] << 8) | *p); 446 p += 4; 447 break; 448 } 449 printf("\n"); 450 } 451 break; 452 } 453 if (feat & 0x80) { 454 printf("\tMax twin cards = %d\n", *p & 7); 455 printf("\tMisc attr:"); 456 if (*p & 0x8) 457 printf(" (Audio-BVD2)"); 458 if (*p & 0x10) 459 printf(" (Read-only)"); 460 if (*p & 0x20) 461 printf(" (Power down supported)"); 462 if (*p & 0x80) { 463 printf(" (Ext byte = 0x%x)", p[1]); 464 p++; 465 } 466 printf("\n"); 467 p++; 468 } 469} 470 471/* 472 * dump_other_cond - Dump other conditions. 473 */ 474void 475dump_other_cond(unsigned char *p) 476{ 477 if (p[0]) { 478 printf("\t"); 479 if (p[0] & 1) 480 printf("(MWAIT)"); 481 if (p[0] & 2) 482 printf(" (3V card)"); 483 if (p[0] & 0x80) 484 printf(" (Extension bytes follow)"); 485 printf("\n"); 486 } 487} 488 489/* 490 * Dump power descriptor. 491 */ 492int 493dump_pwr_desc(unsigned char *p) 494{ 495 int len = 1, i; 496 unsigned char mask; 497 char **expp; 498 static char *pname[] = 499 {"Nominal operating supply voltage", 500 "Minimum operating supply voltage", 501 "Maximum operating supply voltage", 502 "Continuous supply current", 503 "Max current average over 1 second", 504 "Max current average over 10 ms", 505 "Power down supply current", 506 "Reserved" 507 }; 508 static char *vexp[] = 509 {"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"}; 510 static char *cexp[] = 511 {"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"}; 512 static char *mant[] = 513 {"1", "1.2", "1.3", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", 514 "5", "5.5", "6", "7", "8", "9"}; 515 516 mask = *p++; 517 expp = vexp; 518 for (i = 0; i < 8; i++) 519 if (mask & (1 << i)) { 520 len++; 521 if (i >= 3) 522 expp = cexp; 523 printf("\t\t%s: ", pname[i]); 524 printf("%s x %s", 525 mant[(*p >> 3) & 0xF], 526 expp[*p & 7]); 527 while (*p & 0x80) { 528 len++; 529 p++; 530 printf(", ext = 0x%x", *p); 531 } 532 printf("\n"); 533 p++; 534 } 535 return (len); 536} 537 538void 539dump_device_desc(unsigned char *p, int len, char *type) 540{ 541 static char *un_name[] = 542 {"512b", "2Kb", "8Kb", "32Kb", "128Kb", "512Kb", "2Mb", "reserved"}; 543 static char *speed[] = 544 {"No speed", "250nS", "200nS", "150nS", 545 "100nS", "Reserved", "Reserved"}; 546 static char *dev[] = 547 {"No device", "Mask ROM", "OTPROM", "UV EPROM", 548 "EEPROM", "FLASH EEPROM", "SRAM", "DRAM", 549 "Reserved", "Reserved", "Reserved", "Reserved", 550 "Reserved", "Function specific", "Extended", 551 "Reserved"}; 552 int count = 0; 553 554 while (*p != 0xFF && len > 0) { 555 unsigned char x; 556 557 x = *p++; 558 len -= 2; 559 if (count++ == 0) 560 printf("\t%s memory device information:\n", type); 561 printf("\t\tDevice number %d, type %s, WPS = %s\n", 562 count, dev[x >> 4], (x & 0x8) ? "ON" : "OFF"); 563 if ((x & 7) == 7) { 564 len--; 565 if (*p) { 566 printf("\t\t"); 567 print_ext_speed(*p, 0); 568 while (*p & 0x80) { 569 p++; 570 len--; 571 } 572 } 573 p++; 574 } else 575 printf("\t\tSpeed = %s", speed[x & 7]); 576 printf(", Memory block size = %s, %d units\n", 577 un_name[*p & 7], (*p >> 3) + 1); 578 p++; 579 } 580} 581 582/* 583 * Print version info 584 */ 585void 586dump_info_v1(unsigned char *p, int len) 587{ 588 printf("\tVersion = %d.%d", p[0], p[1]); 589 p += 2; 590 printf(", Manuf = [%s],", p); 591 while (*p++); 592 printf("card vers = [%s]\n", p); 593 while (*p++); 594 printf("\tAddit. info = [%s]", p); 595 while (*p++); 596 printf(",[%s]\n", p); 597} 598 599/* 600 * dump functional extension tuple. 601 */ 602void 603dump_func_ext(unsigned char *p, int len) 604{ 605 if (len == 0) 606 return; 607 switch (p[0]) { 608 case 0: 609 case 8: 610 case 10: 611 if (len != 4) { 612 printf("\tWrong length for serial extension\n"); 613 return; 614 } 615 printf("\tSerial interface extension:\n"); 616 switch (p[1] & 0x1F) { 617 default: 618 printf("\t\tUnkn device"); 619 break; 620 case 0: 621 printf("\t\t8250 UART"); 622 break; 623 case 1: 624 printf("\t\t16450 UART"); 625 break; 626 case 2: 627 printf("\t\t16550 UART"); 628 break; 629 } 630 printf(", Parity - %s%s%s%s", 631 (p[2] & 1) ? "Space," : "", 632 (p[2] & 2) ? "Mark," : "", 633 (p[2] & 4) ? "Odd," : "", 634 (p[2] & 8) ? "Even," : ""); 635 printf("\n"); 636 break; 637 case 1: 638 case 5: 639 case 6: 640 case 7: 641 printf("\tModem interface capabilities:\n"); 642 break; 643 case 2: 644 printf("\tData modem services available:\n"); 645 break; 646 case 9: 647 printf("\tFax/modem services available:\n"); 648 break; 649 case 4: 650 printf("\tVoice services available:\n"); 651 break; 652 } 653} 654 655/* 656 * print_ext_speed - Print extended speed. 657 */ 658void 659print_ext_speed(unsigned char x, int scale) 660{ 661 static char *mant[] = 662 {"Reserved", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0", 663 "3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "7.0", "8.0"}; 664 static char *exp[] = 665 {"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us", 666 "1 ms", "10 ms"}; 667 static char *scale_name[] = 668 {"None", "10", "100", "1,000", "10,000", "100,000", 669 "1,000,000", "10,000,000"}; 670 671 printf("Speed = %s x %s", mant[(x >> 3) & 0xF], exp[x & 7]); 672 if (scale) 673 printf(", scaled by %s", scale_name[scale & 7]); 674} 675