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 * Copyright (c) 2018, Joyent, Inc. 25 */ 26 27 /* 28 * This is the user interface module for the pcitool. It checks commandline 29 * arguments and options and stores them in a pcitool_uiargs_t structure passed 30 * back to the rest of the program for processing. 31 * 32 * Please see pcitool_usage.c for a complete commandline description. 33 */ 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <sys/inttypes.h> 39 #include <sys/types.h> 40 #include <sys/param.h> 41 #include <strings.h> 42 #include <errno.h> 43 #include <sys/pci.h> 44 45 #include <sys/pci_tools.h> 46 47 #include "pcitool_ui.h" 48 49 /* 50 * Uncomment the following for useful debugging / development options for this 51 * module only. 52 */ 53 54 /* #define DEBUG 1 */ 55 /* #define STANDALONE 1 */ 56 57 #define DEVNAME_START_PCI "/pci" 58 #define DEVNAME_START_NIU "/niu" 59 60 /* Default read/write size when -s not specified. */ 61 #define DEFAULT_SIZE 4 62 63 /* For get_value64 */ 64 #define HEX_ONLY B_TRUE 65 #define BASE_BY_PREFIX B_FALSE 66 67 #define BITS_PER_BYTE 8 68 69 /* 70 * This defines which main options can be specified by the user. 71 * Options with colons after them require arguments. 72 */ 73 static char *opt_string = ":n:d:i:m:p:rw:o:s:e:b:vaqlcxgy"; 74 75 /* This defines options used singly and only by themselves (no nexus). */ 76 static char *no_dev_opt_string = "ahpqv"; 77 78 static void print_bad_option(char *argv[], int optopt, char *optarg); 79 static boolean_t get_confirmation(void); 80 static int get_value64(char *value_str, uint64_t *value, boolean_t hex_only); 81 static int parse_nexus_opts(char *input, uint64_t *flags_arg, uint8_t *bank_arg, 82 uint64_t *base_addr_arg); 83 static int extract_bdf_arg(char *cvalue, char *fld, uint64_t fld_flag, 84 uint64_t *all_flags, uint8_t *ivalue); 85 static int extract_bdf(char *value, char **bvalue_p, char **dvalue_p, 86 char **fvalue_p); 87 static int parse_device_opts(char *input, uint64_t *flags_arg, 88 uint8_t *bus_arg, uint8_t *device_arg, uint8_t *func_arg, 89 uint8_t *bank_arg); 90 static int parse_ino_opts(char *input, uint64_t *flags_arg, 91 uint32_t *cpu_arg, uint8_t *ino_arg); 92 static int parse_msi_opts(char *input, uint64_t *flags_arg, uint16_t *msi_arg); 93 static int parse_intr_set_opts(char *input, uint64_t *flags_arg, 94 uint32_t *cpu_arg); 95 static int parse_probeone_opts(char *input, uint64_t *flags_arg, 96 uint8_t *bus_arg, uint8_t *device_arg, uint8_t *func_arg); 97 98 #ifdef DEBUG 99 void dump_struct(pcitool_uiargs_t *dump_this); 100 #endif 101 102 /* Exported functions. */ 103 104 /* 105 * Main commandline argument parsing routine. 106 * 107 * Takes argc and argv straight from the commandline. 108 * Returns a pcitool_uiargs_t with flags of options specified, and values 109 * associated with them. 110 */ 111 int 112 get_commandline_args(int argc, char *argv[], pcitool_uiargs_t *parsed_args) 113 { 114 int c; /* Current option being processed. */ 115 boolean_t error = B_FALSE; 116 boolean_t confirm = B_FALSE; 117 uint64_t recv64; 118 119 /* Needed for getopt(3C) */ 120 extern char *optarg; /* Current commandline string. */ 121 extern int optind; /* Index of current commandline string. */ 122 extern int optopt; /* Option (char) which is missing an operand. */ 123 extern int opterr; /* Set to 0 to disable getopt err reporting. */ 124 125 opterr = 0; 126 127 bzero(parsed_args, sizeof (pcitool_uiargs_t)); 128 129 /* No args. probe mode accounting for bus ranges, nonverbose. */ 130 if (argc == 1) { 131 usage(argv[0]); 132 parsed_args->flags = 0; 133 return (SUCCESS); 134 } 135 136 /* 1st arg is not a device name. */ 137 if ((strstr(argv[1], DEVNAME_START_PCI) != argv[1]) && 138 (strstr(argv[1], DEVNAME_START_NIU) != argv[1])) { 139 140 /* Default is to probe all trees accounting for bus ranges. */ 141 parsed_args->flags = PROBEALL_FLAG | PROBERNG_FLAG; 142 143 /* Loop thru the options until complete or an error is found. */ 144 while (((c = getopt(argc, argv, no_dev_opt_string)) != -1) && 145 (error == B_FALSE)) { 146 147 switch (c) { 148 149 /* Help requested. */ 150 case 'h': 151 usage(argv[0]); 152 parsed_args->flags = 0; 153 return (SUCCESS); 154 155 case 'p': 156 /* Take default probe mode */ 157 break; 158 159 case 'a': 160 /* 161 * Enable display of ALL bus numbers. 162 * 163 * This takes precidence over PROBERNG as -a 164 * is explicitly specified. 165 */ 166 parsed_args->flags &= ~PROBERNG_FLAG; 167 break; 168 169 case 'q': 170 parsed_args->flags |= QUIET_FLAG; 171 break; 172 173 /* Verbose mode for full probe. */ 174 case 'v': 175 parsed_args->flags |= VERBOSE_FLAG; 176 break; 177 178 default: 179 error = B_TRUE; 180 break; 181 } 182 } 183 184 /* Check for values straggling at the end of the command. */ 185 if (optind != argc) { 186 (void) fprintf(stderr, "%s: Unrecognized parameter " 187 "at the end of the command.\n", argv[0]); 188 error = B_TRUE; 189 } 190 191 if (error) { 192 print_bad_option(argv, optopt, optarg); 193 return (FAILURE); 194 } 195 196 return (SUCCESS); 197 } 198 199 /* Device node specified on commandline. */ 200 201 /* Skip argv[1] before continuing below. */ 202 optind++; 203 204 /* Loop through the options until complete or an error is found. */ 205 while (((c = getopt(argc, argv, opt_string)) != -1) && 206 (error == B_FALSE)) { 207 208 switch (c) { 209 210 /* Nexus */ 211 case 'n': 212 if (parsed_args->flags & (LEAF_FLAG | 213 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 214 (void) fprintf(stderr, "%s: -n set with " 215 "-d, -p or -i or is set twice\n", argv[0]); 216 error = B_TRUE; 217 break; 218 } 219 parsed_args->flags |= NEXUS_FLAG; 220 if (parse_nexus_opts(optarg, &parsed_args->flags, 221 &parsed_args->bank, &parsed_args->base_address) != 222 SUCCESS) { 223 (void) fprintf(stderr, 224 "%s: Error parsing -n options\n", argv[0]); 225 error = B_TRUE; 226 break; 227 } 228 break; 229 230 /* Device (leaf node) */ 231 case 'd': 232 if (parsed_args->flags & (LEAF_FLAG | 233 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 234 (void) fprintf(stderr, "%s: -d set with " 235 "-n, -p or -i or is set twice\n", argv[0]); 236 error = B_TRUE; 237 break; 238 } 239 parsed_args->flags |= LEAF_FLAG; 240 if (parse_device_opts(optarg, &parsed_args->flags, 241 &parsed_args->bus, &parsed_args->device, 242 &parsed_args->function, 243 &parsed_args->bank) != SUCCESS) { 244 (void) fprintf(stderr, 245 "%s: Error parsing -d options\n", argv[0]); 246 error = B_TRUE; 247 break; 248 } 249 break; 250 251 /* Interrupt */ 252 case 'i': 253 if (parsed_args->flags & (LEAF_FLAG | 254 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 255 (void) fprintf(stderr, "%s: -i set with -m, " 256 "-n, -d or -p or is set twice\n", argv[0]); 257 error = B_TRUE; 258 break; 259 } 260 parsed_args->flags |= INTR_FLAG; 261 262 /* parse input to get ino value. */ 263 if (parse_ino_opts(optarg, &parsed_args->flags, 264 &parsed_args->old_cpu, 265 &parsed_args->intr_ino) != SUCCESS) { 266 (void) fprintf(stderr, 267 "%s: Error parsing interrupt options\n", 268 argv[0]); 269 error = B_TRUE; 270 } 271 break; 272 /* Interrupt */ 273 case 'm': 274 if (parsed_args->flags & (LEAF_FLAG | 275 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 276 (void) fprintf(stderr, "%s: -m set with -i, " 277 "-n, -d or -p or is set twice\n", argv[0]); 278 error = B_TRUE; 279 break; 280 } 281 parsed_args->flags |= INTR_FLAG; 282 283 /* parse input to get msi value. */ 284 if (parse_msi_opts(optarg, &parsed_args->flags, 285 &parsed_args->intr_msi) != SUCCESS) { 286 (void) fprintf(stderr, 287 "%s: Error parsing interrupt options\n", 288 argv[0]); 289 error = B_TRUE; 290 } 291 break; 292 /* Probe */ 293 case 'p': 294 if (parsed_args->flags & (LEAF_FLAG | 295 NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS)) { 296 (void) fprintf(stderr, "%s: -p set with " 297 "-n, -d or -i or is set twice\n", argv[0]); 298 error = B_TRUE; 299 break; 300 } 301 302 /* Process -p with no dedicated options to it. */ 303 if (optarg[0] == '-') { 304 optind--; 305 306 /* Probe given tree observing ranges */ 307 parsed_args->flags |= 308 (PROBETREE_FLAG | PROBERNG_FLAG); 309 continue; 310 } 311 312 /* parse input to get ino value. */ 313 if (parse_probeone_opts(optarg, &parsed_args->flags, 314 &parsed_args->bus, &parsed_args->device, 315 &parsed_args->function) != SUCCESS) { 316 (void) fprintf(stderr, 317 "%s: Error parsing probe options\n", 318 argv[0]); 319 error = B_TRUE; 320 } else { 321 /* 322 * parse_probeone_opts found options to 323 * set up bdf. 324 */ 325 parsed_args->flags |= PROBEDEV_FLAG; 326 } 327 break; 328 329 /* Probe all busses */ 330 case 'a': 331 /* Must follow -p, and -p must have no bdf. */ 332 if (!(parsed_args->flags & PROBETREE_FLAG)) { 333 error = B_TRUE; 334 break; 335 } 336 337 parsed_args->flags &= ~PROBERNG_FLAG; 338 break; 339 340 /* Read */ 341 case 'r': 342 if (!(parsed_args->flags & 343 (LEAF_FLAG | NEXUS_FLAG | INTR_FLAG))) { 344 error = B_TRUE; 345 break; 346 } 347 348 /* 349 * Allow read and write to be set together for now, 350 * since this means write then read back for device and 351 * nexus accesses. Check for this and disallow with 352 * interrupt command later. 353 */ 354 parsed_args->flags |= READ_FLAG; 355 break; 356 357 /* Write */ 358 case 'w': 359 if (!(parsed_args->flags & 360 (LEAF_FLAG | NEXUS_FLAG | INTR_FLAG))) { 361 error = B_TRUE; 362 break; 363 } 364 if (parsed_args->flags & WRITE_FLAG) { 365 (void) fprintf(stderr, "%s: -w set twice\n", 366 argv[0]); 367 error = B_TRUE; 368 break; 369 } 370 371 /* 372 * For device and nexus, get a single register value 373 * to write. 374 */ 375 if (parsed_args->flags & (NEXUS_FLAG | LEAF_FLAG)) { 376 parsed_args->flags |= WRITE_FLAG; 377 if (get_value64(optarg, 378 &parsed_args->write_value, HEX_ONLY) != 379 SUCCESS) { 380 (void) fprintf(stderr, 381 "%s: Error reading value to " 382 "write.\n", argv[0]); 383 error = B_TRUE; 384 break; 385 } 386 387 /* For interrupt, parse input to get cpu value. */ 388 } else if (parsed_args->flags & INTR_FLAG) { 389 parsed_args->flags |= WRITE_FLAG; 390 if (parse_intr_set_opts(optarg, 391 &parsed_args->flags, 392 &parsed_args->intr_cpu) != SUCCESS) { 393 (void) fprintf(stderr, "%s: Error " 394 "parsing interrupt options.\n", 395 argv[0]); 396 error = B_TRUE; 397 break; 398 } 399 400 } else { 401 error = B_TRUE; 402 break; 403 } 404 break; 405 406 /* Offset */ 407 case 'o': 408 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 409 error = B_TRUE; 410 break; 411 } 412 if (parsed_args->flags & OFFSET_FLAG) { 413 (void) fprintf(stderr, "%s: -o set twice\n", 414 argv[0]); 415 error = B_TRUE; 416 break; 417 } 418 parsed_args->flags |= OFFSET_FLAG; 419 if (get_value64(optarg, &recv64, HEX_ONLY) != SUCCESS) { 420 (void) fprintf(stderr, 421 "%s: Error in offset argument\n", argv[0]); 422 error = B_TRUE; 423 break; 424 } 425 parsed_args->offset = (uint32_t)recv64; 426 if (parsed_args->offset != recv64) { 427 (void) fprintf(stderr, "%s: Offset argument " 428 "too large for 32 bits\n", argv[0]); 429 error = B_TRUE; 430 break; 431 } 432 break; 433 434 /* Size */ 435 case 's': 436 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 437 error = B_TRUE; 438 break; 439 } 440 if (parsed_args->flags & SIZE_FLAG) { 441 (void) fprintf(stderr, "%s: -s set twice\n", 442 argv[0]); 443 error = B_TRUE; 444 break; 445 } 446 parsed_args->flags |= SIZE_FLAG; 447 if (get_value64(optarg, &recv64, HEX_ONLY) != SUCCESS) { 448 (void) fprintf(stderr, 449 "%s: Error in size argument\n", argv[0]); 450 error = B_TRUE; 451 break; 452 } 453 switch (recv64) { 454 case 1: 455 case 2: 456 case 4: 457 case 8: 458 break; 459 default: 460 error = B_TRUE; 461 (void) fprintf(stderr, 462 "%s: Error in size argument\n", argv[0]); 463 break; 464 } 465 parsed_args->size |= (uint8_t)recv64; 466 break; 467 468 /* Endian. */ 469 case 'e': 470 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 471 error = B_TRUE; 472 break; 473 } 474 if (parsed_args->flags & ENDIAN_FLAG) { 475 (void) fprintf(stderr, "%s: -e set twice\n", 476 argv[0]); 477 error = B_TRUE; 478 break; 479 } 480 parsed_args->flags |= ENDIAN_FLAG; 481 482 /* Only a single character allowed. */ 483 if (optarg[1] != '\0') { 484 (void) fprintf(stderr, 485 "%s: Error in endian argument\n", argv[0]); 486 error = B_TRUE; 487 break; 488 } 489 490 switch (optarg[0]) { 491 case 'b': 492 parsed_args->big_endian = B_TRUE; 493 break; 494 case 'l': 495 break; 496 default: 497 (void) fprintf(stderr, 498 "%s: Error in endian argument\n", argv[0]); 499 error = B_TRUE; 500 break; 501 } 502 break; 503 504 /* (Byte)dump */ 505 case 'b': 506 if (!(parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG))) { 507 error = B_TRUE; 508 break; 509 } 510 if (parsed_args->flags & BYTEDUMP_FLAG) { 511 (void) fprintf(stderr, "%s: -b set twice\n", 512 argv[0]); 513 error = B_TRUE; 514 break; 515 } 516 parsed_args->flags |= BYTEDUMP_FLAG; 517 if (get_value64(optarg, &recv64, HEX_ONLY) != SUCCESS) { 518 (void) fprintf(stderr, "%s: Error in " 519 "bytedump argument\n", argv[0]); 520 error = B_TRUE; 521 break; 522 } 523 parsed_args->bytedump_amt = (uint32_t)recv64; 524 if (parsed_args->bytedump_amt != recv64) { 525 (void) fprintf(stderr, "%s: Bytedump amount " 526 "too large for 32 bits\n", argv[0]); 527 error = B_TRUE; 528 break; 529 } 530 break; 531 532 /* Verbose. */ 533 case 'v': 534 parsed_args->flags |= VERBOSE_FLAG; 535 break; 536 537 /* 538 * Quiet - no errors reported as messages. 539 * (Status still returned by program, however.) 540 */ 541 case 'q': 542 parsed_args->flags |= QUIET_FLAG; 543 break; 544 545 /* Loop. */ 546 case 'l': 547 parsed_args->flags |= LOOP_FLAG; 548 break; 549 550 /* 551 * Dump characters with bytedump (-b). 552 * Show controller info with -i. 553 */ 554 case 'c': 555 if (parsed_args->flags & BYTEDUMP_FLAG) { 556 parsed_args->flags |= CHARDUMP_FLAG; 557 558 } else if (parsed_args->flags & INTR_FLAG) { 559 parsed_args->flags |= SHOWCTLR_FLAG; 560 561 } else { 562 error = B_TRUE; 563 } 564 break; 565 566 /* Continue on errors with bytedump (-b). */ 567 case 'x': 568 if (!(parsed_args->flags & BYTEDUMP_FLAG)) { 569 error = B_TRUE; 570 break; 571 } 572 parsed_args->flags |= ERRCONT_FLAG; 573 break; 574 575 case 'g': 576 if (!(parsed_args->flags & INTR_FLAG)) { 577 error = B_TRUE; 578 break; 579 } 580 parsed_args->flags |= SETGRP_FLAG; 581 break; 582 583 /* Take -y as confirmation and don't ask (where applicable). */ 584 case 'y': 585 confirm = B_TRUE; 586 break; 587 588 /* Option without operand. */ 589 case ':': 590 switch (optopt) { 591 case 'p': 592 /* Allow -p without bdf spec. */ 593 parsed_args->flags |= 594 (PROBETREE_FLAG | PROBERNG_FLAG); 595 break; 596 default: 597 error = B_TRUE; 598 break; 599 } 600 break; 601 602 /* Unrecognized option. */ 603 case '?': 604 error = B_TRUE; 605 break; 606 } 607 } 608 609 /* 610 * Commandline has been parsed. Check for errors which can be checked 611 * only after commandline parsing is complete. 612 */ 613 614 if (!error) { 615 616 /* Check for values straggling at the end of the command. */ 617 if (optind != argc) { 618 (void) fprintf(stderr, "%s: Unrecognized parameter " 619 "at the end of the command.\n", argv[0]); 620 print_bad_option(argv, optopt, optarg); 621 return (FAILURE); 622 } 623 624 /* No args other than nexus. Default to probing that nexus */ 625 if (!(parsed_args->flags & 626 (LEAF_FLAG | NEXUS_FLAG | INTR_FLAG | PROBE_FLAGS))) { 627 usage(argv[0]); 628 parsed_args->flags = 0; 629 return (SUCCESS); 630 } 631 632 /* 633 * Don't allow any options other than all-bus, verbose or 634 * quiet with probe command. Set default probe flags if nexus 635 * or leaf options are not specified. 636 */ 637 if (parsed_args->flags & (PROBETREE_FLAG | PROBEALL_FLAG)) { 638 if (parsed_args->flags & 639 ~(PROBE_FLAGS | QUIET_FLAG | VERBOSE_FLAG)) 640 error = B_TRUE; 641 } 642 643 /* 644 * Allow only read, write, quiet and verbose flags for 645 * interrupt command. Note that INO_SPEC_FLAG and CPU_SPEC_FLAG 646 * get set for interrupt command. 647 */ 648 if (parsed_args->flags & INTR_FLAG) { 649 if (parsed_args->flags & 650 ~(INTR_FLAG | VERBOSE_FLAG | QUIET_FLAG | 651 READ_FLAG | WRITE_FLAG | SHOWCTLR_FLAG | 652 SETGRP_FLAG | INO_ALL_FLAG | INO_SPEC_FLAG | 653 MSI_ALL_FLAG | MSI_SPEC_FLAG | CPU_SPEC_FLAG)) { 654 (void) fprintf(stderr, "%s: -v, -q, -r, -w, -c " 655 "-g are only options allowed with " 656 "interrupt command.\n", argv[0]); 657 error = B_TRUE; 658 } 659 660 /* Need cpu and ino values for interrupt set command. */ 661 if ((parsed_args->flags & WRITE_FLAG) && 662 !(parsed_args->flags & CPU_SPEC_FLAG) && 663 !((parsed_args->flags & INO_SPEC_FLAG) || 664 (parsed_args->flags & MSI_SPEC_FLAG))) { 665 (void) fprintf(stderr, 666 "%s: Both cpu and ino/msi must be " 667 "specified explicitly for interrupt " 668 "set command.\n", argv[0]); 669 error = B_TRUE; 670 } 671 672 /* Intr write and show ctlr flags are incompatible. */ 673 if ((parsed_args->flags & 674 (WRITE_FLAG + SHOWCTLR_FLAG)) == 675 (WRITE_FLAG + SHOWCTLR_FLAG)) { 676 (void) fprintf(stderr, 677 "%s: -w and -c are incompatible for " 678 "interrupt command.\n", argv[0]); 679 error = B_TRUE; 680 } 681 682 /* Intr setgrp flag valid only for intr writes. */ 683 if ((parsed_args->flags & (WRITE_FLAG + SETGRP_FLAG)) == 684 SETGRP_FLAG) { 685 (void) fprintf(stderr, 686 "%s: -g is incompatible with -r " 687 "for interrupt command.\n", argv[0]); 688 error = B_TRUE; 689 } 690 691 /* 692 * Disallow read & write together in interrupt command. 693 */ 694 if ((parsed_args->flags & (WRITE_FLAG | READ_FLAG)) == 695 (WRITE_FLAG | READ_FLAG)) { 696 (void) fprintf(stderr, "%s: Only one of -r and " 697 "-w can be specified in " 698 "interrupt command.\n", argv[0]); 699 error = B_TRUE; 700 } 701 } 702 703 /* Bytedump incompatible with some other options. */ 704 if ((parsed_args->flags & BYTEDUMP_FLAG) && 705 (parsed_args->flags & 706 (WRITE_FLAG | PROBE_FLAGS | INTR_FLAG))) { 707 (void) fprintf(stderr, 708 "%s: -b is incompatible with " 709 "another specified option.\n", argv[0]); 710 error = B_TRUE; 711 } 712 713 if (parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG)) { 714 715 if (!(parsed_args->flags & SIZE_FLAG)) { 716 parsed_args->size = DEFAULT_SIZE; 717 } 718 if ((parsed_args->flags & WRITE_FLAG) && 719 parsed_args->size < sizeof (uint64_t) && 720 (parsed_args->write_value >> 721 (parsed_args->size * BITS_PER_BYTE))) { 722 (void) fprintf(stderr, 723 "%s: Data to write is larger than " 724 "specified size.\n", argv[0]); 725 error = B_TRUE; 726 } 727 728 } else { /* Looping is compatible only with register cmds. */ 729 730 if (parsed_args->flags & LOOP_FLAG) { 731 (void) fprintf(stderr, "%s: -l is incompatible " 732 "with given command.\n", argv[0]); 733 error = B_TRUE; 734 } 735 } 736 737 /* Call out an erroneous -y and then ignore it. */ 738 if ((confirm) && (!(parsed_args->flags & BASE_SPEC_FLAG))) { 739 (void) fprintf(stderr, 740 "%s: -y is incompatible with given command." 741 " Ignoring.\n", argv[0]); 742 } 743 } 744 745 /* Now fill in the defaults and other holes. */ 746 if (!(error)) { 747 if (!(parsed_args->flags & (READ_FLAG | WRITE_FLAG))) { 748 parsed_args->flags |= READ_FLAG; 749 } 750 751 if (parsed_args->flags & (LEAF_FLAG | NEXUS_FLAG)) { 752 if (!(parsed_args->flags & ENDIAN_FLAG)) { 753 parsed_args->big_endian = B_FALSE; 754 } 755 } 756 757 if (parsed_args->flags & BASE_SPEC_FLAG) { 758 if (!confirm) { 759 confirm = get_confirmation(); 760 } 761 if (!confirm) { 762 parsed_args->flags &= ~ALL_COMMANDS; 763 } 764 } 765 766 /* 767 * As far as other defaults are concerned: 768 * Other fields: bus, device, function, offset, default to 769 * zero. 770 */ 771 772 } else { /* An error occurred. */ 773 774 print_bad_option(argv, optopt, optarg); 775 } 776 return (error); 777 } 778 779 780 /* Module-private functions. */ 781 782 static void 783 print_bad_option(char *argv[], int optopt, char *optarg) 784 { 785 /* Illegal option operand */ 786 if (optarg != NULL) { 787 (void) fprintf(stderr, 788 "%s: illegal operand %s specified for option %c\n", 789 argv[0], optarg, optopt); 790 791 /* Illegal option */ 792 } else if (optopt != 0) { 793 (void) fprintf(stderr, 794 "%s: option %c is illegal or is missing an operand\n", 795 argv[0], optopt); 796 797 /* getopt wasn't even called. Bad device spec. */ 798 } else { 799 (void) fprintf(stderr, 800 "%s: device spec must start with %s or %s...\n", argv[0], 801 DEVNAME_START_PCI, DEVNAME_START_NIU); 802 } 803 804 (void) fprintf(stderr, 805 "%s: Type \"%s -h\" to get help on running this program.\n", 806 argv[0], argv[0]); 807 } 808 809 /* 810 * Warn the user and ask for confirmation. 811 */ 812 static boolean_t 813 get_confirmation() 814 { 815 int i, b; 816 817 (void) printf("WARNING: This cmd with a bad addr can panic " 818 "the system. Continue [y/n] (n)? "); 819 for (i = 0; ; i++) { 820 b = getchar(); 821 switch (b) { 822 case ' ': 823 case '\t': 824 break; 825 case 'y': 826 case 'Y': 827 return (B_TRUE); 828 default: 829 return (B_FALSE); 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 enum nexus_opts_index { 903 bank = 0, 904 base 905 }; 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 enum bdf_opts_index { 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 }; 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 enum p1_bdf_opts_index { 1441 bus = 0, 1442 dev = 1, 1443 func = 2, 1444 bdf = 3 1445 }; 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 { 1521 (void) printf("flags:0x%x\n", dumpthis->flags); 1522 (void) printf("bus:%d (0x%x)\n", 1523 dumpthis->bus, dumpthis->bus); 1524 (void) printf("device:%d (0x%x)\n", dumpthis->device, 1525 dumpthis->device); 1526 (void) printf("function:%d (0x%x)\n", dumpthis->function, 1527 dumpthis->function); 1528 (void) printf("write_value:%" PRIu64 " (0x%" PRIx64 ")\n", 1529 dumpthis->write_value, dumpthis->write_value); 1530 (void) printf("bank:%d (0x%x)\n", 1531 dumpthis->bank, dumpthis->bank); 1532 (void) printf("offset:%d (0x%x)\n", dumpthis->offset, dumpthis->offset); 1533 (void) printf("size:%d, endian:%s\n", dumpthis->size, 1534 dumpthis->big_endian ? "BIG" : "little"); 1535 (void) printf("ino:%d, cpu:%d\n", 1536 dumpthis->intr_ino, dumpthis->intr_cpu); 1537 } 1538 1539 #ifdef STANDALONE 1540 1541 /* Test program for this module. Useful when implementing new options. */ 1542 int 1543 main(int argc, char *argv[]) 1544 { 1545 int status; 1546 pcitool_uiargs_t parsed_args; 1547 1548 status = get_commandline_args(argc, argv, &parsed_args); 1549 if (status) { 1550 (void) printf("Error getting command.\n"); 1551 } 1552 dump_struct(&parsed_args); 1553 1554 return (SUCCESS); 1555 } 1556 1557 #endif /* STANDALONE */ 1558 #endif /* DEBUG */ 1559