1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate */
26*7c478bd9Sstevel@tonic-gate
27*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
28*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
29*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
30*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
31*7c478bd9Sstevel@tonic-gate #include <string.h>
32*7c478bd9Sstevel@tonic-gate #include <strings.h>
33*7c478bd9Sstevel@tonic-gate #include <errno.h>
34*7c478bd9Sstevel@tonic-gate #include <string.h>
35*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
36*7c478bd9Sstevel@tonic-gate #include <stdio.h>
37*7c478bd9Sstevel@tonic-gate #include <unistd.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/nvpair.h>
39*7c478bd9Sstevel@tonic-gate #include "libdevice.h"
40*7c478bd9Sstevel@tonic-gate
41*7c478bd9Sstevel@tonic-gate static int _libdevice_debug = 0;
42*7c478bd9Sstevel@tonic-gate static const char *devctl_minorname = ":devctl";
43*7c478bd9Sstevel@tonic-gate static const char *nullptr = "<null>";
44*7c478bd9Sstevel@tonic-gate static const char *devctl_target_raw = "a,raw";
45*7c478bd9Sstevel@tonic-gate
46*7c478bd9Sstevel@tonic-gate typedef enum { DEVCTL_BUS, DEVCTL_DEVICE, DEVCTL_AP, DEVCTL_CLONE,
47*7c478bd9Sstevel@tonic-gate DEVCTL_PM_DEV, DEVCTL_PM_BUS } dc_type_t;
48*7c478bd9Sstevel@tonic-gate
49*7c478bd9Sstevel@tonic-gate /*
50*7c478bd9Sstevel@tonic-gate * devctl_hdl structures are allocated by the devctl_XX_acquire()
51*7c478bd9Sstevel@tonic-gate * interfaces and passed to the remaining interfaces in this library.
52*7c478bd9Sstevel@tonic-gate */
53*7c478bd9Sstevel@tonic-gate struct devctl_hdl {
54*7c478bd9Sstevel@tonic-gate char *opath; /* copy of the original path */
55*7c478bd9Sstevel@tonic-gate dc_type_t hdltype; /* handle type */
56*7c478bd9Sstevel@tonic-gate int fd; /* nexus device node */
57*7c478bd9Sstevel@tonic-gate char *nodename; /* DEVCTL_DEVICE handles only */
58*7c478bd9Sstevel@tonic-gate char *unitaddr; /* DEVCTL_DEVICE handles only */
59*7c478bd9Sstevel@tonic-gate };
60*7c478bd9Sstevel@tonic-gate #define DCP(x) ((struct devctl_hdl *)(x))
61*7c478bd9Sstevel@tonic-gate
62*7c478bd9Sstevel@tonic-gate static int dc_cmd(uint_t, uint_t, struct devctl_hdl *, nvlist_t *, void *);
63*7c478bd9Sstevel@tonic-gate static devctl_hdl_t dc_mkhndl(dc_type_t, char *, uint_t, devctl_hdl_t);
64*7c478bd9Sstevel@tonic-gate
65*7c478bd9Sstevel@tonic-gate
66*7c478bd9Sstevel@tonic-gate #pragma init(_libdevice_init)
67*7c478bd9Sstevel@tonic-gate void
_libdevice_init()68*7c478bd9Sstevel@tonic-gate _libdevice_init()
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate _libdevice_debug = getenv("LIBDEVICE_DEBUG") != NULL;
71*7c478bd9Sstevel@tonic-gate }
72*7c478bd9Sstevel@tonic-gate
73*7c478bd9Sstevel@tonic-gate /*
74*7c478bd9Sstevel@tonic-gate * release a devctl_hdl structure
75*7c478bd9Sstevel@tonic-gate */
76*7c478bd9Sstevel@tonic-gate void
devctl_release(devctl_hdl_t hdl)77*7c478bd9Sstevel@tonic-gate devctl_release(devctl_hdl_t hdl)
78*7c478bd9Sstevel@tonic-gate {
79*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
80*7c478bd9Sstevel@tonic-gate (void) printf("devctl_release: %p\n", (void *)hdl);
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate if (hdl == NULL)
83*7c478bd9Sstevel@tonic-gate return;
84*7c478bd9Sstevel@tonic-gate
85*7c478bd9Sstevel@tonic-gate if (DCP(hdl)->fd != -1)
86*7c478bd9Sstevel@tonic-gate (void) close(DCP(hdl)->fd);
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gate if (DCP(hdl)->opath != NULL)
89*7c478bd9Sstevel@tonic-gate free(DCP(hdl)->opath);
90*7c478bd9Sstevel@tonic-gate
91*7c478bd9Sstevel@tonic-gate if (DCP(hdl)->nodename != NULL)
92*7c478bd9Sstevel@tonic-gate free(DCP(hdl)->nodename);
93*7c478bd9Sstevel@tonic-gate
94*7c478bd9Sstevel@tonic-gate if (DCP(hdl)->unitaddr != NULL)
95*7c478bd9Sstevel@tonic-gate free(DCP(hdl)->unitaddr);
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate free(hdl);
98*7c478bd9Sstevel@tonic-gate }
99*7c478bd9Sstevel@tonic-gate
100*7c478bd9Sstevel@tonic-gate /*
101*7c478bd9Sstevel@tonic-gate * construct a handle suitable for devctl_bus_*() operations
102*7c478bd9Sstevel@tonic-gate */
103*7c478bd9Sstevel@tonic-gate devctl_hdl_t
devctl_bus_acquire(char * devfs_path,uint_t flags)104*7c478bd9Sstevel@tonic-gate devctl_bus_acquire(char *devfs_path, uint_t flags)
105*7c478bd9Sstevel@tonic-gate {
106*7c478bd9Sstevel@tonic-gate uint_t oflags;
107*7c478bd9Sstevel@tonic-gate
108*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
109*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_acquire: %s (%d)\n",
110*7c478bd9Sstevel@tonic-gate ((devfs_path != NULL) ? devfs_path : nullptr), flags);
111*7c478bd9Sstevel@tonic-gate
112*7c478bd9Sstevel@tonic-gate if ((devfs_path == NULL) || ((flags != 0) && (flags != DC_EXCL))) {
113*7c478bd9Sstevel@tonic-gate errno = EINVAL;
114*7c478bd9Sstevel@tonic-gate return (NULL);
115*7c478bd9Sstevel@tonic-gate }
116*7c478bd9Sstevel@tonic-gate
117*7c478bd9Sstevel@tonic-gate oflags = ((flags & DC_EXCL) != 0) ? O_EXCL|O_RDWR : O_RDWR;
118*7c478bd9Sstevel@tonic-gate return (dc_mkhndl(DEVCTL_BUS, devfs_path, oflags, NULL));
119*7c478bd9Sstevel@tonic-gate }
120*7c478bd9Sstevel@tonic-gate
121*7c478bd9Sstevel@tonic-gate
122*7c478bd9Sstevel@tonic-gate /*
123*7c478bd9Sstevel@tonic-gate * construct a handle suitable for devctl_bus_*() and
124*7c478bd9Sstevel@tonic-gate * devctl_device_*() operations.
125*7c478bd9Sstevel@tonic-gate */
126*7c478bd9Sstevel@tonic-gate devctl_hdl_t
devctl_device_acquire(char * devfs_path,uint_t flags)127*7c478bd9Sstevel@tonic-gate devctl_device_acquire(char *devfs_path, uint_t flags)
128*7c478bd9Sstevel@tonic-gate {
129*7c478bd9Sstevel@tonic-gate uint_t oflags;
130*7c478bd9Sstevel@tonic-gate
131*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
132*7c478bd9Sstevel@tonic-gate (void) printf("devctl_device_acquire: %s (%d)\n",
133*7c478bd9Sstevel@tonic-gate ((devfs_path != NULL) ? devfs_path : nullptr), flags);
134*7c478bd9Sstevel@tonic-gate
135*7c478bd9Sstevel@tonic-gate if ((devfs_path == NULL) || ((flags != 0) && (flags != DC_EXCL))) {
136*7c478bd9Sstevel@tonic-gate errno = EINVAL;
137*7c478bd9Sstevel@tonic-gate return (NULL);
138*7c478bd9Sstevel@tonic-gate }
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate oflags = ((flags & DC_EXCL) != 0) ? O_EXCL|O_RDWR : O_RDWR;
141*7c478bd9Sstevel@tonic-gate return (dc_mkhndl(DEVCTL_DEVICE, devfs_path, oflags, NULL));
142*7c478bd9Sstevel@tonic-gate }
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate
145*7c478bd9Sstevel@tonic-gate /*
146*7c478bd9Sstevel@tonic-gate * given a devfs (/devices) pathname to an attachment point device,
147*7c478bd9Sstevel@tonic-gate * access the device and return a handle to be passed to the
148*7c478bd9Sstevel@tonic-gate * devctl_ap_XXX() functions.
149*7c478bd9Sstevel@tonic-gate */
150*7c478bd9Sstevel@tonic-gate devctl_hdl_t
devctl_ap_acquire(char * devfs_path,uint_t flags)151*7c478bd9Sstevel@tonic-gate devctl_ap_acquire(char *devfs_path, uint_t flags)
152*7c478bd9Sstevel@tonic-gate {
153*7c478bd9Sstevel@tonic-gate uint_t oflags;
154*7c478bd9Sstevel@tonic-gate
155*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
156*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_acquire: %s (%d)\n",
157*7c478bd9Sstevel@tonic-gate ((devfs_path != NULL) ? devfs_path : nullptr), flags);
158*7c478bd9Sstevel@tonic-gate
159*7c478bd9Sstevel@tonic-gate if ((devfs_path == NULL) ||
160*7c478bd9Sstevel@tonic-gate ((flags != 0) && ((flags & DC_EXCL) != 0) &&
161*7c478bd9Sstevel@tonic-gate ((flags & DC_RDONLY) != 0))) {
162*7c478bd9Sstevel@tonic-gate errno = EINVAL;
163*7c478bd9Sstevel@tonic-gate return (NULL);
164*7c478bd9Sstevel@tonic-gate }
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate oflags = ((flags & DC_EXCL) != 0) ? O_EXCL : 0;
167*7c478bd9Sstevel@tonic-gate oflags |= ((flags & DC_RDONLY) != 0) ? O_RDONLY : O_RDWR;
168*7c478bd9Sstevel@tonic-gate
169*7c478bd9Sstevel@tonic-gate return (dc_mkhndl(DEVCTL_AP, devfs_path, oflags, NULL));
170*7c478bd9Sstevel@tonic-gate }
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate
173*7c478bd9Sstevel@tonic-gate /*
174*7c478bd9Sstevel@tonic-gate * given a devfs (/devices) pathname access the device and return
175*7c478bd9Sstevel@tonic-gate * a handle to be passed to the devctl_pm_XXX() functions.
176*7c478bd9Sstevel@tonic-gate * The minor name ":devctl" is appended.
177*7c478bd9Sstevel@tonic-gate */
178*7c478bd9Sstevel@tonic-gate devctl_hdl_t
devctl_pm_bus_acquire(char * devfs_path,uint_t flags)179*7c478bd9Sstevel@tonic-gate devctl_pm_bus_acquire(char *devfs_path, uint_t flags)
180*7c478bd9Sstevel@tonic-gate {
181*7c478bd9Sstevel@tonic-gate uint_t oflags;
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
184*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_bus_acquire: %s (%d)\n",
185*7c478bd9Sstevel@tonic-gate ((devfs_path != NULL) ? devfs_path : nullptr), flags);
186*7c478bd9Sstevel@tonic-gate
187*7c478bd9Sstevel@tonic-gate if ((devfs_path == NULL) || ((flags != 0) && (flags != DC_EXCL))) {
188*7c478bd9Sstevel@tonic-gate errno = EINVAL;
189*7c478bd9Sstevel@tonic-gate return (NULL);
190*7c478bd9Sstevel@tonic-gate }
191*7c478bd9Sstevel@tonic-gate
192*7c478bd9Sstevel@tonic-gate oflags = ((flags & DC_EXCL) != 0) ? (O_EXCL | O_RDWR) : O_RDWR;
193*7c478bd9Sstevel@tonic-gate return (dc_mkhndl(DEVCTL_PM_BUS, devfs_path, oflags, NULL));
194*7c478bd9Sstevel@tonic-gate }
195*7c478bd9Sstevel@tonic-gate
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gate /*
198*7c478bd9Sstevel@tonic-gate * given a devfs (/devices) pathname access the device and return
199*7c478bd9Sstevel@tonic-gate * a handle to be passed to the devctl_pm_XXX() functions.
200*7c478bd9Sstevel@tonic-gate * The minor name is derived from the device name.
201*7c478bd9Sstevel@tonic-gate */
202*7c478bd9Sstevel@tonic-gate devctl_hdl_t
devctl_pm_dev_acquire(char * devfs_path,uint_t flags)203*7c478bd9Sstevel@tonic-gate devctl_pm_dev_acquire(char *devfs_path, uint_t flags)
204*7c478bd9Sstevel@tonic-gate {
205*7c478bd9Sstevel@tonic-gate uint_t oflags;
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
208*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_dev_acquire: %s (%d)\n",
209*7c478bd9Sstevel@tonic-gate ((devfs_path != NULL) ? devfs_path : nullptr), flags);
210*7c478bd9Sstevel@tonic-gate
211*7c478bd9Sstevel@tonic-gate if ((devfs_path == NULL) || ((flags != 0) && (flags != DC_EXCL))) {
212*7c478bd9Sstevel@tonic-gate errno = EINVAL;
213*7c478bd9Sstevel@tonic-gate return (NULL);
214*7c478bd9Sstevel@tonic-gate }
215*7c478bd9Sstevel@tonic-gate
216*7c478bd9Sstevel@tonic-gate oflags = ((flags & DC_EXCL) != 0) ? (O_EXCL | O_RDWR) : O_RDWR;
217*7c478bd9Sstevel@tonic-gate return (dc_mkhndl(DEVCTL_PM_DEV, devfs_path, oflags, NULL));
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate
220*7c478bd9Sstevel@tonic-gate
221*7c478bd9Sstevel@tonic-gate /*
222*7c478bd9Sstevel@tonic-gate * allocate and initalize the devctl_hdl structure for the
223*7c478bd9Sstevel@tonic-gate * particular handle type.
224*7c478bd9Sstevel@tonic-gate */
225*7c478bd9Sstevel@tonic-gate static devctl_hdl_t
dc_mkhndl(dc_type_t type,char * path,uint_t oflags,devctl_hdl_t pc)226*7c478bd9Sstevel@tonic-gate dc_mkhndl(dc_type_t type, char *path, uint_t oflags, devctl_hdl_t pc)
227*7c478bd9Sstevel@tonic-gate {
228*7c478bd9Sstevel@tonic-gate struct devctl_hdl *dcp;
229*7c478bd9Sstevel@tonic-gate struct stat sb;
230*7c478bd9Sstevel@tonic-gate char iocpath[MAXPATHLEN];
231*7c478bd9Sstevel@tonic-gate char *nodename, *unitsep, *minorsep, *chop;
232*7c478bd9Sstevel@tonic-gate char *minorname;
233*7c478bd9Sstevel@tonic-gate size_t strlcpy_size;
234*7c478bd9Sstevel@tonic-gate char *iocpath_dup;
235*7c478bd9Sstevel@tonic-gate char *tok;
236*7c478bd9Sstevel@tonic-gate
237*7c478bd9Sstevel@tonic-gate if ((path == NULL) || (strlen(path) > MAXPATHLEN - 1)) {
238*7c478bd9Sstevel@tonic-gate errno = EINVAL;
239*7c478bd9Sstevel@tonic-gate return (NULL);
240*7c478bd9Sstevel@tonic-gate }
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate /*
243*7c478bd9Sstevel@tonic-gate * allocate handle and make a copy of the original path
244*7c478bd9Sstevel@tonic-gate */
245*7c478bd9Sstevel@tonic-gate if ((dcp = calloc(1, sizeof (*dcp))) == NULL) {
246*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
247*7c478bd9Sstevel@tonic-gate return (NULL);
248*7c478bd9Sstevel@tonic-gate }
249*7c478bd9Sstevel@tonic-gate if ((dcp->opath = strdup(path)) == NULL) {
250*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
251*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
252*7c478bd9Sstevel@tonic-gate return (NULL);
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate
255*7c478bd9Sstevel@tonic-gate (void) strcpy(iocpath, path);
256*7c478bd9Sstevel@tonic-gate dcp->hdltype = type;
257*7c478bd9Sstevel@tonic-gate dcp->fd = -1;
258*7c478bd9Sstevel@tonic-gate
259*7c478bd9Sstevel@tonic-gate /*
260*7c478bd9Sstevel@tonic-gate * break apart the pathname according to the type handle
261*7c478bd9Sstevel@tonic-gate */
262*7c478bd9Sstevel@tonic-gate switch (type) {
263*7c478bd9Sstevel@tonic-gate case DEVCTL_PM_BUS:
264*7c478bd9Sstevel@tonic-gate /*
265*7c478bd9Sstevel@tonic-gate * chop off any minor name and concatenate the
266*7c478bd9Sstevel@tonic-gate * ":devctl" minor node name string.
267*7c478bd9Sstevel@tonic-gate */
268*7c478bd9Sstevel@tonic-gate if ((chop = strrchr(iocpath, ':')) != NULL)
269*7c478bd9Sstevel@tonic-gate *chop = '\0';
270*7c478bd9Sstevel@tonic-gate
271*7c478bd9Sstevel@tonic-gate if (strlcat(iocpath, devctl_minorname, MAXPATHLEN) >=
272*7c478bd9Sstevel@tonic-gate MAXPATHLEN) {
273*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
274*7c478bd9Sstevel@tonic-gate errno = EINVAL;
275*7c478bd9Sstevel@tonic-gate return (NULL);
276*7c478bd9Sstevel@tonic-gate } else if (_libdevice_debug) {
277*7c478bd9Sstevel@tonic-gate (void) printf("DEVCTL_PM_BUS: iocpath %s\n", iocpath);
278*7c478bd9Sstevel@tonic-gate }
279*7c478bd9Sstevel@tonic-gate break;
280*7c478bd9Sstevel@tonic-gate
281*7c478bd9Sstevel@tonic-gate case DEVCTL_PM_DEV:
282*7c478bd9Sstevel@tonic-gate /*
283*7c478bd9Sstevel@tonic-gate * Chop up the last device component in the pathname.
284*7c478bd9Sstevel@tonic-gate * Concatenate either the device name itself, or the
285*7c478bd9Sstevel@tonic-gate * "a,raw" string, as the minor node name, to the iocpath.
286*7c478bd9Sstevel@tonic-gate */
287*7c478bd9Sstevel@tonic-gate if ((iocpath_dup = strdup(iocpath)) == NULL) {
288*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
289*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
290*7c478bd9Sstevel@tonic-gate return (NULL);
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate if ((chop = strrchr(iocpath_dup, '/')) == NULL) {
293*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
294*7c478bd9Sstevel@tonic-gate errno = EINVAL;
295*7c478bd9Sstevel@tonic-gate return (NULL);
296*7c478bd9Sstevel@tonic-gate }
297*7c478bd9Sstevel@tonic-gate *chop = '\0';
298*7c478bd9Sstevel@tonic-gate nodename = chop + 1;
299*7c478bd9Sstevel@tonic-gate
300*7c478bd9Sstevel@tonic-gate /*
301*7c478bd9Sstevel@tonic-gate * remove the "@0,0" string
302*7c478bd9Sstevel@tonic-gate */
303*7c478bd9Sstevel@tonic-gate tok = strtok(nodename, "@");
304*7c478bd9Sstevel@tonic-gate if ((minorname = malloc(strlen(tok) +1)) == NULL) {
305*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
306*7c478bd9Sstevel@tonic-gate (void) printf("DEVCTL_PM_DEV: failed malloc for"
307*7c478bd9Sstevel@tonic-gate " minorname\n");
308*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
309*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
310*7c478bd9Sstevel@tonic-gate return (NULL);
311*7c478bd9Sstevel@tonic-gate }
312*7c478bd9Sstevel@tonic-gate (void) strcpy(minorname, tok);
313*7c478bd9Sstevel@tonic-gate if (_libdevice_debug) {
314*7c478bd9Sstevel@tonic-gate (void) printf("DEVCTL_PM_DEV: minorname %s\n",
315*7c478bd9Sstevel@tonic-gate minorname);
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate
318*7c478bd9Sstevel@tonic-gate /*
319*7c478bd9Sstevel@tonic-gate * construct the name of the ioctl device
320*7c478bd9Sstevel@tonic-gate * by concatenating either ":a,raw" or ":"minorname
321*7c478bd9Sstevel@tonic-gate */
322*7c478bd9Sstevel@tonic-gate (void) strlcat(iocpath, ":", MAXPATHLEN);
323*7c478bd9Sstevel@tonic-gate if (strcmp(minorname, "disk_chan") == 0 ||
324*7c478bd9Sstevel@tonic-gate strcmp(minorname, "disk_wwn") == 0 ||
325*7c478bd9Sstevel@tonic-gate strcmp(minorname, "disk_cdrom") == 0) {
326*7c478bd9Sstevel@tonic-gate strlcpy_size = strlcat(iocpath, devctl_target_raw,
327*7c478bd9Sstevel@tonic-gate MAXPATHLEN);
328*7c478bd9Sstevel@tonic-gate } else {
329*7c478bd9Sstevel@tonic-gate strlcpy_size = strlcat(iocpath, minorname, MAXPATHLEN);
330*7c478bd9Sstevel@tonic-gate }
331*7c478bd9Sstevel@tonic-gate if (strlcpy_size >= MAXPATHLEN) {
332*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
333*7c478bd9Sstevel@tonic-gate errno = EINVAL;
334*7c478bd9Sstevel@tonic-gate return (NULL);
335*7c478bd9Sstevel@tonic-gate } else if (_libdevice_debug) {
336*7c478bd9Sstevel@tonic-gate (void) printf("DEVCTL_PM_DEV: iocpath %s\n",
337*7c478bd9Sstevel@tonic-gate iocpath);
338*7c478bd9Sstevel@tonic-gate }
339*7c478bd9Sstevel@tonic-gate break;
340*7c478bd9Sstevel@tonic-gate
341*7c478bd9Sstevel@tonic-gate case DEVCTL_AP:
342*7c478bd9Sstevel@tonic-gate /*
343*7c478bd9Sstevel@tonic-gate * take the pathname as provided.
344*7c478bd9Sstevel@tonic-gate */
345*7c478bd9Sstevel@tonic-gate break;
346*7c478bd9Sstevel@tonic-gate
347*7c478bd9Sstevel@tonic-gate case DEVCTL_BUS:
348*7c478bd9Sstevel@tonic-gate /*
349*7c478bd9Sstevel@tonic-gate * chop off any minor name and concatenate the
350*7c478bd9Sstevel@tonic-gate * ":devctl" minor node name string.
351*7c478bd9Sstevel@tonic-gate */
352*7c478bd9Sstevel@tonic-gate if ((chop = strrchr(iocpath, ':')) != NULL)
353*7c478bd9Sstevel@tonic-gate *chop = '\0';
354*7c478bd9Sstevel@tonic-gate
355*7c478bd9Sstevel@tonic-gate if (strlcat(iocpath, devctl_minorname, MAXPATHLEN) >=
356*7c478bd9Sstevel@tonic-gate MAXPATHLEN) {
357*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
358*7c478bd9Sstevel@tonic-gate errno = EINVAL;
359*7c478bd9Sstevel@tonic-gate return (NULL);
360*7c478bd9Sstevel@tonic-gate }
361*7c478bd9Sstevel@tonic-gate break;
362*7c478bd9Sstevel@tonic-gate
363*7c478bd9Sstevel@tonic-gate case DEVCTL_CLONE:
364*7c478bd9Sstevel@tonic-gate /*
365*7c478bd9Sstevel@tonic-gate * create a device handle for a new device created
366*7c478bd9Sstevel@tonic-gate * from a call to devctl_bus_dev_create()
367*7c478bd9Sstevel@tonic-gate */
368*7c478bd9Sstevel@tonic-gate dcp->hdltype = DEVCTL_DEVICE;
369*7c478bd9Sstevel@tonic-gate
370*7c478bd9Sstevel@tonic-gate /* FALLTHRU */
371*7c478bd9Sstevel@tonic-gate
372*7c478bd9Sstevel@tonic-gate case DEVCTL_DEVICE:
373*7c478bd9Sstevel@tonic-gate
374*7c478bd9Sstevel@tonic-gate /*
375*7c478bd9Sstevel@tonic-gate * Chop up the last device component in the pathname.
376*7c478bd9Sstevel@tonic-gate * The componets are passed as nodename and unitaddr
377*7c478bd9Sstevel@tonic-gate * in the IOCTL data for DEVCTL ops on devices.
378*7c478bd9Sstevel@tonic-gate */
379*7c478bd9Sstevel@tonic-gate if ((chop = strrchr(iocpath, '/')) == NULL) {
380*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
381*7c478bd9Sstevel@tonic-gate errno = EINVAL;
382*7c478bd9Sstevel@tonic-gate return (NULL);
383*7c478bd9Sstevel@tonic-gate }
384*7c478bd9Sstevel@tonic-gate *chop = '\0';
385*7c478bd9Sstevel@tonic-gate
386*7c478bd9Sstevel@tonic-gate nodename = chop + 1;
387*7c478bd9Sstevel@tonic-gate unitsep = strchr(nodename, '@');
388*7c478bd9Sstevel@tonic-gate minorsep = strchr(nodename, ':');
389*7c478bd9Sstevel@tonic-gate
390*7c478bd9Sstevel@tonic-gate if (unitsep == NULL) {
391*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
392*7c478bd9Sstevel@tonic-gate errno = EINVAL;
393*7c478bd9Sstevel@tonic-gate return (NULL);
394*7c478bd9Sstevel@tonic-gate }
395*7c478bd9Sstevel@tonic-gate
396*7c478bd9Sstevel@tonic-gate /*
397*7c478bd9Sstevel@tonic-gate * copy the nodename and unit address
398*7c478bd9Sstevel@tonic-gate */
399*7c478bd9Sstevel@tonic-gate if (((dcp->nodename = malloc(MAXNAMELEN)) == NULL) ||
400*7c478bd9Sstevel@tonic-gate ((dcp->unitaddr = malloc(MAXNAMELEN)) == NULL)) {
401*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
402*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
403*7c478bd9Sstevel@tonic-gate return (NULL);
404*7c478bd9Sstevel@tonic-gate }
405*7c478bd9Sstevel@tonic-gate *unitsep = '\0';
406*7c478bd9Sstevel@tonic-gate if (minorsep != NULL)
407*7c478bd9Sstevel@tonic-gate *minorsep = '\0';
408*7c478bd9Sstevel@tonic-gate (void) snprintf(dcp->nodename, MAXNAMELEN, "%s", nodename);
409*7c478bd9Sstevel@tonic-gate (void) snprintf(dcp->unitaddr, MAXNAMELEN, "%s", unitsep+1);
410*7c478bd9Sstevel@tonic-gate
411*7c478bd9Sstevel@tonic-gate /*
412*7c478bd9Sstevel@tonic-gate * construct the name of the ioctl device
413*7c478bd9Sstevel@tonic-gate */
414*7c478bd9Sstevel@tonic-gate if (strlcat(iocpath, devctl_minorname, MAXPATHLEN) >=
415*7c478bd9Sstevel@tonic-gate MAXPATHLEN) {
416*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
417*7c478bd9Sstevel@tonic-gate errno = EINVAL;
418*7c478bd9Sstevel@tonic-gate return (NULL);
419*7c478bd9Sstevel@tonic-gate }
420*7c478bd9Sstevel@tonic-gate break;
421*7c478bd9Sstevel@tonic-gate
422*7c478bd9Sstevel@tonic-gate default:
423*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
424*7c478bd9Sstevel@tonic-gate errno = EINVAL;
425*7c478bd9Sstevel@tonic-gate return (NULL);
426*7c478bd9Sstevel@tonic-gate }
427*7c478bd9Sstevel@tonic-gate
428*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
429*7c478bd9Sstevel@tonic-gate (void) printf("dc_mkhndl: iocpath %s ", iocpath);
430*7c478bd9Sstevel@tonic-gate
431*7c478bd9Sstevel@tonic-gate /*
432*7c478bd9Sstevel@tonic-gate * verify the devctl or ap device exists and is a
433*7c478bd9Sstevel@tonic-gate * character device interface.
434*7c478bd9Sstevel@tonic-gate */
435*7c478bd9Sstevel@tonic-gate if (stat(iocpath, &sb) == 0) {
436*7c478bd9Sstevel@tonic-gate if ((sb.st_mode & S_IFMT) != S_IFCHR) {
437*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
438*7c478bd9Sstevel@tonic-gate (void) printf(" - not character device\n");
439*7c478bd9Sstevel@tonic-gate errno = ENODEV;
440*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
441*7c478bd9Sstevel@tonic-gate return (NULL);
442*7c478bd9Sstevel@tonic-gate }
443*7c478bd9Sstevel@tonic-gate } else {
444*7c478bd9Sstevel@tonic-gate /*
445*7c478bd9Sstevel@tonic-gate * return failure with errno value set by stat
446*7c478bd9Sstevel@tonic-gate */
447*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
448*7c478bd9Sstevel@tonic-gate (void) printf(" - stat failed\n");
449*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
450*7c478bd9Sstevel@tonic-gate return (NULL);
451*7c478bd9Sstevel@tonic-gate }
452*7c478bd9Sstevel@tonic-gate
453*7c478bd9Sstevel@tonic-gate /*
454*7c478bd9Sstevel@tonic-gate * if this was a new device, dup the parents handle, otherwise
455*7c478bd9Sstevel@tonic-gate * just open the device.
456*7c478bd9Sstevel@tonic-gate */
457*7c478bd9Sstevel@tonic-gate if (type == DEVCTL_CLONE)
458*7c478bd9Sstevel@tonic-gate dcp->fd = dup(DCP(pc)->fd);
459*7c478bd9Sstevel@tonic-gate else
460*7c478bd9Sstevel@tonic-gate dcp->fd = open(iocpath, oflags);
461*7c478bd9Sstevel@tonic-gate
462*7c478bd9Sstevel@tonic-gate if (dcp->fd == -1) {
463*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
464*7c478bd9Sstevel@tonic-gate (void) printf(" - open/dup failed %d\n", errno);
465*7c478bd9Sstevel@tonic-gate /*
466*7c478bd9Sstevel@tonic-gate * leave errno as set by open/dup
467*7c478bd9Sstevel@tonic-gate */
468*7c478bd9Sstevel@tonic-gate devctl_release((devctl_hdl_t)dcp);
469*7c478bd9Sstevel@tonic-gate return (NULL);
470*7c478bd9Sstevel@tonic-gate }
471*7c478bd9Sstevel@tonic-gate
472*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
473*7c478bd9Sstevel@tonic-gate (void) printf(" - open success\n");
474*7c478bd9Sstevel@tonic-gate
475*7c478bd9Sstevel@tonic-gate return ((devctl_hdl_t)dcp);
476*7c478bd9Sstevel@tonic-gate }
477*7c478bd9Sstevel@tonic-gate
478*7c478bd9Sstevel@tonic-gate /*
479*7c478bd9Sstevel@tonic-gate * Power up component 0, to level MAXPWR, via a pm_raise_power() call
480*7c478bd9Sstevel@tonic-gate */
481*7c478bd9Sstevel@tonic-gate int
devctl_pm_raisepower(devctl_hdl_t dcp)482*7c478bd9Sstevel@tonic-gate devctl_pm_raisepower(devctl_hdl_t dcp)
483*7c478bd9Sstevel@tonic-gate {
484*7c478bd9Sstevel@tonic-gate int rv;
485*7c478bd9Sstevel@tonic-gate
486*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
487*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
488*7c478bd9Sstevel@tonic-gate errno = EINVAL;
489*7c478bd9Sstevel@tonic-gate return (-1);
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate
492*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_RAISE_PWR, 0, DCP(dcp), NULL, NULL);
493*7c478bd9Sstevel@tonic-gate
494*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
495*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_raisepower: %d\n", rv);
496*7c478bd9Sstevel@tonic-gate
497*7c478bd9Sstevel@tonic-gate return (rv);
498*7c478bd9Sstevel@tonic-gate }
499*7c478bd9Sstevel@tonic-gate
500*7c478bd9Sstevel@tonic-gate /*
501*7c478bd9Sstevel@tonic-gate * Power up component 0, to level MAXPWR, via a power_has_changed() call
502*7c478bd9Sstevel@tonic-gate */
503*7c478bd9Sstevel@tonic-gate int
devctl_pm_changepowerhigh(devctl_hdl_t dcp)504*7c478bd9Sstevel@tonic-gate devctl_pm_changepowerhigh(devctl_hdl_t dcp)
505*7c478bd9Sstevel@tonic-gate {
506*7c478bd9Sstevel@tonic-gate int rv;
507*7c478bd9Sstevel@tonic-gate
508*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
509*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
510*7c478bd9Sstevel@tonic-gate errno = EINVAL;
511*7c478bd9Sstevel@tonic-gate return (-1);
512*7c478bd9Sstevel@tonic-gate }
513*7c478bd9Sstevel@tonic-gate
514*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_CHANGE_PWR_HIGH, 0, DCP(dcp), NULL, NULL);
515*7c478bd9Sstevel@tonic-gate
516*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
517*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_changepowerhigh: %d\n", rv);
518*7c478bd9Sstevel@tonic-gate
519*7c478bd9Sstevel@tonic-gate return (rv);
520*7c478bd9Sstevel@tonic-gate }
521*7c478bd9Sstevel@tonic-gate
522*7c478bd9Sstevel@tonic-gate /*
523*7c478bd9Sstevel@tonic-gate * Power down component 0, to level 0, via a pm_change_power() call
524*7c478bd9Sstevel@tonic-gate */
525*7c478bd9Sstevel@tonic-gate int
devctl_pm_changepowerlow(devctl_hdl_t dcp)526*7c478bd9Sstevel@tonic-gate devctl_pm_changepowerlow(devctl_hdl_t dcp)
527*7c478bd9Sstevel@tonic-gate {
528*7c478bd9Sstevel@tonic-gate int rv;
529*7c478bd9Sstevel@tonic-gate
530*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
531*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
532*7c478bd9Sstevel@tonic-gate errno = EINVAL;
533*7c478bd9Sstevel@tonic-gate return (-1);
534*7c478bd9Sstevel@tonic-gate }
535*7c478bd9Sstevel@tonic-gate
536*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_CHANGE_PWR_LOW, 0, DCP(dcp), NULL, NULL);
537*7c478bd9Sstevel@tonic-gate
538*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
539*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_changepowerlow: %d\n", rv);
540*7c478bd9Sstevel@tonic-gate
541*7c478bd9Sstevel@tonic-gate return (rv);
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate
544*7c478bd9Sstevel@tonic-gate /*
545*7c478bd9Sstevel@tonic-gate * mark component 0 idle
546*7c478bd9Sstevel@tonic-gate */
547*7c478bd9Sstevel@tonic-gate int
devctl_pm_idlecomponent(devctl_hdl_t dcp)548*7c478bd9Sstevel@tonic-gate devctl_pm_idlecomponent(devctl_hdl_t dcp)
549*7c478bd9Sstevel@tonic-gate {
550*7c478bd9Sstevel@tonic-gate int rv;
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
553*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
554*7c478bd9Sstevel@tonic-gate errno = EINVAL;
555*7c478bd9Sstevel@tonic-gate return (-1);
556*7c478bd9Sstevel@tonic-gate }
557*7c478bd9Sstevel@tonic-gate
558*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_IDLE_COMP, 0, DCP(dcp), NULL, NULL);
559*7c478bd9Sstevel@tonic-gate
560*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
561*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_idlecomponent: %d\n", rv);
562*7c478bd9Sstevel@tonic-gate
563*7c478bd9Sstevel@tonic-gate return (rv);
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate
566*7c478bd9Sstevel@tonic-gate /*
567*7c478bd9Sstevel@tonic-gate * mark component 0 busy
568*7c478bd9Sstevel@tonic-gate */
569*7c478bd9Sstevel@tonic-gate int
devctl_pm_busycomponent(devctl_hdl_t dcp)570*7c478bd9Sstevel@tonic-gate devctl_pm_busycomponent(devctl_hdl_t dcp)
571*7c478bd9Sstevel@tonic-gate {
572*7c478bd9Sstevel@tonic-gate int rv;
573*7c478bd9Sstevel@tonic-gate
574*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
575*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
576*7c478bd9Sstevel@tonic-gate errno = EINVAL;
577*7c478bd9Sstevel@tonic-gate return (-1);
578*7c478bd9Sstevel@tonic-gate }
579*7c478bd9Sstevel@tonic-gate
580*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_BUSY_COMP, 0, DCP(dcp), NULL, NULL);
581*7c478bd9Sstevel@tonic-gate
582*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
583*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_busycomponent: %d\n", rv);
584*7c478bd9Sstevel@tonic-gate
585*7c478bd9Sstevel@tonic-gate return (rv);
586*7c478bd9Sstevel@tonic-gate }
587*7c478bd9Sstevel@tonic-gate
588*7c478bd9Sstevel@tonic-gate /*
589*7c478bd9Sstevel@tonic-gate * test pm busy state
590*7c478bd9Sstevel@tonic-gate */
591*7c478bd9Sstevel@tonic-gate int
devctl_pm_testbusy(devctl_hdl_t dcp,uint_t * busystate)592*7c478bd9Sstevel@tonic-gate devctl_pm_testbusy(devctl_hdl_t dcp, uint_t *busystate)
593*7c478bd9Sstevel@tonic-gate {
594*7c478bd9Sstevel@tonic-gate int rv;
595*7c478bd9Sstevel@tonic-gate uint_t busy_state = 0;
596*7c478bd9Sstevel@tonic-gate
597*7c478bd9Sstevel@tonic-gate if (busystate == NULL) {
598*7c478bd9Sstevel@tonic-gate errno = EINVAL;
599*7c478bd9Sstevel@tonic-gate return (-1);
600*7c478bd9Sstevel@tonic-gate }
601*7c478bd9Sstevel@tonic-gate
602*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
603*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
604*7c478bd9Sstevel@tonic-gate errno = EINVAL;
605*7c478bd9Sstevel@tonic-gate return (-1);
606*7c478bd9Sstevel@tonic-gate }
607*7c478bd9Sstevel@tonic-gate
608*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_BUSY_COMP_TEST, 0, DCP(dcp), NULL,
609*7c478bd9Sstevel@tonic-gate (void *)&busy_state);
610*7c478bd9Sstevel@tonic-gate
611*7c478bd9Sstevel@tonic-gate if (rv == -1)
612*7c478bd9Sstevel@tonic-gate *busystate = 0;
613*7c478bd9Sstevel@tonic-gate else
614*7c478bd9Sstevel@tonic-gate *busystate = busy_state;
615*7c478bd9Sstevel@tonic-gate
616*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
617*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_bus_testbusy: rv %d busystate %x\n",
618*7c478bd9Sstevel@tonic-gate rv, *busystate);
619*7c478bd9Sstevel@tonic-gate
620*7c478bd9Sstevel@tonic-gate return (rv);
621*7c478bd9Sstevel@tonic-gate }
622*7c478bd9Sstevel@tonic-gate
623*7c478bd9Sstevel@tonic-gate /*
624*7c478bd9Sstevel@tonic-gate * set flag to fail DDI_SUSPEND
625*7c478bd9Sstevel@tonic-gate */
626*7c478bd9Sstevel@tonic-gate int
devctl_pm_failsuspend(devctl_hdl_t dcp)627*7c478bd9Sstevel@tonic-gate devctl_pm_failsuspend(devctl_hdl_t dcp)
628*7c478bd9Sstevel@tonic-gate {
629*7c478bd9Sstevel@tonic-gate int rv;
630*7c478bd9Sstevel@tonic-gate
631*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
632*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
633*7c478bd9Sstevel@tonic-gate errno = EINVAL;
634*7c478bd9Sstevel@tonic-gate return (-1);
635*7c478bd9Sstevel@tonic-gate }
636*7c478bd9Sstevel@tonic-gate
637*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_FAIL_SUSPEND, 0, DCP(dcp), NULL, NULL);
638*7c478bd9Sstevel@tonic-gate
639*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
640*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_failsuspend: %d\n", rv);
641*7c478bd9Sstevel@tonic-gate return (rv);
642*7c478bd9Sstevel@tonic-gate }
643*7c478bd9Sstevel@tonic-gate
644*7c478bd9Sstevel@tonic-gate int
devctl_pm_bus_teststrict(devctl_hdl_t dcp,uint_t * strict)645*7c478bd9Sstevel@tonic-gate devctl_pm_bus_teststrict(devctl_hdl_t dcp, uint_t *strict)
646*7c478bd9Sstevel@tonic-gate {
647*7c478bd9Sstevel@tonic-gate int rv;
648*7c478bd9Sstevel@tonic-gate uint_t strict_state;
649*7c478bd9Sstevel@tonic-gate
650*7c478bd9Sstevel@tonic-gate if (strict == NULL) {
651*7c478bd9Sstevel@tonic-gate errno = EINVAL;
652*7c478bd9Sstevel@tonic-gate return (-1);
653*7c478bd9Sstevel@tonic-gate }
654*7c478bd9Sstevel@tonic-gate
655*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
656*7c478bd9Sstevel@tonic-gate errno = EINVAL;
657*7c478bd9Sstevel@tonic-gate return (-1);
658*7c478bd9Sstevel@tonic-gate }
659*7c478bd9Sstevel@tonic-gate
660*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_BUS_STRICT_TEST, 0, DCP(dcp), NULL,
661*7c478bd9Sstevel@tonic-gate (void *)&strict_state);
662*7c478bd9Sstevel@tonic-gate
663*7c478bd9Sstevel@tonic-gate if (rv == -1)
664*7c478bd9Sstevel@tonic-gate *strict = 0;
665*7c478bd9Sstevel@tonic-gate else
666*7c478bd9Sstevel@tonic-gate *strict = strict_state;
667*7c478bd9Sstevel@tonic-gate
668*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
669*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_bus_teststrict: rv %d strict %x\n",
670*7c478bd9Sstevel@tonic-gate rv, *strict);
671*7c478bd9Sstevel@tonic-gate
672*7c478bd9Sstevel@tonic-gate return (rv);
673*7c478bd9Sstevel@tonic-gate }
674*7c478bd9Sstevel@tonic-gate
675*7c478bd9Sstevel@tonic-gate /*
676*7c478bd9Sstevel@tonic-gate * issue prom_printf() call
677*7c478bd9Sstevel@tonic-gate */
678*7c478bd9Sstevel@tonic-gate int
devctl_pm_device_promprintf(devctl_hdl_t dcp)679*7c478bd9Sstevel@tonic-gate devctl_pm_device_promprintf(devctl_hdl_t dcp)
680*7c478bd9Sstevel@tonic-gate {
681*7c478bd9Sstevel@tonic-gate int rv;
682*7c478bd9Sstevel@tonic-gate
683*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
684*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
685*7c478bd9Sstevel@tonic-gate errno = EINVAL;
686*7c478bd9Sstevel@tonic-gate return (-1);
687*7c478bd9Sstevel@tonic-gate }
688*7c478bd9Sstevel@tonic-gate
689*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_PROM_PRINTF, 0, DCP(dcp), NULL, NULL);
690*7c478bd9Sstevel@tonic-gate
691*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
692*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_device_promprintf: %d\n", rv);
693*7c478bd9Sstevel@tonic-gate return (rv);
694*7c478bd9Sstevel@tonic-gate }
695*7c478bd9Sstevel@tonic-gate
696*7c478bd9Sstevel@tonic-gate /*
697*7c478bd9Sstevel@tonic-gate * set flag to power up the device via
698*7c478bd9Sstevel@tonic-gate * pm_power_has_changed() calls vs.
699*7c478bd9Sstevel@tonic-gate * pm_raise_power(), during DDI_RESUME
700*7c478bd9Sstevel@tonic-gate */
701*7c478bd9Sstevel@tonic-gate int
devctl_pm_device_changeonresume(devctl_hdl_t dcp)702*7c478bd9Sstevel@tonic-gate devctl_pm_device_changeonresume(devctl_hdl_t dcp)
703*7c478bd9Sstevel@tonic-gate {
704*7c478bd9Sstevel@tonic-gate int rv;
705*7c478bd9Sstevel@tonic-gate
706*7c478bd9Sstevel@tonic-gate if (dcp == NULL || (DCP(dcp)->hdltype != DEVCTL_PM_DEV &&
707*7c478bd9Sstevel@tonic-gate DCP(dcp)->hdltype != DEVCTL_PM_BUS)) {
708*7c478bd9Sstevel@tonic-gate errno = EINVAL;
709*7c478bd9Sstevel@tonic-gate return (-1);
710*7c478bd9Sstevel@tonic-gate }
711*7c478bd9Sstevel@tonic-gate
712*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_PWR_HAS_CHANGED_ON_RESUME, 0,
713*7c478bd9Sstevel@tonic-gate DCP(dcp), NULL, NULL);
714*7c478bd9Sstevel@tonic-gate
715*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
716*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_device_changeonresume: %d\n", rv);
717*7c478bd9Sstevel@tonic-gate return (rv);
718*7c478bd9Sstevel@tonic-gate }
719*7c478bd9Sstevel@tonic-gate
720*7c478bd9Sstevel@tonic-gate /*
721*7c478bd9Sstevel@tonic-gate * issue DEVCTL_PM_NO_LOWER_POWER to clear the LOWER_POWER_FLAG
722*7c478bd9Sstevel@tonic-gate * flag: pm_lower_power() will not be called on device detach
723*7c478bd9Sstevel@tonic-gate */
724*7c478bd9Sstevel@tonic-gate int
devctl_pm_device_no_lower_power(devctl_hdl_t dcp)725*7c478bd9Sstevel@tonic-gate devctl_pm_device_no_lower_power(devctl_hdl_t dcp)
726*7c478bd9Sstevel@tonic-gate {
727*7c478bd9Sstevel@tonic-gate int rv;
728*7c478bd9Sstevel@tonic-gate
729*7c478bd9Sstevel@tonic-gate if (dcp == NULL || DCP(dcp)->hdltype != DEVCTL_PM_DEV) {
730*7c478bd9Sstevel@tonic-gate errno = EINVAL;
731*7c478bd9Sstevel@tonic-gate return (-1);
732*7c478bd9Sstevel@tonic-gate }
733*7c478bd9Sstevel@tonic-gate
734*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_NO_LOWER_POWER, 0, DCP(dcp), NULL, NULL);
735*7c478bd9Sstevel@tonic-gate
736*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
737*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_device_no_lower_power: %d\n", rv);
738*7c478bd9Sstevel@tonic-gate return (rv);
739*7c478bd9Sstevel@tonic-gate }
740*7c478bd9Sstevel@tonic-gate
741*7c478bd9Sstevel@tonic-gate /*
742*7c478bd9Sstevel@tonic-gate * issue DEVCTL_PM_BUS_NO_INVOL ioctl to set the NO_INVOL_FLAG
743*7c478bd9Sstevel@tonic-gate * flag: parent driver will mark itself idle twice in
744*7c478bd9Sstevel@tonic-gate * DDI_CTLOPS_DETACH(POST)
745*7c478bd9Sstevel@tonic-gate */
746*7c478bd9Sstevel@tonic-gate int
devctl_pm_bus_no_invol(devctl_hdl_t dcp)747*7c478bd9Sstevel@tonic-gate devctl_pm_bus_no_invol(devctl_hdl_t dcp)
748*7c478bd9Sstevel@tonic-gate {
749*7c478bd9Sstevel@tonic-gate int rv;
750*7c478bd9Sstevel@tonic-gate
751*7c478bd9Sstevel@tonic-gate if (dcp == NULL || DCP(dcp)->hdltype != DEVCTL_PM_BUS) {
752*7c478bd9Sstevel@tonic-gate errno = EINVAL;
753*7c478bd9Sstevel@tonic-gate return (-1);
754*7c478bd9Sstevel@tonic-gate }
755*7c478bd9Sstevel@tonic-gate
756*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_PM_BUS_NO_INVOL, 0, DCP(dcp), NULL, NULL);
757*7c478bd9Sstevel@tonic-gate
758*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
759*7c478bd9Sstevel@tonic-gate (void) printf("devctl_pm_bus_no_invol: %d\n", rv);
760*7c478bd9Sstevel@tonic-gate return (rv);
761*7c478bd9Sstevel@tonic-gate }
762*7c478bd9Sstevel@tonic-gate
763*7c478bd9Sstevel@tonic-gate /*
764*7c478bd9Sstevel@tonic-gate * Place the device ONLINE
765*7c478bd9Sstevel@tonic-gate */
766*7c478bd9Sstevel@tonic-gate int
devctl_device_online(devctl_hdl_t dcp)767*7c478bd9Sstevel@tonic-gate devctl_device_online(devctl_hdl_t dcp)
768*7c478bd9Sstevel@tonic-gate {
769*7c478bd9Sstevel@tonic-gate int rv;
770*7c478bd9Sstevel@tonic-gate
771*7c478bd9Sstevel@tonic-gate if (dcp == NULL || DCP(dcp)->hdltype != DEVCTL_DEVICE) {
772*7c478bd9Sstevel@tonic-gate errno = EINVAL;
773*7c478bd9Sstevel@tonic-gate return (-1);
774*7c478bd9Sstevel@tonic-gate }
775*7c478bd9Sstevel@tonic-gate
776*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_DEVICE_ONLINE, 0, DCP(dcp), NULL, NULL);
777*7c478bd9Sstevel@tonic-gate
778*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
779*7c478bd9Sstevel@tonic-gate (void) printf("devctl_device_online: %d\n", rv);
780*7c478bd9Sstevel@tonic-gate
781*7c478bd9Sstevel@tonic-gate return (rv);
782*7c478bd9Sstevel@tonic-gate }
783*7c478bd9Sstevel@tonic-gate
784*7c478bd9Sstevel@tonic-gate /*
785*7c478bd9Sstevel@tonic-gate * take device OFFLINE
786*7c478bd9Sstevel@tonic-gate */
787*7c478bd9Sstevel@tonic-gate int
devctl_device_offline(devctl_hdl_t dcp)788*7c478bd9Sstevel@tonic-gate devctl_device_offline(devctl_hdl_t dcp)
789*7c478bd9Sstevel@tonic-gate {
790*7c478bd9Sstevel@tonic-gate int rv;
791*7c478bd9Sstevel@tonic-gate
792*7c478bd9Sstevel@tonic-gate if (dcp == NULL || DCP(dcp)->hdltype != DEVCTL_DEVICE) {
793*7c478bd9Sstevel@tonic-gate errno = EINVAL;
794*7c478bd9Sstevel@tonic-gate return (-1);
795*7c478bd9Sstevel@tonic-gate }
796*7c478bd9Sstevel@tonic-gate
797*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_DEVICE_OFFLINE, 0, DCP(dcp), NULL, NULL);
798*7c478bd9Sstevel@tonic-gate
799*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
800*7c478bd9Sstevel@tonic-gate (void) printf("devctl_device_offline: %d\n", rv);
801*7c478bd9Sstevel@tonic-gate
802*7c478bd9Sstevel@tonic-gate return (rv);
803*7c478bd9Sstevel@tonic-gate }
804*7c478bd9Sstevel@tonic-gate
805*7c478bd9Sstevel@tonic-gate /*
806*7c478bd9Sstevel@tonic-gate * take the device OFFLINE and remove its dev_info node
807*7c478bd9Sstevel@tonic-gate */
808*7c478bd9Sstevel@tonic-gate int
devctl_device_remove(devctl_hdl_t dcp)809*7c478bd9Sstevel@tonic-gate devctl_device_remove(devctl_hdl_t dcp)
810*7c478bd9Sstevel@tonic-gate {
811*7c478bd9Sstevel@tonic-gate int rv;
812*7c478bd9Sstevel@tonic-gate
813*7c478bd9Sstevel@tonic-gate if (dcp == NULL || DCP(dcp)->hdltype != DEVCTL_DEVICE) {
814*7c478bd9Sstevel@tonic-gate errno = EINVAL;
815*7c478bd9Sstevel@tonic-gate return (-1);
816*7c478bd9Sstevel@tonic-gate }
817*7c478bd9Sstevel@tonic-gate
818*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_DEVICE_REMOVE, 0, DCP(dcp), NULL, NULL);
819*7c478bd9Sstevel@tonic-gate
820*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
821*7c478bd9Sstevel@tonic-gate (void) printf("devctl_device_remove: %d\n", rv);
822*7c478bd9Sstevel@tonic-gate
823*7c478bd9Sstevel@tonic-gate return (rv);
824*7c478bd9Sstevel@tonic-gate }
825*7c478bd9Sstevel@tonic-gate
826*7c478bd9Sstevel@tonic-gate
827*7c478bd9Sstevel@tonic-gate /*
828*7c478bd9Sstevel@tonic-gate * QUIESCE the bus
829*7c478bd9Sstevel@tonic-gate */
830*7c478bd9Sstevel@tonic-gate int
devctl_bus_quiesce(devctl_hdl_t dcp)831*7c478bd9Sstevel@tonic-gate devctl_bus_quiesce(devctl_hdl_t dcp)
832*7c478bd9Sstevel@tonic-gate {
833*7c478bd9Sstevel@tonic-gate int rv;
834*7c478bd9Sstevel@tonic-gate
835*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_QUIESCE, 0, DCP(dcp), NULL, NULL);
836*7c478bd9Sstevel@tonic-gate
837*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
838*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_quiesce: %d\n", rv);
839*7c478bd9Sstevel@tonic-gate
840*7c478bd9Sstevel@tonic-gate return (rv);
841*7c478bd9Sstevel@tonic-gate }
842*7c478bd9Sstevel@tonic-gate
843*7c478bd9Sstevel@tonic-gate int
devctl_bus_unquiesce(devctl_hdl_t dcp)844*7c478bd9Sstevel@tonic-gate devctl_bus_unquiesce(devctl_hdl_t dcp)
845*7c478bd9Sstevel@tonic-gate {
846*7c478bd9Sstevel@tonic-gate int rv;
847*7c478bd9Sstevel@tonic-gate
848*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_UNQUIESCE, 0, DCP(dcp), NULL, NULL);
849*7c478bd9Sstevel@tonic-gate
850*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
851*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_unquiesce: %d\n", rv);
852*7c478bd9Sstevel@tonic-gate
853*7c478bd9Sstevel@tonic-gate return (rv);
854*7c478bd9Sstevel@tonic-gate }
855*7c478bd9Sstevel@tonic-gate
856*7c478bd9Sstevel@tonic-gate int
devctl_bus_reset(devctl_hdl_t dcp)857*7c478bd9Sstevel@tonic-gate devctl_bus_reset(devctl_hdl_t dcp)
858*7c478bd9Sstevel@tonic-gate {
859*7c478bd9Sstevel@tonic-gate int rv;
860*7c478bd9Sstevel@tonic-gate
861*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_RESET, 0, DCP(dcp), NULL, NULL);
862*7c478bd9Sstevel@tonic-gate
863*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
864*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_reset: %d\n", rv);
865*7c478bd9Sstevel@tonic-gate
866*7c478bd9Sstevel@tonic-gate return (rv);
867*7c478bd9Sstevel@tonic-gate }
868*7c478bd9Sstevel@tonic-gate
869*7c478bd9Sstevel@tonic-gate int
devctl_bus_resetall(devctl_hdl_t dcp)870*7c478bd9Sstevel@tonic-gate devctl_bus_resetall(devctl_hdl_t dcp)
871*7c478bd9Sstevel@tonic-gate {
872*7c478bd9Sstevel@tonic-gate int rv;
873*7c478bd9Sstevel@tonic-gate
874*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_RESETALL, 0, DCP(dcp), NULL, NULL);
875*7c478bd9Sstevel@tonic-gate
876*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
877*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_resetall: %d\n", rv);
878*7c478bd9Sstevel@tonic-gate
879*7c478bd9Sstevel@tonic-gate return (rv);
880*7c478bd9Sstevel@tonic-gate }
881*7c478bd9Sstevel@tonic-gate
882*7c478bd9Sstevel@tonic-gate int
devctl_device_reset(devctl_hdl_t dcp)883*7c478bd9Sstevel@tonic-gate devctl_device_reset(devctl_hdl_t dcp)
884*7c478bd9Sstevel@tonic-gate {
885*7c478bd9Sstevel@tonic-gate int rv;
886*7c478bd9Sstevel@tonic-gate
887*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_DEVICE_RESET, 0, DCP(dcp), NULL, NULL);
888*7c478bd9Sstevel@tonic-gate
889*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
890*7c478bd9Sstevel@tonic-gate (void) printf("devctl_device_reset: %d\n", rv);
891*7c478bd9Sstevel@tonic-gate
892*7c478bd9Sstevel@tonic-gate return (rv);
893*7c478bd9Sstevel@tonic-gate }
894*7c478bd9Sstevel@tonic-gate
895*7c478bd9Sstevel@tonic-gate int
devctl_device_getstate(devctl_hdl_t dcp,uint_t * devstate)896*7c478bd9Sstevel@tonic-gate devctl_device_getstate(devctl_hdl_t dcp, uint_t *devstate)
897*7c478bd9Sstevel@tonic-gate {
898*7c478bd9Sstevel@tonic-gate int rv;
899*7c478bd9Sstevel@tonic-gate uint_t device_state;
900*7c478bd9Sstevel@tonic-gate
901*7c478bd9Sstevel@tonic-gate if (devstate == NULL) {
902*7c478bd9Sstevel@tonic-gate errno = EINVAL;
903*7c478bd9Sstevel@tonic-gate return (-1);
904*7c478bd9Sstevel@tonic-gate }
905*7c478bd9Sstevel@tonic-gate
906*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_DEVICE_GETSTATE, 0, DCP(dcp), NULL,
907*7c478bd9Sstevel@tonic-gate (void *)&device_state);
908*7c478bd9Sstevel@tonic-gate
909*7c478bd9Sstevel@tonic-gate if (rv == -1)
910*7c478bd9Sstevel@tonic-gate *devstate = 0;
911*7c478bd9Sstevel@tonic-gate else
912*7c478bd9Sstevel@tonic-gate *devstate = device_state;
913*7c478bd9Sstevel@tonic-gate
914*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
915*7c478bd9Sstevel@tonic-gate (void) printf("devctl_device_getstate: rv %d state %x\n",
916*7c478bd9Sstevel@tonic-gate rv, *devstate);
917*7c478bd9Sstevel@tonic-gate
918*7c478bd9Sstevel@tonic-gate return (rv);
919*7c478bd9Sstevel@tonic-gate }
920*7c478bd9Sstevel@tonic-gate
921*7c478bd9Sstevel@tonic-gate int
devctl_bus_getstate(devctl_hdl_t dcp,uint_t * devstate)922*7c478bd9Sstevel@tonic-gate devctl_bus_getstate(devctl_hdl_t dcp, uint_t *devstate)
923*7c478bd9Sstevel@tonic-gate {
924*7c478bd9Sstevel@tonic-gate int rv;
925*7c478bd9Sstevel@tonic-gate uint_t device_state;
926*7c478bd9Sstevel@tonic-gate
927*7c478bd9Sstevel@tonic-gate if (devstate == NULL) {
928*7c478bd9Sstevel@tonic-gate errno = EINVAL;
929*7c478bd9Sstevel@tonic-gate return (-1);
930*7c478bd9Sstevel@tonic-gate }
931*7c478bd9Sstevel@tonic-gate
932*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_GETSTATE, 0, DCP(dcp), NULL,
933*7c478bd9Sstevel@tonic-gate (void *)&device_state);
934*7c478bd9Sstevel@tonic-gate
935*7c478bd9Sstevel@tonic-gate if (rv == -1)
936*7c478bd9Sstevel@tonic-gate *devstate = 0;
937*7c478bd9Sstevel@tonic-gate else
938*7c478bd9Sstevel@tonic-gate *devstate = device_state;
939*7c478bd9Sstevel@tonic-gate
940*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
941*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_getstate: rv %d, state %x\n",
942*7c478bd9Sstevel@tonic-gate rv, *devstate);
943*7c478bd9Sstevel@tonic-gate
944*7c478bd9Sstevel@tonic-gate return (rv);
945*7c478bd9Sstevel@tonic-gate }
946*7c478bd9Sstevel@tonic-gate
947*7c478bd9Sstevel@tonic-gate int
devctl_bus_configure(devctl_hdl_t dcp)948*7c478bd9Sstevel@tonic-gate devctl_bus_configure(devctl_hdl_t dcp)
949*7c478bd9Sstevel@tonic-gate {
950*7c478bd9Sstevel@tonic-gate int rv;
951*7c478bd9Sstevel@tonic-gate
952*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_CONFIGURE, 0, DCP(dcp), NULL, NULL);
953*7c478bd9Sstevel@tonic-gate
954*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
955*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_configure: %d\n", rv);
956*7c478bd9Sstevel@tonic-gate
957*7c478bd9Sstevel@tonic-gate return (rv);
958*7c478bd9Sstevel@tonic-gate }
959*7c478bd9Sstevel@tonic-gate
960*7c478bd9Sstevel@tonic-gate int
devctl_bus_unconfigure(devctl_hdl_t dcp)961*7c478bd9Sstevel@tonic-gate devctl_bus_unconfigure(devctl_hdl_t dcp)
962*7c478bd9Sstevel@tonic-gate {
963*7c478bd9Sstevel@tonic-gate int rv;
964*7c478bd9Sstevel@tonic-gate
965*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_UNCONFIGURE, 0, DCP(dcp), NULL, NULL);
966*7c478bd9Sstevel@tonic-gate
967*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
968*7c478bd9Sstevel@tonic-gate (void) printf("devctl_bus_unconfigure: %d\n", rv);
969*7c478bd9Sstevel@tonic-gate
970*7c478bd9Sstevel@tonic-gate return (rv);
971*7c478bd9Sstevel@tonic-gate }
972*7c478bd9Sstevel@tonic-gate
973*7c478bd9Sstevel@tonic-gate /*
974*7c478bd9Sstevel@tonic-gate * devctl_bus_dev_create() - create a new child device
975*7c478bd9Sstevel@tonic-gate * Attempt to construct and attach a new child device below a
976*7c478bd9Sstevel@tonic-gate * bus nexus (dcp). The device is defined using the devctl_ddef_*()
977*7c478bd9Sstevel@tonic-gate * routines to specify the set of bus-specific properties required
978*7c478bd9Sstevel@tonic-gate * to initalize and attach the device.
979*7c478bd9Sstevel@tonic-gate */
980*7c478bd9Sstevel@tonic-gate int
devctl_bus_dev_create(devctl_hdl_t dcp,devctl_ddef_t ddef_hdl,uint_t flags,devctl_hdl_t * new_dcp)981*7c478bd9Sstevel@tonic-gate devctl_bus_dev_create(devctl_hdl_t dcp, devctl_ddef_t ddef_hdl,
982*7c478bd9Sstevel@tonic-gate uint_t flags, devctl_hdl_t *new_dcp)
983*7c478bd9Sstevel@tonic-gate {
984*7c478bd9Sstevel@tonic-gate char devname[MAXNAMELEN];
985*7c478bd9Sstevel@tonic-gate char devpath[MAXPATHLEN];
986*7c478bd9Sstevel@tonic-gate int rv = 0;
987*7c478bd9Sstevel@tonic-gate
988*7c478bd9Sstevel@tonic-gate if (dcp == NULL || ddef_hdl == NULL) {
989*7c478bd9Sstevel@tonic-gate errno = EINVAL;
990*7c478bd9Sstevel@tonic-gate return (-1);
991*7c478bd9Sstevel@tonic-gate }
992*7c478bd9Sstevel@tonic-gate
993*7c478bd9Sstevel@tonic-gate (void) memset(devname, 0, sizeof (devname));
994*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_BUS_DEV_CREATE, flags, DCP(dcp),
995*7c478bd9Sstevel@tonic-gate (nvlist_t *)ddef_hdl, devname);
996*7c478bd9Sstevel@tonic-gate
997*7c478bd9Sstevel@tonic-gate /*
998*7c478bd9Sstevel@tonic-gate * construct a device handle for the new device
999*7c478bd9Sstevel@tonic-gate */
1000*7c478bd9Sstevel@tonic-gate if ((rv == 0) && (new_dcp != NULL)) {
1001*7c478bd9Sstevel@tonic-gate char *minorname, *lastslash;
1002*7c478bd9Sstevel@tonic-gate
1003*7c478bd9Sstevel@tonic-gate (void) memset(devpath, 0, sizeof (devpath));
1004*7c478bd9Sstevel@tonic-gate (void) strcat(devpath, DCP(dcp)->opath);
1005*7c478bd9Sstevel@tonic-gate
1006*7c478bd9Sstevel@tonic-gate /*
1007*7c478bd9Sstevel@tonic-gate * Take the pathname of the parent device, chop off
1008*7c478bd9Sstevel@tonic-gate * any minor name info, and append the name@addr of
1009*7c478bd9Sstevel@tonic-gate * the new child device.
1010*7c478bd9Sstevel@tonic-gate * Call dc_mkhndl() with this constructed path and
1011*7c478bd9Sstevel@tonic-gate * the CLONE handle type to create a new handle which
1012*7c478bd9Sstevel@tonic-gate * references the new child device.
1013*7c478bd9Sstevel@tonic-gate */
1014*7c478bd9Sstevel@tonic-gate lastslash = strrchr(devpath, '/');
1015*7c478bd9Sstevel@tonic-gate if (*(lastslash + 1) == '\0') {
1016*7c478bd9Sstevel@tonic-gate *lastslash = '\0';
1017*7c478bd9Sstevel@tonic-gate } else {
1018*7c478bd9Sstevel@tonic-gate if ((minorname = strchr(lastslash, ':')) != NULL)
1019*7c478bd9Sstevel@tonic-gate *minorname = '\0';
1020*7c478bd9Sstevel@tonic-gate }
1021*7c478bd9Sstevel@tonic-gate (void) strcat(devpath, "/");
1022*7c478bd9Sstevel@tonic-gate (void) strlcat(devpath, devname, MAXPATHLEN);
1023*7c478bd9Sstevel@tonic-gate *new_dcp = dc_mkhndl(DEVCTL_CLONE, devpath, 0, dcp);
1024*7c478bd9Sstevel@tonic-gate if (*new_dcp == NULL)
1025*7c478bd9Sstevel@tonic-gate rv = -1;
1026*7c478bd9Sstevel@tonic-gate }
1027*7c478bd9Sstevel@tonic-gate
1028*7c478bd9Sstevel@tonic-gate return (rv);
1029*7c478bd9Sstevel@tonic-gate }
1030*7c478bd9Sstevel@tonic-gate
1031*7c478bd9Sstevel@tonic-gate int
devctl_ap_connect(devctl_hdl_t dcp,nvlist_t * ap_data)1032*7c478bd9Sstevel@tonic-gate devctl_ap_connect(devctl_hdl_t dcp, nvlist_t *ap_data)
1033*7c478bd9Sstevel@tonic-gate {
1034*7c478bd9Sstevel@tonic-gate int rv;
1035*7c478bd9Sstevel@tonic-gate
1036*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_CONNECT, 0, DCP(dcp), ap_data, NULL);
1037*7c478bd9Sstevel@tonic-gate
1038*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1039*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_connect: %d\n", rv);
1040*7c478bd9Sstevel@tonic-gate
1041*7c478bd9Sstevel@tonic-gate return (rv);
1042*7c478bd9Sstevel@tonic-gate }
1043*7c478bd9Sstevel@tonic-gate
1044*7c478bd9Sstevel@tonic-gate int
devctl_ap_disconnect(devctl_hdl_t dcp,nvlist_t * ap_data)1045*7c478bd9Sstevel@tonic-gate devctl_ap_disconnect(devctl_hdl_t dcp, nvlist_t *ap_data)
1046*7c478bd9Sstevel@tonic-gate {
1047*7c478bd9Sstevel@tonic-gate int rv;
1048*7c478bd9Sstevel@tonic-gate
1049*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_DISCONNECT, 0, DCP(dcp), ap_data, NULL);
1050*7c478bd9Sstevel@tonic-gate
1051*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1052*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_disconnect: %d\n", rv);
1053*7c478bd9Sstevel@tonic-gate
1054*7c478bd9Sstevel@tonic-gate return (rv);
1055*7c478bd9Sstevel@tonic-gate }
1056*7c478bd9Sstevel@tonic-gate
1057*7c478bd9Sstevel@tonic-gate int
devctl_ap_insert(devctl_hdl_t dcp,nvlist_t * ap_data)1058*7c478bd9Sstevel@tonic-gate devctl_ap_insert(devctl_hdl_t dcp, nvlist_t *ap_data)
1059*7c478bd9Sstevel@tonic-gate {
1060*7c478bd9Sstevel@tonic-gate int rv;
1061*7c478bd9Sstevel@tonic-gate
1062*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_INSERT, 0, DCP(dcp), ap_data, NULL);
1063*7c478bd9Sstevel@tonic-gate
1064*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1065*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_insert: %d\n", rv);
1066*7c478bd9Sstevel@tonic-gate
1067*7c478bd9Sstevel@tonic-gate return (rv);
1068*7c478bd9Sstevel@tonic-gate }
1069*7c478bd9Sstevel@tonic-gate
1070*7c478bd9Sstevel@tonic-gate int
devctl_ap_remove(devctl_hdl_t dcp,nvlist_t * ap_data)1071*7c478bd9Sstevel@tonic-gate devctl_ap_remove(devctl_hdl_t dcp, nvlist_t *ap_data)
1072*7c478bd9Sstevel@tonic-gate {
1073*7c478bd9Sstevel@tonic-gate int rv;
1074*7c478bd9Sstevel@tonic-gate
1075*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_REMOVE, 0, DCP(dcp), ap_data, NULL);
1076*7c478bd9Sstevel@tonic-gate
1077*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1078*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_remove: %d\n", rv);
1079*7c478bd9Sstevel@tonic-gate
1080*7c478bd9Sstevel@tonic-gate return (rv);
1081*7c478bd9Sstevel@tonic-gate }
1082*7c478bd9Sstevel@tonic-gate
1083*7c478bd9Sstevel@tonic-gate int
devctl_ap_configure(devctl_hdl_t dcp,nvlist_t * ap_data)1084*7c478bd9Sstevel@tonic-gate devctl_ap_configure(devctl_hdl_t dcp, nvlist_t *ap_data)
1085*7c478bd9Sstevel@tonic-gate {
1086*7c478bd9Sstevel@tonic-gate int rv;
1087*7c478bd9Sstevel@tonic-gate
1088*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_CONFIGURE, 0, DCP(dcp), ap_data, NULL);
1089*7c478bd9Sstevel@tonic-gate
1090*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1091*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_configure: %d\n", rv);
1092*7c478bd9Sstevel@tonic-gate
1093*7c478bd9Sstevel@tonic-gate return (rv);
1094*7c478bd9Sstevel@tonic-gate }
1095*7c478bd9Sstevel@tonic-gate
1096*7c478bd9Sstevel@tonic-gate int
devctl_ap_unconfigure(devctl_hdl_t dcp,nvlist_t * ap_data)1097*7c478bd9Sstevel@tonic-gate devctl_ap_unconfigure(devctl_hdl_t dcp, nvlist_t *ap_data)
1098*7c478bd9Sstevel@tonic-gate {
1099*7c478bd9Sstevel@tonic-gate int rv;
1100*7c478bd9Sstevel@tonic-gate
1101*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_UNCONFIGURE, 0, DCP(dcp), ap_data, NULL);
1102*7c478bd9Sstevel@tonic-gate
1103*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1104*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_unconfigure: %d\n", rv);
1105*7c478bd9Sstevel@tonic-gate
1106*7c478bd9Sstevel@tonic-gate return (rv);
1107*7c478bd9Sstevel@tonic-gate }
1108*7c478bd9Sstevel@tonic-gate
1109*7c478bd9Sstevel@tonic-gate int
devctl_ap_getstate(devctl_hdl_t dcp,nvlist_t * ap_data,devctl_ap_state_t * apstate)1110*7c478bd9Sstevel@tonic-gate devctl_ap_getstate(devctl_hdl_t dcp, nvlist_t *ap_data,
1111*7c478bd9Sstevel@tonic-gate devctl_ap_state_t *apstate)
1112*7c478bd9Sstevel@tonic-gate {
1113*7c478bd9Sstevel@tonic-gate int rv;
1114*7c478bd9Sstevel@tonic-gate devctl_ap_state_t ap_state;
1115*7c478bd9Sstevel@tonic-gate
1116*7c478bd9Sstevel@tonic-gate rv = dc_cmd(DEVCTL_AP_GETSTATE, 0, DCP(dcp), ap_data,
1117*7c478bd9Sstevel@tonic-gate (void *)&ap_state);
1118*7c478bd9Sstevel@tonic-gate
1119*7c478bd9Sstevel@tonic-gate if (rv == -1)
1120*7c478bd9Sstevel@tonic-gate (void) memset(apstate, 0, sizeof (struct devctl_ap_state));
1121*7c478bd9Sstevel@tonic-gate else
1122*7c478bd9Sstevel@tonic-gate *apstate = ap_state;
1123*7c478bd9Sstevel@tonic-gate
1124*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1125*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ap_getstate: %d\n", rv);
1126*7c478bd9Sstevel@tonic-gate
1127*7c478bd9Sstevel@tonic-gate return (rv);
1128*7c478bd9Sstevel@tonic-gate }
1129*7c478bd9Sstevel@tonic-gate
1130*7c478bd9Sstevel@tonic-gate /*
1131*7c478bd9Sstevel@tonic-gate * Allocate a device 'definition' handle, in reality a list of
1132*7c478bd9Sstevel@tonic-gate * nvpair data.
1133*7c478bd9Sstevel@tonic-gate */
1134*7c478bd9Sstevel@tonic-gate /* ARGSUSED */
1135*7c478bd9Sstevel@tonic-gate devctl_ddef_t
devctl_ddef_alloc(char * nodename,int flags)1136*7c478bd9Sstevel@tonic-gate devctl_ddef_alloc(char *nodename, int flags)
1137*7c478bd9Sstevel@tonic-gate {
1138*7c478bd9Sstevel@tonic-gate
1139*7c478bd9Sstevel@tonic-gate nvlist_t *nvlp;
1140*7c478bd9Sstevel@tonic-gate
1141*7c478bd9Sstevel@tonic-gate if ((nodename == NULL) || *nodename == '\0') {
1142*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1143*7c478bd9Sstevel@tonic-gate return (NULL);
1144*7c478bd9Sstevel@tonic-gate }
1145*7c478bd9Sstevel@tonic-gate
1146*7c478bd9Sstevel@tonic-gate /*
1147*7c478bd9Sstevel@tonic-gate * allocate nvlist structure which is returned as an
1148*7c478bd9Sstevel@tonic-gate * opaque handle to the caller. If this fails, return
1149*7c478bd9Sstevel@tonic-gate * NULL with errno left set to the value
1150*7c478bd9Sstevel@tonic-gate */
1151*7c478bd9Sstevel@tonic-gate if (nvlist_alloc(&nvlp, NV_UNIQUE_NAME_TYPE, 0) != 0) {
1152*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
1153*7c478bd9Sstevel@tonic-gate return (NULL);
1154*7c478bd9Sstevel@tonic-gate }
1155*7c478bd9Sstevel@tonic-gate
1156*7c478bd9Sstevel@tonic-gate /*
1157*7c478bd9Sstevel@tonic-gate * add the nodename of the new device to the list
1158*7c478bd9Sstevel@tonic-gate */
1159*7c478bd9Sstevel@tonic-gate if (nvlist_add_string(nvlp, DC_DEVI_NODENAME, nodename) != 0) {
1160*7c478bd9Sstevel@tonic-gate nvlist_free(nvlp);
1161*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
1162*7c478bd9Sstevel@tonic-gate return (NULL);
1163*7c478bd9Sstevel@tonic-gate }
1164*7c478bd9Sstevel@tonic-gate
1165*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1166*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ddef_alloc: node %s nvp %p\n", nodename,
1167*7c478bd9Sstevel@tonic-gate (void *)nvlp);
1168*7c478bd9Sstevel@tonic-gate
1169*7c478bd9Sstevel@tonic-gate return ((devctl_ddef_t)nvlp);
1170*7c478bd9Sstevel@tonic-gate }
1171*7c478bd9Sstevel@tonic-gate
1172*7c478bd9Sstevel@tonic-gate /*
1173*7c478bd9Sstevel@tonic-gate * free the definition handle
1174*7c478bd9Sstevel@tonic-gate */
1175*7c478bd9Sstevel@tonic-gate void
devctl_ddef_free(devctl_ddef_t ddef_hdl)1176*7c478bd9Sstevel@tonic-gate devctl_ddef_free(devctl_ddef_t ddef_hdl)
1177*7c478bd9Sstevel@tonic-gate {
1178*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1179*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ddef_free: nvp %p\n", (void *)ddef_hdl);
1180*7c478bd9Sstevel@tonic-gate
1181*7c478bd9Sstevel@tonic-gate if (ddef_hdl != NULL) {
1182*7c478bd9Sstevel@tonic-gate nvlist_free((nvlist_t *)ddef_hdl);
1183*7c478bd9Sstevel@tonic-gate }
1184*7c478bd9Sstevel@tonic-gate }
1185*7c478bd9Sstevel@tonic-gate
1186*7c478bd9Sstevel@tonic-gate /*
1187*7c478bd9Sstevel@tonic-gate * define an integer property
1188*7c478bd9Sstevel@tonic-gate */
1189*7c478bd9Sstevel@tonic-gate int
devctl_ddef_int(devctl_ddef_t ddef_hdl,char * name,int32_t value)1190*7c478bd9Sstevel@tonic-gate devctl_ddef_int(devctl_ddef_t ddef_hdl, char *name, int32_t value)
1191*7c478bd9Sstevel@tonic-gate {
1192*7c478bd9Sstevel@tonic-gate
1193*7c478bd9Sstevel@tonic-gate int rv;
1194*7c478bd9Sstevel@tonic-gate
1195*7c478bd9Sstevel@tonic-gate if (ddef_hdl == NULL || name == NULL || *name == '\0') {
1196*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1197*7c478bd9Sstevel@tonic-gate return (-1);
1198*7c478bd9Sstevel@tonic-gate }
1199*7c478bd9Sstevel@tonic-gate
1200*7c478bd9Sstevel@tonic-gate rv = nvlist_add_int32((nvlist_t *)ddef_hdl, name, value);
1201*7c478bd9Sstevel@tonic-gate
1202*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1203*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ddef_int: rv %d nvp %p name %s val %d\n",
1204*7c478bd9Sstevel@tonic-gate rv, (void *)ddef_hdl, name, value);
1205*7c478bd9Sstevel@tonic-gate
1206*7c478bd9Sstevel@tonic-gate return (rv);
1207*7c478bd9Sstevel@tonic-gate }
1208*7c478bd9Sstevel@tonic-gate
1209*7c478bd9Sstevel@tonic-gate /*
1210*7c478bd9Sstevel@tonic-gate * define an integer array property
1211*7c478bd9Sstevel@tonic-gate */
1212*7c478bd9Sstevel@tonic-gate int
devctl_ddef_int_array(devctl_ddef_t ddef_hdl,char * name,int nelements,int32_t * value)1213*7c478bd9Sstevel@tonic-gate devctl_ddef_int_array(devctl_ddef_t ddef_hdl, char *name, int nelements,
1214*7c478bd9Sstevel@tonic-gate int32_t *value)
1215*7c478bd9Sstevel@tonic-gate {
1216*7c478bd9Sstevel@tonic-gate int rv, i;
1217*7c478bd9Sstevel@tonic-gate
1218*7c478bd9Sstevel@tonic-gate if (ddef_hdl == NULL || name == NULL || *name == '\0') {
1219*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1220*7c478bd9Sstevel@tonic-gate return (-1);
1221*7c478bd9Sstevel@tonic-gate }
1222*7c478bd9Sstevel@tonic-gate
1223*7c478bd9Sstevel@tonic-gate rv = nvlist_add_int32_array((nvlist_t *)ddef_hdl, name, value,
1224*7c478bd9Sstevel@tonic-gate nelements);
1225*7c478bd9Sstevel@tonic-gate
1226*7c478bd9Sstevel@tonic-gate if (_libdevice_debug) {
1227*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ddef_int_array: rv %d nvp %p name %s: ",
1228*7c478bd9Sstevel@tonic-gate rv, (void *)ddef_hdl, name);
1229*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelements; i++)
1230*7c478bd9Sstevel@tonic-gate (void) printf("0x%x ", value[i]);
1231*7c478bd9Sstevel@tonic-gate (void) printf("\n");
1232*7c478bd9Sstevel@tonic-gate }
1233*7c478bd9Sstevel@tonic-gate
1234*7c478bd9Sstevel@tonic-gate return (rv);
1235*7c478bd9Sstevel@tonic-gate }
1236*7c478bd9Sstevel@tonic-gate
1237*7c478bd9Sstevel@tonic-gate /*
1238*7c478bd9Sstevel@tonic-gate * define a string property
1239*7c478bd9Sstevel@tonic-gate */
1240*7c478bd9Sstevel@tonic-gate int
devctl_ddef_string(devctl_ddef_t ddef_hdl,char * name,char * value)1241*7c478bd9Sstevel@tonic-gate devctl_ddef_string(devctl_ddef_t ddef_hdl, char *name, char *value)
1242*7c478bd9Sstevel@tonic-gate {
1243*7c478bd9Sstevel@tonic-gate int rv;
1244*7c478bd9Sstevel@tonic-gate
1245*7c478bd9Sstevel@tonic-gate if (ddef_hdl == NULL || name == NULL || *name == '\0') {
1246*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1247*7c478bd9Sstevel@tonic-gate return (-1);
1248*7c478bd9Sstevel@tonic-gate }
1249*7c478bd9Sstevel@tonic-gate
1250*7c478bd9Sstevel@tonic-gate rv = nvlist_add_string((nvlist_t *)ddef_hdl, name, value);
1251*7c478bd9Sstevel@tonic-gate
1252*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1253*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ddef_string: rv %d nvp %p %s=\"%s\"\n",
1254*7c478bd9Sstevel@tonic-gate rv, (void *)ddef_hdl, name, value);
1255*7c478bd9Sstevel@tonic-gate
1256*7c478bd9Sstevel@tonic-gate return (rv);
1257*7c478bd9Sstevel@tonic-gate }
1258*7c478bd9Sstevel@tonic-gate
1259*7c478bd9Sstevel@tonic-gate /*
1260*7c478bd9Sstevel@tonic-gate * define a string array property
1261*7c478bd9Sstevel@tonic-gate */
1262*7c478bd9Sstevel@tonic-gate int
devctl_ddef_string_array(devctl_ddef_t ddef_hdl,char * name,int nelements,char ** value)1263*7c478bd9Sstevel@tonic-gate devctl_ddef_string_array(devctl_ddef_t ddef_hdl, char *name, int nelements,
1264*7c478bd9Sstevel@tonic-gate char **value)
1265*7c478bd9Sstevel@tonic-gate {
1266*7c478bd9Sstevel@tonic-gate int rv, i;
1267*7c478bd9Sstevel@tonic-gate
1268*7c478bd9Sstevel@tonic-gate if (ddef_hdl == NULL || name == NULL || *name == '\0') {
1269*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1270*7c478bd9Sstevel@tonic-gate return (-1);
1271*7c478bd9Sstevel@tonic-gate }
1272*7c478bd9Sstevel@tonic-gate
1273*7c478bd9Sstevel@tonic-gate rv = nvlist_add_string_array((nvlist_t *)ddef_hdl, name,
1274*7c478bd9Sstevel@tonic-gate value, nelements);
1275*7c478bd9Sstevel@tonic-gate
1276*7c478bd9Sstevel@tonic-gate if (_libdevice_debug) {
1277*7c478bd9Sstevel@tonic-gate (void) printf("devctl_ddef_string_array: rv %d nvp %p "
1278*7c478bd9Sstevel@tonic-gate "name %s:\n", rv, (void *)ddef_hdl, name);
1279*7c478bd9Sstevel@tonic-gate for (i = 0; i < nelements; i++)
1280*7c478bd9Sstevel@tonic-gate (void) printf("\t%d: \"%s\"\n", i, value[i]);
1281*7c478bd9Sstevel@tonic-gate }
1282*7c478bd9Sstevel@tonic-gate return (rv);
1283*7c478bd9Sstevel@tonic-gate }
1284*7c478bd9Sstevel@tonic-gate
1285*7c478bd9Sstevel@tonic-gate /*
1286*7c478bd9Sstevel@tonic-gate * define a byte array property
1287*7c478bd9Sstevel@tonic-gate */
1288*7c478bd9Sstevel@tonic-gate int
devctl_ddef_byte_array(devctl_ddef_t ddef_hdl,char * name,int nelements,uchar_t * value)1289*7c478bd9Sstevel@tonic-gate devctl_ddef_byte_array(devctl_ddef_t ddef_hdl, char *name, int nelements,
1290*7c478bd9Sstevel@tonic-gate uchar_t *value)
1291*7c478bd9Sstevel@tonic-gate {
1292*7c478bd9Sstevel@tonic-gate int rv;
1293*7c478bd9Sstevel@tonic-gate
1294*7c478bd9Sstevel@tonic-gate if (ddef_hdl == NULL || name == NULL || *name == '\0') {
1295*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1296*7c478bd9Sstevel@tonic-gate return (-1);
1297*7c478bd9Sstevel@tonic-gate }
1298*7c478bd9Sstevel@tonic-gate
1299*7c478bd9Sstevel@tonic-gate rv = nvlist_add_byte_array((nvlist_t *)ddef_hdl, name, value,
1300*7c478bd9Sstevel@tonic-gate nelements);
1301*7c478bd9Sstevel@tonic-gate
1302*7c478bd9Sstevel@tonic-gate return (rv);
1303*7c478bd9Sstevel@tonic-gate }
1304*7c478bd9Sstevel@tonic-gate
1305*7c478bd9Sstevel@tonic-gate /*
1306*7c478bd9Sstevel@tonic-gate * return the pathname which was used to acquire the handle
1307*7c478bd9Sstevel@tonic-gate */
1308*7c478bd9Sstevel@tonic-gate char *
devctl_get_pathname(devctl_hdl_t dcp,char * pathbuf,size_t bufsz)1309*7c478bd9Sstevel@tonic-gate devctl_get_pathname(devctl_hdl_t dcp, char *pathbuf, size_t bufsz)
1310*7c478bd9Sstevel@tonic-gate {
1311*7c478bd9Sstevel@tonic-gate if (dcp == NULL || pathbuf == NULL || bufsz == 0) {
1312*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1313*7c478bd9Sstevel@tonic-gate return (NULL);
1314*7c478bd9Sstevel@tonic-gate }
1315*7c478bd9Sstevel@tonic-gate
1316*7c478bd9Sstevel@tonic-gate (void) snprintf(pathbuf, bufsz, "%s", DCP(dcp)->opath);
1317*7c478bd9Sstevel@tonic-gate return (pathbuf);
1318*7c478bd9Sstevel@tonic-gate }
1319*7c478bd9Sstevel@tonic-gate
1320*7c478bd9Sstevel@tonic-gate
1321*7c478bd9Sstevel@tonic-gate /*
1322*7c478bd9Sstevel@tonic-gate * execute the IOCTL request
1323*7c478bd9Sstevel@tonic-gate */
1324*7c478bd9Sstevel@tonic-gate static int
dc_cmd(uint_t cmd,uint_t flags,struct devctl_hdl * dcp,nvlist_t * ulp,void * retinfo)1325*7c478bd9Sstevel@tonic-gate dc_cmd(uint_t cmd, uint_t flags, struct devctl_hdl *dcp, nvlist_t *ulp,
1326*7c478bd9Sstevel@tonic-gate void *retinfo)
1327*7c478bd9Sstevel@tonic-gate {
1328*7c478bd9Sstevel@tonic-gate struct devctl_iocdata iocdata;
1329*7c478bd9Sstevel@tonic-gate int rv = 0;
1330*7c478bd9Sstevel@tonic-gate
1331*7c478bd9Sstevel@tonic-gate if (_libdevice_debug)
1332*7c478bd9Sstevel@tonic-gate (void) printf("dc_cmd: %x dcp %p ulp %p flags %x rv %p\n", cmd,
1333*7c478bd9Sstevel@tonic-gate (void *)dcp, (void *)ulp, flags, retinfo);
1334*7c478bd9Sstevel@tonic-gate
1335*7c478bd9Sstevel@tonic-gate if ((dcp == NULL) || (DCP(dcp)->fd == -1)) {
1336*7c478bd9Sstevel@tonic-gate errno = EINVAL;
1337*7c478bd9Sstevel@tonic-gate return (-1);
1338*7c478bd9Sstevel@tonic-gate }
1339*7c478bd9Sstevel@tonic-gate
1340*7c478bd9Sstevel@tonic-gate (void) memset(&iocdata, 0, sizeof (struct devctl_iocdata));
1341*7c478bd9Sstevel@tonic-gate
1342*7c478bd9Sstevel@tonic-gate /*
1343*7c478bd9Sstevel@tonic-gate * if there was any user supplied data in the form of a nvlist,
1344*7c478bd9Sstevel@tonic-gate * pack the list prior to copyin.
1345*7c478bd9Sstevel@tonic-gate */
1346*7c478bd9Sstevel@tonic-gate if (ulp != NULL) {
1347*7c478bd9Sstevel@tonic-gate if (rv = nvlist_pack(ulp, (char **)&iocdata.nvl_user,
1348*7c478bd9Sstevel@tonic-gate &iocdata.nvl_usersz, NV_ENCODE_NATIVE, 0)) {
1349*7c478bd9Sstevel@tonic-gate /*
1350*7c478bd9Sstevel@tonic-gate * exit with errno set by nvlist_pack()
1351*7c478bd9Sstevel@tonic-gate */
1352*7c478bd9Sstevel@tonic-gate goto exit;
1353*7c478bd9Sstevel@tonic-gate }
1354*7c478bd9Sstevel@tonic-gate } else {
1355*7c478bd9Sstevel@tonic-gate iocdata.nvl_user = NULL;
1356*7c478bd9Sstevel@tonic-gate iocdata.nvl_usersz = 0;
1357*7c478bd9Sstevel@tonic-gate }
1358*7c478bd9Sstevel@tonic-gate
1359*7c478bd9Sstevel@tonic-gate /*
1360*7c478bd9Sstevel@tonic-gate * finish initalizing the request and execute the IOCTL
1361*7c478bd9Sstevel@tonic-gate */
1362*7c478bd9Sstevel@tonic-gate iocdata.cmd = cmd;
1363*7c478bd9Sstevel@tonic-gate iocdata.flags = flags;
1364*7c478bd9Sstevel@tonic-gate iocdata.c_nodename = dcp->nodename;
1365*7c478bd9Sstevel@tonic-gate iocdata.c_unitaddr = dcp->unitaddr;
1366*7c478bd9Sstevel@tonic-gate iocdata.cpyout_buf = retinfo;
1367*7c478bd9Sstevel@tonic-gate rv = ioctl(dcp->fd, cmd, &iocdata);
1368*7c478bd9Sstevel@tonic-gate if (rv < 0 && _libdevice_debug) {
1369*7c478bd9Sstevel@tonic-gate (void) printf("dc_cmd: exited with rv %d, errno(%d):%s\n",
1370*7c478bd9Sstevel@tonic-gate rv, errno, strerror(errno));
1371*7c478bd9Sstevel@tonic-gate }
1372*7c478bd9Sstevel@tonic-gate
1373*7c478bd9Sstevel@tonic-gate exit:
1374*7c478bd9Sstevel@tonic-gate if (iocdata.nvl_user != NULL)
1375*7c478bd9Sstevel@tonic-gate free(iocdata.nvl_user);
1376*7c478bd9Sstevel@tonic-gate
1377*7c478bd9Sstevel@tonic-gate return (rv);
1378*7c478bd9Sstevel@tonic-gate }
1379