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