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.
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.
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]
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2012 Milan Jurik. All rights reserved.
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.
31 * Please see pcitool_usage.c for a complete commandline description.
37 #include <sys/inttypes.h>
38 #include <sys/types.h>
39 #include <sys/param.h>
44 #include <sys/pci_tools.h>
46 #include "pcitool_ui.h"
49 * Uncomment the following for useful debugging / development options for this
54 /* #define STANDALONE 1 */
56 #define DEVNAME_START_PCI "/pci"
57 #define DEVNAME_START_NIU "/niu"
59 /* Default read/write size when -s not specified. */
60 #define DEFAULT_SIZE 4
63 #define HEX_ONLY B_TRUE
64 #define BASE_BY_PREFIX B_FALSE
66 #define BITS_PER_BYTE 8
69 * This defines which main options can be specified by the user.
70 * Options with colons after them require arguments.
72 static char *opt_string
= ":n:d:i:m:p:rw:o:s:e:b:vaqlcxgy";
74 /* This defines options used singly and only by themselves (no nexus). */
75 static char *no_dev_opt_string
= "ahpqv";
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
,
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
,
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
,
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
);
98 void dump_struct(pcitool_uiargs_t
*dump_this
);
101 /* Exported functions. */
104 * Main commandline argument parsing routine.
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.
111 get_commandline_args(int argc
, char *argv
[], pcitool_uiargs_t
*parsed_args
)
113 int c
; /* Current option being processed. */
114 boolean_t error
= B_FALSE
;
115 boolean_t confirm
= B_FALSE
;
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. */
126 bzero(parsed_args
, sizeof (pcitool_uiargs_t
));
128 /* No args. probe mode accounting for bus ranges, nonverbose. */
131 parsed_args
->flags
= 0;
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])) {
139 /* Default is to probe all trees accounting for bus ranges. */
140 parsed_args
->flags
= PROBEALL_FLAG
| PROBERNG_FLAG
;
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
)) {
148 /* Help requested. */
151 parsed_args
->flags
= 0;
155 /* Take default probe mode */
160 * Enable display of ALL bus numbers.
162 * This takes precidence over PROBERNG as -a
163 * is explicitly specified.
165 parsed_args
->flags
&= ~PROBERNG_FLAG
;
169 parsed_args
->flags
|= QUIET_FLAG
;
172 /* Verbose mode for full probe. */
174 parsed_args
->flags
|= VERBOSE_FLAG
;
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]);
191 print_bad_option(argv
, optopt
, optarg
);
198 /* Device node specified on commandline. */
200 /* Skip argv[1] before continuing below. */
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
)) {
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]);
218 parsed_args
->flags
|= NEXUS_FLAG
;
219 if (parse_nexus_opts(optarg
, &parsed_args
->flags
,
220 &parsed_args
->bank
, &parsed_args
->base_address
) !=
222 (void) fprintf(stderr
,
223 "%s: Error parsing -n options\n", argv
[0]);
229 /* Device (leaf node) */
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]);
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]);
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]);
259 parsed_args
->flags
|= INTR_FLAG
;
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",
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]);
280 parsed_args
->flags
|= INTR_FLAG
;
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",
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]);
301 /* Process -p with no dedicated options to it. */
302 if (optarg
[0] == '-') {
305 /* Probe given tree observing ranges */
306 parsed_args
->flags
|=
307 (PROBETREE_FLAG
| PROBERNG_FLAG
);
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",
321 * parse_probeone_opts found options to
324 parsed_args
->flags
|= PROBEDEV_FLAG
;
328 /* Probe all busses */
330 /* Must follow -p, and -p must have no bdf. */
331 if (!(parsed_args
->flags
& PROBETREE_FLAG
)) {
336 parsed_args
->flags
&= ~PROBERNG_FLAG
;
341 if (!(parsed_args
->flags
&
342 (LEAF_FLAG
| NEXUS_FLAG
| INTR_FLAG
))) {
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.
353 parsed_args
->flags
|= READ_FLAG
;
358 if (!(parsed_args
->flags
&
359 (LEAF_FLAG
| NEXUS_FLAG
| INTR_FLAG
))) {
363 if (parsed_args
->flags
& WRITE_FLAG
) {
364 (void) fprintf(stderr
, "%s: -w set twice\n",
371 * For device and nexus, get a single register value
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
) !=
379 (void) fprintf(stderr
,
380 "%s: Error reading value to "
381 "write.\n", argv
[0]);
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
,
391 &parsed_args
->intr_cpu
) != SUCCESS
) {
392 (void) fprintf(stderr
, "%s: Error "
393 "parsing interrupt options.\n",
407 if (!(parsed_args
->flags
& (LEAF_FLAG
| NEXUS_FLAG
))) {
411 if (parsed_args
->flags
& OFFSET_FLAG
) {
412 (void) fprintf(stderr
, "%s: -o set twice\n",
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]);
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]);
435 if (!(parsed_args
->flags
& (LEAF_FLAG
| NEXUS_FLAG
))) {
439 if (parsed_args
->flags
& SIZE_FLAG
) {
440 (void) fprintf(stderr
, "%s: -s set twice\n",
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]);
460 (void) fprintf(stderr
,
461 "%s: Error in size argument\n", argv
[0]);
464 parsed_args
->size
|= (uint8_t)recv64
;
469 if (!(parsed_args
->flags
& (LEAF_FLAG
| NEXUS_FLAG
))) {
473 if (parsed_args
->flags
& ENDIAN_FLAG
) {
474 (void) fprintf(stderr
, "%s: -e set twice\n",
479 parsed_args
->flags
|= ENDIAN_FLAG
;
481 /* Only a single character allowed. */
482 if (optarg
[1] != '\0') {
483 (void) fprintf(stderr
,
484 "%s: Error in endian argument\n", argv
[0]);
491 parsed_args
->big_endian
= B_TRUE
;
496 (void) fprintf(stderr
,
497 "%s: Error in endian argument\n", argv
[0]);
505 if (!(parsed_args
->flags
& (LEAF_FLAG
| NEXUS_FLAG
))) {
509 if (parsed_args
->flags
& BYTEDUMP_FLAG
) {
510 (void) fprintf(stderr
, "%s: -b set twice\n",
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]);
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]);
533 parsed_args
->flags
|= VERBOSE_FLAG
;
537 * Quiet - no errors reported as messages.
538 * (Status still returned by program, however.)
541 parsed_args
->flags
|= QUIET_FLAG
;
546 parsed_args
->flags
|= LOOP_FLAG
;
550 * Dump characters with bytedump (-b).
551 * Show controller info with -i.
554 if (parsed_args
->flags
& BYTEDUMP_FLAG
) {
555 parsed_args
->flags
|= CHARDUMP_FLAG
;
557 } else if (parsed_args
->flags
& INTR_FLAG
) {
558 parsed_args
->flags
|= SHOWCTLR_FLAG
;
565 /* Continue on errors with bytedump (-b). */
567 if (!(parsed_args
->flags
& BYTEDUMP_FLAG
)) {
571 parsed_args
->flags
|= ERRCONT_FLAG
;
575 if (!(parsed_args
->flags
& INTR_FLAG
)) {
579 parsed_args
->flags
|= SETGRP_FLAG
;
582 /* Take -y as confirmation and don't ask (where applicable). */
587 /* Option without operand. */
591 /* Allow -p without bdf spec. */
592 parsed_args
->flags
|=
593 (PROBETREE_FLAG
| PROBERNG_FLAG
);
601 /* Unrecognized option. */
609 * Commandline has been parsed. Check for errors which can be checked
610 * only after commandline parsing is complete.
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
);
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
))) {
627 parsed_args
->flags
= 0;
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.
636 if (parsed_args
->flags
& (PROBETREE_FLAG
| PROBEALL_FLAG
)) {
637 if (parsed_args
->flags
&
638 ~(PROBE_FLAGS
| QUIET_FLAG
| VERBOSE_FLAG
))
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.
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]);
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]);
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]);
681 /* Intr setgrp flag valid only for intr writes. */
682 if ((parsed_args
->flags
& (WRITE_FLAG
+ SETGRP_FLAG
)) ==
684 (void) fprintf(stderr
,
685 "%s: -g is incompatible with -r "
686 "for interrupt command.\n", argv
[0]);
691 * Disallow read & write together in interrupt command.
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]);
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]);
712 if (parsed_args
->flags
& (LEAF_FLAG
| NEXUS_FLAG
)) {
714 if (!(parsed_args
->flags
& SIZE_FLAG
)) {
715 parsed_args
->size
= DEFAULT_SIZE
;
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]);
727 } else { /* Looping is compatible only with register cmds. */
729 if (parsed_args
->flags
& LOOP_FLAG
) {
730 (void) fprintf(stderr
, "%s: -l is incompatible "
731 "with given command.\n", argv
[0]);
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]);
744 /* Now fill in the defaults and other holes. */
746 if (!(parsed_args
->flags
& (READ_FLAG
| WRITE_FLAG
))) {
747 parsed_args
->flags
|= READ_FLAG
;
750 if (parsed_args
->flags
& (LEAF_FLAG
| NEXUS_FLAG
)) {
751 if (!(parsed_args
->flags
& ENDIAN_FLAG
)) {
752 parsed_args
->big_endian
= B_FALSE
;
756 if (parsed_args
->flags
& BASE_SPEC_FLAG
) {
758 confirm
= get_confirmation();
761 parsed_args
->flags
&= ~ALL_COMMANDS
;
766 * As far as other defaults are concerned:
767 * Other fields: bus, device, function, offset, default to
771 } else { /* An error occurred. */
773 print_bad_option(argv
, optopt
, optarg
);
779 /* Module-private functions. */
782 print_bad_option(char *argv
[], int optopt
, char *optarg
)
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
);
791 } else if (optopt
!= 0) {
792 (void) fprintf(stderr
,
793 "%s: option %c is illegal or is missing an operand\n",
796 /* getopt wasn't even called. Bad device spec. */
798 (void) fprintf(stderr
,
799 "%s: device spec must start with %s or %s...\n", argv
[0],
800 DEVNAME_START_PCI
, DEVNAME_START_NIU
);
803 (void) fprintf(stderr
,
804 "%s: Type \"%s -h\" to get help on running this program.\n",
809 * Warn the user and ask for confirmation.
816 (void) printf("WARNING: This cmd with a bad addr can panic "
817 "the system. Continue [y/n] (n)? ");
835 * Given a digit string, return a 64 bit value.
837 * If the hex_only arg is true, interpret all strings as hex.
838 * Otherwise, interpret as strtoull(3C) does with base=0.
841 get_value64(char *value_str
, uint64_t *value
, boolean_t hex_only
)
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";
850 char *string_to_check
;
852 if ((value_str
== NULL
) || (strlen(value_str
) == 0)) {
853 (void) fprintf(stderr
, "Missing value argument.\n");
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 */
867 digit_string
= oct_digits
;
868 string_to_check
= value_str
;
872 * Verify value is all proper digits.
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.
877 if (strspn(string_to_check
, digit_string
) != strlen(string_to_check
)) {
878 (void) fprintf(stderr
,
879 "Value must contain only valid digits.\n");
883 *value
= strtoull(value_str
, NULL
, (hex_only
? 16 : 0));
890 * Parse nexus options. This includes:
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.
898 parse_nexus_opts(char *input
, uint64_t *flags_arg
, uint8_t *bank_arg
,
899 uint64_t *base_addr_arg
)
904 } nexus_opts_index_t
;
906 static char *nexus_opts
[] = {
918 (void) fprintf(stderr
, "Missing argument.\n");
922 while ((*input
!= '\0') && (rval
== SUCCESS
)) {
923 switch (getsubopt(&input
, nexus_opts
, &value
)) {
925 if (*flags_arg
& BANK_SPEC_FLAG
) {
926 (void) fprintf(stderr
, "The bank or bar arg is "
927 "specified more than once.\n");
931 if (*flags_arg
& BASE_SPEC_FLAG
) {
932 (void) fprintf(stderr
, "Bank and base address "
933 "cannot both be specified.\n");
938 (void) fprintf(stderr
, "Missing bank value.\n");
942 if ((rval
= get_value64(value
, &recv64
, HEX_ONLY
)) !=
946 *bank_arg
= (uint8_t)recv64
;
947 if (*bank_arg
!= recv64
) {
948 (void) fprintf(stderr
,
949 "Bank argument must fit into 8 bits.\n");
953 *flags_arg
|= BANK_SPEC_FLAG
;
957 if (*flags_arg
& BASE_SPEC_FLAG
) {
958 (void) fprintf(stderr
, "The base address "
959 "is specified more than once.\n");
963 if (*flags_arg
& BANK_SPEC_FLAG
) {
964 (void) fprintf(stderr
, "Bank and base address "
965 "cannot both be specified.\n");
970 (void) fprintf(stderr
,
971 "Missing base addr value.\n");
975 if ((rval
= get_value64(value
, base_addr_arg
,
976 HEX_ONLY
)) != SUCCESS
) {
979 *flags_arg
|= BASE_SPEC_FLAG
;
983 (void) fprintf(stderr
, "Unrecognized option for -n\n");
994 extract_bdf_arg(char *cvalue
, char *fld
, uint64_t fld_flag
, uint64_t *all_flags
,
999 if (*all_flags
& fld_flag
) {
1000 (void) fprintf(stderr
,
1001 "The %s is specified more than once.\n", fld
);
1004 if (get_value64(cvalue
, &recv64
, HEX_ONLY
) != SUCCESS
)
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");
1016 *all_flags
|= fld_flag
;
1021 static int extract_bdf(char *value
, char **bvalue_p
, char **dvalue_p
,
1026 static char *separator
= ".";
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
);
1033 /* Return failure only if too many values specified. */
1034 return ((dummy
) ? FAILURE
: SUCCESS
);
1038 * Parse device options. This includes:
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.
1058 char *input
, uint64_t *flags_arg
, uint8_t *bus_arg
, uint8_t *device_arg
,
1059 uint8_t *func_arg
, uint8_t *bank_arg
)
1061 /* Needed by getsubopt(3C) */
1078 /* Needed by getsubopt(3C) */
1079 static char *bdf_opts
[] = {
1095 char *value
; /* Current suboption being processed. */
1096 uint64_t recv64
; /* Temporary value. */
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"};
1104 while ((*input
!= '\0') && (rval
== SUCCESS
)) {
1105 switch (getsubopt(&input
, bdf_opts
, &value
)) {
1109 char *bvalue
, *dvalue
, *fvalue
;
1111 if ((rval
= extract_bdf(value
, &bvalue
, &dvalue
,
1112 &fvalue
)) != SUCCESS
) {
1116 if (!bvalue
| !dvalue
| !fvalue
) {
1120 if ((rval
= extract_bdf_arg(bvalue
, "bus",
1121 BUS_SPEC_FLAG
, flags_arg
, bus_arg
)) != SUCCESS
) {
1124 if ((rval
= extract_bdf_arg(dvalue
, "dev",
1125 DEV_SPEC_FLAG
, flags_arg
, device_arg
)) != SUCCESS
) {
1128 rval
= extract_bdf_arg(fvalue
, "func",
1129 FUNC_SPEC_FLAG
, flags_arg
, func_arg
);
1134 rval
= extract_bdf_arg(value
, "bus", BUS_SPEC_FLAG
,
1135 flags_arg
, bus_arg
);
1140 rval
= extract_bdf_arg(value
, "dev", DEV_SPEC_FLAG
,
1141 flags_arg
, device_arg
);
1146 rval
= extract_bdf_arg(value
, "func", FUNC_SPEC_FLAG
,
1147 flags_arg
, func_arg
);
1152 if (*flags_arg
& BANK_SPEC_FLAG
) {
1153 (void) fprintf(stderr
, bank_err
);
1157 if ((rval
= get_value64(value
, &recv64
, HEX_ONLY
)) !=
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");
1168 *flags_arg
|= BANK_SPEC_FLAG
;
1173 if (*flags_arg
& BANK_SPEC_FLAG
) {
1174 (void) fprintf(stderr
, bank_err
);
1178 *bank_arg
= PCITOOL_CONFIG
;
1179 *flags_arg
|= BANK_SPEC_FLAG
;
1184 if (*flags_arg
& BANK_SPEC_FLAG
) {
1185 (void) fprintf(stderr
, bank_err
);
1189 *bank_arg
= PCITOOL_BAR0
;
1190 *flags_arg
|= BANK_SPEC_FLAG
;
1195 if (*flags_arg
& BANK_SPEC_FLAG
) {
1196 (void) fprintf(stderr
, bank_err
);
1200 *bank_arg
= PCITOOL_BAR1
;
1201 *flags_arg
|= BANK_SPEC_FLAG
;
1206 if (*flags_arg
& BANK_SPEC_FLAG
) {
1207 (void) fprintf(stderr
, bank_err
);
1211 *bank_arg
= PCITOOL_BAR2
;
1212 *flags_arg
|= BANK_SPEC_FLAG
;
1217 if (*flags_arg
& BANK_SPEC_FLAG
) {
1218 (void) fprintf(stderr
, bank_err
);
1222 *bank_arg
= PCITOOL_BAR3
;
1223 *flags_arg
|= BANK_SPEC_FLAG
;
1228 if (*flags_arg
& BANK_SPEC_FLAG
) {
1229 (void) fprintf(stderr
, bank_err
);
1233 *bank_arg
= PCITOOL_BAR4
;
1234 *flags_arg
|= BANK_SPEC_FLAG
;
1239 if (*flags_arg
& BANK_SPEC_FLAG
) {
1240 (void) fprintf(stderr
, bank_err
);
1244 *bank_arg
= PCITOOL_BAR5
;
1245 *flags_arg
|= BANK_SPEC_FLAG
;
1250 if (*flags_arg
& BANK_SPEC_FLAG
) {
1251 (void) fprintf(stderr
, bank_err
);
1255 *bank_arg
= PCITOOL_ROM
;
1256 *flags_arg
|= BANK_SPEC_FLAG
;
1260 (void) fprintf(stderr
, "Unrecognized option for -d\n");
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
)) {
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
;
1282 * Parse INO options. This includes:
1285 * input is the string of options to parse. flags_arg returns modified with
1286 * specified options set. Other args return their respective values.
1289 parse_ino_opts(char *input
, uint64_t *flags_arg
, uint32_t *cpu_arg
,
1296 if (strcmp(input
, "all") == 0) {
1297 *flags_arg
|= INO_ALL_FLAG
;
1299 } else if (strstr(input
, ",") == NULL
) {
1300 (void) fprintf(stderr
,
1301 "Interrupt format should be <cpu#,ino#>.\n");
1304 } else if (strstr(input
, ",") == NULL
) {
1305 if ((rval
= get_value64(input
, &value
, HEX_ONLY
)) == SUCCESS
)
1306 *ino_arg
= (uint8_t)value
;
1308 if (*ino_arg
!= value
) {
1309 (void) fprintf(stderr
,
1310 "ino argument must fit into 8 bits.\n");
1313 *flags_arg
|= INO_SPEC_FLAG
;
1316 } else if (charvalue
= strtok(input
, ",")) {
1318 get_value64(charvalue
, &value
, HEX_ONLY
)) == SUCCESS
) {
1319 *cpu_arg
= (int)value
;
1322 input
= strtok(NULL
, ",");
1323 if (input
== NULL
) {
1324 (void) fprintf(stderr
, "ino argument is need.\n");
1328 if ((rval
= get_value64(input
, &value
, HEX_ONLY
)) == SUCCESS
)
1329 *ino_arg
= (uint8_t)value
;
1331 if (*ino_arg
!= value
) {
1332 (void) fprintf(stderr
,
1333 "ino argument must fit into 8 bits.\n");
1336 *flags_arg
|= INO_SPEC_FLAG
;
1339 (void) fprintf(stderr
,
1340 "Unrecognized option for -i\n");
1349 * Parse MSI options. This includes:
1352 * input is the string of options to parse. flags_arg returns modified with
1353 * specified options set. Other args return their respective values.
1356 parse_msi_opts(char *input
, uint64_t *flags_arg
, uint16_t *msi_arg
)
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
;
1367 if (*msi_arg
!= value
) {
1368 (void) fprintf(stderr
,
1369 "msi argument must fit into 16 bits.\n");
1372 *flags_arg
|= MSI_SPEC_FLAG
;
1374 } else if (strtok(input
, ",")) {
1375 input
= strtok(NULL
, ",");
1376 if (input
== NULL
) {
1377 (void) fprintf(stderr
, "msi argument is need.\n");
1381 if ((rval
= get_value64(input
, &value
, HEX_ONLY
)) == SUCCESS
)
1382 *msi_arg
= (uint16_t)value
;
1384 if (*msi_arg
!= value
) {
1385 (void) fprintf(stderr
,
1386 "msi argument must fit into 16 bits.\n");
1389 *flags_arg
|= MSI_SPEC_FLAG
;
1392 (void) fprintf(stderr
,
1393 "Unrecognized option for -m\n");
1402 * Parse interrupt set options. This includes:
1405 * input is the string of options to parse. flags_arg returns modified with
1406 * specified options set. Other args return their respective values.
1409 parse_intr_set_opts(char *input
, uint64_t *flags_arg
, uint32_t *cpu_arg
)
1414 if ((rval
= get_value64(input
, &value
, HEX_ONLY
)) == SUCCESS
) {
1416 if ((long)value
> sysconf(_SC_CPUID_MAX
)) {
1417 (void) fprintf(stderr
, "Cpu argument "
1418 "exceeds maximum for this system type.\n");
1421 *cpu_arg
= (uint32_t)value
;
1422 *flags_arg
|= CPU_SPEC_FLAG
;
1425 (void) fprintf(stderr
,
1426 "Unrecognized option for -i -m -w\n");
1435 parse_probeone_opts(
1436 char *input
, uint64_t *flags_arg
, uint8_t *bus_arg
, uint8_t *device_arg
,
1444 } p1_bdf_opts_index_t
;
1446 /* Needed by getsubopt(3C) */
1447 static char *p1_bdf_opts
[] = {
1454 char *value
; /* Current suboption being processed. */
1458 while ((*input
!= '\0') && (rval
== SUCCESS
)) {
1459 switch (getsubopt(&input
, p1_bdf_opts
, &value
)) {
1463 char *bvalue
, *dvalue
, *fvalue
;
1465 if ((rval
= extract_bdf(value
, &bvalue
, &dvalue
,
1466 &fvalue
)) != SUCCESS
) {
1470 if ((rval
= extract_bdf_arg(bvalue
, "bus",
1471 BUS_SPEC_FLAG
, flags_arg
, bus_arg
)) !=
1476 if ((rval
= extract_bdf_arg(dvalue
, "dev",
1477 DEV_SPEC_FLAG
, flags_arg
, device_arg
)) !=
1482 rval
= extract_bdf_arg(fvalue
, "func",
1483 FUNC_SPEC_FLAG
, flags_arg
, func_arg
);
1488 rval
= extract_bdf_arg(value
, "bus", BUS_SPEC_FLAG
,
1489 flags_arg
, bus_arg
);
1494 rval
= extract_bdf_arg(value
, "dev", DEV_SPEC_FLAG
,
1495 flags_arg
, device_arg
);
1500 rval
= extract_bdf_arg(value
, "func", FUNC_SPEC_FLAG
,
1501 flags_arg
, func_arg
);
1505 (void) fprintf(stderr
, "Unrecognized option for -p\n");
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
,
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
);
1539 /* Test program for this module. Useful when implementing new options. */
1541 main(int argc
, char *argv
[])
1544 pcitool_uiargs_t parsed_args
;
1546 status
= get_commandline_args(argc
, argv
, &parsed_args
);
1548 (void) printf("Error getting command.\n");
1550 dump_struct(&parsed_args
);
1555 #endif /* STANDALONE */