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 */
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
get_commandline_args(int argc,char * argv[],pcitool_uiargs_t * parsed_args)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
print_bad_option(char * argv[],int optopt,char * optarg)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
get_confirmation()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
get_value64(char * value_str,uint64_t * value,boolean_t hex_only)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
parse_nexus_opts(char * input,uint64_t * flags_arg,uint8_t * bank_arg,uint64_t * base_addr_arg)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
extract_bdf_arg(char * cvalue,char * fld,uint64_t fld_flag,uint64_t * all_flags,uint8_t * ivalue)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
extract_bdf(char * value,char ** bvalue_p,char ** dvalue_p,char ** fvalue_p)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
parse_device_opts(char * input,uint64_t * flags_arg,uint8_t * bus_arg,uint8_t * device_arg,uint8_t * func_arg,uint8_t * bank_arg)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
parse_ino_opts(char * input,uint64_t * flags_arg,uint32_t * cpu_arg,uint8_t * ino_arg)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
parse_msi_opts(char * input,uint64_t * flags_arg,uint16_t * msi_arg)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
parse_intr_set_opts(char * input,uint64_t * flags_arg,uint32_t * cpu_arg)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
parse_probeone_opts(char * input,uint64_t * flags_arg,uint8_t * bus_arg,uint8_t * device_arg,uint8_t * func_arg)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
dump_struct(pcitool_uiargs_t * dumpthis)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
main(int argc,char * argv[])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