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