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