1 /*====================================================================== 2 3 PC Card CIS dump utility 4 5 dump_cis.c 1.63 2001/11/30 23:10:17 6 7 The contents of this file are subject to the Mozilla Public 8 License Version 1.1 (the "License"); you may not use this file 9 except in compliance with the License. You may obtain a copy of 10 the License at http://www.mozilla.org/MPL/ 11 12 Software distributed under the License is distributed on an "AS 13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 14 implied. See the License for the specific language governing 15 rights and limitations under the License. 16 17 The initial developer of the original code is David A. Hinds 18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds 19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved. 20 21 Alternatively, the contents of this file may be used under the 22 terms of the GNU General Public License version 2 (the "GPL"), in 23 which case the provisions of the GPL are applicable instead of the 24 above. If you wish to allow the use of your version of this file 25 only under the terms of the GPL and not to allow others to use 26 your version of this file under the MPL, indicate your decision 27 by deleting the provisions above and replace them with the notice 28 and other provisions required by the GPL. If you do not delete 29 the provisions above, a recipient may use your version of this 30 file under either the MPL or the GPL. 31 32 ======================================================================*/ 33 #if (defined(__BEOS__) || defined(__HAIKU__)) 34 #include <OS.h> 35 #endif 36 #include <sys/types.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <unistd.h> 41 #include <fcntl.h> 42 #include <errno.h> 43 #include <sys/time.h> 44 #include <sys/ioctl.h> 45 #include <sys/stat.h> 46 47 #include <pcmcia/cs_types.h> 48 #include <pcmcia/cs.h> 49 #include <pcmcia/cistpl.h> 50 #include <pcmcia/ds.h> 51 52 static int verbose = 0; 53 static char indent[10] = " "; 54 55 /*====================================================================*/ 56 #if (!defined(__BEOS__) && !defined(__HAIKU__)) 57 static int major = 0; 58 59 static int lookup_dev(char *name) 60 { 61 FILE *f; 62 int n; 63 char s[32], t[32]; 64 65 f = fopen("/proc/devices", "r"); 66 if (f == NULL) 67 return -1; 68 while (fgets(s, 32, f) != NULL) { 69 if (sscanf(s, "%d %s", &n, t) == 2) 70 if (strcmp(name, t) == 0) 71 break; 72 } 73 fclose(f); 74 if (strcmp(name, t) == 0) 75 return n; 76 else 77 return -1; 78 } 79 #endif 80 /*====================================================================*/ 81 82 static int open_sock(int sock) 83 { 84 #if (defined(__BEOS__) || defined(__HAIKU__)) 85 char fn[B_OS_NAME_LENGTH]; 86 sprintf(fn, "/dev/bus/pcmcia/sock/%d", sock); 87 return open(fn, O_RDONLY); 88 #else 89 static char *paths[] = { 90 "/var/lib/pcmcia", "/var/run", "/dev", "/tmp", NULL 91 }; 92 int fd; 93 char **p, fn[64]; 94 dev_t dev = (major<<8) + sock; 95 96 for (p = paths; *p; p++) { 97 sprintf(fn, "%s/dc%d", *p, getpid()); 98 if (mknod(fn, (S_IFCHR|S_IREAD|S_IWRITE), dev) == 0) { 99 fd = open(fn, O_RDONLY); 100 unlink(fn); 101 if (fd >= 0) 102 return fd; 103 if (errno == ENODEV) break; 104 } 105 } 106 return -1; 107 #endif 108 } /* open_sock */ 109 110 /*====================================================================*/ 111 112 static void print_tuple(tuple_parse_t *tup) 113 { 114 int i; 115 printf("%soffset 0x%2.2x, tuple 0x%2.2x, link 0x%2.2x\n", 116 indent, tup->tuple.CISOffset, tup->tuple.TupleCode, 117 tup->tuple.TupleLink); 118 for (i = 0; i < tup->tuple.TupleDataLen; i++) { 119 if ((i % 16) == 0) printf("%s ", indent); 120 printf("%2.2x ", (u_char)tup->data[i]); 121 if ((i % 16) == 15) putchar('\n'); 122 } 123 if ((i % 16) != 0) putchar('\n'); 124 } 125 126 /*====================================================================*/ 127 128 static void print_funcid(cistpl_funcid_t *fn) 129 { 130 printf("%sfuncid ", indent); 131 switch (fn->func) { 132 case CISTPL_FUNCID_MULTI: 133 printf("multi_function"); break; 134 case CISTPL_FUNCID_MEMORY: 135 printf("memory_card"); break; 136 case CISTPL_FUNCID_SERIAL: 137 printf("serial_port"); break; 138 case CISTPL_FUNCID_PARALLEL: 139 printf("parallel_port"); break; 140 case CISTPL_FUNCID_FIXED: 141 printf("fixed_disk"); break; 142 case CISTPL_FUNCID_VIDEO: 143 printf("video_adapter"); break; 144 case CISTPL_FUNCID_NETWORK: 145 printf("network_adapter"); break; 146 case CISTPL_FUNCID_AIMS: 147 printf("aims_card"); break; 148 case CISTPL_FUNCID_SCSI: 149 printf("scsi_adapter"); break; 150 default: 151 printf("unknown"); break; 152 } 153 if (fn->sysinit & CISTPL_SYSINIT_POST) 154 printf(" [post]"); 155 if (fn->sysinit & CISTPL_SYSINIT_ROM) 156 printf(" [rom]"); 157 putchar('\n'); 158 } 159 160 /*====================================================================*/ 161 162 static void print_size(u_int size) 163 { 164 if (size < 1024) 165 printf("%ub", size); 166 else if (size < 1024*1024) 167 printf("%ukb", size/1024); 168 else 169 printf("%umb", size/(1024*1024)); 170 } 171 172 static void print_unit(u_int v, char *unit, char tag) 173 { 174 int n; 175 for (n = 0; (v % 1000) == 0; n++) v /= 1000; 176 printf("%u", v); 177 if (n < strlen(unit)) putchar(unit[n]); 178 putchar(tag); 179 } 180 181 static void print_time(u_int tm, u_long scale) 182 { 183 print_unit(tm * scale, "num", 's'); 184 } 185 186 static void print_volt(u_int vi) 187 { 188 print_unit(vi * 10, "um", 'V'); 189 } 190 191 static void print_current(u_int ii) 192 { 193 print_unit(ii / 10, "um", 'A'); 194 } 195 196 static void print_speed(u_int b) 197 { 198 if (b < 1000) 199 printf("%u bits/sec", b); 200 else if (b < 1000000) 201 printf("%u kb/sec", b/1000); 202 else 203 printf("%u mb/sec", b/1000000); 204 } 205 206 /*====================================================================*/ 207 208 static const char *dtype[] = { 209 "NULL", "ROM", "OTPROM", "EPROM", "EEPROM", "FLASH", "SRAM", 210 "DRAM", "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", "fn_specific", 211 "extended", "rsvd" 212 }; 213 214 static void print_device(cistpl_device_t *dev) 215 { 216 int i; 217 for (i = 0; i < dev->ndev; i++) { 218 printf("%s %s ", indent, dtype[dev->dev[i].type]); 219 printf("%uns, ", dev->dev[i].speed); 220 print_size(dev->dev[i].size); 221 putchar('\n'); 222 } 223 if (dev->ndev == 0) 224 printf("%s no_info\n", indent); 225 } 226 227 /*====================================================================*/ 228 229 static void print_power(char *tag, cistpl_power_t *power) 230 { 231 int i, n; 232 for (i = n = 0; i < 8; i++) 233 if (power->present & (1<<i)) n++; 234 i = 0; 235 printf("%s %s", indent, tag); 236 if (power->present & (1<<CISTPL_POWER_VNOM)) { 237 printf(" Vnom "); i++; 238 print_volt(power->param[CISTPL_POWER_VNOM]); 239 } 240 if (power->present & (1<<CISTPL_POWER_VMIN)) { 241 printf(" Vmin "); i++; 242 print_volt(power->param[CISTPL_POWER_VMIN]); 243 } 244 if (power->present & (1<<CISTPL_POWER_VMAX)) { 245 printf(" Vmax "); i++; 246 print_volt(power->param[CISTPL_POWER_VMAX]); 247 } 248 if (power->present & (1<<CISTPL_POWER_ISTATIC)) { 249 printf(" Istatic "); i++; 250 print_current(power->param[CISTPL_POWER_ISTATIC]); 251 } 252 if (power->present & (1<<CISTPL_POWER_IAVG)) { 253 if (++i == 5) printf("\n%s ", indent); 254 printf(" Iavg "); 255 print_current(power->param[CISTPL_POWER_IAVG]); 256 } 257 if (power->present & (1<<CISTPL_POWER_IPEAK)) { 258 if (++i == 5) printf("\n%s ", indent); 259 printf(" Ipeak "); 260 print_current(power->param[CISTPL_POWER_IPEAK]); 261 } 262 if (power->present & (1<<CISTPL_POWER_IDOWN)) { 263 if (++i == 5) printf("\n%s ", indent); 264 printf(" Idown "); 265 print_current(power->param[CISTPL_POWER_IDOWN]); 266 } 267 if (power->flags & CISTPL_POWER_HIGHZ_OK) { 268 if (++i == 5) printf("\n%s ", indent); 269 printf(" [highz OK]"); 270 } 271 if (power->flags & CISTPL_POWER_HIGHZ_REQ) { 272 printf(" [highz]"); 273 } 274 putchar('\n'); 275 } 276 277 /*====================================================================*/ 278 279 static void print_cftable_entry(cistpl_cftable_entry_t *entry) 280 { 281 int i; 282 283 printf("%scftable_entry 0x%2.2x%s\n", indent, entry->index, 284 (entry->flags & CISTPL_CFTABLE_DEFAULT) ? " [default]" : ""); 285 286 if (entry->flags & ~CISTPL_CFTABLE_DEFAULT) { 287 printf("%s ", indent); 288 if (entry->flags & CISTPL_CFTABLE_BVDS) 289 printf(" [bvd]"); 290 if (entry->flags & CISTPL_CFTABLE_WP) 291 printf(" [wp]"); 292 if (entry->flags & CISTPL_CFTABLE_RDYBSY) 293 printf(" [rdybsy]"); 294 if (entry->flags & CISTPL_CFTABLE_MWAIT) 295 printf(" [mwait]"); 296 if (entry->flags & CISTPL_CFTABLE_AUDIO) 297 printf(" [audio]"); 298 if (entry->flags & CISTPL_CFTABLE_READONLY) 299 printf(" [readonly]"); 300 if (entry->flags & CISTPL_CFTABLE_PWRDOWN) 301 printf(" [pwrdown]"); 302 putchar('\n'); 303 } 304 305 if (entry->vcc.present) 306 print_power("Vcc", &entry->vcc); 307 if (entry->vpp1.present) 308 print_power("Vpp1", &entry->vpp1); 309 if (entry->vpp2.present) 310 print_power("Vpp2", &entry->vpp2); 311 312 if ((entry->timing.wait != 0) || (entry->timing.ready != 0) || 313 (entry->timing.reserved != 0)) { 314 printf("%s timing", indent); 315 if (entry->timing.wait != 0) { 316 printf(" wait "); 317 print_time(entry->timing.wait, entry->timing.waitscale); 318 } 319 if (entry->timing.ready != 0) { 320 printf(" ready "); 321 print_time(entry->timing.ready, entry->timing.rdyscale); 322 } 323 if (entry->timing.reserved != 0) { 324 printf(" reserved "); 325 print_time(entry->timing.reserved, entry->timing.rsvscale); 326 } 327 putchar('\n'); 328 } 329 330 if (entry->io.nwin) { 331 cistpl_io_t *io = &entry->io; 332 printf("%s io", indent); 333 for (i = 0; i < io->nwin; i++) { 334 if (i) putchar(','); 335 printf(" 0x%4.4x-0x%4.4x", io->win[i].base, 336 io->win[i].base+io->win[i].len-1); 337 } 338 printf(" [lines=%d]", io->flags & CISTPL_IO_LINES_MASK); 339 if (io->flags & CISTPL_IO_8BIT) printf(" [8bit]"); 340 if (io->flags & CISTPL_IO_16BIT) printf(" [16bit]"); 341 if (io->flags & CISTPL_IO_RANGE) printf(" [range]"); 342 putchar('\n'); 343 } 344 345 if (entry->irq.IRQInfo1) { 346 printf("%s irq ", indent); 347 if (entry->irq.IRQInfo1 & IRQ_INFO2_VALID) 348 printf("mask 0x%04x", entry->irq.IRQInfo2); 349 else 350 printf("%u", entry->irq.IRQInfo1 & IRQ_MASK); 351 if (entry->irq.IRQInfo1 & IRQ_LEVEL_ID) printf(" [level]"); 352 if (entry->irq.IRQInfo1 & IRQ_PULSE_ID) printf(" [pulse]"); 353 if (entry->irq.IRQInfo1 & IRQ_SHARE_ID) printf(" [shared]"); 354 putchar('\n'); 355 } 356 357 if (entry->mem.nwin) { 358 cistpl_mem_t *mem = &entry->mem; 359 printf("%s memory", indent); 360 for (i = 0; i < mem->nwin; i++) { 361 if (i) putchar(','); 362 printf(" 0x%4.4x-0x%4.4x @ 0x%4.4x", mem->win[i].card_addr, 363 mem->win[i].card_addr + mem->win[i].len-1, 364 mem->win[i].host_addr); 365 } 366 putchar('\n'); 367 } 368 369 if (verbose && entry->subtuples) 370 printf("%s %d bytes in subtuples\n", indent, entry->subtuples); 371 372 } 373 374 /*====================================================================*/ 375 376 static void print_cftable_entry_cb(cistpl_cftable_entry_cb_t *entry) 377 { 378 int i; 379 380 printf("%scftable_entry_cb 0x%2.2x%s\n", indent, entry->index, 381 (entry->flags & CISTPL_CFTABLE_DEFAULT) ? " [default]" : ""); 382 383 if (entry->flags & ~CISTPL_CFTABLE_DEFAULT) { 384 printf("%s ", indent); 385 if (entry->flags & CISTPL_CFTABLE_MASTER) 386 printf(" [master]"); 387 if (entry->flags & CISTPL_CFTABLE_INVALIDATE) 388 printf(" [invalidate]"); 389 if (entry->flags & CISTPL_CFTABLE_VGA_PALETTE) 390 printf(" [vga palette]"); 391 if (entry->flags & CISTPL_CFTABLE_PARITY) 392 printf(" [parity]"); 393 if (entry->flags & CISTPL_CFTABLE_WAIT) 394 printf(" [wait]"); 395 if (entry->flags & CISTPL_CFTABLE_SERR) 396 printf(" [serr]"); 397 if (entry->flags & CISTPL_CFTABLE_FAST_BACK) 398 printf(" [fast back]"); 399 if (entry->flags & CISTPL_CFTABLE_BINARY_AUDIO) 400 printf(" [binary audio]"); 401 if (entry->flags & CISTPL_CFTABLE_PWM_AUDIO) 402 printf(" [pwm audio]"); 403 putchar('\n'); 404 } 405 406 if (entry->vcc.present) 407 print_power("Vcc", &entry->vcc); 408 if (entry->vpp1.present) 409 print_power("Vpp1", &entry->vpp1); 410 if (entry->vpp2.present) 411 print_power("Vpp2", &entry->vpp2); 412 413 if (entry->io) { 414 printf("%s io_base", indent); 415 for (i = 0; i < 8; i++) 416 if (entry->io & (1<<i)) printf(" %d", i); 417 putchar('\n'); 418 } 419 420 if (entry->irq.IRQInfo1) { 421 printf("%s irq ", indent); 422 if (entry->irq.IRQInfo1 & IRQ_INFO2_VALID) 423 printf("mask 0x%4.4x", entry->irq.IRQInfo2); 424 else 425 printf("%u", entry->irq.IRQInfo1 & IRQ_MASK); 426 if (entry->irq.IRQInfo1 & IRQ_LEVEL_ID) printf(" [level]"); 427 if (entry->irq.IRQInfo1 & IRQ_PULSE_ID) printf(" [pulse]"); 428 if (entry->irq.IRQInfo1 & IRQ_SHARE_ID) printf(" [shared]"); 429 putchar('\n'); 430 } 431 432 if (entry->mem) { 433 printf("%s mem_base", indent); 434 for (i = 0; i < 8; i++) 435 if (entry->mem & (1<<i)) printf(" %d", i); 436 putchar('\n'); 437 } 438 439 if (verbose && entry->subtuples) 440 printf("%s %d bytes in subtuples\n", indent, entry->subtuples); 441 442 } 443 444 /*====================================================================*/ 445 446 static void print_jedec(cistpl_jedec_t *j) 447 { 448 int i; 449 for (i = 0; i < j->nid; i++) { 450 if (i != 0) putchar(','); 451 printf(" 0x%02x 0x%02x", j->id[i].mfr, j->id[i].info); 452 } 453 putchar('\n'); 454 } 455 456 /*====================================================================*/ 457 458 static void print_device_geo(cistpl_device_geo_t *geo) 459 { 460 int i; 461 for (i = 0; i < geo->ngeo; i++) { 462 printf("%s width %d erase 0x%x read 0x%x write 0x%x " 463 "partition 0x%x interleave 0x%x\n", indent, 464 geo->geo[i].buswidth, geo->geo[i].erase_block, 465 geo->geo[i].read_block, geo->geo[i].write_block, 466 geo->geo[i].partition, geo->geo[i].interleave); 467 } 468 } 469 470 /*====================================================================*/ 471 472 static void print_org(cistpl_org_t *org) 473 { 474 printf("%sdata_org ", indent); 475 switch (org->data_org) { 476 case CISTPL_ORG_FS: 477 printf("[filesystem]"); break; 478 case CISTPL_ORG_APPSPEC: 479 printf("[app_specific]"); break; 480 case CISTPL_ORG_XIP: 481 printf("[code]"); break; 482 default: 483 if (org->data_org < 0x80) 484 printf("[reserved]"); 485 else 486 printf("[vendor_specific]"); 487 } 488 printf(", \"%s\"\n", org->desc); 489 } 490 491 /*====================================================================*/ 492 493 static char *data_mod[] = { 494 "Bell103", "V.21", "V.23", "V.22", "Bell212A", "V.22bis", 495 "V.26", "V.26bis", "V.27bis", "V.29", "V.32", "V.32bis", 496 "V.34", "rfu", "rfu", "rfu" 497 }; 498 static char *fax_mod[] = { 499 "V.21-C2", "V.27ter", "V.29", "V.17", "V.33", "rfu", "rfu", "rfu" 500 }; 501 static char *fax_features[] = { 502 "T.3", "T.4", "T.6", "error", "voice", "poll", "file", "passwd" 503 }; 504 static char *cmd_protocol[] = { 505 "AT1", "AT2", "AT3", "MNP_AT", "V.25bis", "V.25A", "DMCL" 506 }; 507 static char *uart[] = { 508 "8250", "16450", "16550", "8251", "8530", "85230" 509 }; 510 static char *parity[] = { "space", "mark", "odd", "even" }; 511 static char *stop[] = { "1", "1.5", "2" }; 512 static char *flow[] = { 513 "XON/XOFF xmit", "XON/XOFF rcv", "hw xmit", "hw rcv", "transparent" 514 }; 515 static void print_serial(cistpl_funce_t *funce) 516 { 517 cistpl_serial_t *s; 518 cistpl_data_serv_t *ds; 519 cistpl_fax_serv_t *fs; 520 cistpl_modem_cap_t *cp; 521 int i, j; 522 523 switch (funce->type & 0x0f) { 524 case CISTPL_FUNCE_SERIAL_IF: 525 case CISTPL_FUNCE_SERIAL_IF_DATA: 526 case CISTPL_FUNCE_SERIAL_IF_FAX: 527 case CISTPL_FUNCE_SERIAL_IF_VOICE: 528 s = (cistpl_serial_t *)(funce->data); 529 printf("%sserial_interface", indent); 530 if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_DATA) 531 printf("_data"); 532 else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_FAX) 533 printf("_fax"); 534 else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_VOICE) 535 printf("_voice"); 536 printf("\n%s uart %s", indent, 537 (s->uart_type < 6) ? uart[s->uart_type] : "reserved"); 538 if (s->uart_cap_0) { 539 printf(" ["); 540 for (i = 0; i < 4; i++) 541 if (s->uart_cap_0 & (1<<i)) 542 printf("%s%s", parity[i], 543 (s->uart_cap_0 >= (2<<i)) ? "/" : "]"); 544 } 545 if (s->uart_cap_1) { 546 int m = s->uart_cap_1 & 0x0f; 547 int n = s->uart_cap_1 >> 4; 548 printf(" ["); 549 for (i = 0; i < 4; i++) 550 if (m & (1<<i)) 551 printf("%d%s", i+5, (m >= (2<<i)) ? "/" : ""); 552 printf("] ["); 553 for (i = 0; i < 3; i++) 554 if (n & (1<<i)) 555 printf("%s%s", stop[i], (n >= (2<<i)) ? "/" : "]"); 556 } 557 printf("\n"); 558 break; 559 case CISTPL_FUNCE_SERIAL_CAP: 560 case CISTPL_FUNCE_SERIAL_CAP_DATA: 561 case CISTPL_FUNCE_SERIAL_CAP_FAX: 562 case CISTPL_FUNCE_SERIAL_CAP_VOICE: 563 cp = (cistpl_modem_cap_t *)(funce->data); 564 printf("%sserial_modem_cap", indent); 565 if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_DATA) 566 printf("_data"); 567 else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_FAX) 568 printf("_fax"); 569 else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_VOICE) 570 printf("_voice"); 571 if (cp->flow) { 572 printf("\n%s flow", indent); 573 for (i = 0; i < 5; i++) 574 if (cp->flow & (1<<i)) 575 printf(" [%s]", flow[i]); 576 } 577 printf("\n%s cmd_buf %d rcv_buf %d xmit_buf %d\n", 578 indent, 4*(cp->cmd_buf+1), 579 cp->rcv_buf_0+(cp->rcv_buf_1<<8)+(cp->rcv_buf_2<<16), 580 cp->xmit_buf_0+(cp->xmit_buf_1<<8)+(cp->xmit_buf_2<<16)); 581 break; 582 case CISTPL_FUNCE_SERIAL_SERV_DATA: 583 ds = (cistpl_data_serv_t *)(funce->data); 584 printf("%sserial_data_services\n", indent); 585 printf("%s data_rate %d\n", indent, 586 75*((ds->max_data_0<<8) + ds->max_data_1)); 587 printf("%s modulation", indent); 588 for (i = j = 0; i < 16; i++) 589 if (((ds->modulation_1<<8) + ds->modulation_0) & (1<<i)) { 590 if (++j % 6 == 0) 591 printf("\n%s ", indent); 592 printf(" [%s]", data_mod[i]); 593 } 594 printf("\n"); 595 if (ds->error_control) { 596 printf("%s error_control", indent); 597 if (ds->error_control & CISTPL_SERIAL_ERR_MNP2_4) 598 printf(" [MNP2-4]"); 599 if (ds->error_control & CISTPL_SERIAL_ERR_V42_LAPM) 600 printf(" [V.42/LAPM]"); 601 printf("\n"); 602 } 603 if (ds->compression) { 604 printf("%s compression", indent); 605 if (ds->compression & CISTPL_SERIAL_CMPR_V42BIS) 606 printf(" [V.42bis]"); 607 if (ds->compression & CISTPL_SERIAL_CMPR_MNP5) 608 printf(" [MNP5]"); 609 printf("\n"); 610 } 611 if (ds->cmd_protocol) { 612 printf("%s cmd_protocol", indent); 613 for (i = 0; i < 7; i++) 614 if (ds->cmd_protocol & (1<<i)) 615 printf(" [%s]", cmd_protocol[i]); 616 printf("\n"); 617 } 618 break; 619 620 case CISTPL_FUNCE_SERIAL_SERV_FAX: 621 fs = (cistpl_fax_serv_t *)(funce->data); 622 printf("%sserial_fax_services [class=%d]\n", 623 indent, funce->type>>4); 624 printf("%s data_rate %d\n", indent, 625 75*((fs->max_data_0<<8) + fs->max_data_1)); 626 printf("%s modulation", indent); 627 for (i = 0; i < 8; i++) 628 if (fs->modulation & (1<<i)) 629 printf(" [%s]", fax_mod[i]); 630 printf("\n"); 631 if (fs->features_0) { 632 printf("%s features", indent); 633 for (i = 0; i < 8; i++) 634 if (fs->features_0 & (1<<i)) 635 printf(" [%s]", fax_features[i]); 636 printf("\n"); 637 } 638 break; 639 } 640 } 641 642 /*====================================================================*/ 643 644 static void print_fixed(cistpl_funce_t *funce) 645 { 646 cistpl_ide_interface_t *i; 647 cistpl_ide_feature_t *f; 648 649 switch (funce->type) { 650 case CISTPL_FUNCE_IDE_IFACE: 651 i = (cistpl_ide_interface_t *)(funce->data); 652 printf("%sdisk_interface ", indent); 653 if (i->interface == CISTPL_IDE_INTERFACE) 654 printf("[ide]\n"); 655 else 656 printf("[undefined]\n"); 657 break; 658 case CISTPL_FUNCE_IDE_MASTER: 659 case CISTPL_FUNCE_IDE_SLAVE: 660 f = (cistpl_ide_feature_t *)(funce->data); 661 printf("%sdisk_features", indent); 662 if (f->feature1 & CISTPL_IDE_SILICON) 663 printf(" [silicon]"); 664 else 665 printf(" [rotating]"); 666 if (f->feature1 & CISTPL_IDE_UNIQUE) 667 printf(" [unique]"); 668 if (f->feature1 & CISTPL_IDE_DUAL) 669 printf(" [dual]"); 670 else 671 printf(" [single]"); 672 if (f->feature1 && f->feature2) 673 printf("\n%s ", indent); 674 if (f->feature2 & CISTPL_IDE_HAS_SLEEP) 675 printf(" [sleep]"); 676 if (f->feature2 & CISTPL_IDE_HAS_STANDBY) 677 printf(" [standby]"); 678 if (f->feature2 & CISTPL_IDE_HAS_IDLE) 679 printf(" [idle]"); 680 if (f->feature2 & CISTPL_IDE_LOW_POWER) 681 printf(" [low power]"); 682 if (f->feature2 & CISTPL_IDE_REG_INHIBIT) 683 printf(" [reg inhibit]"); 684 if (f->feature2 & CISTPL_IDE_HAS_INDEX) 685 printf(" [index]"); 686 if (f->feature2 & CISTPL_IDE_IOIS16) 687 printf(" [iois16]"); 688 putchar('\n'); 689 break; 690 } 691 } 692 693 /*====================================================================*/ 694 695 static const char *tech[] = { 696 "undefined", "ARCnet", "ethernet", "token_ring", "localtalk", 697 "FDDI/CDDI", "ATM", "wireless" 698 }; 699 700 static const char *media[] = { 701 "undefined", "unshielded_twisted_pair", "shielded_twisted_pair", 702 "thin_coax", "thick_coax", "fiber", "900_MHz", "2.4_GHz", 703 "5.4_GHz", "diffuse_infrared", "point_to_point_infrared" 704 }; 705 706 static void print_network(cistpl_funce_t *funce) 707 { 708 cistpl_lan_tech_t *t; 709 cistpl_lan_speed_t *s; 710 cistpl_lan_media_t *m; 711 cistpl_lan_node_id_t *n; 712 cistpl_lan_connector_t *c; 713 int i; 714 715 switch (funce->type) { 716 case CISTPL_FUNCE_LAN_TECH: 717 t = (cistpl_lan_tech_t *)(funce->data); 718 printf("%slan_technology %s\n", indent, tech[t->tech]); 719 break; 720 case CISTPL_FUNCE_LAN_SPEED: 721 s = (cistpl_lan_speed_t *)(funce->data); 722 printf("%slan_speed ", indent); 723 print_speed(s->speed); 724 putchar('\n'); 725 break; 726 case CISTPL_FUNCE_LAN_MEDIA: 727 m = (cistpl_lan_media_t *)(funce->data); 728 printf("%slan_media %s\n", indent, media[m->media]); 729 break; 730 case CISTPL_FUNCE_LAN_NODE_ID: 731 n = (cistpl_lan_node_id_t *)(funce->data); 732 printf("%slan_node_id", indent); 733 for (i = 0; i < n->nb; i++) 734 printf(" %02x", n->id[i]); 735 putchar('\n'); 736 break; 737 case CISTPL_FUNCE_LAN_CONNECTOR: 738 c = (cistpl_lan_connector_t *)(funce->data); 739 printf("%slan_connector ", indent); 740 if (c->code == 0) 741 printf("Open connector standard\n"); 742 else 743 printf("Closed connector standard\n"); 744 break; 745 } 746 } 747 748 /*====================================================================*/ 749 750 static void print_vers_1(cistpl_vers_1_t *v1) 751 { 752 int i, n; 753 char s[32]; 754 sprintf(s, "%svers_1 %d.%d", indent, v1->major, v1->minor); 755 printf("%s", s); 756 n = strlen(s); 757 for (i = 0; i < v1->ns; i++) { 758 if (n + strlen(v1->str + v1->ofs[i]) + 4 > 72) { 759 n = strlen(indent) + 2; 760 printf(",\n%s ", indent); 761 } else { 762 printf(", "); 763 n += 2; 764 } 765 printf("\"%s\"", v1->str + v1->ofs[i]); 766 n += strlen(v1->str + v1->ofs[i]) + 2; 767 } 768 putchar('\n'); 769 } 770 771 /*====================================================================*/ 772 773 static void print_vers_2(cistpl_vers_2_t *v2) 774 { 775 printf("%sversion 0x%2.2x, compliance 0x%2.2x, dindex 0x%4.4x\n", 776 indent, v2->vers, v2->comply, v2->dindex); 777 printf("%s vspec8 0x%2.2x, vspec9 0x%2.2x, nhdr %d\n", 778 indent, v2->vspec8, v2->vspec9, v2->nhdr); 779 printf("%s vendor \"%s\"\n", indent, v2->str+v2->vendor); 780 printf("%s info \"%s\"\n", indent, v2->str+v2->info); 781 } 782 783 /*====================================================================*/ 784 785 #ifdef CISTPL_FORMAT_DISK 786 static void print_format(cistpl_format_t *fmt) 787 { 788 if (fmt->type == CISTPL_FORMAT_DISK) 789 printf("%s [disk]", indent); 790 else if (fmt->type == CISTPL_FORMAT_MEM) 791 printf("%s [memory]", indent); 792 else 793 printf("%s [type 0x%02x]\n", indent, fmt->type); 794 if (fmt->edc == CISTPL_EDC_NONE) 795 printf(" [no edc]"); 796 else if (fmt->edc == CISTPL_EDC_CKSUM) 797 printf(" [cksum]"); 798 else if (fmt->edc == CISTPL_EDC_CRC) 799 printf(" [crc]"); 800 else if (fmt->edc == CISTPL_EDC_PCC) 801 printf(" [pcc]"); 802 else 803 printf(" [edc 0x%02x]", fmt->edc); 804 printf(" offset 0x%04x length ", fmt->offset); 805 print_size(fmt->length); 806 putchar('\n'); 807 } 808 #endif 809 810 /*====================================================================*/ 811 812 static void print_config(int code, cistpl_config_t *cfg) 813 { 814 printf("%sconfig%s base 0x%4.4x", indent, 815 (code == CISTPL_CONFIG_CB) ? "_cb" : "", 816 cfg->base); 817 if (code == CISTPL_CONFIG) 818 printf(" mask 0x%4.4x", cfg->rmask[0]); 819 printf(" last_index 0x%2.2x\n", cfg->last_idx); 820 if (verbose && cfg->subtuples) 821 printf("%s %d bytes in subtuples\n", indent, cfg->subtuples); 822 } 823 824 /*====================================================================*/ 825 826 static int nfn = 0, cur = 0; 827 828 static void print_parse(tuple_parse_t *tup) 829 { 830 static int func = 0; 831 int i; 832 833 switch (tup->tuple.TupleCode) { 834 case CISTPL_DEVICE: 835 case CISTPL_DEVICE_A: 836 if (tup->tuple.TupleCode == CISTPL_DEVICE) 837 printf("%sdev_info\n", indent); 838 else 839 printf("%sattr_dev_info\n", indent); 840 print_device(&tup->parse.device); 841 break; 842 case CISTPL_CHECKSUM: 843 printf("%schecksum 0x%04x-0x%04x = 0x%02x\n", 844 indent, tup->parse.checksum.addr, 845 tup->parse.checksum.addr+tup->parse.checksum.len-1, 846 tup->parse.checksum.sum); 847 break; 848 case CISTPL_LONGLINK_A: 849 if (verbose) 850 printf("%slong_link_attr 0x%04x\n", indent, 851 tup->parse.longlink.addr); 852 break; 853 case CISTPL_LONGLINK_C: 854 if (verbose) 855 printf("%slong_link 0x%04x\n", indent, 856 tup->parse.longlink.addr); 857 break; 858 case CISTPL_LONGLINK_MFC: 859 if (verbose) { 860 printf("%smfc_long_link\n", indent); 861 for (i = 0; i < tup->parse.longlink_mfc.nfn; i++) 862 printf("%s function %d: %s 0x%04x\n", indent, i, 863 tup->parse.longlink_mfc.fn[i].space ? "common" : "attr", 864 tup->parse.longlink_mfc.fn[i].addr); 865 } else { 866 printf("%smfc {\n", indent); 867 nfn = tup->parse.longlink_mfc.nfn; 868 cur = 0; 869 strcat(indent, " "); 870 } 871 break; 872 case CISTPL_NO_LINK: 873 if (verbose) 874 printf("%sno_long_link\n", indent); 875 break; 876 #ifdef CISTPL_INDIRECT 877 case CISTPL_INDIRECT: 878 if (verbose) 879 printf("%sindirect_access\n", indent); 880 break; 881 #endif 882 case CISTPL_LINKTARGET: 883 if (verbose) 884 printf("%slink_target\n", indent); 885 else { 886 if (cur++) printf("%s}, {\n", indent+2); 887 } 888 break; 889 case CISTPL_VERS_1: 890 print_vers_1(&tup->parse.version_1); 891 break; 892 case CISTPL_ALTSTR: 893 break; 894 case CISTPL_JEDEC_A: 895 case CISTPL_JEDEC_C: 896 if (tup->tuple.TupleCode == CISTPL_JEDEC_C) 897 printf("%scommon_jedec", indent); 898 else 899 printf("%sattr_jedec", indent); 900 print_jedec(&tup->parse.jedec); 901 break; 902 case CISTPL_DEVICE_GEO: 903 case CISTPL_DEVICE_GEO_A: 904 if (tup->tuple.TupleCode == CISTPL_DEVICE_GEO) 905 printf("%scommon_geometry\n", indent); 906 else 907 printf("%sattr_geometry\n", indent); 908 print_device_geo(&tup->parse.device_geo); 909 break; 910 case CISTPL_MANFID: 911 printf("%smanfid 0x%4.4x, 0x%4.4x\n", indent, 912 tup->parse.manfid.manf, tup->parse.manfid.card); 913 break; 914 case CISTPL_FUNCID: 915 print_funcid(&tup->parse.funcid); 916 func = tup->parse.funcid.func; 917 break; 918 case CISTPL_FUNCE: 919 switch (func) { 920 case CISTPL_FUNCID_SERIAL: 921 print_serial(&tup->parse.funce); 922 break; 923 case CISTPL_FUNCID_FIXED: 924 print_fixed(&tup->parse.funce); 925 break; 926 case CISTPL_FUNCID_NETWORK: 927 print_network(&tup->parse.funce); 928 break; 929 } 930 break; 931 case CISTPL_BAR: 932 printf("%sBAR %d size ", indent, 933 tup->parse.bar.attr & CISTPL_BAR_SPACE); 934 print_size(tup->parse.bar.size); 935 if (tup->parse.bar.attr & CISTPL_BAR_SPACE_IO) 936 printf(" [io]"); 937 else 938 printf(" [mem]"); 939 if (tup->parse.bar.attr & CISTPL_BAR_PREFETCH) 940 printf(" [prefetch]"); 941 if (tup->parse.bar.attr & CISTPL_BAR_CACHEABLE) 942 printf(" [cacheable]"); 943 if (tup->parse.bar.attr & CISTPL_BAR_1MEG_MAP) 944 printf(" [<1mb]"); 945 putchar('\n'); 946 break; 947 case CISTPL_CONFIG: 948 case CISTPL_CONFIG_CB: 949 print_config(tup->tuple.TupleCode, &tup->parse.config); 950 break; 951 case CISTPL_CFTABLE_ENTRY: 952 print_cftable_entry(&tup->parse.cftable_entry); 953 break; 954 case CISTPL_CFTABLE_ENTRY_CB: 955 print_cftable_entry_cb(&tup->parse.cftable_entry_cb); 956 break; 957 case CISTPL_VERS_2: 958 print_vers_2(&tup->parse.vers_2); 959 break; 960 case CISTPL_ORG: 961 print_org(&tup->parse.org); 962 break; 963 #ifdef CISTPL_FORMAT_DISK 964 case CISTPL_FORMAT: 965 case CISTPL_FORMAT_A: 966 if (tup->tuple.TupleCode == CISTPL_FORMAT) 967 printf("%scommon_format\n", indent); 968 else 969 printf("%sattr_format\n", indent); 970 print_format(&tup->parse.format); 971 #endif 972 } 973 } 974 975 /*====================================================================*/ 976 977 static int get_tuple_buf(int fd, ds_ioctl_arg_t *arg, int first) 978 { 979 u_int ofs; 980 static int nb = 0; 981 static u_char buf[1024]; 982 983 if (first) { 984 nb = read(fd, buf, sizeof(buf)); 985 arg->tuple.TupleLink = arg->tuple.CISOffset = 0; 986 } 987 ofs = arg->tuple.CISOffset + arg->tuple.TupleLink; 988 if (ofs >= nb) return -1; 989 arg->tuple.TupleCode = buf[ofs++]; 990 arg->tuple.TupleDataLen = arg->tuple.TupleLink = buf[ofs++]; 991 arg->tuple.CISOffset = ofs; 992 memcpy(arg->tuple_parse.data, buf+ofs, arg->tuple.TupleLink); 993 return 0; 994 } 995 996 static int get_tuple(int fd, ds_ioctl_arg_t *arg, int first) 997 { 998 int cmd = (first) ? DS_GET_FIRST_TUPLE : DS_GET_NEXT_TUPLE; 999 if (ioctl(fd, cmd, arg) != 0) { 1000 if (errno == ENODEV) 1001 printf("%sno card\n", indent); 1002 else if (errno != ENODATA) 1003 printf("%sget tuple: %s\n", indent, strerror(errno)); 1004 return -1; 1005 } 1006 if (ioctl(fd, DS_GET_TUPLE_DATA, arg) != 0) { 1007 printf("%sget tuple data: %s\n", indent, strerror(errno)); 1008 return -1; 1009 } 1010 return 0; 1011 } 1012 1013 /*====================================================================*/ 1014 1015 #define MAX_SOCKS 8 1016 1017 int main(int argc, char *argv[]) 1018 { 1019 int i, fd, pfd = -1; 1020 ds_ioctl_arg_t arg; 1021 int optch, errflg, first; 1022 int force = 0; 1023 char *infile = NULL; 1024 1025 errflg = 0; 1026 while ((optch = getopt(argc, argv, "fvi:")) != -1) { 1027 switch (optch) { 1028 case 'f': 1029 force = 1; break; 1030 case 'v': 1031 verbose = 1; break; 1032 case 'i': 1033 infile = strdup(optarg); break; 1034 default: 1035 errflg = 1; break; 1036 } 1037 } 1038 if (errflg || (optind < argc)) { 1039 fprintf(stderr, "usage: %s [-v] [-f] [-i infile]\n", argv[0]); 1040 exit(EXIT_FAILURE); 1041 } 1042 1043 #if (!defined(__BEOS__) && !defined(__HAIKU__)) 1044 major = lookup_dev("pcmcia"); 1045 if (major < 0) { 1046 fprintf(stderr, "no pcmcia driver in /proc/devices\n"); 1047 exit(EXIT_FAILURE); 1048 } 1049 #endif 1050 1051 for (i = 0; (i < MAX_SOCKS) && !(i && infile); i++) { 1052 nfn = cur = 0; 1053 if (infile) { 1054 indent[0] = '\0'; 1055 fd = open(infile, O_RDONLY); 1056 if (fd < 0) { 1057 perror("open()"); 1058 return -1; 1059 } 1060 pfd = open_sock(0); 1061 } else { 1062 strcpy(indent, " "); 1063 fd = pfd = open_sock(i); 1064 } 1065 if (pfd < 0) 1066 break; 1067 if (!verbose && (i > 0)) putchar('\n'); 1068 if (!infile) printf("Socket %d:\n", i); 1069 1070 if (!force && !infile) { 1071 if (ioctl(fd, DS_VALIDATE_CIS, &arg) != 0) { 1072 printf("%svalidate CIS: %s\n", indent, strerror(errno)); 1073 continue; 1074 } 1075 if (arg.cisinfo.Chains == 0) { 1076 printf("%sno CIS present\n", indent); 1077 continue; 1078 } 1079 } 1080 1081 arg.tuple.TupleDataMax = sizeof(arg.tuple_parse.data); 1082 arg.tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON; 1083 arg.tuple.DesiredTuple = RETURN_FIRST_TUPLE; 1084 arg.tuple.TupleOffset = 0; 1085 1086 for (first = 1; ; first = 0) { 1087 if (infile) { 1088 if (get_tuple_buf(fd, &arg, first) != 0) break; 1089 } else { 1090 if (get_tuple(fd, &arg, first) != 0) break; 1091 } 1092 if (verbose) print_tuple(&arg.tuple_parse); 1093 if (ioctl(pfd, DS_PARSE_TUPLE, &arg) == 0) 1094 print_parse(&arg.tuple_parse); 1095 else if (errno != ENOSYS) 1096 printf("%sparse error: %s\n", indent, 1097 strerror(errno)); 1098 if (verbose) putchar('\n'); 1099 if (arg.tuple.TupleCode == CISTPL_END) 1100 break; 1101 } 1102 1103 if (!verbose && (nfn > 0)) 1104 printf("%s}\n", indent+2); 1105 } 1106 if ((i == 0) && (pfd < 0)) { 1107 perror("open()"); 1108 return -1; 1109 } 1110 1111 return 0; 1112 } 1113