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