1993e3fafSRobert Mustacchi /*
2993e3fafSRobert Mustacchi * This file and its contents are supplied under the terms of the
3993e3fafSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4993e3fafSRobert Mustacchi * You may only use this file in accordance with the terms of version
5993e3fafSRobert Mustacchi * 1.0 of the CDDL.
6993e3fafSRobert Mustacchi *
7993e3fafSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8993e3fafSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9993e3fafSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10993e3fafSRobert Mustacchi */
11993e3fafSRobert Mustacchi
12993e3fafSRobert Mustacchi /*
13993e3fafSRobert Mustacchi * Copyright 2016 Joyent, Inc.
14993e3fafSRobert Mustacchi */
15993e3fafSRobert Mustacchi
16993e3fafSRobert Mustacchi /*
17993e3fafSRobert Mustacchi * This is a private utility that combines a number of minor debugging routines
18993e3fafSRobert Mustacchi * for xhci.
19993e3fafSRobert Mustacchi */
20993e3fafSRobert Mustacchi
21993e3fafSRobert Mustacchi #include <stdio.h>
22993e3fafSRobert Mustacchi #include <stdarg.h>
23993e3fafSRobert Mustacchi #include <stdlib.h>
24993e3fafSRobert Mustacchi #include <unistd.h>
25993e3fafSRobert Mustacchi #include <err.h>
26993e3fafSRobert Mustacchi #include <string.h>
27993e3fafSRobert Mustacchi #include <sys/types.h>
28993e3fafSRobert Mustacchi #include <sys/stat.h>
29993e3fafSRobert Mustacchi #include <fcntl.h>
30993e3fafSRobert Mustacchi #include <libdevinfo.h>
31993e3fafSRobert Mustacchi #include <sys/usb/hcd/xhci/xhci_ioctl.h>
32993e3fafSRobert Mustacchi #include <sys/usb/hcd/xhci/xhcireg.h>
33993e3fafSRobert Mustacchi
34993e3fafSRobert Mustacchi static char *xp_devpath = NULL;
35993e3fafSRobert Mustacchi static int xp_npaths;
36993e3fafSRobert Mustacchi static const char *xp_path;
37993e3fafSRobert Mustacchi static const char *xp_state = NULL;
38993e3fafSRobert Mustacchi static uint32_t xp_port;
39993e3fafSRobert Mustacchi static boolean_t xp_verbose = B_FALSE;
40993e3fafSRobert Mustacchi static boolean_t xp_clear = B_FALSE;
41993e3fafSRobert Mustacchi static boolean_t xp_list = B_FALSE;
42993e3fafSRobert Mustacchi extern const char *__progname;
43993e3fafSRobert Mustacchi
44993e3fafSRobert Mustacchi static int
xp_usage(const char * format,...)45993e3fafSRobert Mustacchi xp_usage(const char *format, ...)
46993e3fafSRobert Mustacchi {
47993e3fafSRobert Mustacchi if (format != NULL) {
48993e3fafSRobert Mustacchi va_list alist;
49993e3fafSRobert Mustacchi
50993e3fafSRobert Mustacchi va_start(alist, format);
51993e3fafSRobert Mustacchi vwarnx(format, alist);
52993e3fafSRobert Mustacchi va_end(alist);
53993e3fafSRobert Mustacchi }
54993e3fafSRobert Mustacchi
55993e3fafSRobert Mustacchi (void) fprintf(stderr, "usage: %s [-l] [-v] [-c] [-d path] [-p port] "
56993e3fafSRobert Mustacchi "[-s state]\n", __progname);
57993e3fafSRobert Mustacchi return (2);
58993e3fafSRobert Mustacchi }
59993e3fafSRobert Mustacchi
60993e3fafSRobert Mustacchi static const char *xp_pls_strings[] = {
61993e3fafSRobert Mustacchi "U0",
62993e3fafSRobert Mustacchi "U1",
63993e3fafSRobert Mustacchi "U2",
64993e3fafSRobert Mustacchi "U3 (suspended)",
65993e3fafSRobert Mustacchi "Disabled",
66993e3fafSRobert Mustacchi "RxDetect",
67993e3fafSRobert Mustacchi "Inactive",
68993e3fafSRobert Mustacchi "Polling",
69993e3fafSRobert Mustacchi "Recovery",
70993e3fafSRobert Mustacchi "Hot Reset",
71993e3fafSRobert Mustacchi "Compliance Mode",
72993e3fafSRobert Mustacchi "Test Mode",
73993e3fafSRobert Mustacchi "Reserved",
74993e3fafSRobert Mustacchi "Reserved",
75993e3fafSRobert Mustacchi "Reserved",
76993e3fafSRobert Mustacchi "Resume",
77993e3fafSRobert Mustacchi NULL
78993e3fafSRobert Mustacchi };
79993e3fafSRobert Mustacchi
80993e3fafSRobert Mustacchi static void
xp_dump_verbose(uint32_t portsc)81993e3fafSRobert Mustacchi xp_dump_verbose(uint32_t portsc)
82993e3fafSRobert Mustacchi {
83993e3fafSRobert Mustacchi if (portsc & XHCI_PS_CCS)
84993e3fafSRobert Mustacchi (void) printf("\t\t\tCCS\n");
85993e3fafSRobert Mustacchi if (portsc & XHCI_PS_PED)
86993e3fafSRobert Mustacchi (void) printf("\t\t\tPED\n");
87993e3fafSRobert Mustacchi if (portsc & XHCI_PS_OCA)
88993e3fafSRobert Mustacchi (void) printf("\t\t\tOCA\n");
89993e3fafSRobert Mustacchi if (portsc & XHCI_PS_PR)
90993e3fafSRobert Mustacchi (void) printf("\t\t\tPR\n");
91993e3fafSRobert Mustacchi if (portsc & XHCI_PS_PP) {
92993e3fafSRobert Mustacchi (void) printf("\t\t\tPLS: %s (%d)\n",
93993e3fafSRobert Mustacchi xp_pls_strings[XHCI_PS_PLS_GET(portsc)],
94993e3fafSRobert Mustacchi XHCI_PS_PLS_GET(portsc));
95993e3fafSRobert Mustacchi (void) printf("\t\t\tPP\n");
96993e3fafSRobert Mustacchi } else {
97993e3fafSRobert Mustacchi (void) printf("\t\t\tPLS: undefined (No PP)\n");
98993e3fafSRobert Mustacchi }
99993e3fafSRobert Mustacchi
100993e3fafSRobert Mustacchi if (XHCI_PS_SPEED_GET(portsc) != 0) {
101993e3fafSRobert Mustacchi (void) printf("\t\t\tPort Speed: ");
102993e3fafSRobert Mustacchi switch (XHCI_PS_SPEED_GET(portsc)) {
103993e3fafSRobert Mustacchi case 0:
104993e3fafSRobert Mustacchi (void) printf("Undefined ");
105993e3fafSRobert Mustacchi break;
106993e3fafSRobert Mustacchi case XHCI_SPEED_FULL:
107993e3fafSRobert Mustacchi (void) printf("Full ");
108993e3fafSRobert Mustacchi break;
109993e3fafSRobert Mustacchi case XHCI_SPEED_LOW:
110993e3fafSRobert Mustacchi (void) printf("Low ");
111993e3fafSRobert Mustacchi break;
112993e3fafSRobert Mustacchi case XHCI_SPEED_HIGH:
113993e3fafSRobert Mustacchi (void) printf("High ");
114993e3fafSRobert Mustacchi break;
115993e3fafSRobert Mustacchi case XHCI_SPEED_SUPER:
116993e3fafSRobert Mustacchi (void) printf("Super ");
117993e3fafSRobert Mustacchi break;
118993e3fafSRobert Mustacchi default:
119993e3fafSRobert Mustacchi (void) printf("Unknown ");
120993e3fafSRobert Mustacchi break;
121993e3fafSRobert Mustacchi }
122993e3fafSRobert Mustacchi (void) printf("(%d)\n", XHCI_PS_SPEED_GET(portsc));
123993e3fafSRobert Mustacchi }
124993e3fafSRobert Mustacchi if (XHCI_PS_PIC_GET(portsc) != 0)
125993e3fafSRobert Mustacchi (void) printf("\t\t\tPIC: %d\n", XHCI_PS_PIC_GET(portsc));
126993e3fafSRobert Mustacchi
127993e3fafSRobert Mustacchi if (portsc & XHCI_PS_LWS)
128993e3fafSRobert Mustacchi (void) printf("\t\t\tLWS\n");
129993e3fafSRobert Mustacchi if (portsc & XHCI_PS_CSC)
130993e3fafSRobert Mustacchi (void) printf("\t\t\tCSC\n");
131993e3fafSRobert Mustacchi if (portsc & XHCI_PS_PEC)
132993e3fafSRobert Mustacchi (void) printf("\t\t\tPEC\n");
133993e3fafSRobert Mustacchi if (portsc & XHCI_PS_WRC)
134993e3fafSRobert Mustacchi (void) printf("\t\t\tWRC\n");
135993e3fafSRobert Mustacchi if (portsc & XHCI_PS_OCC)
136993e3fafSRobert Mustacchi (void) printf("\t\t\tOCC\n");
137993e3fafSRobert Mustacchi if (portsc & XHCI_PS_PRC)
138993e3fafSRobert Mustacchi (void) printf("\t\t\tPRC\n");
139993e3fafSRobert Mustacchi if (portsc & XHCI_PS_PLC)
140993e3fafSRobert Mustacchi (void) printf("\t\t\tPLC\n");
141993e3fafSRobert Mustacchi if (portsc & XHCI_PS_CEC)
142993e3fafSRobert Mustacchi (void) printf("\t\t\tCEC\n");
143993e3fafSRobert Mustacchi if (portsc & XHCI_PS_CAS)
144993e3fafSRobert Mustacchi (void) printf("\t\t\tCAS\n");
145993e3fafSRobert Mustacchi if (portsc & XHCI_PS_WCE)
146993e3fafSRobert Mustacchi (void) printf("\t\t\tWCE\n");
147993e3fafSRobert Mustacchi if (portsc & XHCI_PS_WDE)
148993e3fafSRobert Mustacchi (void) printf("\t\t\tWDE\n");
149993e3fafSRobert Mustacchi if (portsc & XHCI_PS_WOE)
150993e3fafSRobert Mustacchi (void) printf("\t\t\tWOE\n");
151993e3fafSRobert Mustacchi if (portsc & XHCI_PS_DR)
152993e3fafSRobert Mustacchi (void) printf("\t\t\tDR\n");
153993e3fafSRobert Mustacchi if (portsc & XHCI_PS_WPR)
154993e3fafSRobert Mustacchi (void) printf("\t\t\tWPR\n");
155993e3fafSRobert Mustacchi }
156993e3fafSRobert Mustacchi
157993e3fafSRobert Mustacchi static void
xp_dump(const char * path)158993e3fafSRobert Mustacchi xp_dump(const char *path)
159993e3fafSRobert Mustacchi {
160993e3fafSRobert Mustacchi int fd, i;
161993e3fafSRobert Mustacchi xhci_ioctl_portsc_t xhi = { 0 };
162993e3fafSRobert Mustacchi
163993e3fafSRobert Mustacchi fd = open(path, O_RDWR);
164993e3fafSRobert Mustacchi if (fd < 0) {
165993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to open %s", path);
166993e3fafSRobert Mustacchi }
167993e3fafSRobert Mustacchi
168993e3fafSRobert Mustacchi if (ioctl(fd, XHCI_IOCTL_PORTSC, &xhi) != 0)
169993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to get port status");
170993e3fafSRobert Mustacchi
171993e3fafSRobert Mustacchi (void) close(fd);
172993e3fafSRobert Mustacchi
173993e3fafSRobert Mustacchi for (i = 1; i <= xhi.xhi_nports; i++) {
174993e3fafSRobert Mustacchi if (xp_port != 0 && i != xp_port)
175993e3fafSRobert Mustacchi continue;
176993e3fafSRobert Mustacchi
177993e3fafSRobert Mustacchi (void) printf("port %2d:\t0x%08x\n", i, xhi.xhi_portsc[i]);
178993e3fafSRobert Mustacchi if (xp_verbose == B_TRUE)
179993e3fafSRobert Mustacchi xp_dump_verbose(xhi.xhi_portsc[i]);
180993e3fafSRobert Mustacchi }
181993e3fafSRobert Mustacchi }
182993e3fafSRobert Mustacchi
183993e3fafSRobert Mustacchi static void
xp_set_pls(const char * path,uint32_t port,const char * state)184993e3fafSRobert Mustacchi xp_set_pls(const char *path, uint32_t port, const char *state)
185993e3fafSRobert Mustacchi {
186993e3fafSRobert Mustacchi int fd, i;
187993e3fafSRobert Mustacchi xhci_ioctl_setpls_t xis;
188993e3fafSRobert Mustacchi
189993e3fafSRobert Mustacchi fd = open(path, O_RDWR);
190993e3fafSRobert Mustacchi if (fd < 0) {
191993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to open %s", path);
192993e3fafSRobert Mustacchi }
193993e3fafSRobert Mustacchi
194993e3fafSRobert Mustacchi xis.xis_port = port;
195993e3fafSRobert Mustacchi for (i = 0; xp_pls_strings[i] != NULL; i++) {
196993e3fafSRobert Mustacchi if (strcasecmp(state, xp_pls_strings[i]) == 0)
197993e3fafSRobert Mustacchi break;
198993e3fafSRobert Mustacchi }
199993e3fafSRobert Mustacchi
200993e3fafSRobert Mustacchi if (xp_pls_strings[i] == NULL) {
201993e3fafSRobert Mustacchi errx(EXIT_FAILURE, "unknown state string: %s\n", state);
202993e3fafSRobert Mustacchi }
203993e3fafSRobert Mustacchi
204993e3fafSRobert Mustacchi xis.xis_pls = i;
205993e3fafSRobert Mustacchi (void) printf("setting port %d with pls %d\n", port, xis.xis_pls);
206993e3fafSRobert Mustacchi
207993e3fafSRobert Mustacchi if (ioctl(fd, XHCI_IOCTL_SETPLS, &xis) != 0)
208993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to set port status");
209993e3fafSRobert Mustacchi
210993e3fafSRobert Mustacchi (void) close(fd);
211993e3fafSRobert Mustacchi }
212993e3fafSRobert Mustacchi
213993e3fafSRobert Mustacchi static void
xp_clear_change(const char * path,uint32_t port)214993e3fafSRobert Mustacchi xp_clear_change(const char *path, uint32_t port)
215993e3fafSRobert Mustacchi {
216993e3fafSRobert Mustacchi int fd;
217993e3fafSRobert Mustacchi xhci_ioctl_clear_t xic;
218993e3fafSRobert Mustacchi
219993e3fafSRobert Mustacchi fd = open(path, O_RDWR);
220993e3fafSRobert Mustacchi if (fd < 0) {
221993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to open %s", path);
222993e3fafSRobert Mustacchi }
223993e3fafSRobert Mustacchi
224993e3fafSRobert Mustacchi xic.xic_port = port;
225993e3fafSRobert Mustacchi (void) printf("clearing change bits on port %d\n", port);
226993e3fafSRobert Mustacchi if (ioctl(fd, XHCI_IOCTL_CLEAR, &xic) != 0)
227993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to set port status");
228993e3fafSRobert Mustacchi
229993e3fafSRobert Mustacchi (void) close(fd);
230993e3fafSRobert Mustacchi }
231993e3fafSRobert Mustacchi
232993e3fafSRobert Mustacchi /* ARGSUSED */
233993e3fafSRobert Mustacchi static int
xp_devinfo_cb(di_node_t node,void * arg)234993e3fafSRobert Mustacchi xp_devinfo_cb(di_node_t node, void *arg)
235993e3fafSRobert Mustacchi {
236993e3fafSRobert Mustacchi char *drv;
237993e3fafSRobert Mustacchi di_minor_t minor;
238993e3fafSRobert Mustacchi boolean_t *do_print = arg;
239993e3fafSRobert Mustacchi
240993e3fafSRobert Mustacchi drv = di_driver_name(node);
241993e3fafSRobert Mustacchi if (drv == NULL)
242993e3fafSRobert Mustacchi return (DI_WALK_CONTINUE);
243993e3fafSRobert Mustacchi if (strcmp(drv, "xhci") != 0)
244993e3fafSRobert Mustacchi return (DI_WALK_CONTINUE);
245993e3fafSRobert Mustacchi
246993e3fafSRobert Mustacchi /*
247993e3fafSRobert Mustacchi * We have an instance of the xhci driver. We need to find the minor
248993e3fafSRobert Mustacchi * node for the hubd instance. These are all usually greater than
249993e3fafSRobert Mustacchi * HUBD_IS_ROOT_HUB. However, to avoid hardcoding that here, we instead
250993e3fafSRobert Mustacchi * rely on the fact that the minor node for the actual device has a
251993e3fafSRobert Mustacchi * :hubd as the intance.
252993e3fafSRobert Mustacchi */
253993e3fafSRobert Mustacchi minor = DI_MINOR_NIL;
254993e3fafSRobert Mustacchi while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
255993e3fafSRobert Mustacchi char *mname, *path;
256993e3fafSRobert Mustacchi
257993e3fafSRobert Mustacchi mname = di_minor_name(minor);
258993e3fafSRobert Mustacchi if (mname == NULL)
259993e3fafSRobert Mustacchi continue;
260993e3fafSRobert Mustacchi if (strcmp(mname, "hubd") != 0)
261993e3fafSRobert Mustacchi continue;
262993e3fafSRobert Mustacchi path = di_devfs_minor_path(minor);
263993e3fafSRobert Mustacchi if (*do_print == B_TRUE) {
264993e3fafSRobert Mustacchi (void) printf("/devices%s\n", path);
265993e3fafSRobert Mustacchi di_devfs_path_free(path);
266993e3fafSRobert Mustacchi } else {
267993e3fafSRobert Mustacchi xp_npaths++;
268993e3fafSRobert Mustacchi if (xp_devpath == NULL)
269993e3fafSRobert Mustacchi xp_devpath = path;
270993e3fafSRobert Mustacchi else
271993e3fafSRobert Mustacchi di_devfs_path_free(path);
272993e3fafSRobert Mustacchi }
273993e3fafSRobert Mustacchi }
274993e3fafSRobert Mustacchi
275993e3fafSRobert Mustacchi return (DI_WALK_PRUNECHILD);
276993e3fafSRobert Mustacchi }
277993e3fafSRobert Mustacchi
278993e3fafSRobert Mustacchi /*
279993e3fafSRobert Mustacchi * We need to find all minor nodes of instances of the xhci driver whose name is
280993e3fafSRobert Mustacchi * 'hubd'.
281993e3fafSRobert Mustacchi */
282993e3fafSRobert Mustacchi static void
xp_find_devs(boolean_t print)283993e3fafSRobert Mustacchi xp_find_devs(boolean_t print)
284993e3fafSRobert Mustacchi {
285993e3fafSRobert Mustacchi di_node_t root;
286993e3fafSRobert Mustacchi
287993e3fafSRobert Mustacchi if ((root = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
288993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to initialize devices tree");
289993e3fafSRobert Mustacchi }
290993e3fafSRobert Mustacchi
291993e3fafSRobert Mustacchi if (di_walk_node(root, DI_WALK_CLDFIRST, &print, xp_devinfo_cb) != 0)
292993e3fafSRobert Mustacchi err(EXIT_FAILURE, "failed to walk devices tree");
293993e3fafSRobert Mustacchi }
294993e3fafSRobert Mustacchi
295993e3fafSRobert Mustacchi int
main(int argc,char * argv[])296993e3fafSRobert Mustacchi main(int argc, char *argv[])
297993e3fafSRobert Mustacchi {
298993e3fafSRobert Mustacchi int c;
299993e3fafSRobert Mustacchi char devpath[PATH_MAX];
300993e3fafSRobert Mustacchi
301993e3fafSRobert Mustacchi while ((c = getopt(argc, argv, ":d:vlcp:s:")) != -1) {
302993e3fafSRobert Mustacchi switch (c) {
303993e3fafSRobert Mustacchi case 'c':
304993e3fafSRobert Mustacchi xp_clear = B_TRUE;
305993e3fafSRobert Mustacchi break;
306993e3fafSRobert Mustacchi case 'd':
307993e3fafSRobert Mustacchi xp_path = optarg;
308993e3fafSRobert Mustacchi break;
309993e3fafSRobert Mustacchi case 'l':
310993e3fafSRobert Mustacchi xp_list = B_TRUE;
311993e3fafSRobert Mustacchi break;
312993e3fafSRobert Mustacchi case 'v':
313993e3fafSRobert Mustacchi xp_verbose = B_TRUE;
314993e3fafSRobert Mustacchi break;
315993e3fafSRobert Mustacchi case 'p':
316993e3fafSRobert Mustacchi xp_port = atoi(optarg);
317993e3fafSRobert Mustacchi if (xp_port < 1 || xp_port > XHCI_PORTSC_NPORTS)
318993e3fafSRobert Mustacchi return (xp_usage("invalid port for -p: %d\n",
319993e3fafSRobert Mustacchi optarg));
320993e3fafSRobert Mustacchi break;
321993e3fafSRobert Mustacchi case 's':
322993e3fafSRobert Mustacchi xp_state = optarg;
323993e3fafSRobert Mustacchi break;
324993e3fafSRobert Mustacchi case ':':
325993e3fafSRobert Mustacchi return (xp_usage("-%c requires an operand\n", optopt));
326993e3fafSRobert Mustacchi case '?':
327993e3fafSRobert Mustacchi return (xp_usage("unknown option: -%c\n", optopt));
328993e3fafSRobert Mustacchi default:
329993e3fafSRobert Mustacchi abort();
330993e3fafSRobert Mustacchi }
331993e3fafSRobert Mustacchi }
332993e3fafSRobert Mustacchi
333993e3fafSRobert Mustacchi if (xp_list == B_TRUE && (xp_path != NULL || xp_clear == B_TRUE ||
334993e3fafSRobert Mustacchi xp_port > 0 || xp_state != NULL)) {
335993e3fafSRobert Mustacchi return (xp_usage("-l cannot be used with other options\n"));
336993e3fafSRobert Mustacchi }
337993e3fafSRobert Mustacchi
338993e3fafSRobert Mustacchi if (xp_list == B_TRUE) {
339993e3fafSRobert Mustacchi xp_find_devs(B_TRUE);
340993e3fafSRobert Mustacchi return (0);
341993e3fafSRobert Mustacchi }
342993e3fafSRobert Mustacchi
343993e3fafSRobert Mustacchi if (xp_path == NULL) {
344993e3fafSRobert Mustacchi xp_find_devs(B_FALSE);
345993e3fafSRobert Mustacchi if (xp_npaths == 0) {
346993e3fafSRobert Mustacchi errx(EXIT_FAILURE, "no xhci devices found");
347993e3fafSRobert Mustacchi } else if (xp_npaths > 1) {
348993e3fafSRobert Mustacchi errx(EXIT_FAILURE, "more than one xhci device found, "
349993e3fafSRobert Mustacchi "please specify device with -d, use -l to list");
350993e3fafSRobert Mustacchi }
351993e3fafSRobert Mustacchi if (snprintf(devpath, sizeof (devpath), "/devices/%s",
352993e3fafSRobert Mustacchi xp_devpath) >= sizeof (devpath))
353993e3fafSRobert Mustacchi errx(EXIT_FAILURE, "xhci path found at %s overflows "
354*6b1325cfSRobert Mustacchi "internal device path", xp_devpath);
355993e3fafSRobert Mustacchi di_devfs_path_free(xp_devpath);
356993e3fafSRobert Mustacchi xp_devpath = NULL;
357993e3fafSRobert Mustacchi xp_path = devpath;
358993e3fafSRobert Mustacchi }
359993e3fafSRobert Mustacchi
360993e3fafSRobert Mustacchi if (xp_clear == B_TRUE && xp_state != NULL) {
361993e3fafSRobert Mustacchi return (xp_usage("-c and -s can't be used together\n"));
362993e3fafSRobert Mustacchi }
363993e3fafSRobert Mustacchi
364993e3fafSRobert Mustacchi if (xp_state != NULL) {
365993e3fafSRobert Mustacchi xp_set_pls(xp_path, xp_port, xp_state);
366993e3fafSRobert Mustacchi } else if (xp_clear == B_TRUE) {
367993e3fafSRobert Mustacchi xp_clear_change(xp_path, xp_port);
368993e3fafSRobert Mustacchi } else {
369993e3fafSRobert Mustacchi xp_dump(xp_path);
370993e3fafSRobert Mustacchi }
371993e3fafSRobert Mustacchi
372993e3fafSRobert Mustacchi return (0);
373993e3fafSRobert Mustacchi }
374