1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 23 * Copyright 2012 Milan Jurik. All rights reserved. 24 */ 25 26 /* 27 * This is the user interface module for the pcitool. It checks commandline 28 * arguments and options and stores them in a pcitool_uiargs_t structure passed 29 * back to the rest of the program for processing. 30 * 31 * Please see pcitool_usage.c for a complete commandline description. 32 */ 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <unistd.h> 37 #include <sys/inttypes.h> 38 #include <sys/types.h> 39 #include <sys/param.h> 40 #include <strings.h> 41 #include <errno.h> 42 #include <sys/pci.h> 43 44 #include <sys/pci_tools.h> 45 46 #include "pcitool_ui.h" 47 48 /* 49 * Uncomment the following for useful debugging / development options for this 50 * module only. 51 */ 52 53 /* #define DEBUG 1 */ 54 /* #define STANDALONE 1 */ 55 56 #define DEVNAME_START_PCI "/pci" 57 #define DEVNAME_START_NIU "/niu" 58 59 /* Default read/write size when -s not specified. */ 60 #define DEFAULT_SIZE 4 61 62 /* For get_value64 */ 63 #define HEX_ONLY B_TRUE 64 #define BASE_BY_PREFIX B_FALSE 65 66 #define BITS_PER_BYTE 8 67 68 /* 69 * This defines which main options can be specified by the user. 70 * Options with colons after them require arguments. 71 */ 72 static char *opt_string = ":n:d:i:m:p:rw:o:s:e:b:vaqlcxgy"; 73 74 /* This defines options used singly and only by themselves (no nexus). */ 75 static char *no_dev_opt_string = "ahpqv"; 76 77 static void print_bad_option(char *argv[], int optopt, char *optarg); 78 static boolean_t get_confirmation(void); 79 static int get_value64(char *value_str, uint64_t *value, boolean_t hex_only); 80 static int parse_nexus_opts(char *input, uint64_t *flags_arg, uint8_t *bank_arg, 81 uint64_t *base_addr_arg); 82 static int extract_bdf_arg(char *cvalue, char *fld, uint64_t fld_flag, 83 uint64_t *all_flags, uint8_t *ivalue); 84 static int extract_bdf(char *value, char **bvalue_p, char **dvalue_p, 85 char **fvalue_p); 86 static int parse_device_opts(char *input, uint64_t *flags_arg, 87 uint8_t *bus_arg, uint8_t *device_arg, uint8_t *func_arg, 88 uint8_t *bank_arg); 89 static int parse_ino_opts(char *input, uint64_t *flags_arg, 90 uint32_t *cpu_arg, uint8_t *ino_arg); 91 static int parse_msi_opts(char *input, uint64_t *flags_arg, uint16_t *msi_arg); 92 static int parse_intr_set_opts(char *input, uint64_t *flags_arg, 93 uint32_t *cpu_arg); 94 static int parse_probeone_opts(char *input, uint64_t *flags_arg, 95 uint8_t *bus_arg, uint8_t *device_arg, uint8_t *func_arg); 96 97 #ifdef DEBUG 98 void dump_struct(pcitool_uiargs_t *dump_this); 99 #endif 100 101 /* Exported functions. */ 102 103 /* 104 * Main commandline argument parsing routine. 105 * 106 * Takes argc and argv straight from the commandline. 107 * Returns a pcitool_uiargs_t with flags of options specified, and values 108 * associated with them. 109 */ 110 int 111 get_commandline_args(int argc, char *argv[], pcitool_uiargs_t *parsed_args) 112 { 113 int c; /* Current option being processed. */ 114 boolean_t error = B_FALSE; 115 boolean_t confirm = B_FALSE; 116 uint64_t recv64; 117 118 /* Needed for getopt(3C) */ 119 extern char *optarg; /* Current commandline string. */ 120 extern int optind; /* Index of current commandline string. */ 121 extern int optopt; /* Option (char) which is missing an operand. */ 122 extern int opterr; /* Set to 0 to disable getopt err reporting. */ 123 124 opterr = 0; 125 126 bzero(parsed_args, sizeof (pcitool_uiargs_t)); 127 128 /* No args. probe mode accounting for bus ranges, nonverbose. */ 129 if (argc == 1) { 130 usage(argv[0]); 131 parsed_args->flags = 0; 132 return (SUCCESS); 133 } 134 135 /* 1st arg is not a device name. */ 136 if ((strstr(argv[1], DEVNAME_START_PCI) != argv[1]) && 137 (strstr(argv[1], DEVNAME_START_NIU) != argv[1])) { 138 139 /* Default is to probe all trees accounting for bus ranges. */ 140 parsed_args->flags = PROBEALL_FLAG | PROBERNG_FLAG; 141 142 /* Loop thru the options until complete or an error is found. */ 143 while (((c = getopt(argc, argv, no_dev_opt_string)) != -1) && 144 (error == B_FALSE)) { 145 146 switch (c) { 147 148 /* Help requested. */ 149 case 'h': 150 usage(argv[0]); 151 parsed_args->flags = 0; 152 return (SUCCESS); 153 154 case 'p': 155 /* Take default probe mode */ 156 break; 157 158 case 'a': 159 /* 160 * Enable display of ALL bus numbers. 161 * 162 * This takes precidence over PROBERNG as -a 163 * is explicitly specified. 164 */ 165 parsed_args->flags &= ~PROBERNG_FLAG; 166 break; 167 168 case 'q': 169 parsed_args->flags |= QUIET_FLAG; 170 break; 171 172 /* Verbose mode for full probe. */ 173 case 'v': 174 parsed_args->flags |= VERBOSE_FLAG; 175 break; 176 177 default: 178 error = B_TRUE; 179 break; 180 } 181 } 182 183 /* Check for values straggling at the end of the command. */ 184 if (optind != argc) { 185 (void) fprintf(stderr, "%s: Unrecognized parameter " 186 "at the end of the command.\n", argv[0]); 187 error = B_TRUE; 188 } 189 190 if (error) { 191 print_bad_option(argv, optopt, optarg); 192 return (FAILURE); 193 } 194 195 return (SUCCESS); 196 } 197 198 /* Device node specified on commandline. */ 199 200 /* Skip argv[1] before continuing below. */ 201 optind++; 202 203 /* Loop through the options until complete or an error is found. */ 204 while (((c = getopt(argc, argv, opt_string)) != -1) && 205 (error == B_FALSE)) { 206 207 switch (c) { 208 209 /* Nexus */ 210 case 'n': 211 if (parsed_args->flags & (LEAF_FLAG | 212 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 213 (void) fprintf(stderr, "%s: -n set with " 214 "-d, -p or -i or is set twice\n", argv[0]); 215 error = B_TRUE; 216 break; 217 } 218 parsed_args->flags |= NEXUS_FLAG; 219 if (parse_nexus_opts(optarg, &parsed_args->flags, 220 &parsed_args->bank, &parsed_args->base_address) != 221 SUCCESS) { 222 (void) fprintf(stderr, 223 "%s: Error parsing -n options\n", argv[0]); 224 error = B_TRUE; 225 break; 226 } 227 break; 228 229 /* Device (leaf node) */ 230 case 'd': 231 if (parsed_args->flags & (LEAF_FLAG | 232 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 233 (void) fprintf(stderr, "%s: -d set with " 234 "-n, -p or -i or is set twice\n", argv[0]); 235 error = B_TRUE; 236 break; 237 } 238 parsed_args->flags |= LEAF_FLAG; 239 if (parse_device_opts(optarg, &parsed_args->flags, 240 &parsed_args->bus, &parsed_args->device, 241 &parsed_args->function, 242 &parsed_args->bank) != SUCCESS) { 243 (void) fprintf(stderr, 244 "%s: Error parsing -d options\n", argv[0]); 245 error = B_TRUE; 246 break; 247 } 248 break; 249 250 /* Interrupt */ 251 case 'i': 252 if (parsed_args->flags & (LEAF_FLAG | 253 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 254 (void) fprintf(stderr, "%s: -i set with -m, " 255 "-n, -d or -p or is set twice\n", argv[0]); 256 error = B_TRUE; 257 break; 258 } 259 parsed_args->flags |= INTR_FLAG; 260 261 /* parse input to get ino value. */ 262 if (parse_ino_opts(optarg, &parsed_args->flags, 263 &parsed_args->old_cpu, 264 &parsed_args->intr_ino) != SUCCESS) { 265 (void) fprintf(stderr, 266 "%s: Error parsing interrupt options\n", 267 argv[0]); 268 error = B_TRUE; 269 } 270 break; 271 /* Interrupt */ 272 case 'm': 273 if (parsed_args->flags & (LEAF_FLAG | 274 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 275 (void) fprintf(stderr, "%s: -m set with -i, " 276 "-n, -d or -p or is set twice\n", argv[0]); 277 error = B_TRUE; 278 break; 279 } 280 parsed_args->flags |= INTR_FLAG; 281 282 /* parse input to get msi value. */ 283 if (parse_msi_opts(optarg, &parsed_args->flags, 284 &parsed_args->intr_msi) != SUCCESS) { 285 (void) fprintf(stderr, 286 "%s: Error parsing interrupt options\n", 287 argv[0]); 288 error = B_TRUE; 289 } 290 break; 291 /* Probe */ 292 case 'p': 293 if (parsed_args->flags & (LEAF_FLAG | 294 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 295 (void) fprintf(stderr, "%s: -p set with " 296 "-n, -d or -i or is set twice\n", argv[0]); 297 error = B_TRUE; 298 break; 299 } 300 301 /* Process -p with no dedicated options to it. */ 302 if (optarg[0] == '-') { 303 optind--; 304 305 /* Probe given tree observing ranges */ 306 parsed_args->flags |= 307 (PROBETREE_FLAG | PROBERNG_FLAG); 308 continue; 309 } 310 311 /* parse input to get ino value. */ 312 if (parse_probeone_opts(optarg, &parsed_args->flags, 313 &parsed_args->bus, &parsed_args->device, 314 &parsed_args->function) != SUCCESS) { 315 (void) fprintf(stderr, 316 "%s: Error parsing probe options\n", 317 argv[0]); 318 error = B_TRUE; 319 } else { 320 /* 321 * parse_probeone_opts found options to 322 * set up bdf. 323 */ 324 parsed_args->flags |= PROBEDEV_FLAG; 325 } 326 break; 327 328 /* Probe all busses */ 329 case 'a': 330 /* Must follow -p, and -p must have no bdf. */ 331 if (!(parsed_args->flags & PROBETREE_FLAG)) { 332 error = B_TRUE; 333 break; 334 } 335 336 parsed_args->flags &= ~PROBERNG_FLAG; 337 break; 338 339 /* Read */ 340 case 'r': 341 if (!(parsed_args->flags & 342 (LEAF_FLAG | NEXUS_FLAG | INTR_FLAG))) { 343 error = B_TRUE; 344 break; 345 } 346 347 /* 348 * Allow read and write to be set together for now, 349 * since this means write then read back for device and 350 * nexus accesses. Check for this and disallow with 351 * interrupt command later. 352 */ 353 parsed_args->flags |= READ_FLAG; 354 break; 355 356 /* Write */ 357 case 'w': 358 if (!(parsed_args->flags & 359 (LEAF_FLAG | NEXUS_FLAG | INTR_FLAG))) { 360 error = B_TRUE; 361 break; 362 } 363 if (parsed_args->flags & WRITE_FLAG) { 364 (void) fprintf(stderr, "%s: -w set twice\n", 365 argv[0]); 366 error = B_TRUE; 367 break; 368 } 369 370 /* 371 * For device and nexus, get a single register value 372 * to write. 373 */ 374 if (parsed_args->flags & (NEXUS_FLAG | LEAF_FLAG)) { 375 parsed_args->flags |= WRITE_FLAG; 376 if (get_value64(optarg, 377 &parsed_args->write_value, HEX_ONLY) != 378 SUCCESS) { 379 (void) fprintf(stderr, 380 "%s: Error reading value to " 381 "write.\n", argv[0]); 382 error = B_TRUE; 383 break; 384 } 385 386 /* For interrupt, parse input to get cpu value. */ 387 } else if (parsed_args->flags & INTR_FLAG) { 388 parsed_args->flags |= WRITE_FLAG; 389 if (parse_intr_set_opts(optarg, 390 &parsed_args->flags, 391 &parsed_args->intr_cpu) != SUCCESS) { 392 (void) fprintf(stderr, "%s: Error " 393 "parsing interrupt options.\n", 394 argv[0]); 395 error = B_TRUE; 396 break; 397 } 398 399 } else { 400 error = B_TRUE; 401 break; 402 } 403 break; 404 405 /* Offset */ 406 case 'o': 407 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 408 error = B_TRUE; 409 break; 410 } 411 if (parsed_args->flags & OFFSET_FLAG) { 412 (void) fprintf(stderr, "%s: -o set twice\n", 413 argv[0]); 414 error = B_TRUE; 415 break; 416 } 417 parsed_args->flags |= OFFSET_FLAG; 418 if (get_value64(optarg, &recv64, HEX_ONLY) != SUCCESS) { 419 (void) fprintf(stderr, 420 "%s: Error in offset argument\n", argv[0]); 421 error = B_TRUE; 422 break; 423 } 424 parsed_args->offset = (uint32_t)recv64; 425 if (parsed_args->offset != recv64) { 426 (void) fprintf(stderr, "%s: Offset argument " 427 "too large for 32 bits\n", argv[0]); 428 error = B_TRUE; 429 break; 430 } 431 break; 432 433 /* Size */ 434 case 's': 435 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 436 error = B_TRUE; 437 break; 438 } 439 if (parsed_args->flags & SIZE_FLAG) { 440 (void) fprintf(stderr, "%s: -s set twice\n", 441 argv[0]); 442 error = B_TRUE; 443 break; 444 } 445 parsed_args->flags |= SIZE_FLAG; 446 if (get_value64(optarg, &recv64, HEX_ONLY) != SUCCESS) { 447 (void) fprintf(stderr, 448 "%s: Error in size argument\n", argv[0]); 449 error = B_TRUE; 450 break; 451 } 452 switch (recv64) { 453 case 1: 454 case 2: 455 case 4: 456 case 8: 457 break; 458 default: 459 error = B_TRUE; 460 (void) fprintf(stderr, 461 "%s: Error in size argument\n", argv[0]); 462 break; 463 } 464 parsed_args->size |= (uint8_t)recv64; 465 break; 466 467 /* Endian. */ 468 case 'e': 469 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 470 error = B_TRUE; 471 break; 472 } 473 if (parsed_args->flags & ENDIAN_FLAG) { 474 (void) fprintf(stderr, "%s: -e set twice\n", 475 argv[0]); 476 error = B_TRUE; 477 break; 478 } 479 parsed_args->flags |= ENDIAN_FLAG; 480 481 /* Only a single character allowed. */ 482 if (optarg[1] != '\0') { 483 (void) fprintf(stderr, 484 "%s: Error in endian argument\n", argv[0]); 485 error = B_TRUE; 486 break; 487 } 488 489 switch (optarg[0]) { 490 case 'b': 491 parsed_args->big_endian = B_TRUE; 492 break; 493 case 'l': 494 break; 495 default: 496 (void) fprintf(stderr, 497 "%s: Error in endian argument\n", argv[0]); 498 error = B_TRUE; 499 break; 500 } 501 break; 502 503 /* (Byte)dump */ 504 case 'b': 505 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 506 error = B_TRUE; 507 break; 508 } 509 if (parsed_args->flags & BYTEDUMP_FLAG) { 510 (void) fprintf(stderr, "%s: -b set twice\n", 511 argv[0]); 512 error = B_TRUE; 513 break; 514 } 515 parsed_args->flags |= BYTEDUMP_FLAG; 516 if (get_value64(optarg, &recv64, HEX_ONLY) != SUCCESS) { 517 (void) fprintf(stderr, "%s: Error in " 518 "bytedump argument\n", argv[0]); 519 error = B_TRUE; 520 break; 521 } 522 parsed_args->bytedump_amt = (uint32_t)recv64; 523 if (parsed_args->bytedump_amt != recv64) { 524 (void) fprintf(stderr, "%s: Bytedump amount " 525 "too large for 32 bits\n", argv[0]); 526 error = B_TRUE; 527 break; 528 } 529 break; 530 531 /* Verbose. */ 532 case 'v': 533 parsed_args->flags |= VERBOSE_FLAG; 534 break; 535 536 /* 537 * Quiet - no errors reported as messages. 538 * (Status still returned by program, however.) 539 */ 540 case 'q': 541 parsed_args->flags |= QUIET_FLAG; 542 break; 543 544 /* Loop. */ 545 case 'l': 546 parsed_args->flags |= LOOP_FLAG; 547 break; 548 549 /* 550 * Dump characters with bytedump (-b). 551 * Show controller info with -i. 552 */ 553 case 'c': 554 if (parsed_args->flags & BYTEDUMP_FLAG) { 555 parsed_args->flags |= CHARDUMP_FLAG; 556 557 } else if (parsed_args->flags & INTR_FLAG) { 558 parsed_args->flags |= SHOWCTLR_FLAG; 559 560 } else { 561 error = B_TRUE; 562 } 563 break; 564 565 /* Continue on errors with bytedump (-b). */ 566 case 'x': 567 if (!(parsed_args->flags & BYTEDUMP_FLAG)) { 568 error = B_TRUE; 569 break; 570 } 571 parsed_args->flags |= ERRCONT_FLAG; 572 break; 573 574 case 'g': 575 if (!(parsed_args->flags & INTR_FLAG)) { 576 error = B_TRUE; 577 break; 578 } 579 parsed_args->flags |= SETGRP_FLAG; 580 break; 581 582 /* Take -y as confirmation and don't ask (where applicable). */ 583 case 'y': 584 confirm = B_TRUE; 585 break; 586 587 /* Option without operand. */ 588 case ':': 589 switch (optopt) { 590 case 'p': 591 /* Allow -p without bdf spec. */ 592 parsed_args->flags |= 593 (PROBETREE_FLAG | PROBERNG_FLAG); 594 break; 595 default: 596 error = B_TRUE; 597 break; 598 } 599 break; 600 601 /* Unrecognized option. */ 602 case '?': 603 error = B_TRUE; 604 break; 605 } 606 } 607 608 /* 609 * Commandline has been parsed. Check for errors which can be checked 610 * only after commandline parsing is complete. 611 */ 612 613 if (!error) { 614 615 /* Check for values straggling at the end of the command. */ 616 if (optind != argc) { 617 (void) fprintf(stderr, "%s: Unrecognized parameter " 618 "at the end of the command.\n", argv[0]); 619 print_bad_option(argv, optopt, optarg); 620 return (FAILURE); 621 } 622 623 /* No args other than nexus. Default to probing that nexus */ 624 if (!(parsed_args->flags & 625 (LEAF_FLAG | NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS))) { 626 usage(argv[0]); 627 parsed_args->flags = 0; 628 return (SUCCESS); 629 } 630 631 /* 632 * Don't allow any options other than all-bus, verbose or 633 * quiet with probe command. Set default probe flags if nexus 634 * or leaf options are not specified. 635 */ 636 if (parsed_args->flags & (PROBETREE_FLAG | PROBEALL_FLAG)) { 637 if (parsed_args->flags & 638 ~(PROBE_FLAGS | QUIET_FLAG | VERBOSE_FLAG)) 639 error = B_TRUE; 640 } 641 642 /* 643 * Allow only read, write, quiet and verbose flags for 644 * interrupt command. Note that INO_SPEC_FLAG and CPU_SPEC_FLAG 645 * get set for interrupt command. 646 */ 647 if (parsed_args->flags & INTR_FLAG) { 648 if (parsed_args->flags & 649 ~(INTR_FLAG | VERBOSE_FLAG | QUIET_FLAG | 650 READ_FLAG | WRITE_FLAG | SHOWCTLR_FLAG | 651 SETGRP_FLAG | INO_ALL_FLAG | INO_SPEC_FLAG | 652 MSI_ALL_FLAG | MSI_SPEC_FLAG | CPU_SPEC_FLAG)) { 653 (void) fprintf(stderr, "%s: -v, -q, -r, -w, -c " 654 "-g are only options allowed with " 655 "interrupt command.\n", argv[0]); 656 error = B_TRUE; 657 } 658 659 /* Need cpu and ino values for interrupt set command. */ 660 if ((parsed_args->flags & WRITE_FLAG) && 661 !(parsed_args->flags & CPU_SPEC_FLAG) && 662 !((parsed_args->flags & INO_SPEC_FLAG) || 663 (parsed_args->flags & MSI_SPEC_FLAG))) { 664 (void) fprintf(stderr, 665 "%s: Both cpu and ino/msi must be " 666 "specified explicitly for interrupt " 667 "set command.\n", argv[0]); 668 error = B_TRUE; 669 } 670 671 /* Intr write and show ctlr flags are incompatible. */ 672 if ((parsed_args->flags & 673 (WRITE_FLAG + SHOWCTLR_FLAG)) == 674 (WRITE_FLAG + SHOWCTLR_FLAG)) { 675 (void) fprintf(stderr, 676 "%s: -w and -c are incompatible for " 677 "interrupt command.\n", argv[0]); 678 error = B_TRUE; 679 } 680 681 /* Intr setgrp flag valid only for intr writes. */ 682 if ((parsed_args->flags & (WRITE_FLAG + SETGRP_FLAG)) == 683 SETGRP_FLAG) { 684 (void) fprintf(stderr, 685 "%s: -g is incompatible with -r " 686 "for interrupt command.\n", argv[0]); 687 error = B_TRUE; 688 } 689 690 /* 691 * Disallow read & write together in interrupt command. 692 */ 693 if ((parsed_args->flags & (WRITE_FLAG | READ_FLAG)) == 694 (WRITE_FLAG | READ_FLAG)) { 695 (void) fprintf(stderr, "%s: Only one of -r and " 696 "-w can be specified in " 697 "interrupt command.\n", argv[0]); 698 error = B_TRUE; 699 } 700 } 701 702 /* Bytedump incompatible with some other options. */ 703 if ((parsed_args->flags & BYTEDUMP_FLAG) && 704 (parsed_args->flags & 705 (WRITE_FLAG | PROBE_FLAGS | INTR_FLAG))) { 706 (void) fprintf(stderr, 707 "%s: -b is incompatible with " 708 "another specified option.\n", argv[0]); 709 error = B_TRUE; 710 } 711 712 if (parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG)) { 713 714 if (!(parsed_args->flags & SIZE_FLAG)) { 715 parsed_args->size = DEFAULT_SIZE; 716 } 717 if ((parsed_args->flags & WRITE_FLAG) && 718 parsed_args->size < sizeof (uint64_t) && 719 (parsed_args->write_value >> 720 (parsed_args->size * BITS_PER_BYTE))) { 721 (void) fprintf(stderr, 722 "%s: Data to write is larger than " 723 "specified size.\n", argv[0]); 724 error = B_TRUE; 725 } 726 727 } else { /* Looping is compatible only with register cmds. */ 728 729 if (parsed_args->flags & LOOP_FLAG) { 730 (void) fprintf(stderr, "%s: -l is incompatible " 731 "with given command.\n", argv[0]); 732 error = B_TRUE; 733 } 734 } 735 736 /* Call out an erroneous -y and then ignore it. */ 737 if ((confirm) && (!(parsed_args->flags & BASE_SPEC_FLAG))) { 738 (void) fprintf(stderr, 739 "%s: -y is incompatible with given command." 740 " Ignoring.\n", argv[0]); 741 } 742 } 743 744 /* Now fill in the defaults and other holes. */ 745 if (!(error)) { 746 if (!(parsed_args->flags & (READ_FLAG | WRITE_FLAG))) { 747 parsed_args->flags |= READ_FLAG; 748 } 749 750 if (parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG)) { 751 if (!(parsed_args->flags & ENDIAN_FLAG)) { 752 parsed_args->big_endian = B_FALSE; 753 } 754 } 755 756 if (parsed_args->flags & BASE_SPEC_FLAG) { 757 if (!confirm) { 758 confirm = get_confirmation(); 759 } 760 if (!confirm) { 761 parsed_args->flags &= ~ALL_COMMANDS; 762 } 763 } 764 765 /* 766 * As far as other defaults are concerned: 767 * Other fields: bus, device, function, offset, default to 768 * zero. 769 */ 770 771 } else { /* An error occurred. */ 772 773 print_bad_option(argv, optopt, optarg); 774 } 775 return (error); 776 } 777 778 779 /* Module-private functions. */ 780 781 static void 782 print_bad_option(char *argv[], int optopt, char *optarg) 783 { 784 /* Illegal option operand */ 785 if (optarg != NULL) { 786 (void) fprintf(stderr, 787 "%s: illegal operand %s specified for option %c\n", 788 argv[0], optarg, optopt); 789 790 /* Illegal option */ 791 } else if (optopt != 0) { 792 (void) fprintf(stderr, 793 "%s: option %c is illegal or is missing an operand\n", 794 argv[0], optopt); 795 796 /* getopt wasn't even called. Bad device spec. */ 797 } else { 798 (void) fprintf(stderr, 799 "%s: device spec must start with %s or %s...\n", argv[0], 800 DEVNAME_START_PCI, DEVNAME_START_NIU); 801 } 802 803 (void) fprintf(stderr, 804 "%s: Type \"%s -h\" to get help on running this program.\n", 805 argv[0], argv[0]); 806 } 807 808 /* 809 * Warn the user and ask for confirmation. 810 */ 811 static boolean_t 812 get_confirmation() 813 { 814 int i, b; 815 816 (void) printf("WARNING: This cmd with a bad addr can panic " 817 "the system. Continue [y/n] (n)? "); 818 for (i = 0; ; i++) { 819 b = getchar(); 820 switch (b) { 821 case ' ': 822 case '\t': 823 break; 824 case 'y': 825 case 'Y': 826 return (B_TRUE); 827 default: 828 return (B_FALSE); 829 } 830 } 831 } 832 833 834 /* 835 * Given a digit string, return a 64 bit value. 836 * 837 * If the hex_only arg is true, interpret all strings as hex. 838 * Otherwise, interpret as strtoull(3C) does with base=0. 839 */ 840 static int 841 get_value64(char *value_str, uint64_t *value, boolean_t hex_only) 842 { 843 844 /* This is overkill for now, as everything is in hex. */ 845 static char dec_digits[] = "0123456789"; 846 static char hex_digits[] = "01234567890abcdefABCDEF"; 847 static char oct_digits[] = "01234567"; 848 849 char *digit_string; 850 char *string_to_check; 851 852 if ((value_str == NULL) || (strlen(value_str) == 0)) { 853 (void) fprintf(stderr, "Missing value argument.\n"); 854 return (FAILURE); 855 } 856 857 if (!hex_only && (value_str[0] != '0')) { 858 digit_string = dec_digits; 859 string_to_check = value_str; 860 } else if ((value_str[1] == 'X') || (value_str[1] == 'x')) { 861 digit_string = hex_digits; 862 string_to_check = &value_str[2]; /* Ignore 0x of hex */ 863 } else if (hex_only) { 864 digit_string = hex_digits; 865 string_to_check = value_str; /* Hex number, no 0x prefix */ 866 } else { 867 digit_string = oct_digits; 868 string_to_check = value_str; 869 } 870 871 /* 872 * Verify value is all proper digits. 873 * 874 * For some reason, strtoull doesn't return an error when it cannot 875 * interpret the value. This is why we do the checking ourselves. 876 */ 877 if (strspn(string_to_check, digit_string) != strlen(string_to_check)) { 878 (void) fprintf(stderr, 879 "Value must contain only valid digits.\n"); 880 return (FAILURE); 881 } 882 883 *value = strtoull(value_str, NULL, (hex_only ? 16 : 0)); 884 885 return (SUCCESS); 886 } 887 888 889 /* 890 * Parse nexus options. This includes: 891 * bank=number 892 * 893 * input is what the user specified for the options on the commandline, 894 * flags_arg is modified with the option set, and bank_arg returns the value 895 * specified for bank. 896 */ 897 static int 898 parse_nexus_opts(char *input, uint64_t *flags_arg, uint8_t *bank_arg, 899 uint64_t *base_addr_arg) 900 { 901 typedef enum { 902 bank = 0, 903 base 904 } nexus_opts_index_t; 905 906 static char *nexus_opts[] = { 907 "bank", 908 "base", 909 NULL 910 }; 911 912 char *value; 913 uint64_t recv64; 914 915 int rval = SUCCESS; 916 917 if (input == NULL) { 918 (void) fprintf(stderr, "Missing argument.\n"); 919 return (FAILURE); 920 } 921 922 while ((*input != '\0') && (rval == SUCCESS)) { 923 switch (getsubopt(&input, nexus_opts, &value)) { 924 case bank: 925 if (*flags_arg & BANK_SPEC_FLAG) { 926 (void) fprintf(stderr, "The bank or bar arg is " 927 "specified more than once.\n"); 928 rval = FAILURE; 929 break; 930 } 931 if (*flags_arg & BASE_SPEC_FLAG) { 932 (void) fprintf(stderr, "Bank and base address " 933 "cannot both be specified.\n"); 934 rval = FAILURE; 935 break; 936 } 937 if (value == NULL) { 938 (void) fprintf(stderr, "Missing bank value.\n"); 939 rval = FAILURE; 940 break; 941 } 942 if ((rval = get_value64(value, &recv64, HEX_ONLY)) != 943 SUCCESS) { 944 break; 945 } 946 *bank_arg = (uint8_t)recv64; 947 if (*bank_arg != recv64) { 948 (void) fprintf(stderr, 949 "Bank argument must fit into 8 bits.\n"); 950 rval = FAILURE; 951 break; 952 } 953 *flags_arg |= BANK_SPEC_FLAG; 954 break; 955 956 case base: 957 if (*flags_arg & BASE_SPEC_FLAG) { 958 (void) fprintf(stderr, "The base address " 959 "is specified more than once.\n"); 960 rval = FAILURE; 961 break; 962 } 963 if (*flags_arg & BANK_SPEC_FLAG) { 964 (void) fprintf(stderr, "Bank and base address " 965 "cannot both be specified.\n"); 966 rval = FAILURE; 967 break; 968 } 969 if (value == NULL) { 970 (void) fprintf(stderr, 971 "Missing base addr value.\n"); 972 rval = FAILURE; 973 break; 974 } 975 if ((rval = get_value64(value, base_addr_arg, 976 HEX_ONLY)) != SUCCESS) { 977 break; 978 } 979 *flags_arg |= BASE_SPEC_FLAG; 980 break; 981 982 default: 983 (void) fprintf(stderr, "Unrecognized option for -n\n"); 984 rval = FAILURE; 985 break; 986 } 987 } 988 989 return (rval); 990 } 991 992 993 static int 994 extract_bdf_arg(char *cvalue, char *fld, uint64_t fld_flag, uint64_t *all_flags, 995 uint8_t *ivalue) 996 { 997 uint64_t recv64; 998 999 if (*all_flags & fld_flag) { 1000 (void) fprintf(stderr, 1001 "The %s is specified more than once.\n", fld); 1002 return (FAILURE); 1003 } 1004 if (get_value64(cvalue, &recv64, HEX_ONLY) != SUCCESS) 1005 return (FAILURE); 1006 1007 *ivalue = (uint8_t)recv64; 1008 if (recv64 != *ivalue) { 1009 (void) fprintf(stderr, 1010 "This program limits the %s argument to 8 bits.\n", fld); 1011 (void) fprintf(stderr, "The actual maximum may be " 1012 "smaller but cannot be enforced by this program.\n"); 1013 return (FAILURE); 1014 } 1015 1016 *all_flags |= fld_flag; 1017 return (SUCCESS); 1018 } 1019 1020 1021 static int extract_bdf(char *value, char **bvalue_p, char **dvalue_p, 1022 char **fvalue_p) 1023 { 1024 char *strtok_state; 1025 char *dummy; 1026 static char *separator = "."; 1027 1028 *bvalue_p = strtok_r(value, separator, &strtok_state); 1029 *dvalue_p = strtok_r(NULL, separator, &strtok_state); 1030 *fvalue_p = strtok_r(NULL, separator, &strtok_state); 1031 dummy = strtok_r(NULL, separator, &strtok_state); 1032 1033 /* Return failure only if too many values specified. */ 1034 return ((dummy) ? FAILURE : SUCCESS); 1035 } 1036 1037 /* 1038 * Parse device options. This includes: 1039 * bus=number 1040 * dev=number 1041 * func=number 1042 * bank=number 1043 * config 1044 * bar0 1045 * bar1 1046 * bar2 1047 * bar3 1048 * bar4 1049 * bar5 1050 * rom 1051 * 1052 * input is what the user specified for the options on the commandline, 1053 * flags_arg is modified with the options set, and the rest of the args return 1054 * their respective values. 1055 */ 1056 static int 1057 parse_device_opts( 1058 char *input, uint64_t *flags_arg, uint8_t *bus_arg, uint8_t *device_arg, 1059 uint8_t *func_arg, uint8_t *bank_arg) 1060 { 1061 /* Needed by getsubopt(3C) */ 1062 typedef enum { 1063 bus = 0, 1064 dev = 1, 1065 func = 2, 1066 bdf = 3, 1067 bank = 4, 1068 config = 5, 1069 bar0 = 6, 1070 bar1 = 7, 1071 bar2 = 8, 1072 bar3 = 9, 1073 bar4 = 10, 1074 bar5 = 11, 1075 rom = 12 1076 } bdf_opts_index_t; 1077 1078 /* Needed by getsubopt(3C) */ 1079 static char *bdf_opts[] = { 1080 "bus", 1081 "dev", 1082 "func", 1083 "bdf", 1084 "bank", 1085 "config", 1086 "bar0", 1087 "bar1", 1088 "bar2", 1089 "bar3", 1090 "bar4", 1091 "bar5", 1092 "rom", 1093 NULL }; 1094 1095 char *value; /* Current suboption being processed. */ 1096 uint64_t recv64; /* Temporary value. */ 1097 1098 /* This error message is used in many places. */ 1099 static char bank_err[] = 1100 {"The bank or bar arg is specified more than once.\n"}; 1101 1102 int rval = SUCCESS; 1103 1104 while ((*input != '\0') && (rval == SUCCESS)) { 1105 switch (getsubopt(&input, bdf_opts, &value)) { 1106 1107 /* bus=number */ 1108 case bdf: { 1109 char *bvalue, *dvalue, *fvalue; 1110 1111 if ((rval = extract_bdf(value, &bvalue, &dvalue, 1112 &fvalue)) != SUCCESS) { 1113 break; 1114 } 1115 1116 if (!bvalue | !dvalue | !fvalue) { 1117 break; 1118 } 1119 1120 if ((rval = extract_bdf_arg(bvalue, "bus", 1121 BUS_SPEC_FLAG, flags_arg, bus_arg)) != SUCCESS) { 1122 break; 1123 } 1124 if ((rval = extract_bdf_arg(dvalue, "dev", 1125 DEV_SPEC_FLAG, flags_arg, device_arg)) != SUCCESS) { 1126 break; 1127 } 1128 rval = extract_bdf_arg(fvalue, "func", 1129 FUNC_SPEC_FLAG, flags_arg, func_arg); 1130 break; 1131 } 1132 1133 case bus: 1134 rval = extract_bdf_arg(value, "bus", BUS_SPEC_FLAG, 1135 flags_arg, bus_arg); 1136 break; 1137 1138 /* dev=number */ 1139 case dev: 1140 rval = extract_bdf_arg(value, "dev", DEV_SPEC_FLAG, 1141 flags_arg, device_arg); 1142 break; 1143 1144 /* func=number */ 1145 case func: 1146 rval = extract_bdf_arg(value, "func", FUNC_SPEC_FLAG, 1147 flags_arg, func_arg); 1148 break; 1149 1150 /* bank=number */ 1151 case bank: 1152 if (*flags_arg & BANK_SPEC_FLAG) { 1153 (void) fprintf(stderr, bank_err); 1154 rval = FAILURE; 1155 break; 1156 } 1157 if ((rval = get_value64(value, &recv64, HEX_ONLY)) != 1158 SUCCESS) { 1159 break; 1160 } 1161 *bank_arg = (uint8_t)recv64; 1162 if (rval || (*bank_arg != recv64)) { 1163 (void) fprintf(stderr, "Bank argument must" 1164 " fit into 8 bits.\n"); 1165 rval = FAILURE; 1166 break; 1167 } 1168 *flags_arg |= BANK_SPEC_FLAG; 1169 break; 1170 1171 /* config */ 1172 case config: 1173 if (*flags_arg & BANK_SPEC_FLAG) { 1174 (void) fprintf(stderr, bank_err); 1175 rval = FAILURE; 1176 break; 1177 } 1178 *bank_arg = PCITOOL_CONFIG; 1179 *flags_arg |= BANK_SPEC_FLAG; 1180 break; 1181 1182 /* bar0 */ 1183 case bar0: 1184 if (*flags_arg & BANK_SPEC_FLAG) { 1185 (void) fprintf(stderr, bank_err); 1186 rval = FAILURE; 1187 break; 1188 } 1189 *bank_arg = PCITOOL_BAR0; 1190 *flags_arg |= BANK_SPEC_FLAG; 1191 break; 1192 1193 /* bar1 */ 1194 case bar1: 1195 if (*flags_arg & BANK_SPEC_FLAG) { 1196 (void) fprintf(stderr, bank_err); 1197 rval = FAILURE; 1198 break; 1199 } 1200 *bank_arg = PCITOOL_BAR1; 1201 *flags_arg |= BANK_SPEC_FLAG; 1202 break; 1203 1204 /* bar2 */ 1205 case bar2: 1206 if (*flags_arg & BANK_SPEC_FLAG) { 1207 (void) fprintf(stderr, bank_err); 1208 rval = FAILURE; 1209 break; 1210 } 1211 *bank_arg = PCITOOL_BAR2; 1212 *flags_arg |= BANK_SPEC_FLAG; 1213 break; 1214 1215 /* bar3 */ 1216 case bar3: 1217 if (*flags_arg & BANK_SPEC_FLAG) { 1218 (void) fprintf(stderr, bank_err); 1219 rval = FAILURE; 1220 break; 1221 } 1222 *bank_arg = PCITOOL_BAR3; 1223 *flags_arg |= BANK_SPEC_FLAG; 1224 break; 1225 1226 /* bar4 */ 1227 case bar4: 1228 if (*flags_arg & BANK_SPEC_FLAG) { 1229 (void) fprintf(stderr, bank_err); 1230 rval = FAILURE; 1231 break; 1232 } 1233 *bank_arg = PCITOOL_BAR4; 1234 *flags_arg |= BANK_SPEC_FLAG; 1235 break; 1236 1237 /* bar5 */ 1238 case bar5: 1239 if (*flags_arg & BANK_SPEC_FLAG) { 1240 (void) fprintf(stderr, bank_err); 1241 rval = FAILURE; 1242 break; 1243 } 1244 *bank_arg = PCITOOL_BAR5; 1245 *flags_arg |= BANK_SPEC_FLAG; 1246 break; 1247 1248 /* rom */ 1249 case rom: 1250 if (*flags_arg & BANK_SPEC_FLAG) { 1251 (void) fprintf(stderr, bank_err); 1252 rval = FAILURE; 1253 break; 1254 } 1255 *bank_arg = PCITOOL_ROM; 1256 *flags_arg |= BANK_SPEC_FLAG; 1257 break; 1258 1259 default: 1260 (void) fprintf(stderr, "Unrecognized option for -d\n"); 1261 rval = FAILURE; 1262 break; 1263 } 1264 } 1265 1266 /* Bus, dev and func must all be specified. */ 1267 if ((*flags_arg & (BUS_SPEC_FLAG | DEV_SPEC_FLAG | FUNC_SPEC_FLAG)) != 1268 (BUS_SPEC_FLAG | DEV_SPEC_FLAG | FUNC_SPEC_FLAG)) { 1269 rval = FAILURE; 1270 1271 /* No bank specified in any way. Default to config space */ 1272 } else if ((*flags_arg & BANK_SPEC_FLAG) == 0) { 1273 *flags_arg |= BANK_SPEC_FLAG; 1274 *bank_arg = PCITOOL_CONFIG; 1275 } 1276 1277 return (rval); 1278 } 1279 1280 1281 /* 1282 * Parse INO options. This includes: 1283 * ino# | all 1284 * 1285 * input is the string of options to parse. flags_arg returns modified with 1286 * specified options set. Other args return their respective values. 1287 */ 1288 static int 1289 parse_ino_opts(char *input, uint64_t *flags_arg, uint32_t *cpu_arg, 1290 uint8_t *ino_arg) 1291 { 1292 uint64_t value; 1293 char *charvalue; 1294 int rval = SUCCESS; 1295 1296 if (strcmp(input, "all") == 0) { 1297 *flags_arg |= INO_ALL_FLAG; 1298 #ifdef __x86 1299 } else if (strstr(input, ",") == NULL) { 1300 (void) fprintf(stderr, 1301 "Interrupt format should be <cpu#,ino#>.\n"); 1302 rval = FAILURE; 1303 #else 1304 } else if (strstr(input, ",") == NULL) { 1305 if ((rval = get_value64(input, &value, HEX_ONLY)) == SUCCESS) 1306 *ino_arg = (uint8_t)value; 1307 1308 if (*ino_arg != value) { 1309 (void) fprintf(stderr, 1310 "ino argument must fit into 8 bits.\n"); 1311 rval = FAILURE; 1312 } else { 1313 *flags_arg |= INO_SPEC_FLAG; 1314 } 1315 #endif 1316 } else if (charvalue = strtok(input, ",")) { 1317 if ((rval = 1318 get_value64(charvalue, &value, HEX_ONLY)) == SUCCESS) { 1319 *cpu_arg = (int)value; 1320 } 1321 1322 input = strtok(NULL, ","); 1323 if (input == NULL) { 1324 (void) fprintf(stderr, "ino argument is need.\n"); 1325 return (FAILURE); 1326 } 1327 1328 if ((rval = get_value64(input, &value, HEX_ONLY)) == SUCCESS) 1329 *ino_arg = (uint8_t)value; 1330 1331 if (*ino_arg != value) { 1332 (void) fprintf(stderr, 1333 "ino argument must fit into 8 bits.\n"); 1334 rval = FAILURE; 1335 } else { 1336 *flags_arg |= INO_SPEC_FLAG; 1337 } 1338 } else { 1339 (void) fprintf(stderr, 1340 "Unrecognized option for -i\n"); 1341 rval = FAILURE; 1342 } 1343 1344 return (rval); 1345 } 1346 1347 1348 /* 1349 * Parse MSI options. This includes: 1350 * msi# | all 1351 * 1352 * input is the string of options to parse. flags_arg returns modified with 1353 * specified options set. Other args return their respective values. 1354 */ 1355 static int 1356 parse_msi_opts(char *input, uint64_t *flags_arg, uint16_t *msi_arg) 1357 { 1358 uint64_t value; 1359 int rval = SUCCESS; 1360 1361 if (strcmp(input, "all") == 0) { 1362 *flags_arg |= MSI_ALL_FLAG; 1363 } else if (strstr(input, ",") == NULL) { 1364 if ((rval = get_value64(input, &value, HEX_ONLY)) == SUCCESS) 1365 *msi_arg = (uint16_t)value; 1366 1367 if (*msi_arg != value) { 1368 (void) fprintf(stderr, 1369 "msi argument must fit into 16 bits.\n"); 1370 rval = FAILURE; 1371 } else { 1372 *flags_arg |= MSI_SPEC_FLAG; 1373 } 1374 } else if (strtok(input, ",")) { 1375 input = strtok(NULL, ","); 1376 if (input == NULL) { 1377 (void) fprintf(stderr, "msi argument is need.\n"); 1378 return (FAILURE); 1379 } 1380 1381 if ((rval = get_value64(input, &value, HEX_ONLY)) == SUCCESS) 1382 *msi_arg = (uint16_t)value; 1383 1384 if (*msi_arg != value) { 1385 (void) fprintf(stderr, 1386 "msi argument must fit into 16 bits.\n"); 1387 rval = FAILURE; 1388 } else { 1389 *flags_arg |= MSI_SPEC_FLAG; 1390 } 1391 } else { 1392 (void) fprintf(stderr, 1393 "Unrecognized option for -m\n"); 1394 rval = FAILURE; 1395 } 1396 1397 return (rval); 1398 } 1399 1400 1401 /* 1402 * Parse interrupt set options. This includes: 1403 * cpu=number 1404 * 1405 * input is the string of options to parse. flags_arg returns modified with 1406 * specified options set. Other args return their respective values. 1407 */ 1408 static int 1409 parse_intr_set_opts(char *input, uint64_t *flags_arg, uint32_t *cpu_arg) 1410 { 1411 uint64_t value; 1412 int rval = SUCCESS; 1413 1414 if ((rval = get_value64(input, &value, HEX_ONLY)) == SUCCESS) { 1415 1416 if ((long)value > sysconf(_SC_CPUID_MAX)) { 1417 (void) fprintf(stderr, "Cpu argument " 1418 "exceeds maximum for this system type.\n"); 1419 rval = FAILURE; 1420 } else { 1421 *cpu_arg = (uint32_t)value; 1422 *flags_arg |= CPU_SPEC_FLAG; 1423 } 1424 } else { 1425 (void) fprintf(stderr, 1426 "Unrecognized option for -i -m -w\n"); 1427 rval = FAILURE; 1428 } 1429 1430 return (rval); 1431 } 1432 1433 1434 static int 1435 parse_probeone_opts( 1436 char *input, uint64_t *flags_arg, uint8_t *bus_arg, uint8_t *device_arg, 1437 uint8_t *func_arg) 1438 { 1439 typedef enum { 1440 bus = 0, 1441 dev = 1, 1442 func = 2, 1443 bdf = 3 1444 } p1_bdf_opts_index_t; 1445 1446 /* Needed by getsubopt(3C) */ 1447 static char *p1_bdf_opts[] = { 1448 "bus", 1449 "dev", 1450 "func", 1451 "bdf", 1452 NULL }; 1453 1454 char *value; /* Current suboption being processed. */ 1455 1456 int rval = SUCCESS; 1457 1458 while ((*input != '\0') && (rval == SUCCESS)) { 1459 switch (getsubopt(&input, p1_bdf_opts, &value)) { 1460 1461 /* bus=number */ 1462 case bdf: { 1463 char *bvalue, *dvalue, *fvalue; 1464 1465 if ((rval = extract_bdf(value, &bvalue, &dvalue, 1466 &fvalue)) != SUCCESS) { 1467 break; 1468 } 1469 if (bvalue) 1470 if ((rval = extract_bdf_arg(bvalue, "bus", 1471 BUS_SPEC_FLAG, flags_arg, bus_arg)) != 1472 SUCCESS) { 1473 break; 1474 } 1475 if (dvalue) 1476 if ((rval = extract_bdf_arg(dvalue, "dev", 1477 DEV_SPEC_FLAG, flags_arg, device_arg)) != 1478 SUCCESS) { 1479 break; 1480 } 1481 if (fvalue) 1482 rval = extract_bdf_arg(fvalue, "func", 1483 FUNC_SPEC_FLAG, flags_arg, func_arg); 1484 break; 1485 } 1486 1487 case bus: 1488 rval = extract_bdf_arg(value, "bus", BUS_SPEC_FLAG, 1489 flags_arg, bus_arg); 1490 break; 1491 1492 /* dev=number */ 1493 case dev: 1494 rval = extract_bdf_arg(value, "dev", DEV_SPEC_FLAG, 1495 flags_arg, device_arg); 1496 break; 1497 1498 /* func=number */ 1499 case func: 1500 rval = extract_bdf_arg(value, "func", FUNC_SPEC_FLAG, 1501 flags_arg, func_arg); 1502 break; 1503 1504 default: 1505 (void) fprintf(stderr, "Unrecognized option for -p\n"); 1506 rval = FAILURE; 1507 break; 1508 } 1509 } 1510 1511 return (rval); 1512 } 1513 1514 1515 #ifdef DEBUG 1516 1517 static void 1518 dump_struct(pcitool_uiargs_t *dumpthis) { 1519 (void) printf("flags:0x%x\n", dumpthis->flags); 1520 (void) printf("bus:%d (0x%x)\n", 1521 dumpthis->bus, dumpthis->bus); 1522 (void) printf("device:%d (0x%x)\n", dumpthis->device, 1523 dumpthis->device); 1524 (void) printf("function:%d (0x%x)\n", dumpthis->function, 1525 dumpthis->function); 1526 (void) printf("write_value:%" PRIu64 " (0x%" PRIx64 ")\n", 1527 dumpthis->write_value, dumpthis->write_value); 1528 (void) printf("bank:%d (0x%x)\n", 1529 dumpthis->bank, dumpthis->bank); 1530 (void) printf("offset:%d (0x%x)\n", dumpthis->offset, dumpthis->offset); 1531 (void) printf("size:%d, endian:%s\n", dumpthis->size, 1532 dumpthis->big_endian ? "BIG" : "little"); 1533 (void) printf("ino:%d, cpu:%d\n", 1534 dumpthis->intr_ino, dumpthis->intr_cpu); 1535 } 1536 1537 #ifdef STANDALONE 1538 1539 /* Test program for this module. Useful when implementing new options. */ 1540 int 1541 main(int argc, char *argv[]) 1542 { 1543 int status; 1544 pcitool_uiargs_t parsed_args; 1545 1546 status = get_commandline_args(argc, argv, &parsed_args); 1547 if (status) { 1548 (void) printf("Error getting command.\n"); 1549 } 1550 dump_struct(&parsed_args); 1551 1552 return (SUCCESS); 1553 } 1554 1555 #endif /* STANDALONE */ 1556 #endif /* DEBUG */ 1557