xref: /onnv-gate/usr/src/cmd/hotplug/hotplug.c (revision 10923:df470fd79c3c)
1*10923SEvan.Yan@Sun.COM /*
2*10923SEvan.Yan@Sun.COM  * CDDL HEADER START
3*10923SEvan.Yan@Sun.COM  *
4*10923SEvan.Yan@Sun.COM  * The contents of this file are subject to the terms of the
5*10923SEvan.Yan@Sun.COM  * Common Development and Distribution License (the "License").
6*10923SEvan.Yan@Sun.COM  * You may not use this file except in compliance with the License.
7*10923SEvan.Yan@Sun.COM  *
8*10923SEvan.Yan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10923SEvan.Yan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10923SEvan.Yan@Sun.COM  * See the License for the specific language governing permissions
11*10923SEvan.Yan@Sun.COM  * and limitations under the License.
12*10923SEvan.Yan@Sun.COM  *
13*10923SEvan.Yan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10923SEvan.Yan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10923SEvan.Yan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10923SEvan.Yan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10923SEvan.Yan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10923SEvan.Yan@Sun.COM  *
19*10923SEvan.Yan@Sun.COM  * CDDL HEADER END
20*10923SEvan.Yan@Sun.COM  */
21*10923SEvan.Yan@Sun.COM /*
22*10923SEvan.Yan@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*10923SEvan.Yan@Sun.COM  * Use is subject to license terms.
24*10923SEvan.Yan@Sun.COM  */
25*10923SEvan.Yan@Sun.COM 
26*10923SEvan.Yan@Sun.COM #include <stdio.h>
27*10923SEvan.Yan@Sun.COM #include <stdlib.h>
28*10923SEvan.Yan@Sun.COM #include <string.h>
29*10923SEvan.Yan@Sun.COM #include <locale.h>
30*10923SEvan.Yan@Sun.COM #include <libintl.h>
31*10923SEvan.Yan@Sun.COM #include <alloca.h>
32*10923SEvan.Yan@Sun.COM #include <getopt.h>
33*10923SEvan.Yan@Sun.COM #include <libhotplug.h>
34*10923SEvan.Yan@Sun.COM #include <sys/types.h>
35*10923SEvan.Yan@Sun.COM #include <sys/sunddi.h>
36*10923SEvan.Yan@Sun.COM #include <sys/ddi_hp.h>
37*10923SEvan.Yan@Sun.COM 
38*10923SEvan.Yan@Sun.COM #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
39*10923SEvan.Yan@Sun.COM #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it wasn't */
40*10923SEvan.Yan@Sun.COM #endif
41*10923SEvan.Yan@Sun.COM 
42*10923SEvan.Yan@Sun.COM /*
43*10923SEvan.Yan@Sun.COM  * Function prototypes.
44*10923SEvan.Yan@Sun.COM  */
45*10923SEvan.Yan@Sun.COM static int	cmd_list(int, char **, const char *);
46*10923SEvan.Yan@Sun.COM static int	cmd_online(int, char **, const char *);
47*10923SEvan.Yan@Sun.COM static int	cmd_offline(int, char **, const char *);
48*10923SEvan.Yan@Sun.COM static int	cmd_enable(int, char **, const char *);
49*10923SEvan.Yan@Sun.COM static int	cmd_disable(int, char **, const char *);
50*10923SEvan.Yan@Sun.COM static int	cmd_poweron(int, char **, const char *);
51*10923SEvan.Yan@Sun.COM static int	cmd_poweroff(int, char **, const char *);
52*10923SEvan.Yan@Sun.COM static int	cmd_getpriv(int, char **, const char *);
53*10923SEvan.Yan@Sun.COM static int	cmd_setpriv(int, char **, const char *);
54*10923SEvan.Yan@Sun.COM static int	cmd_changestate(int, char **, const char *);
55*10923SEvan.Yan@Sun.COM static void	parse_common(int, char **, const char *);
56*10923SEvan.Yan@Sun.COM static void	parse_flags(int, char **, int *, const char *);
57*10923SEvan.Yan@Sun.COM static void	parse_target(int, char **, char **, char **, const char *);
58*10923SEvan.Yan@Sun.COM static void	parse_options(int, char **, char **, const char *);
59*10923SEvan.Yan@Sun.COM static void	bad_option(int, int, const char *);
60*10923SEvan.Yan@Sun.COM static void	usage(const char *);
61*10923SEvan.Yan@Sun.COM static int	list_cb(hp_node_t, void *);
62*10923SEvan.Yan@Sun.COM static int	list_long_cb(hp_node_t, void *);
63*10923SEvan.Yan@Sun.COM static int	error_cb(hp_node_t, void *);
64*10923SEvan.Yan@Sun.COM static void	print_options(const char *);
65*10923SEvan.Yan@Sun.COM static void	print_error(int);
66*10923SEvan.Yan@Sun.COM static int	state_atoi(char *);
67*10923SEvan.Yan@Sun.COM static char	*state_itoa(int);
68*10923SEvan.Yan@Sun.COM static short	valid_target(int);
69*10923SEvan.Yan@Sun.COM 
70*10923SEvan.Yan@Sun.COM /*
71*10923SEvan.Yan@Sun.COM  * Define a conversion table for hotplug states.
72*10923SEvan.Yan@Sun.COM  */
73*10923SEvan.Yan@Sun.COM typedef struct {
74*10923SEvan.Yan@Sun.COM 	int	state;
75*10923SEvan.Yan@Sun.COM 	char	*state_str;
76*10923SEvan.Yan@Sun.COM 	short	valid_target;
77*10923SEvan.Yan@Sun.COM } hpstate_t;
78*10923SEvan.Yan@Sun.COM 
79*10923SEvan.Yan@Sun.COM static hpstate_t hpstates[] = {
80*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_EMPTY,	"EMPTY",	0 },
81*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_PRESENT,	"PRESENT",	1 },
82*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_POWERED,	"POWERED",	1 },
83*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_ENABLED,	"ENABLED",	1 },
84*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_PORT_EMPTY,	"PORT-EMPTY",	0 },
85*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_PORT_PRESENT,	"PORT-PRESENT",	1 },
86*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_OFFLINE,	"OFFLINE",	1 },
87*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_ATTACHED,	"ATTACHED",	0 },
88*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_MAINTENANCE,	"MAINTENANCE",	0 },
89*10923SEvan.Yan@Sun.COM 	{ DDI_HP_CN_STATE_ONLINE,	"ONLINE",	1 },
90*10923SEvan.Yan@Sun.COM 	{ 0, 0, 0 }
91*10923SEvan.Yan@Sun.COM };
92*10923SEvan.Yan@Sun.COM 
93*10923SEvan.Yan@Sun.COM /*
94*10923SEvan.Yan@Sun.COM  * Define tables of supported subcommands.
95*10923SEvan.Yan@Sun.COM  */
96*10923SEvan.Yan@Sun.COM typedef struct {
97*10923SEvan.Yan@Sun.COM 	char		*usage_str;
98*10923SEvan.Yan@Sun.COM 	char		*cmd_str;
99*10923SEvan.Yan@Sun.COM 	int		(*func)(int argc, char *argv[], const char *usage_str);
100*10923SEvan.Yan@Sun.COM } subcmd_t;
101*10923SEvan.Yan@Sun.COM 
102*10923SEvan.Yan@Sun.COM static subcmd_t	subcmds[] = {
103*10923SEvan.Yan@Sun.COM 	{ "list       [-l] [-v] [<path> [<connection>]]", "list", cmd_list },
104*10923SEvan.Yan@Sun.COM 	{ "online     <path> <port>", "online", cmd_online },
105*10923SEvan.Yan@Sun.COM 	{ "offline    [-f] [-q] <path> <port>", "offline", cmd_offline },
106*10923SEvan.Yan@Sun.COM 	{ "enable     <path> <connector>", "enable", cmd_enable },
107*10923SEvan.Yan@Sun.COM 	{ "disable    [-f] [-q] <path> <connector>", "disable", cmd_disable },
108*10923SEvan.Yan@Sun.COM 	{ "poweron    <path> <connector>", "poweron", cmd_poweron },
109*10923SEvan.Yan@Sun.COM 	{ "poweroff   [-f] [-q] <path> <connector>", "poweroff", cmd_poweroff },
110*10923SEvan.Yan@Sun.COM 	{ "get        -o <options> <path> <connector>", "get", cmd_getpriv },
111*10923SEvan.Yan@Sun.COM 	{ "set        -o <options> <path> <connector>", "set", cmd_setpriv }
112*10923SEvan.Yan@Sun.COM };
113*10923SEvan.Yan@Sun.COM 
114*10923SEvan.Yan@Sun.COM static subcmd_t hidden_subcmds[] = {
115*10923SEvan.Yan@Sun.COM 	{ "changestate  [-f] [-q] -s <state> <path> <connection>",
116*10923SEvan.Yan@Sun.COM 	    "changestate", cmd_changestate }
117*10923SEvan.Yan@Sun.COM };
118*10923SEvan.Yan@Sun.COM 
119*10923SEvan.Yan@Sun.COM /*
120*10923SEvan.Yan@Sun.COM  * Define tables of command line options.
121*10923SEvan.Yan@Sun.COM  */
122*10923SEvan.Yan@Sun.COM static const struct option common_opts[] = {
123*10923SEvan.Yan@Sun.COM 	{ "help",	no_argument,		0, '?' },
124*10923SEvan.Yan@Sun.COM 	{ "version",	no_argument,		0, 'V' },
125*10923SEvan.Yan@Sun.COM 	{ 0, 0, 0, 0 }
126*10923SEvan.Yan@Sun.COM };
127*10923SEvan.Yan@Sun.COM 
128*10923SEvan.Yan@Sun.COM static const struct option list_opts[] = {
129*10923SEvan.Yan@Sun.COM 	{ "list-path",	no_argument,		0, 'l' },
130*10923SEvan.Yan@Sun.COM 	{ "verbose",	no_argument,		0, 'v' },
131*10923SEvan.Yan@Sun.COM 	{ 0, 0,	0, 0 }
132*10923SEvan.Yan@Sun.COM };
133*10923SEvan.Yan@Sun.COM 
134*10923SEvan.Yan@Sun.COM static const struct option flag_opts[] = {
135*10923SEvan.Yan@Sun.COM 	{ "force",	no_argument,		0, 'f' },
136*10923SEvan.Yan@Sun.COM 	{ "query",	no_argument,		0, 'q' },
137*10923SEvan.Yan@Sun.COM 	{ 0, 0,	0, 0 }
138*10923SEvan.Yan@Sun.COM };
139*10923SEvan.Yan@Sun.COM 
140*10923SEvan.Yan@Sun.COM static const struct option private_opts[] = {
141*10923SEvan.Yan@Sun.COM 	{ "options",	required_argument,	0, 'o' },
142*10923SEvan.Yan@Sun.COM 	{ 0, 0,	0, 0 }
143*10923SEvan.Yan@Sun.COM };
144*10923SEvan.Yan@Sun.COM 
145*10923SEvan.Yan@Sun.COM static const struct option changestate_opts[] = {
146*10923SEvan.Yan@Sun.COM 	{ "force",	no_argument,		0, 'f' },
147*10923SEvan.Yan@Sun.COM 	{ "query",	no_argument,		0, 'q' },
148*10923SEvan.Yan@Sun.COM 	{ "state",	required_argument,	0, 's' },
149*10923SEvan.Yan@Sun.COM 	{ 0, 0,	0, 0 }
150*10923SEvan.Yan@Sun.COM };
151*10923SEvan.Yan@Sun.COM 
152*10923SEvan.Yan@Sun.COM /*
153*10923SEvan.Yan@Sun.COM  * Define exit codes.
154*10923SEvan.Yan@Sun.COM  */
155*10923SEvan.Yan@Sun.COM #define	EXIT_OK		0
156*10923SEvan.Yan@Sun.COM #define	EXIT_EINVAL	1	/* invalid arguments */
157*10923SEvan.Yan@Sun.COM #define	EXIT_ENOENT	2	/* path or connection doesn't exist */
158*10923SEvan.Yan@Sun.COM #define	EXIT_FAILED	3	/* operation failed */
159*10923SEvan.Yan@Sun.COM #define	EXIT_UNAVAIL	4	/* service not available */
160*10923SEvan.Yan@Sun.COM 
161*10923SEvan.Yan@Sun.COM /*
162*10923SEvan.Yan@Sun.COM  * Global variables.
163*10923SEvan.Yan@Sun.COM  */
164*10923SEvan.Yan@Sun.COM static char 	*prog;
165*10923SEvan.Yan@Sun.COM static char	version[] = "1.0";
166*10923SEvan.Yan@Sun.COM extern int	errno;
167*10923SEvan.Yan@Sun.COM 
168*10923SEvan.Yan@Sun.COM /*
169*10923SEvan.Yan@Sun.COM  * main()
170*10923SEvan.Yan@Sun.COM  *
171*10923SEvan.Yan@Sun.COM  *	The main routine determines which subcommand is used,
172*10923SEvan.Yan@Sun.COM  *	and dispatches control to the corresponding function.
173*10923SEvan.Yan@Sun.COM  */
174*10923SEvan.Yan@Sun.COM int
main(int argc,char * argv[])175*10923SEvan.Yan@Sun.COM main(int argc, char *argv[])
176*10923SEvan.Yan@Sun.COM {
177*10923SEvan.Yan@Sun.COM 	int 		i, rv;
178*10923SEvan.Yan@Sun.COM 
179*10923SEvan.Yan@Sun.COM 	(void) setlocale(LC_ALL, "");
180*10923SEvan.Yan@Sun.COM 	(void) textdomain(TEXT_DOMAIN);
181*10923SEvan.Yan@Sun.COM 
182*10923SEvan.Yan@Sun.COM 	if ((prog = strrchr(argv[0], '/')) == NULL)
183*10923SEvan.Yan@Sun.COM 		prog = argv[0];
184*10923SEvan.Yan@Sun.COM 	else
185*10923SEvan.Yan@Sun.COM 		prog++;
186*10923SEvan.Yan@Sun.COM 
187*10923SEvan.Yan@Sun.COM 	if (argc < 2) {
188*10923SEvan.Yan@Sun.COM 		usage(NULL);
189*10923SEvan.Yan@Sun.COM 		return (EXIT_EINVAL);
190*10923SEvan.Yan@Sun.COM 	}
191*10923SEvan.Yan@Sun.COM 
192*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, NULL);
193*10923SEvan.Yan@Sun.COM 
194*10923SEvan.Yan@Sun.COM 	/* Check the list of defined subcommands. */
195*10923SEvan.Yan@Sun.COM 	for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++) {
196*10923SEvan.Yan@Sun.COM 		if (strcmp(argv[1], subcmds[i].cmd_str) == 0) {
197*10923SEvan.Yan@Sun.COM 			rv = subcmds[i].func(argc - 1, &argv[1],
198*10923SEvan.Yan@Sun.COM 			    subcmds[i].usage_str);
199*10923SEvan.Yan@Sun.COM 			goto finished;
200*10923SEvan.Yan@Sun.COM 		}
201*10923SEvan.Yan@Sun.COM 	}
202*10923SEvan.Yan@Sun.COM 
203*10923SEvan.Yan@Sun.COM 	/* Check the list of hidden subcommands. */
204*10923SEvan.Yan@Sun.COM 	for (i = 0; i < (sizeof (hidden_subcmds) / sizeof (subcmd_t)); i++) {
205*10923SEvan.Yan@Sun.COM 		if (strcmp(argv[1], hidden_subcmds[i].cmd_str) == 0) {
206*10923SEvan.Yan@Sun.COM 			rv = hidden_subcmds[i].func(argc - 1, &argv[1],
207*10923SEvan.Yan@Sun.COM 			    hidden_subcmds[i].usage_str);
208*10923SEvan.Yan@Sun.COM 			goto finished;
209*10923SEvan.Yan@Sun.COM 		}
210*10923SEvan.Yan@Sun.COM 	}
211*10923SEvan.Yan@Sun.COM 
212*10923SEvan.Yan@Sun.COM 	/* No matching subcommand found. */
213*10923SEvan.Yan@Sun.COM 	(void) fprintf(stderr, gettext("ERROR: %s: unknown subcommand '%s'\n"),
214*10923SEvan.Yan@Sun.COM 	    prog, argv[1]);
215*10923SEvan.Yan@Sun.COM 	usage(NULL);
216*10923SEvan.Yan@Sun.COM 	exit(EXIT_EINVAL);
217*10923SEvan.Yan@Sun.COM 
218*10923SEvan.Yan@Sun.COM finished:
219*10923SEvan.Yan@Sun.COM 	/* Determine exit code */
220*10923SEvan.Yan@Sun.COM 	switch (rv) {
221*10923SEvan.Yan@Sun.COM 	case 0:
222*10923SEvan.Yan@Sun.COM 		break;
223*10923SEvan.Yan@Sun.COM 	case EINVAL:
224*10923SEvan.Yan@Sun.COM 		return (EXIT_EINVAL);
225*10923SEvan.Yan@Sun.COM 	case ENXIO:
226*10923SEvan.Yan@Sun.COM 	case ENOENT:
227*10923SEvan.Yan@Sun.COM 		return (EXIT_ENOENT);
228*10923SEvan.Yan@Sun.COM 	case EBADF:
229*10923SEvan.Yan@Sun.COM 		return (EXIT_UNAVAIL);
230*10923SEvan.Yan@Sun.COM 	default:
231*10923SEvan.Yan@Sun.COM 		return (EXIT_FAILED);
232*10923SEvan.Yan@Sun.COM 	}
233*10923SEvan.Yan@Sun.COM 
234*10923SEvan.Yan@Sun.COM 	return (EXIT_OK);
235*10923SEvan.Yan@Sun.COM }
236*10923SEvan.Yan@Sun.COM 
237*10923SEvan.Yan@Sun.COM /*
238*10923SEvan.Yan@Sun.COM  * cmd_list()
239*10923SEvan.Yan@Sun.COM  *
240*10923SEvan.Yan@Sun.COM  *	Subcommand to list hotplug information.
241*10923SEvan.Yan@Sun.COM  */
242*10923SEvan.Yan@Sun.COM static int
cmd_list(int argc,char * argv[],const char * usage_str)243*10923SEvan.Yan@Sun.COM cmd_list(int argc, char *argv[], const char *usage_str)
244*10923SEvan.Yan@Sun.COM {
245*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
246*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
247*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
248*10923SEvan.Yan@Sun.COM 	boolean_t	long_flag = B_FALSE;
249*10923SEvan.Yan@Sun.COM 	int		flags = 0;
250*10923SEvan.Yan@Sun.COM 	int		opt;
251*10923SEvan.Yan@Sun.COM 
252*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
253*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
254*10923SEvan.Yan@Sun.COM 	while ((opt = getopt_clip(argc, argv, "lv", list_opts, NULL)) != -1) {
255*10923SEvan.Yan@Sun.COM 		switch (opt) {
256*10923SEvan.Yan@Sun.COM 		case 'l':
257*10923SEvan.Yan@Sun.COM 			long_flag = B_TRUE;
258*10923SEvan.Yan@Sun.COM 			break;
259*10923SEvan.Yan@Sun.COM 		case 'v':
260*10923SEvan.Yan@Sun.COM 			flags |= HPINFOUSAGE;
261*10923SEvan.Yan@Sun.COM 			break;
262*10923SEvan.Yan@Sun.COM 		default:
263*10923SEvan.Yan@Sun.COM 			bad_option(opt, optopt, usage_str);
264*10923SEvan.Yan@Sun.COM 			break;
265*10923SEvan.Yan@Sun.COM 		}
266*10923SEvan.Yan@Sun.COM 	}
267*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
268*10923SEvan.Yan@Sun.COM 
269*10923SEvan.Yan@Sun.COM 	/* Default path is "/" */
270*10923SEvan.Yan@Sun.COM 	if (path == NULL)
271*10923SEvan.Yan@Sun.COM 		path = "/";
272*10923SEvan.Yan@Sun.COM 
273*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
274*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, flags)) == NULL) {
275*10923SEvan.Yan@Sun.COM 		print_error(errno);
276*10923SEvan.Yan@Sun.COM 		return (errno);
277*10923SEvan.Yan@Sun.COM 	}
278*10923SEvan.Yan@Sun.COM 
279*10923SEvan.Yan@Sun.COM 	/* Display hotplug information */
280*10923SEvan.Yan@Sun.COM 	(void) hp_traverse(root, NULL, long_flag ? list_long_cb : list_cb);
281*10923SEvan.Yan@Sun.COM 
282*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
283*10923SEvan.Yan@Sun.COM 	hp_fini(root);
284*10923SEvan.Yan@Sun.COM 
285*10923SEvan.Yan@Sun.COM 	return (0);
286*10923SEvan.Yan@Sun.COM }
287*10923SEvan.Yan@Sun.COM 
288*10923SEvan.Yan@Sun.COM /*
289*10923SEvan.Yan@Sun.COM  * cmd_online()
290*10923SEvan.Yan@Sun.COM  *
291*10923SEvan.Yan@Sun.COM  *	Subcommand to online a hotplug port.
292*10923SEvan.Yan@Sun.COM  */
293*10923SEvan.Yan@Sun.COM static int
cmd_online(int argc,char * argv[],const char * usage_str)294*10923SEvan.Yan@Sun.COM cmd_online(int argc, char *argv[], const char *usage_str)
295*10923SEvan.Yan@Sun.COM {
296*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
297*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
298*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
299*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
300*10923SEvan.Yan@Sun.COM 	int		rv;
301*10923SEvan.Yan@Sun.COM 
302*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
303*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
304*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
305*10923SEvan.Yan@Sun.COM 
306*10923SEvan.Yan@Sun.COM 	/* Path and connection are required */
307*10923SEvan.Yan@Sun.COM 	if ((path == NULL) || (connection == NULL)) {
308*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
309*10923SEvan.Yan@Sun.COM 		usage(usage_str);
310*10923SEvan.Yan@Sun.COM 		return (EINVAL);
311*10923SEvan.Yan@Sun.COM 	}
312*10923SEvan.Yan@Sun.COM 
313*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
314*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
315*10923SEvan.Yan@Sun.COM 		print_error(errno);
316*10923SEvan.Yan@Sun.COM 		return (errno);
317*10923SEvan.Yan@Sun.COM 	}
318*10923SEvan.Yan@Sun.COM 
319*10923SEvan.Yan@Sun.COM 	/* Verify target is a port */
320*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_PORT) {
321*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
322*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a port).\n"));
323*10923SEvan.Yan@Sun.COM 		hp_fini(root);
324*10923SEvan.Yan@Sun.COM 		return (EINVAL);
325*10923SEvan.Yan@Sun.COM 	}
326*10923SEvan.Yan@Sun.COM 
327*10923SEvan.Yan@Sun.COM 	/* Do state change */
328*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ONLINE, &results);
329*10923SEvan.Yan@Sun.COM 
330*10923SEvan.Yan@Sun.COM 	/* Display results */
331*10923SEvan.Yan@Sun.COM 	if (rv == EIO) {
332*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: failed to attach device "
333*10923SEvan.Yan@Sun.COM 		    "drivers or other internal errors.\n"));
334*10923SEvan.Yan@Sun.COM 	} else if (rv != 0) {
335*10923SEvan.Yan@Sun.COM 		print_error(rv);
336*10923SEvan.Yan@Sun.COM 	}
337*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
338*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
339*10923SEvan.Yan@Sun.COM 		hp_fini(results);
340*10923SEvan.Yan@Sun.COM 	}
341*10923SEvan.Yan@Sun.COM 
342*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
343*10923SEvan.Yan@Sun.COM 	hp_fini(root);
344*10923SEvan.Yan@Sun.COM 
345*10923SEvan.Yan@Sun.COM 	return (rv);
346*10923SEvan.Yan@Sun.COM }
347*10923SEvan.Yan@Sun.COM 
348*10923SEvan.Yan@Sun.COM /*
349*10923SEvan.Yan@Sun.COM  * cmd_offline()
350*10923SEvan.Yan@Sun.COM  *
351*10923SEvan.Yan@Sun.COM  *	Subcommand to offline a hotplug port.
352*10923SEvan.Yan@Sun.COM  */
353*10923SEvan.Yan@Sun.COM static int
cmd_offline(int argc,char * argv[],const char * usage_str)354*10923SEvan.Yan@Sun.COM cmd_offline(int argc, char *argv[], const char *usage_str)
355*10923SEvan.Yan@Sun.COM {
356*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
357*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
358*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
359*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
360*10923SEvan.Yan@Sun.COM 	int		flags = 0;
361*10923SEvan.Yan@Sun.COM 	int		rv;
362*10923SEvan.Yan@Sun.COM 
363*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
364*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
365*10923SEvan.Yan@Sun.COM 	parse_flags(argc, argv, &flags, usage_str);
366*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
367*10923SEvan.Yan@Sun.COM 
368*10923SEvan.Yan@Sun.COM 	/* Path and connection are required */
369*10923SEvan.Yan@Sun.COM 	if ((path == NULL) || (connection == NULL)) {
370*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
371*10923SEvan.Yan@Sun.COM 		usage(usage_str);
372*10923SEvan.Yan@Sun.COM 		return (EINVAL);
373*10923SEvan.Yan@Sun.COM 	}
374*10923SEvan.Yan@Sun.COM 
375*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
376*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
377*10923SEvan.Yan@Sun.COM 		print_error(errno);
378*10923SEvan.Yan@Sun.COM 		return (errno);
379*10923SEvan.Yan@Sun.COM 	}
380*10923SEvan.Yan@Sun.COM 
381*10923SEvan.Yan@Sun.COM 	/* Verify target is a port */
382*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_PORT) {
383*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
384*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a port).\n"));
385*10923SEvan.Yan@Sun.COM 		hp_fini(root);
386*10923SEvan.Yan@Sun.COM 		return (EINVAL);
387*10923SEvan.Yan@Sun.COM 	}
388*10923SEvan.Yan@Sun.COM 
389*10923SEvan.Yan@Sun.COM 	/* Do state change */
390*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, flags, DDI_HP_CN_STATE_OFFLINE, &results);
391*10923SEvan.Yan@Sun.COM 
392*10923SEvan.Yan@Sun.COM 	/* Display results */
393*10923SEvan.Yan@Sun.COM 	print_error(rv);
394*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
395*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
396*10923SEvan.Yan@Sun.COM 		hp_fini(results);
397*10923SEvan.Yan@Sun.COM 	}
398*10923SEvan.Yan@Sun.COM 
399*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
400*10923SEvan.Yan@Sun.COM 	hp_fini(root);
401*10923SEvan.Yan@Sun.COM 
402*10923SEvan.Yan@Sun.COM 	return (rv);
403*10923SEvan.Yan@Sun.COM }
404*10923SEvan.Yan@Sun.COM 
405*10923SEvan.Yan@Sun.COM /*
406*10923SEvan.Yan@Sun.COM  * cmd_enable()
407*10923SEvan.Yan@Sun.COM  *
408*10923SEvan.Yan@Sun.COM  *	Subcommand to enable a hotplug connector.
409*10923SEvan.Yan@Sun.COM  */
410*10923SEvan.Yan@Sun.COM static int
cmd_enable(int argc,char * argv[],const char * usage_str)411*10923SEvan.Yan@Sun.COM cmd_enable(int argc, char *argv[], const char *usage_str)
412*10923SEvan.Yan@Sun.COM {
413*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
414*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
415*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
416*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
417*10923SEvan.Yan@Sun.COM 	int		rv;
418*10923SEvan.Yan@Sun.COM 
419*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
420*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
421*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
422*10923SEvan.Yan@Sun.COM 
423*10923SEvan.Yan@Sun.COM 	/* Path and connection are required */
424*10923SEvan.Yan@Sun.COM 	if ((path == NULL) || (connection == NULL)) {
425*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
426*10923SEvan.Yan@Sun.COM 		usage(usage_str);
427*10923SEvan.Yan@Sun.COM 		return (EINVAL);
428*10923SEvan.Yan@Sun.COM 	}
429*10923SEvan.Yan@Sun.COM 
430*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
431*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
432*10923SEvan.Yan@Sun.COM 		print_error(errno);
433*10923SEvan.Yan@Sun.COM 		return (errno);
434*10923SEvan.Yan@Sun.COM 	}
435*10923SEvan.Yan@Sun.COM 
436*10923SEvan.Yan@Sun.COM 	/* Verify target is a connector */
437*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_CONNECTOR) {
438*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
439*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a connector).\n"));
440*10923SEvan.Yan@Sun.COM 		hp_fini(root);
441*10923SEvan.Yan@Sun.COM 		return (EINVAL);
442*10923SEvan.Yan@Sun.COM 	}
443*10923SEvan.Yan@Sun.COM 
444*10923SEvan.Yan@Sun.COM 	/* Do state change */
445*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, 0, DDI_HP_CN_STATE_ENABLED, &results);
446*10923SEvan.Yan@Sun.COM 
447*10923SEvan.Yan@Sun.COM 	/* Display results */
448*10923SEvan.Yan@Sun.COM 	print_error(rv);
449*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
450*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
451*10923SEvan.Yan@Sun.COM 		hp_fini(results);
452*10923SEvan.Yan@Sun.COM 	}
453*10923SEvan.Yan@Sun.COM 
454*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
455*10923SEvan.Yan@Sun.COM 	hp_fini(root);
456*10923SEvan.Yan@Sun.COM 
457*10923SEvan.Yan@Sun.COM 	return (rv);
458*10923SEvan.Yan@Sun.COM }
459*10923SEvan.Yan@Sun.COM 
460*10923SEvan.Yan@Sun.COM /*
461*10923SEvan.Yan@Sun.COM  * cmd_disable()
462*10923SEvan.Yan@Sun.COM  *
463*10923SEvan.Yan@Sun.COM  *	Subcommand to disable a hotplug connector.
464*10923SEvan.Yan@Sun.COM  */
465*10923SEvan.Yan@Sun.COM static int
cmd_disable(int argc,char * argv[],const char * usage_str)466*10923SEvan.Yan@Sun.COM cmd_disable(int argc, char *argv[], const char *usage_str)
467*10923SEvan.Yan@Sun.COM {
468*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
469*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
470*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
471*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
472*10923SEvan.Yan@Sun.COM 	int		flags = 0;
473*10923SEvan.Yan@Sun.COM 	int		rv;
474*10923SEvan.Yan@Sun.COM 
475*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
476*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
477*10923SEvan.Yan@Sun.COM 	parse_flags(argc, argv, &flags, usage_str);
478*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
479*10923SEvan.Yan@Sun.COM 
480*10923SEvan.Yan@Sun.COM 	/* Path and connection are required */
481*10923SEvan.Yan@Sun.COM 	if ((path == NULL) || (connection == NULL)) {
482*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
483*10923SEvan.Yan@Sun.COM 		usage(usage_str);
484*10923SEvan.Yan@Sun.COM 		return (EINVAL);
485*10923SEvan.Yan@Sun.COM 	}
486*10923SEvan.Yan@Sun.COM 
487*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
488*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
489*10923SEvan.Yan@Sun.COM 		print_error(errno);
490*10923SEvan.Yan@Sun.COM 		return (errno);
491*10923SEvan.Yan@Sun.COM 	}
492*10923SEvan.Yan@Sun.COM 
493*10923SEvan.Yan@Sun.COM 	/* Verify target is a connector */
494*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_CONNECTOR) {
495*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
496*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a connector).\n"));
497*10923SEvan.Yan@Sun.COM 		hp_fini(root);
498*10923SEvan.Yan@Sun.COM 		return (EINVAL);
499*10923SEvan.Yan@Sun.COM 	}
500*10923SEvan.Yan@Sun.COM 
501*10923SEvan.Yan@Sun.COM 	/*
502*10923SEvan.Yan@Sun.COM 	 * Do nothing unless the connector is in the ENABLED state.
503*10923SEvan.Yan@Sun.COM 	 * Otherwise this subcommand becomes an alias for 'poweron.'
504*10923SEvan.Yan@Sun.COM 	 */
505*10923SEvan.Yan@Sun.COM 	if (hp_state(root) != DDI_HP_CN_STATE_ENABLED) {
506*10923SEvan.Yan@Sun.COM 		hp_fini(root);
507*10923SEvan.Yan@Sun.COM 		return (0);
508*10923SEvan.Yan@Sun.COM 	}
509*10923SEvan.Yan@Sun.COM 
510*10923SEvan.Yan@Sun.COM 	/* Do state change */
511*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, flags, DDI_HP_CN_STATE_POWERED, &results);
512*10923SEvan.Yan@Sun.COM 
513*10923SEvan.Yan@Sun.COM 	/* Display results */
514*10923SEvan.Yan@Sun.COM 	print_error(rv);
515*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
516*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
517*10923SEvan.Yan@Sun.COM 		hp_fini(results);
518*10923SEvan.Yan@Sun.COM 	}
519*10923SEvan.Yan@Sun.COM 
520*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
521*10923SEvan.Yan@Sun.COM 	hp_fini(root);
522*10923SEvan.Yan@Sun.COM 
523*10923SEvan.Yan@Sun.COM 	return (rv);
524*10923SEvan.Yan@Sun.COM }
525*10923SEvan.Yan@Sun.COM 
526*10923SEvan.Yan@Sun.COM /*
527*10923SEvan.Yan@Sun.COM  * cmd_poweron()
528*10923SEvan.Yan@Sun.COM  *
529*10923SEvan.Yan@Sun.COM  *	Subcommand to power on a hotplug connector.
530*10923SEvan.Yan@Sun.COM  */
531*10923SEvan.Yan@Sun.COM static int
cmd_poweron(int argc,char * argv[],const char * usage_str)532*10923SEvan.Yan@Sun.COM cmd_poweron(int argc, char *argv[], const char *usage_str)
533*10923SEvan.Yan@Sun.COM {
534*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
535*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
536*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
537*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
538*10923SEvan.Yan@Sun.COM 	int		rv;
539*10923SEvan.Yan@Sun.COM 
540*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
541*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
542*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
543*10923SEvan.Yan@Sun.COM 
544*10923SEvan.Yan@Sun.COM 	/* Path and connection are required */
545*10923SEvan.Yan@Sun.COM 	if ((path == NULL) || (connection == NULL)) {
546*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
547*10923SEvan.Yan@Sun.COM 		usage(usage_str);
548*10923SEvan.Yan@Sun.COM 		return (EINVAL);
549*10923SEvan.Yan@Sun.COM 	}
550*10923SEvan.Yan@Sun.COM 
551*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
552*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
553*10923SEvan.Yan@Sun.COM 		print_error(errno);
554*10923SEvan.Yan@Sun.COM 		return (errno);
555*10923SEvan.Yan@Sun.COM 	}
556*10923SEvan.Yan@Sun.COM 
557*10923SEvan.Yan@Sun.COM 	/* Verify target is a connector */
558*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_CONNECTOR) {
559*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
560*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a connector).\n"));
561*10923SEvan.Yan@Sun.COM 		hp_fini(root);
562*10923SEvan.Yan@Sun.COM 		return (EINVAL);
563*10923SEvan.Yan@Sun.COM 	}
564*10923SEvan.Yan@Sun.COM 
565*10923SEvan.Yan@Sun.COM 	/*
566*10923SEvan.Yan@Sun.COM 	 * Do nothing if the connector is already powered.
567*10923SEvan.Yan@Sun.COM 	 * Otherwise this subcommand becomes an alias for 'disable.'
568*10923SEvan.Yan@Sun.COM 	 */
569*10923SEvan.Yan@Sun.COM 	if (hp_state(root) >= DDI_HP_CN_STATE_POWERED) {
570*10923SEvan.Yan@Sun.COM 		hp_fini(root);
571*10923SEvan.Yan@Sun.COM 		return (0);
572*10923SEvan.Yan@Sun.COM 	}
573*10923SEvan.Yan@Sun.COM 
574*10923SEvan.Yan@Sun.COM 	/* Do state change */
575*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, 0, DDI_HP_CN_STATE_POWERED, &results);
576*10923SEvan.Yan@Sun.COM 
577*10923SEvan.Yan@Sun.COM 	/* Display results */
578*10923SEvan.Yan@Sun.COM 	print_error(rv);
579*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
580*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
581*10923SEvan.Yan@Sun.COM 		hp_fini(results);
582*10923SEvan.Yan@Sun.COM 	}
583*10923SEvan.Yan@Sun.COM 
584*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
585*10923SEvan.Yan@Sun.COM 	hp_fini(root);
586*10923SEvan.Yan@Sun.COM 
587*10923SEvan.Yan@Sun.COM 	return (rv);
588*10923SEvan.Yan@Sun.COM }
589*10923SEvan.Yan@Sun.COM 
590*10923SEvan.Yan@Sun.COM /*
591*10923SEvan.Yan@Sun.COM  * cmd_poweroff()
592*10923SEvan.Yan@Sun.COM  *
593*10923SEvan.Yan@Sun.COM  *	Subcommand to power off a hotplug connector.
594*10923SEvan.Yan@Sun.COM  */
595*10923SEvan.Yan@Sun.COM static int
cmd_poweroff(int argc,char * argv[],const char * usage_str)596*10923SEvan.Yan@Sun.COM cmd_poweroff(int argc, char *argv[], const char *usage_str)
597*10923SEvan.Yan@Sun.COM {
598*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
599*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
600*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
601*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
602*10923SEvan.Yan@Sun.COM 	int		flags = 0;
603*10923SEvan.Yan@Sun.COM 	int		rv;
604*10923SEvan.Yan@Sun.COM 
605*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
606*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
607*10923SEvan.Yan@Sun.COM 	parse_flags(argc, argv, &flags, usage_str);
608*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
609*10923SEvan.Yan@Sun.COM 
610*10923SEvan.Yan@Sun.COM 	/* Path and connection are required */
611*10923SEvan.Yan@Sun.COM 	if ((path == NULL) || (connection == NULL)) {
612*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
613*10923SEvan.Yan@Sun.COM 		usage(usage_str);
614*10923SEvan.Yan@Sun.COM 		return (EINVAL);
615*10923SEvan.Yan@Sun.COM 	}
616*10923SEvan.Yan@Sun.COM 
617*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
618*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
619*10923SEvan.Yan@Sun.COM 		print_error(errno);
620*10923SEvan.Yan@Sun.COM 		return (errno);
621*10923SEvan.Yan@Sun.COM 	}
622*10923SEvan.Yan@Sun.COM 
623*10923SEvan.Yan@Sun.COM 	/* Verify target is a connector */
624*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_CONNECTOR) {
625*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
626*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a connector).\n"));
627*10923SEvan.Yan@Sun.COM 		hp_fini(root);
628*10923SEvan.Yan@Sun.COM 		return (EINVAL);
629*10923SEvan.Yan@Sun.COM 	}
630*10923SEvan.Yan@Sun.COM 
631*10923SEvan.Yan@Sun.COM 	/* Do state change */
632*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, flags, DDI_HP_CN_STATE_PRESENT, &results);
633*10923SEvan.Yan@Sun.COM 
634*10923SEvan.Yan@Sun.COM 	/* Display results */
635*10923SEvan.Yan@Sun.COM 	print_error(rv);
636*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
637*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
638*10923SEvan.Yan@Sun.COM 		hp_fini(results);
639*10923SEvan.Yan@Sun.COM 	}
640*10923SEvan.Yan@Sun.COM 
641*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
642*10923SEvan.Yan@Sun.COM 	hp_fini(root);
643*10923SEvan.Yan@Sun.COM 
644*10923SEvan.Yan@Sun.COM 	return (rv);
645*10923SEvan.Yan@Sun.COM }
646*10923SEvan.Yan@Sun.COM 
647*10923SEvan.Yan@Sun.COM /*
648*10923SEvan.Yan@Sun.COM  * cmd_getpriv()
649*10923SEvan.Yan@Sun.COM  *
650*10923SEvan.Yan@Sun.COM  *	Subcommand to get and display bus private options.
651*10923SEvan.Yan@Sun.COM  */
652*10923SEvan.Yan@Sun.COM static int
cmd_getpriv(int argc,char * argv[],const char * usage_str)653*10923SEvan.Yan@Sun.COM cmd_getpriv(int argc, char *argv[], const char *usage_str)
654*10923SEvan.Yan@Sun.COM {
655*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
656*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
657*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
658*10923SEvan.Yan@Sun.COM 	char		*options = NULL;
659*10923SEvan.Yan@Sun.COM 	char		*results = NULL;
660*10923SEvan.Yan@Sun.COM 	int		rv;
661*10923SEvan.Yan@Sun.COM 
662*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
663*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
664*10923SEvan.Yan@Sun.COM 	parse_options(argc, argv, &options, usage_str);
665*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
666*10923SEvan.Yan@Sun.COM 
667*10923SEvan.Yan@Sun.COM 	/* Options, path, and connection are all required */
668*10923SEvan.Yan@Sun.COM 	if ((options == NULL) || (path == NULL) || (connection == NULL)) {
669*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
670*10923SEvan.Yan@Sun.COM 		usage(usage_str);
671*10923SEvan.Yan@Sun.COM 		return (EINVAL);
672*10923SEvan.Yan@Sun.COM 	}
673*10923SEvan.Yan@Sun.COM 
674*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
675*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
676*10923SEvan.Yan@Sun.COM 		print_error(errno);
677*10923SEvan.Yan@Sun.COM 		return (errno);
678*10923SEvan.Yan@Sun.COM 	}
679*10923SEvan.Yan@Sun.COM 
680*10923SEvan.Yan@Sun.COM 	/* Verify target is a connector */
681*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_CONNECTOR) {
682*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
683*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a connector).\n"));
684*10923SEvan.Yan@Sun.COM 		hp_fini(root);
685*10923SEvan.Yan@Sun.COM 		return (EINVAL);
686*10923SEvan.Yan@Sun.COM 	}
687*10923SEvan.Yan@Sun.COM 
688*10923SEvan.Yan@Sun.COM 	/* Do the operation */
689*10923SEvan.Yan@Sun.COM 	rv = hp_get_private(root, options, &results);
690*10923SEvan.Yan@Sun.COM 
691*10923SEvan.Yan@Sun.COM 	/* Display results */
692*10923SEvan.Yan@Sun.COM 	if (rv == ENOTSUP) {
693*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
694*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: unsupported property name or value.\n"));
695*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
696*10923SEvan.Yan@Sun.COM 		    gettext("(Properties may depend upon connector state.)\n"));
697*10923SEvan.Yan@Sun.COM 	} else if (rv != 0) {
698*10923SEvan.Yan@Sun.COM 		print_error(rv);
699*10923SEvan.Yan@Sun.COM 	}
700*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
701*10923SEvan.Yan@Sun.COM 		print_options(results);
702*10923SEvan.Yan@Sun.COM 		free(results);
703*10923SEvan.Yan@Sun.COM 	}
704*10923SEvan.Yan@Sun.COM 
705*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
706*10923SEvan.Yan@Sun.COM 	hp_fini(root);
707*10923SEvan.Yan@Sun.COM 
708*10923SEvan.Yan@Sun.COM 	return (rv);
709*10923SEvan.Yan@Sun.COM }
710*10923SEvan.Yan@Sun.COM 
711*10923SEvan.Yan@Sun.COM /*
712*10923SEvan.Yan@Sun.COM  * cmd_setpriv()
713*10923SEvan.Yan@Sun.COM  *
714*10923SEvan.Yan@Sun.COM  *	Subcommand to set bus private options.
715*10923SEvan.Yan@Sun.COM  */
716*10923SEvan.Yan@Sun.COM static int
cmd_setpriv(int argc,char * argv[],const char * usage_str)717*10923SEvan.Yan@Sun.COM cmd_setpriv(int argc, char *argv[], const char *usage_str)
718*10923SEvan.Yan@Sun.COM {
719*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
720*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
721*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
722*10923SEvan.Yan@Sun.COM 	char		*options = NULL;
723*10923SEvan.Yan@Sun.COM 	char		*results = NULL;
724*10923SEvan.Yan@Sun.COM 	int		rv;
725*10923SEvan.Yan@Sun.COM 
726*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
727*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
728*10923SEvan.Yan@Sun.COM 	parse_options(argc, argv, &options, usage_str);
729*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
730*10923SEvan.Yan@Sun.COM 
731*10923SEvan.Yan@Sun.COM 	/* Options, path, and connection are all required */
732*10923SEvan.Yan@Sun.COM 	if ((options == NULL) || (path == NULL) || (connection == NULL)) {
733*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
734*10923SEvan.Yan@Sun.COM 		usage(usage_str);
735*10923SEvan.Yan@Sun.COM 		return (EINVAL);
736*10923SEvan.Yan@Sun.COM 	}
737*10923SEvan.Yan@Sun.COM 
738*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
739*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
740*10923SEvan.Yan@Sun.COM 		print_error(errno);
741*10923SEvan.Yan@Sun.COM 		return (errno);
742*10923SEvan.Yan@Sun.COM 	}
743*10923SEvan.Yan@Sun.COM 
744*10923SEvan.Yan@Sun.COM 	/* Verify target is a connector */
745*10923SEvan.Yan@Sun.COM 	if (hp_type(root) != HP_NODE_CONNECTOR) {
746*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
747*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target (must be a connector).\n"));
748*10923SEvan.Yan@Sun.COM 		hp_fini(root);
749*10923SEvan.Yan@Sun.COM 		return (EINVAL);
750*10923SEvan.Yan@Sun.COM 	}
751*10923SEvan.Yan@Sun.COM 
752*10923SEvan.Yan@Sun.COM 	/* Do the operation */
753*10923SEvan.Yan@Sun.COM 	rv = hp_set_private(root, options, &results);
754*10923SEvan.Yan@Sun.COM 
755*10923SEvan.Yan@Sun.COM 	/* Display results */
756*10923SEvan.Yan@Sun.COM 	if (rv == ENOTSUP) {
757*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
758*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: unsupported property name or value.\n"));
759*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
760*10923SEvan.Yan@Sun.COM 		    gettext("(Properties may depend upon connector state.)\n"));
761*10923SEvan.Yan@Sun.COM 	} else if (rv != 0) {
762*10923SEvan.Yan@Sun.COM 		print_error(rv);
763*10923SEvan.Yan@Sun.COM 	}
764*10923SEvan.Yan@Sun.COM 	if (results != NULL) {
765*10923SEvan.Yan@Sun.COM 		print_options(results);
766*10923SEvan.Yan@Sun.COM 		free(results);
767*10923SEvan.Yan@Sun.COM 	}
768*10923SEvan.Yan@Sun.COM 
769*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
770*10923SEvan.Yan@Sun.COM 	hp_fini(root);
771*10923SEvan.Yan@Sun.COM 
772*10923SEvan.Yan@Sun.COM 	return (rv);
773*10923SEvan.Yan@Sun.COM }
774*10923SEvan.Yan@Sun.COM 
775*10923SEvan.Yan@Sun.COM /*
776*10923SEvan.Yan@Sun.COM  * cmd_changestate()
777*10923SEvan.Yan@Sun.COM  *
778*10923SEvan.Yan@Sun.COM  *	Subcommand to initiate a state change operation.  This is
779*10923SEvan.Yan@Sun.COM  *	a hidden subcommand to directly set a connector or port to
780*10923SEvan.Yan@Sun.COM  *	a specific target state.
781*10923SEvan.Yan@Sun.COM  */
782*10923SEvan.Yan@Sun.COM static int
cmd_changestate(int argc,char * argv[],const char * usage_str)783*10923SEvan.Yan@Sun.COM cmd_changestate(int argc, char *argv[], const char *usage_str)
784*10923SEvan.Yan@Sun.COM {
785*10923SEvan.Yan@Sun.COM 	hp_node_t	root;
786*10923SEvan.Yan@Sun.COM 	hp_node_t	results = NULL;
787*10923SEvan.Yan@Sun.COM 	char		*path = NULL;
788*10923SEvan.Yan@Sun.COM 	char		*connection = NULL;
789*10923SEvan.Yan@Sun.COM 	int		state = -1;
790*10923SEvan.Yan@Sun.COM 	int		flags = 0;
791*10923SEvan.Yan@Sun.COM 	int		opt, rv;
792*10923SEvan.Yan@Sun.COM 
793*10923SEvan.Yan@Sun.COM 	/* Parse command line options */
794*10923SEvan.Yan@Sun.COM 	parse_common(argc, argv, usage_str);
795*10923SEvan.Yan@Sun.COM 	while ((opt = getopt_clip(argc, argv, "fqs:", changestate_opts,
796*10923SEvan.Yan@Sun.COM 	    NULL)) != -1) {
797*10923SEvan.Yan@Sun.COM 		switch (opt) {
798*10923SEvan.Yan@Sun.COM 		case 'f':
799*10923SEvan.Yan@Sun.COM 			flags |= HPFORCE;
800*10923SEvan.Yan@Sun.COM 			break;
801*10923SEvan.Yan@Sun.COM 		case 'q':
802*10923SEvan.Yan@Sun.COM 			flags |= HPQUERY;
803*10923SEvan.Yan@Sun.COM 			break;
804*10923SEvan.Yan@Sun.COM 		case 's':
805*10923SEvan.Yan@Sun.COM 			if ((state = state_atoi(optarg)) == -1) {
806*10923SEvan.Yan@Sun.COM 				(void) printf("ERROR: invalid target state\n");
807*10923SEvan.Yan@Sun.COM 				return (EINVAL);
808*10923SEvan.Yan@Sun.COM 			}
809*10923SEvan.Yan@Sun.COM 			break;
810*10923SEvan.Yan@Sun.COM 		default:
811*10923SEvan.Yan@Sun.COM 			bad_option(opt, optopt, usage_str);
812*10923SEvan.Yan@Sun.COM 			break;
813*10923SEvan.Yan@Sun.COM 		}
814*10923SEvan.Yan@Sun.COM 	}
815*10923SEvan.Yan@Sun.COM 	parse_target(argc, argv, &path, &connection, usage_str);
816*10923SEvan.Yan@Sun.COM 
817*10923SEvan.Yan@Sun.COM 	/* State, path, and connection are all required */
818*10923SEvan.Yan@Sun.COM 	if ((state == -1) || (path == NULL) || (connection == NULL)) {
819*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too few arguments.\n"));
820*10923SEvan.Yan@Sun.COM 		usage(usage_str);
821*10923SEvan.Yan@Sun.COM 		return (EINVAL);
822*10923SEvan.Yan@Sun.COM 	}
823*10923SEvan.Yan@Sun.COM 
824*10923SEvan.Yan@Sun.COM 	/* Check that target state is valid */
825*10923SEvan.Yan@Sun.COM 	if (valid_target(state) == 0) {
826*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
827*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid target state\n"));
828*10923SEvan.Yan@Sun.COM 		return (EINVAL);
829*10923SEvan.Yan@Sun.COM 	}
830*10923SEvan.Yan@Sun.COM 
831*10923SEvan.Yan@Sun.COM 	/* Get hotplug information snapshot */
832*10923SEvan.Yan@Sun.COM 	if ((root = hp_init(path, connection, 0)) == NULL) {
833*10923SEvan.Yan@Sun.COM 		print_error(errno);
834*10923SEvan.Yan@Sun.COM 		return (errno);
835*10923SEvan.Yan@Sun.COM 	}
836*10923SEvan.Yan@Sun.COM 
837*10923SEvan.Yan@Sun.COM 	/* Initiate state change operation on root of snapshot */
838*10923SEvan.Yan@Sun.COM 	rv = hp_set_state(root, flags, state, &results);
839*10923SEvan.Yan@Sun.COM 
840*10923SEvan.Yan@Sun.COM 	/* Display results */
841*10923SEvan.Yan@Sun.COM 	print_error(rv);
842*10923SEvan.Yan@Sun.COM 	if (results) {
843*10923SEvan.Yan@Sun.COM 		(void) hp_traverse(results, NULL, error_cb);
844*10923SEvan.Yan@Sun.COM 		hp_fini(results);
845*10923SEvan.Yan@Sun.COM 	}
846*10923SEvan.Yan@Sun.COM 
847*10923SEvan.Yan@Sun.COM 	/* Discard hotplug information snapshot */
848*10923SEvan.Yan@Sun.COM 	hp_fini(root);
849*10923SEvan.Yan@Sun.COM 
850*10923SEvan.Yan@Sun.COM 	return (rv);
851*10923SEvan.Yan@Sun.COM }
852*10923SEvan.Yan@Sun.COM 
853*10923SEvan.Yan@Sun.COM /*
854*10923SEvan.Yan@Sun.COM  * parse_common()
855*10923SEvan.Yan@Sun.COM  *
856*10923SEvan.Yan@Sun.COM  *	Parse command line options that are common to the
857*10923SEvan.Yan@Sun.COM  *	entire program, and to each of its subcommands.
858*10923SEvan.Yan@Sun.COM  */
859*10923SEvan.Yan@Sun.COM static void
parse_common(int argc,char * argv[],const char * usage_str)860*10923SEvan.Yan@Sun.COM parse_common(int argc, char *argv[], const char *usage_str)
861*10923SEvan.Yan@Sun.COM {
862*10923SEvan.Yan@Sun.COM 	int		opt;
863*10923SEvan.Yan@Sun.COM 	extern int	opterr;
864*10923SEvan.Yan@Sun.COM 	extern int	optind;
865*10923SEvan.Yan@Sun.COM 
866*10923SEvan.Yan@Sun.COM 	/* Turn off error reporting */
867*10923SEvan.Yan@Sun.COM 	opterr = 0;
868*10923SEvan.Yan@Sun.COM 
869*10923SEvan.Yan@Sun.COM 	while ((opt = getopt_clip(argc, argv, "?V", common_opts, NULL)) != -1) {
870*10923SEvan.Yan@Sun.COM 		switch (opt) {
871*10923SEvan.Yan@Sun.COM 		case '?':
872*10923SEvan.Yan@Sun.COM 			if (optopt == '?') {
873*10923SEvan.Yan@Sun.COM 				usage(usage_str);
874*10923SEvan.Yan@Sun.COM 				exit(0);
875*10923SEvan.Yan@Sun.COM 			}
876*10923SEvan.Yan@Sun.COM 			break;
877*10923SEvan.Yan@Sun.COM 		case 'V':
878*10923SEvan.Yan@Sun.COM 			(void) printf(gettext("%s: Version %s\n"),
879*10923SEvan.Yan@Sun.COM 			    prog, version);
880*10923SEvan.Yan@Sun.COM 			exit(0);
881*10923SEvan.Yan@Sun.COM 		default:
882*10923SEvan.Yan@Sun.COM 			break;
883*10923SEvan.Yan@Sun.COM 		}
884*10923SEvan.Yan@Sun.COM 	}
885*10923SEvan.Yan@Sun.COM 
886*10923SEvan.Yan@Sun.COM 	/* Reset option index */
887*10923SEvan.Yan@Sun.COM 	optind = 1;
888*10923SEvan.Yan@Sun.COM }
889*10923SEvan.Yan@Sun.COM 
890*10923SEvan.Yan@Sun.COM /*
891*10923SEvan.Yan@Sun.COM  * parse_flags()
892*10923SEvan.Yan@Sun.COM  *
893*10923SEvan.Yan@Sun.COM  *	Parse command line flags common to all downward state
894*10923SEvan.Yan@Sun.COM  *	change operations (offline, disable, poweoff).
895*10923SEvan.Yan@Sun.COM  */
896*10923SEvan.Yan@Sun.COM static void
parse_flags(int argc,char * argv[],int * flagsp,const char * usage_str)897*10923SEvan.Yan@Sun.COM parse_flags(int argc, char *argv[], int *flagsp, const char *usage_str)
898*10923SEvan.Yan@Sun.COM {
899*10923SEvan.Yan@Sun.COM 	int	opt;
900*10923SEvan.Yan@Sun.COM 	int	flags = 0;
901*10923SEvan.Yan@Sun.COM 
902*10923SEvan.Yan@Sun.COM 	while ((opt = getopt_clip(argc, argv, "fq", flag_opts, NULL)) != -1) {
903*10923SEvan.Yan@Sun.COM 		switch (opt) {
904*10923SEvan.Yan@Sun.COM 		case 'f':
905*10923SEvan.Yan@Sun.COM 			flags |= HPFORCE;
906*10923SEvan.Yan@Sun.COM 			break;
907*10923SEvan.Yan@Sun.COM 		case 'q':
908*10923SEvan.Yan@Sun.COM 			flags |= HPQUERY;
909*10923SEvan.Yan@Sun.COM 			break;
910*10923SEvan.Yan@Sun.COM 		default:
911*10923SEvan.Yan@Sun.COM 			bad_option(opt, optopt, usage_str);
912*10923SEvan.Yan@Sun.COM 			break;
913*10923SEvan.Yan@Sun.COM 		}
914*10923SEvan.Yan@Sun.COM 	}
915*10923SEvan.Yan@Sun.COM 
916*10923SEvan.Yan@Sun.COM 	*flagsp = flags;
917*10923SEvan.Yan@Sun.COM }
918*10923SEvan.Yan@Sun.COM 
919*10923SEvan.Yan@Sun.COM /*
920*10923SEvan.Yan@Sun.COM  * parse_options()
921*10923SEvan.Yan@Sun.COM  *
922*10923SEvan.Yan@Sun.COM  *	Parse command line options common to the bus private set and
923*10923SEvan.Yan@Sun.COM  *	get subcommands.
924*10923SEvan.Yan@Sun.COM  */
925*10923SEvan.Yan@Sun.COM static void
parse_options(int argc,char * argv[],char ** optionsp,const char * usage_str)926*10923SEvan.Yan@Sun.COM parse_options(int argc, char *argv[], char **optionsp, const char *usage_str)
927*10923SEvan.Yan@Sun.COM {
928*10923SEvan.Yan@Sun.COM 	int	opt;
929*10923SEvan.Yan@Sun.COM 
930*10923SEvan.Yan@Sun.COM 	while ((opt = getopt_clip(argc, argv, "o:", private_opts,
931*10923SEvan.Yan@Sun.COM 	    NULL)) != -1) {
932*10923SEvan.Yan@Sun.COM 		switch (opt) {
933*10923SEvan.Yan@Sun.COM 		case 'o':
934*10923SEvan.Yan@Sun.COM 			*optionsp = optarg;
935*10923SEvan.Yan@Sun.COM 			break;
936*10923SEvan.Yan@Sun.COM 		default:
937*10923SEvan.Yan@Sun.COM 			bad_option(opt, optopt, usage_str);
938*10923SEvan.Yan@Sun.COM 			break;
939*10923SEvan.Yan@Sun.COM 		}
940*10923SEvan.Yan@Sun.COM 	}
941*10923SEvan.Yan@Sun.COM }
942*10923SEvan.Yan@Sun.COM 
943*10923SEvan.Yan@Sun.COM /*
944*10923SEvan.Yan@Sun.COM  * parse_target()
945*10923SEvan.Yan@Sun.COM  *
946*10923SEvan.Yan@Sun.COM  *	Parse the target path and connection name from the command line.
947*10923SEvan.Yan@Sun.COM  */
948*10923SEvan.Yan@Sun.COM static void
parse_target(int argc,char * argv[],char ** pathp,char ** connectionp,const char * usage_str)949*10923SEvan.Yan@Sun.COM parse_target(int argc, char *argv[], char **pathp, char **connectionp,
950*10923SEvan.Yan@Sun.COM     const char *usage_str)
951*10923SEvan.Yan@Sun.COM {
952*10923SEvan.Yan@Sun.COM 	extern int	optind;
953*10923SEvan.Yan@Sun.COM 
954*10923SEvan.Yan@Sun.COM 	if (optind < argc)
955*10923SEvan.Yan@Sun.COM 		*pathp = argv[optind++];
956*10923SEvan.Yan@Sun.COM 
957*10923SEvan.Yan@Sun.COM 	if (optind < argc)
958*10923SEvan.Yan@Sun.COM 		*connectionp = argv[optind++];
959*10923SEvan.Yan@Sun.COM 
960*10923SEvan.Yan@Sun.COM 	if (optind < argc) {
961*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: too many arguments.\n"));
962*10923SEvan.Yan@Sun.COM 		usage(usage_str);
963*10923SEvan.Yan@Sun.COM 		exit(EINVAL);
964*10923SEvan.Yan@Sun.COM 	}
965*10923SEvan.Yan@Sun.COM }
966*10923SEvan.Yan@Sun.COM 
967*10923SEvan.Yan@Sun.COM /*
968*10923SEvan.Yan@Sun.COM  * bad_option()
969*10923SEvan.Yan@Sun.COM  *
970*10923SEvan.Yan@Sun.COM  *	Routine to handle bad command line options.
971*10923SEvan.Yan@Sun.COM  */
972*10923SEvan.Yan@Sun.COM static void
bad_option(int opt,int optopt,const char * usage_str)973*10923SEvan.Yan@Sun.COM bad_option(int opt, int optopt, const char *usage_str)
974*10923SEvan.Yan@Sun.COM {
975*10923SEvan.Yan@Sun.COM 	switch (opt) {
976*10923SEvan.Yan@Sun.COM 	case ':':
977*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
978*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: option '%c' requires an argument.\n"),
979*10923SEvan.Yan@Sun.COM 		    optopt);
980*10923SEvan.Yan@Sun.COM 		break;
981*10923SEvan.Yan@Sun.COM 	default:
982*10923SEvan.Yan@Sun.COM 		if (optopt == '?') {
983*10923SEvan.Yan@Sun.COM 			usage(usage_str);
984*10923SEvan.Yan@Sun.COM 			exit(EXIT_OK);
985*10923SEvan.Yan@Sun.COM 		}
986*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
987*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: unrecognized option '%c'.\n"), optopt);
988*10923SEvan.Yan@Sun.COM 		break;
989*10923SEvan.Yan@Sun.COM 	}
990*10923SEvan.Yan@Sun.COM 
991*10923SEvan.Yan@Sun.COM 	usage(usage_str);
992*10923SEvan.Yan@Sun.COM 
993*10923SEvan.Yan@Sun.COM 	exit(EXIT_EINVAL);
994*10923SEvan.Yan@Sun.COM }
995*10923SEvan.Yan@Sun.COM 
996*10923SEvan.Yan@Sun.COM /*
997*10923SEvan.Yan@Sun.COM  * usage()
998*10923SEvan.Yan@Sun.COM  *
999*10923SEvan.Yan@Sun.COM  *	Display general usage of the command.  Including
1000*10923SEvan.Yan@Sun.COM  *	the usage synopsis of each defined subcommand.
1001*10923SEvan.Yan@Sun.COM  */
1002*10923SEvan.Yan@Sun.COM static void
usage(const char * usage_str)1003*10923SEvan.Yan@Sun.COM usage(const char *usage_str)
1004*10923SEvan.Yan@Sun.COM {
1005*10923SEvan.Yan@Sun.COM 	int	i;
1006*10923SEvan.Yan@Sun.COM 
1007*10923SEvan.Yan@Sun.COM 	if (usage_str != NULL) {
1008*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("Usage:   %s  %s\n\n"),
1009*10923SEvan.Yan@Sun.COM 		    prog, usage_str);
1010*10923SEvan.Yan@Sun.COM 		return;
1011*10923SEvan.Yan@Sun.COM 	}
1012*10923SEvan.Yan@Sun.COM 
1013*10923SEvan.Yan@Sun.COM 	(void) fprintf(stderr, gettext("Usage:  %s  <subcommand> [<args>]\n\n"),
1014*10923SEvan.Yan@Sun.COM 	    prog);
1015*10923SEvan.Yan@Sun.COM 
1016*10923SEvan.Yan@Sun.COM 	(void) fprintf(stderr, gettext("Subcommands:\n\n"));
1017*10923SEvan.Yan@Sun.COM 
1018*10923SEvan.Yan@Sun.COM 	for (i = 0; i < (sizeof (subcmds) / sizeof (subcmd_t)); i++)
1019*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, "   %s\n\n", subcmds[i].usage_str);
1020*10923SEvan.Yan@Sun.COM }
1021*10923SEvan.Yan@Sun.COM 
1022*10923SEvan.Yan@Sun.COM /*
1023*10923SEvan.Yan@Sun.COM  * list_cb()
1024*10923SEvan.Yan@Sun.COM  *
1025*10923SEvan.Yan@Sun.COM  *	Callback function for hp_traverse(), to display nodes
1026*10923SEvan.Yan@Sun.COM  *	of a hotplug information snapshot.  (Short version.)
1027*10923SEvan.Yan@Sun.COM  */
1028*10923SEvan.Yan@Sun.COM /*ARGSUSED*/
1029*10923SEvan.Yan@Sun.COM static int
list_cb(hp_node_t node,void * arg)1030*10923SEvan.Yan@Sun.COM list_cb(hp_node_t node, void *arg)
1031*10923SEvan.Yan@Sun.COM {
1032*10923SEvan.Yan@Sun.COM 	hp_node_t	parent;
1033*10923SEvan.Yan@Sun.COM 
1034*10923SEvan.Yan@Sun.COM 	/* Indent */
1035*10923SEvan.Yan@Sun.COM 	for (parent = hp_parent(node); parent; parent = hp_parent(parent))
1036*10923SEvan.Yan@Sun.COM 		if (hp_type(parent) == HP_NODE_DEVICE)
1037*10923SEvan.Yan@Sun.COM 			(void) printf("     ");
1038*10923SEvan.Yan@Sun.COM 
1039*10923SEvan.Yan@Sun.COM 	switch (hp_type(node)) {
1040*10923SEvan.Yan@Sun.COM 	case HP_NODE_DEVICE:
1041*10923SEvan.Yan@Sun.COM 		(void) printf("%s\n", hp_name(node));
1042*10923SEvan.Yan@Sun.COM 		break;
1043*10923SEvan.Yan@Sun.COM 
1044*10923SEvan.Yan@Sun.COM 	case HP_NODE_CONNECTOR:
1045*10923SEvan.Yan@Sun.COM 		(void) printf("[%s]", hp_name(node));
1046*10923SEvan.Yan@Sun.COM 		(void) printf("  (%s)", state_itoa(hp_state(node)));
1047*10923SEvan.Yan@Sun.COM 		(void) printf("\n");
1048*10923SEvan.Yan@Sun.COM 		break;
1049*10923SEvan.Yan@Sun.COM 
1050*10923SEvan.Yan@Sun.COM 	case HP_NODE_PORT:
1051*10923SEvan.Yan@Sun.COM 		(void) printf("<%s>", hp_name(node));
1052*10923SEvan.Yan@Sun.COM 		(void) printf("  (%s)", state_itoa(hp_state(node)));
1053*10923SEvan.Yan@Sun.COM 		(void) printf("\n");
1054*10923SEvan.Yan@Sun.COM 		break;
1055*10923SEvan.Yan@Sun.COM 
1056*10923SEvan.Yan@Sun.COM 	case HP_NODE_USAGE:
1057*10923SEvan.Yan@Sun.COM 		(void) printf("{ %s }\n", hp_usage(node));
1058*10923SEvan.Yan@Sun.COM 		break;
1059*10923SEvan.Yan@Sun.COM 	}
1060*10923SEvan.Yan@Sun.COM 
1061*10923SEvan.Yan@Sun.COM 	return (HP_WALK_CONTINUE);
1062*10923SEvan.Yan@Sun.COM }
1063*10923SEvan.Yan@Sun.COM 
1064*10923SEvan.Yan@Sun.COM /*
1065*10923SEvan.Yan@Sun.COM  * list_long_cb()
1066*10923SEvan.Yan@Sun.COM  *
1067*10923SEvan.Yan@Sun.COM  *	Callback function for hp_traverse(), to display nodes
1068*10923SEvan.Yan@Sun.COM  *	of a hotplug information snapshot.  (Long version.)
1069*10923SEvan.Yan@Sun.COM  */
1070*10923SEvan.Yan@Sun.COM /*ARGSUSED*/
1071*10923SEvan.Yan@Sun.COM static int
list_long_cb(hp_node_t node,void * arg)1072*10923SEvan.Yan@Sun.COM list_long_cb(hp_node_t node, void *arg)
1073*10923SEvan.Yan@Sun.COM {
1074*10923SEvan.Yan@Sun.COM 	char	path[MAXPATHLEN];
1075*10923SEvan.Yan@Sun.COM 	char	connection[MAXPATHLEN];
1076*10923SEvan.Yan@Sun.COM 
1077*10923SEvan.Yan@Sun.COM 	if (hp_type(node) != HP_NODE_USAGE) {
1078*10923SEvan.Yan@Sun.COM 		if (hp_path(node, path, connection) != 0)
1079*10923SEvan.Yan@Sun.COM 			return (HP_WALK_CONTINUE);
1080*10923SEvan.Yan@Sun.COM 		(void) printf("%s", path);
1081*10923SEvan.Yan@Sun.COM 	}
1082*10923SEvan.Yan@Sun.COM 
1083*10923SEvan.Yan@Sun.COM 	switch (hp_type(node)) {
1084*10923SEvan.Yan@Sun.COM 	case HP_NODE_CONNECTOR:
1085*10923SEvan.Yan@Sun.COM 		(void) printf(" [%s]", connection);
1086*10923SEvan.Yan@Sun.COM 		(void) printf(" (%s)", state_itoa(hp_state(node)));
1087*10923SEvan.Yan@Sun.COM 		break;
1088*10923SEvan.Yan@Sun.COM 
1089*10923SEvan.Yan@Sun.COM 	case HP_NODE_PORT:
1090*10923SEvan.Yan@Sun.COM 		(void) printf(" <%s>", connection);
1091*10923SEvan.Yan@Sun.COM 		(void) printf(" (%s)", state_itoa(hp_state(node)));
1092*10923SEvan.Yan@Sun.COM 		break;
1093*10923SEvan.Yan@Sun.COM 
1094*10923SEvan.Yan@Sun.COM 	case HP_NODE_USAGE:
1095*10923SEvan.Yan@Sun.COM 		(void) printf("    { %s }", hp_usage(node));
1096*10923SEvan.Yan@Sun.COM 		break;
1097*10923SEvan.Yan@Sun.COM 	}
1098*10923SEvan.Yan@Sun.COM 
1099*10923SEvan.Yan@Sun.COM 	(void) printf("\n");
1100*10923SEvan.Yan@Sun.COM 
1101*10923SEvan.Yan@Sun.COM 	return (HP_WALK_CONTINUE);
1102*10923SEvan.Yan@Sun.COM }
1103*10923SEvan.Yan@Sun.COM 
1104*10923SEvan.Yan@Sun.COM /*
1105*10923SEvan.Yan@Sun.COM  * error_cb()
1106*10923SEvan.Yan@Sun.COM  *
1107*10923SEvan.Yan@Sun.COM  *	Callback function for hp_traverse(), to display
1108*10923SEvan.Yan@Sun.COM  *	error results from a state change operation.
1109*10923SEvan.Yan@Sun.COM  */
1110*10923SEvan.Yan@Sun.COM /*ARGSUSED*/
1111*10923SEvan.Yan@Sun.COM static int
error_cb(hp_node_t node,void * arg)1112*10923SEvan.Yan@Sun.COM error_cb(hp_node_t node, void *arg)
1113*10923SEvan.Yan@Sun.COM {
1114*10923SEvan.Yan@Sun.COM 	hp_node_t	child;
1115*10923SEvan.Yan@Sun.COM 	char		*usage_str;
1116*10923SEvan.Yan@Sun.COM 	static char	path[MAXPATHLEN];
1117*10923SEvan.Yan@Sun.COM 	static char	connection[MAXPATHLEN];
1118*10923SEvan.Yan@Sun.COM 
1119*10923SEvan.Yan@Sun.COM 	if (((child = hp_child(node)) != NULL) &&
1120*10923SEvan.Yan@Sun.COM 	    (hp_type(child) == HP_NODE_USAGE)) {
1121*10923SEvan.Yan@Sun.COM 		if (hp_path(node, path, connection) == 0)
1122*10923SEvan.Yan@Sun.COM 			(void) printf("%s:\n", path);
1123*10923SEvan.Yan@Sun.COM 		return (HP_WALK_CONTINUE);
1124*10923SEvan.Yan@Sun.COM 	}
1125*10923SEvan.Yan@Sun.COM 
1126*10923SEvan.Yan@Sun.COM 	if ((hp_type(node) == HP_NODE_USAGE) &&
1127*10923SEvan.Yan@Sun.COM 	    ((usage_str = hp_usage(node)) != NULL))
1128*10923SEvan.Yan@Sun.COM 		(void) printf("   { %s }\n", usage_str);
1129*10923SEvan.Yan@Sun.COM 
1130*10923SEvan.Yan@Sun.COM 	return (HP_WALK_CONTINUE);
1131*10923SEvan.Yan@Sun.COM }
1132*10923SEvan.Yan@Sun.COM 
1133*10923SEvan.Yan@Sun.COM /*
1134*10923SEvan.Yan@Sun.COM  * print_options()
1135*10923SEvan.Yan@Sun.COM  *
1136*10923SEvan.Yan@Sun.COM  *	Parse and display bus private options.  The options are
1137*10923SEvan.Yan@Sun.COM  *	formatted as a string which conforms to the getsubopt(3C)
1138*10923SEvan.Yan@Sun.COM  *	format.  This routine only splits the string elements as
1139*10923SEvan.Yan@Sun.COM  *	separated by commas, and displays each portion on its own
1140*10923SEvan.Yan@Sun.COM  *	separate line of output.
1141*10923SEvan.Yan@Sun.COM  */
1142*10923SEvan.Yan@Sun.COM static void
print_options(const char * options)1143*10923SEvan.Yan@Sun.COM print_options(const char *options)
1144*10923SEvan.Yan@Sun.COM {
1145*10923SEvan.Yan@Sun.COM 	char	*buf, *curr, *next;
1146*10923SEvan.Yan@Sun.COM 	size_t	len;
1147*10923SEvan.Yan@Sun.COM 
1148*10923SEvan.Yan@Sun.COM 	/* Do nothing if options string is empty */
1149*10923SEvan.Yan@Sun.COM 	if ((len = strlen(options)) == 0)
1150*10923SEvan.Yan@Sun.COM 		return;
1151*10923SEvan.Yan@Sun.COM 
1152*10923SEvan.Yan@Sun.COM 	/* To avoid modifying the input string, make a copy on the stack */
1153*10923SEvan.Yan@Sun.COM 	if ((buf = (char *)alloca(len + 1)) == NULL) {
1154*10923SEvan.Yan@Sun.COM 		(void) printf("%s\n", options);
1155*10923SEvan.Yan@Sun.COM 		return;
1156*10923SEvan.Yan@Sun.COM 	}
1157*10923SEvan.Yan@Sun.COM 	(void) strlcpy(buf, options, len + 1);
1158*10923SEvan.Yan@Sun.COM 
1159*10923SEvan.Yan@Sun.COM 	/* Iterate through each comma-separated name/value pair */
1160*10923SEvan.Yan@Sun.COM 	curr = buf;
1161*10923SEvan.Yan@Sun.COM 	do {
1162*10923SEvan.Yan@Sun.COM 		if ((next = strchr(curr, ',')) != NULL) {
1163*10923SEvan.Yan@Sun.COM 			*next = '\0';
1164*10923SEvan.Yan@Sun.COM 			next++;
1165*10923SEvan.Yan@Sun.COM 		}
1166*10923SEvan.Yan@Sun.COM 		(void) printf("%s\n", curr);
1167*10923SEvan.Yan@Sun.COM 	} while ((curr = next) != NULL);
1168*10923SEvan.Yan@Sun.COM }
1169*10923SEvan.Yan@Sun.COM 
1170*10923SEvan.Yan@Sun.COM /*
1171*10923SEvan.Yan@Sun.COM  * print_error()
1172*10923SEvan.Yan@Sun.COM  *
1173*10923SEvan.Yan@Sun.COM  *	Common routine to print error numbers in an appropriate way.
1174*10923SEvan.Yan@Sun.COM  *	Prints nothing if error code is 0.
1175*10923SEvan.Yan@Sun.COM  */
1176*10923SEvan.Yan@Sun.COM static void
print_error(int error)1177*10923SEvan.Yan@Sun.COM print_error(int error)
1178*10923SEvan.Yan@Sun.COM {
1179*10923SEvan.Yan@Sun.COM 	switch (error) {
1180*10923SEvan.Yan@Sun.COM 	case 0:
1181*10923SEvan.Yan@Sun.COM 		/* No error */
1182*10923SEvan.Yan@Sun.COM 		return;
1183*10923SEvan.Yan@Sun.COM 	case EACCES:
1184*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1185*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: operation not authorized.\n"));
1186*10923SEvan.Yan@Sun.COM 		break;
1187*10923SEvan.Yan@Sun.COM 	case EBADF:
1188*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1189*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: hotplug service is not available.\n"));
1190*10923SEvan.Yan@Sun.COM 		break;
1191*10923SEvan.Yan@Sun.COM 	case EBUSY:
1192*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1193*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: devices or resources are busy.\n"));
1194*10923SEvan.Yan@Sun.COM 		break;
1195*10923SEvan.Yan@Sun.COM 	case EEXIST:
1196*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1197*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: resource already exists.\n"));
1198*10923SEvan.Yan@Sun.COM 		break;
1199*10923SEvan.Yan@Sun.COM 	case EFAULT:
1200*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1201*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: internal failure in hotplug service.\n"));
1202*10923SEvan.Yan@Sun.COM 		break;
1203*10923SEvan.Yan@Sun.COM 	case EINVAL:
1204*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1205*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: invalid arguments.\n"));
1206*10923SEvan.Yan@Sun.COM 		break;
1207*10923SEvan.Yan@Sun.COM 	case ENOENT:
1208*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1209*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: there are no connections to display.\n"));
1210*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1211*10923SEvan.Yan@Sun.COM 		    gettext("(See hotplug(1m) for more information.)\n"));
1212*10923SEvan.Yan@Sun.COM 		break;
1213*10923SEvan.Yan@Sun.COM 	case ENXIO:
1214*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1215*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: no such path or connection.\n"));
1216*10923SEvan.Yan@Sun.COM 		break;
1217*10923SEvan.Yan@Sun.COM 	case ENOMEM:
1218*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1219*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: not enough memory.\n"));
1220*10923SEvan.Yan@Sun.COM 		break;
1221*10923SEvan.Yan@Sun.COM 	case ENOTSUP:
1222*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1223*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: operation not supported.\n"));
1224*10923SEvan.Yan@Sun.COM 		break;
1225*10923SEvan.Yan@Sun.COM 	case EIO:
1226*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr,
1227*10923SEvan.Yan@Sun.COM 		    gettext("ERROR: hardware or driver specific failure.\n"));
1228*10923SEvan.Yan@Sun.COM 		break;
1229*10923SEvan.Yan@Sun.COM 	default:
1230*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, gettext("ERROR: operation failed: %s\n"),
1231*10923SEvan.Yan@Sun.COM 		    strerror(error));
1232*10923SEvan.Yan@Sun.COM 		break;
1233*10923SEvan.Yan@Sun.COM 	}
1234*10923SEvan.Yan@Sun.COM }
1235*10923SEvan.Yan@Sun.COM 
1236*10923SEvan.Yan@Sun.COM /*
1237*10923SEvan.Yan@Sun.COM  * state_atoi()
1238*10923SEvan.Yan@Sun.COM  *
1239*10923SEvan.Yan@Sun.COM  *	Convert a hotplug state from a string to an integer.
1240*10923SEvan.Yan@Sun.COM  */
1241*10923SEvan.Yan@Sun.COM static int
state_atoi(char * state)1242*10923SEvan.Yan@Sun.COM state_atoi(char *state)
1243*10923SEvan.Yan@Sun.COM {
1244*10923SEvan.Yan@Sun.COM 	int	i;
1245*10923SEvan.Yan@Sun.COM 
1246*10923SEvan.Yan@Sun.COM 	for (i = 0; hpstates[i].state_str != NULL; i++)
1247*10923SEvan.Yan@Sun.COM 		if (strcasecmp(state, hpstates[i].state_str) == 0)
1248*10923SEvan.Yan@Sun.COM 			return (hpstates[i].state);
1249*10923SEvan.Yan@Sun.COM 
1250*10923SEvan.Yan@Sun.COM 	return (-1);
1251*10923SEvan.Yan@Sun.COM }
1252*10923SEvan.Yan@Sun.COM 
1253*10923SEvan.Yan@Sun.COM /*
1254*10923SEvan.Yan@Sun.COM  * state_itoa()
1255*10923SEvan.Yan@Sun.COM  *
1256*10923SEvan.Yan@Sun.COM  *	Convert a hotplug state from an integer to a string.
1257*10923SEvan.Yan@Sun.COM  */
1258*10923SEvan.Yan@Sun.COM static char *
state_itoa(int state)1259*10923SEvan.Yan@Sun.COM state_itoa(int state)
1260*10923SEvan.Yan@Sun.COM {
1261*10923SEvan.Yan@Sun.COM 	static char	unknown[] = "UNKNOWN";
1262*10923SEvan.Yan@Sun.COM 	int		i;
1263*10923SEvan.Yan@Sun.COM 
1264*10923SEvan.Yan@Sun.COM 	for (i = 0; hpstates[i].state_str != NULL; i++)
1265*10923SEvan.Yan@Sun.COM 		if (state == hpstates[i].state)
1266*10923SEvan.Yan@Sun.COM 			return (hpstates[i].state_str);
1267*10923SEvan.Yan@Sun.COM 
1268*10923SEvan.Yan@Sun.COM 	return (unknown);
1269*10923SEvan.Yan@Sun.COM }
1270*10923SEvan.Yan@Sun.COM 
1271*10923SEvan.Yan@Sun.COM /*
1272*10923SEvan.Yan@Sun.COM  * valid_target()
1273*10923SEvan.Yan@Sun.COM  *
1274*10923SEvan.Yan@Sun.COM  *	Check if a state is a valid target for a changestate command.
1275*10923SEvan.Yan@Sun.COM  */
1276*10923SEvan.Yan@Sun.COM static short
valid_target(int state)1277*10923SEvan.Yan@Sun.COM valid_target(int state)
1278*10923SEvan.Yan@Sun.COM {
1279*10923SEvan.Yan@Sun.COM 	int	i;
1280*10923SEvan.Yan@Sun.COM 
1281*10923SEvan.Yan@Sun.COM 	for (i = 0; hpstates[i].state_str != NULL; i++)
1282*10923SEvan.Yan@Sun.COM 		if (state == hpstates[i].state)
1283*10923SEvan.Yan@Sun.COM 			return (hpstates[i].valid_target);
1284*10923SEvan.Yan@Sun.COM 
1285*10923SEvan.Yan@Sun.COM 	return (0);
1286*10923SEvan.Yan@Sun.COM }
1287