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