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 /* 30*7c478bd9Sstevel@tonic-gate * Interfaces for getting device configuration data from kernel 31*7c478bd9Sstevel@tonic-gate * through the devinfo driver. 32*7c478bd9Sstevel@tonic-gate */ 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #include <stdio.h> 35*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 36*7c478bd9Sstevel@tonic-gate #include <string.h> 37*7c478bd9Sstevel@tonic-gate #include <strings.h> 38*7c478bd9Sstevel@tonic-gate #include <stropts.h> 39*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 40*7c478bd9Sstevel@tonic-gate #include <poll.h> 41*7c478bd9Sstevel@tonic-gate #include <synch.h> 42*7c478bd9Sstevel@tonic-gate #include <unistd.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/obpdefs.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/autoconf.h> 49*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate #define NDEBUG 1 52*7c478bd9Sstevel@tonic-gate #include <assert.h> 53*7c478bd9Sstevel@tonic-gate 54*7c478bd9Sstevel@tonic-gate #include "libdevinfo.h" 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate /* 57*7c478bd9Sstevel@tonic-gate * Debug message levels 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate typedef enum { 60*7c478bd9Sstevel@tonic-gate DI_QUIET = 0, /* No debug messages - the default */ 61*7c478bd9Sstevel@tonic-gate DI_ERR = 1, 62*7c478bd9Sstevel@tonic-gate DI_INFO, 63*7c478bd9Sstevel@tonic-gate DI_TRACE, 64*7c478bd9Sstevel@tonic-gate DI_TRACE1, 65*7c478bd9Sstevel@tonic-gate DI_TRACE2 66*7c478bd9Sstevel@tonic-gate } di_debug_t; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate int di_debug = DI_QUIET; 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate #define DPRINTF(args) { if (di_debug != DI_QUIET) dprint args; } 71*7c478bd9Sstevel@tonic-gate 72*7c478bd9Sstevel@tonic-gate void dprint(di_debug_t msglevel, const char *fmt, ...); 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate #pragma init(_libdevinfo_init) 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate void 78*7c478bd9Sstevel@tonic-gate _libdevinfo_init() 79*7c478bd9Sstevel@tonic-gate { 80*7c478bd9Sstevel@tonic-gate char *debug_str = getenv("_LIBDEVINFO_DEBUG"); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate if (debug_str) { 83*7c478bd9Sstevel@tonic-gate errno = 0; 84*7c478bd9Sstevel@tonic-gate di_debug = atoi(debug_str); 85*7c478bd9Sstevel@tonic-gate if (errno || di_debug < DI_QUIET) 86*7c478bd9Sstevel@tonic-gate di_debug = DI_QUIET; 87*7c478bd9Sstevel@tonic-gate } 88*7c478bd9Sstevel@tonic-gate } 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gate di_node_t 91*7c478bd9Sstevel@tonic-gate di_init(const char *phys_path, uint_t flag) 92*7c478bd9Sstevel@tonic-gate { 93*7c478bd9Sstevel@tonic-gate return (di_init_impl(phys_path, flag, NULL)); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * We use blocking_open() to guarantee access to the devinfo device, if open() 98*7c478bd9Sstevel@tonic-gate * is failing with EAGAIN. 99*7c478bd9Sstevel@tonic-gate */ 100*7c478bd9Sstevel@tonic-gate static int 101*7c478bd9Sstevel@tonic-gate blocking_open(const char *path, int oflag) 102*7c478bd9Sstevel@tonic-gate { 103*7c478bd9Sstevel@tonic-gate int fd; 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate while ((fd = open(path, oflag)) == -1 && errno == EAGAIN) 106*7c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, 1 * MILLISEC); 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate return (fd); 109*7c478bd9Sstevel@tonic-gate } 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate /* private interface */ 112*7c478bd9Sstevel@tonic-gate di_node_t 113*7c478bd9Sstevel@tonic-gate di_init_driver(const char *drv_name, uint_t flag) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate int fd; 116*7c478bd9Sstevel@tonic-gate char driver[MAXPATHLEN]; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate /* 119*7c478bd9Sstevel@tonic-gate * Don't allow drv_name to exceed MAXPATHLEN - 1, or 1023, 120*7c478bd9Sstevel@tonic-gate * which should be sufficient for any sensible programmer. 121*7c478bd9Sstevel@tonic-gate */ 122*7c478bd9Sstevel@tonic-gate if ((drv_name == NULL) || (strlen(drv_name) >= MAXPATHLEN)) { 123*7c478bd9Sstevel@tonic-gate errno = EINVAL; 124*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate (void) strcpy(driver, drv_name); 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate /* 129*7c478bd9Sstevel@tonic-gate * open the devinfo driver 130*7c478bd9Sstevel@tonic-gate */ 131*7c478bd9Sstevel@tonic-gate if ((fd = blocking_open("/devices/pseudo/devinfo@0:devinfo", 132*7c478bd9Sstevel@tonic-gate O_RDONLY)) == -1) { 133*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo open failed: errno = %d\n", errno)); 134*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 135*7c478bd9Sstevel@tonic-gate } 136*7c478bd9Sstevel@tonic-gate 137*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DINFOLODRV, driver) != 0) { 138*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "failed to load driver %s\n", driver)); 139*7c478bd9Sstevel@tonic-gate (void) close(fd); 140*7c478bd9Sstevel@tonic-gate errno = ENXIO; 141*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate (void) close(fd); 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * Driver load succeeded, return a snapshot 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate return (di_init("/", flag)); 149*7c478bd9Sstevel@tonic-gate } 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate di_node_t 152*7c478bd9Sstevel@tonic-gate di_init_impl(const char *phys_path, uint_t flag, 153*7c478bd9Sstevel@tonic-gate struct di_priv_data *priv) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate caddr_t pa; 156*7c478bd9Sstevel@tonic-gate int fd, map_size; 157*7c478bd9Sstevel@tonic-gate struct di_all *dap; 158*7c478bd9Sstevel@tonic-gate struct dinfo_io dinfo_io; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate uint_t pageoffset = sysconf(_SC_PAGESIZE) - 1; 161*7c478bd9Sstevel@tonic-gate uint_t pagemask = ~pageoffset; 162*7c478bd9Sstevel@tonic-gate 163*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_init: taking a snapshot\n")); 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* 166*7c478bd9Sstevel@tonic-gate * Make sure there is no minor name in the path 167*7c478bd9Sstevel@tonic-gate * and the path do not start with /devices.... 168*7c478bd9Sstevel@tonic-gate */ 169*7c478bd9Sstevel@tonic-gate if (strchr(phys_path, ':') || 170*7c478bd9Sstevel@tonic-gate (strncmp(phys_path, "/devices", 8) == 0) || 171*7c478bd9Sstevel@tonic-gate (strlen(phys_path) > MAXPATHLEN)) { 172*7c478bd9Sstevel@tonic-gate errno = EINVAL; 173*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if (strlen(phys_path) == 0) 177*7c478bd9Sstevel@tonic-gate (void) sprintf(dinfo_io.root_path, "/"); 178*7c478bd9Sstevel@tonic-gate else if (*phys_path != '/') 179*7c478bd9Sstevel@tonic-gate (void) snprintf(dinfo_io.root_path, sizeof (dinfo_io.root_path), 180*7c478bd9Sstevel@tonic-gate "/%s", phys_path); 181*7c478bd9Sstevel@tonic-gate else 182*7c478bd9Sstevel@tonic-gate (void) snprintf(dinfo_io.root_path, sizeof (dinfo_io.root_path), 183*7c478bd9Sstevel@tonic-gate "%s", phys_path); 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate /* 186*7c478bd9Sstevel@tonic-gate * If private data is requested, copy the format specification 187*7c478bd9Sstevel@tonic-gate */ 188*7c478bd9Sstevel@tonic-gate if (flag & DINFOPRIVDATA & 0xff) { 189*7c478bd9Sstevel@tonic-gate if (priv) 190*7c478bd9Sstevel@tonic-gate bcopy(priv, &dinfo_io.priv, 191*7c478bd9Sstevel@tonic-gate sizeof (struct di_priv_data)); 192*7c478bd9Sstevel@tonic-gate else { 193*7c478bd9Sstevel@tonic-gate errno = EINVAL; 194*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* 199*7c478bd9Sstevel@tonic-gate * Attempt to open the devinfo driver. Make a second attempt at the 200*7c478bd9Sstevel@tonic-gate * read-only minor node if we don't have privileges to open the full 201*7c478bd9Sstevel@tonic-gate * version _and_ if we're not requesting operations that the read-only 202*7c478bd9Sstevel@tonic-gate * node can't perform. (Setgid processes would fail an access() test, 203*7c478bd9Sstevel@tonic-gate * of course.) 204*7c478bd9Sstevel@tonic-gate */ 205*7c478bd9Sstevel@tonic-gate if ((fd = blocking_open("/devices/pseudo/devinfo@0:devinfo", 206*7c478bd9Sstevel@tonic-gate O_RDONLY)) == -1) { 207*7c478bd9Sstevel@tonic-gate if ((flag & DINFOFORCE) == DINFOFORCE || 208*7c478bd9Sstevel@tonic-gate (flag & DINFOPRIVDATA) == DINFOPRIVDATA) { 209*7c478bd9Sstevel@tonic-gate /* 210*7c478bd9Sstevel@tonic-gate * We wanted to perform a privileged operation, but the 211*7c478bd9Sstevel@tonic-gate * privileged node isn't available. Don't modify errno 212*7c478bd9Sstevel@tonic-gate * on our way out (but display it if we're running with 213*7c478bd9Sstevel@tonic-gate * di_debug set). 214*7c478bd9Sstevel@tonic-gate */ 215*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo open failed: errno = %d\n", 216*7c478bd9Sstevel@tonic-gate errno)); 217*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate if ((fd = blocking_open("/devices/pseudo/devinfo@0:devinfo,ro", 221*7c478bd9Sstevel@tonic-gate O_RDONLY)) == -1) { 222*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo open failed: errno = %d\n", 223*7c478bd9Sstevel@tonic-gate errno)); 224*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 225*7c478bd9Sstevel@tonic-gate } 226*7c478bd9Sstevel@tonic-gate } 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate /* 229*7c478bd9Sstevel@tonic-gate * Verify that there is no major conflict, i.e., we are indeed opening 230*7c478bd9Sstevel@tonic-gate * the devinfo driver. 231*7c478bd9Sstevel@tonic-gate */ 232*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DINFOIDENT, NULL) != DI_MAGIC) { 233*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, 234*7c478bd9Sstevel@tonic-gate "driver ID failed; check for major conflict\n")); 235*7c478bd9Sstevel@tonic-gate (void) close(fd); 236*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 237*7c478bd9Sstevel@tonic-gate } 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * create snapshot 241*7c478bd9Sstevel@tonic-gate */ 242*7c478bd9Sstevel@tonic-gate if ((map_size = ioctl(fd, flag, &dinfo_io)) < 0) { 243*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo ioctl failed with " 244*7c478bd9Sstevel@tonic-gate "error: %d\n", errno)); 245*7c478bd9Sstevel@tonic-gate (void) close(fd); 246*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 247*7c478bd9Sstevel@tonic-gate } else if (map_size == 0) { 248*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "%s not found\n", phys_path)); 249*7c478bd9Sstevel@tonic-gate errno = ENXIO; 250*7c478bd9Sstevel@tonic-gate (void) close(fd); 251*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate /* 255*7c478bd9Sstevel@tonic-gate * copy snapshot to userland 256*7c478bd9Sstevel@tonic-gate */ 257*7c478bd9Sstevel@tonic-gate map_size = (map_size + pageoffset) & pagemask; 258*7c478bd9Sstevel@tonic-gate if ((pa = valloc(map_size)) == NULL) { 259*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "valloc failed for snapshot\n")); 260*7c478bd9Sstevel@tonic-gate (void) close(fd); 261*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 262*7c478bd9Sstevel@tonic-gate } 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate if (ioctl(fd, DINFOUSRLD, pa) != map_size) { 265*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "failed to copy snapshot to usrld\n")); 266*7c478bd9Sstevel@tonic-gate (void) close(fd); 267*7c478bd9Sstevel@tonic-gate free(pa); 268*7c478bd9Sstevel@tonic-gate errno = EFAULT; 269*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 270*7c478bd9Sstevel@tonic-gate } 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate (void) close(fd); 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate dap = DI_ALL(pa); 275*7c478bd9Sstevel@tonic-gate if (dap->top_devinfo == 0) { /* phys_path not found */ 276*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "%s not found\n", phys_path)); 277*7c478bd9Sstevel@tonic-gate free(pa); 278*7c478bd9Sstevel@tonic-gate errno = EINVAL; 279*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 280*7c478bd9Sstevel@tonic-gate } 281*7c478bd9Sstevel@tonic-gate 282*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + dap->top_devinfo)); 283*7c478bd9Sstevel@tonic-gate } 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate void 286*7c478bd9Sstevel@tonic-gate di_fini(di_node_t root) 287*7c478bd9Sstevel@tonic-gate { 288*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_fini: freeing a snapshot\n")); 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate /* 293*7c478bd9Sstevel@tonic-gate * paranoid checking 294*7c478bd9Sstevel@tonic-gate */ 295*7c478bd9Sstevel@tonic-gate if (root == DI_NODE_NIL) { 296*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "di_fini called with NIL arg\n")); 297*7c478bd9Sstevel@tonic-gate return; 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate /* 301*7c478bd9Sstevel@tonic-gate * The root contains its own offset--self. 302*7c478bd9Sstevel@tonic-gate * Subtracting it from root address, we get the starting addr. 303*7c478bd9Sstevel@tonic-gate * The map_size is stored at the beginning of snapshot. 304*7c478bd9Sstevel@tonic-gate * Once we have starting address and size, we can free(). 305*7c478bd9Sstevel@tonic-gate */ 306*7c478bd9Sstevel@tonic-gate pa = (caddr_t)root - DI_NODE(root)->self; 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate free(pa); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate di_node_t 312*7c478bd9Sstevel@tonic-gate di_parent_node(di_node_t node) 313*7c478bd9Sstevel@tonic-gate { 314*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 315*7c478bd9Sstevel@tonic-gate 316*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 317*7c478bd9Sstevel@tonic-gate errno = EINVAL; 318*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 319*7c478bd9Sstevel@tonic-gate } 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get parent of node %s\n", di_node_name(node))); 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent) { 326*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->parent)); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate /* 330*7c478bd9Sstevel@tonic-gate * Deal with error condition: 331*7c478bd9Sstevel@tonic-gate * If parent doesn't exist and node is not the root, 332*7c478bd9Sstevel@tonic-gate * set errno to ENOTSUP. Otherwise, set errno to ENXIO. 333*7c478bd9Sstevel@tonic-gate */ 334*7c478bd9Sstevel@tonic-gate if (strcmp(DI_ALL(pa)->root_path, "/") != 0) 335*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 336*7c478bd9Sstevel@tonic-gate else 337*7c478bd9Sstevel@tonic-gate errno = ENXIO; 338*7c478bd9Sstevel@tonic-gate 339*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate di_node_t 343*7c478bd9Sstevel@tonic-gate di_sibling_node(di_node_t node) 344*7c478bd9Sstevel@tonic-gate { 345*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 348*7c478bd9Sstevel@tonic-gate errno = EINVAL; 349*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get sibling of node %s\n", di_node_name(node))); 353*7c478bd9Sstevel@tonic-gate 354*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->sibling) { 357*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->sibling)); 358*7c478bd9Sstevel@tonic-gate } 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Deal with error condition: 362*7c478bd9Sstevel@tonic-gate * Sibling doesn't exist, figure out if ioctl command 363*7c478bd9Sstevel@tonic-gate * has DINFOSUBTREE set. If it doesn't, set errno to 364*7c478bd9Sstevel@tonic-gate * ENOTSUP. 365*7c478bd9Sstevel@tonic-gate */ 366*7c478bd9Sstevel@tonic-gate if (!(DI_ALL(pa)->command & DINFOSUBTREE)) 367*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 368*7c478bd9Sstevel@tonic-gate else 369*7c478bd9Sstevel@tonic-gate errno = ENXIO; 370*7c478bd9Sstevel@tonic-gate 371*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate di_node_t 375*7c478bd9Sstevel@tonic-gate di_child_node(di_node_t node) 376*7c478bd9Sstevel@tonic-gate { 377*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get child of node %s\n", di_node_name(node))); 380*7c478bd9Sstevel@tonic-gate 381*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 382*7c478bd9Sstevel@tonic-gate errno = EINVAL; 383*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->child) { 389*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->child)); 390*7c478bd9Sstevel@tonic-gate } 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate /* 393*7c478bd9Sstevel@tonic-gate * Deal with error condition: 394*7c478bd9Sstevel@tonic-gate * Child doesn't exist, figure out if DINFOSUBTREE is set. 395*7c478bd9Sstevel@tonic-gate * If it isn't, set errno to ENOTSUP. 396*7c478bd9Sstevel@tonic-gate */ 397*7c478bd9Sstevel@tonic-gate if (!(DI_ALL(pa)->command & DINFOSUBTREE)) 398*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 399*7c478bd9Sstevel@tonic-gate else 400*7c478bd9Sstevel@tonic-gate errno = ENXIO; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate 405*7c478bd9Sstevel@tonic-gate di_node_t 406*7c478bd9Sstevel@tonic-gate di_drv_first_node(const char *drv_name, di_node_t root) 407*7c478bd9Sstevel@tonic-gate { 408*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 409*7c478bd9Sstevel@tonic-gate int major, devcnt; 410*7c478bd9Sstevel@tonic-gate struct di_devnm *devnm; 411*7c478bd9Sstevel@tonic-gate 412*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Get first node of driver %s\n", drv_name)); 413*7c478bd9Sstevel@tonic-gate 414*7c478bd9Sstevel@tonic-gate if (root == DI_NODE_NIL) { 415*7c478bd9Sstevel@tonic-gate errno = EINVAL; 416*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * get major number of driver 421*7c478bd9Sstevel@tonic-gate */ 422*7c478bd9Sstevel@tonic-gate pa = (caddr_t)root - DI_NODE(root)->self; 423*7c478bd9Sstevel@tonic-gate devcnt = DI_ALL(pa)->devcnt; 424*7c478bd9Sstevel@tonic-gate devnm = DI_DEVNM(pa + DI_ALL(pa)->devnames); 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate for (major = 0; major < devcnt; major++) 427*7c478bd9Sstevel@tonic-gate if (devnm[major].name && (strcmp(drv_name, 428*7c478bd9Sstevel@tonic-gate (char *)(pa + devnm[major].name)) == 0)) 429*7c478bd9Sstevel@tonic-gate break; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate if (major >= devcnt) { 432*7c478bd9Sstevel@tonic-gate errno = EINVAL; 433*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate if (!(devnm[major].head)) { 437*7c478bd9Sstevel@tonic-gate errno = ENXIO; 438*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 439*7c478bd9Sstevel@tonic-gate } 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + devnm[major].head)); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate 444*7c478bd9Sstevel@tonic-gate di_node_t 445*7c478bd9Sstevel@tonic-gate di_drv_next_node(di_node_t node) 446*7c478bd9Sstevel@tonic-gate { 447*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 450*7c478bd9Sstevel@tonic-gate errno = EINVAL; 451*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 452*7c478bd9Sstevel@tonic-gate } 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "next node on per driver list:" 455*7c478bd9Sstevel@tonic-gate " current=%s, driver=%s\n", 456*7c478bd9Sstevel@tonic-gate di_node_name(node), di_driver_name(node))); 457*7c478bd9Sstevel@tonic-gate 458*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->next == (di_off_t)-1) { 459*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 460*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate 463*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->next == NULL) { 466*7c478bd9Sstevel@tonic-gate errno = ENXIO; 467*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->next)); 471*7c478bd9Sstevel@tonic-gate } 472*7c478bd9Sstevel@tonic-gate 473*7c478bd9Sstevel@tonic-gate /* 474*7c478bd9Sstevel@tonic-gate * Internal library interfaces: 475*7c478bd9Sstevel@tonic-gate * node_list etc. for node walking 476*7c478bd9Sstevel@tonic-gate */ 477*7c478bd9Sstevel@tonic-gate struct node_list { 478*7c478bd9Sstevel@tonic-gate struct node_list *next; 479*7c478bd9Sstevel@tonic-gate di_node_t node; 480*7c478bd9Sstevel@tonic-gate }; 481*7c478bd9Sstevel@tonic-gate 482*7c478bd9Sstevel@tonic-gate static void 483*7c478bd9Sstevel@tonic-gate free_node_list(struct node_list **headp) 484*7c478bd9Sstevel@tonic-gate { 485*7c478bd9Sstevel@tonic-gate struct node_list *tmp; 486*7c478bd9Sstevel@tonic-gate 487*7c478bd9Sstevel@tonic-gate while (*headp) { 488*7c478bd9Sstevel@tonic-gate tmp = *headp; 489*7c478bd9Sstevel@tonic-gate *headp = (*headp)->next; 490*7c478bd9Sstevel@tonic-gate free(tmp); 491*7c478bd9Sstevel@tonic-gate } 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate static void 495*7c478bd9Sstevel@tonic-gate append_node_list(struct node_list **headp, struct node_list *list) 496*7c478bd9Sstevel@tonic-gate { 497*7c478bd9Sstevel@tonic-gate struct node_list *tmp; 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate if (*headp == NULL) { 500*7c478bd9Sstevel@tonic-gate *headp = list; 501*7c478bd9Sstevel@tonic-gate return; 502*7c478bd9Sstevel@tonic-gate } 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate if (list == NULL) /* a minor optimization */ 505*7c478bd9Sstevel@tonic-gate return; 506*7c478bd9Sstevel@tonic-gate 507*7c478bd9Sstevel@tonic-gate tmp = *headp; 508*7c478bd9Sstevel@tonic-gate while (tmp->next) 509*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 510*7c478bd9Sstevel@tonic-gate 511*7c478bd9Sstevel@tonic-gate tmp->next = list; 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate 514*7c478bd9Sstevel@tonic-gate static void 515*7c478bd9Sstevel@tonic-gate prepend_node_list(struct node_list **headp, struct node_list *list) 516*7c478bd9Sstevel@tonic-gate { 517*7c478bd9Sstevel@tonic-gate struct node_list *tmp; 518*7c478bd9Sstevel@tonic-gate 519*7c478bd9Sstevel@tonic-gate if (list == NULL) 520*7c478bd9Sstevel@tonic-gate return; 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate tmp = *headp; 523*7c478bd9Sstevel@tonic-gate *headp = list; 524*7c478bd9Sstevel@tonic-gate 525*7c478bd9Sstevel@tonic-gate if (tmp == NULL) /* a minor optimization */ 526*7c478bd9Sstevel@tonic-gate return; 527*7c478bd9Sstevel@tonic-gate 528*7c478bd9Sstevel@tonic-gate while (list->next) 529*7c478bd9Sstevel@tonic-gate list = list->next; 530*7c478bd9Sstevel@tonic-gate 531*7c478bd9Sstevel@tonic-gate list->next = tmp; 532*7c478bd9Sstevel@tonic-gate } 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate /* 535*7c478bd9Sstevel@tonic-gate * returns 1 if node is a descendant of parent, 0 otherwise 536*7c478bd9Sstevel@tonic-gate */ 537*7c478bd9Sstevel@tonic-gate static int 538*7c478bd9Sstevel@tonic-gate is_descendant(di_node_t node, di_node_t parent) 539*7c478bd9Sstevel@tonic-gate { 540*7c478bd9Sstevel@tonic-gate /* 541*7c478bd9Sstevel@tonic-gate * DI_NODE_NIL is parent of root, so it is 542*7c478bd9Sstevel@tonic-gate * the parent of all nodes. 543*7c478bd9Sstevel@tonic-gate */ 544*7c478bd9Sstevel@tonic-gate if (parent == DI_NODE_NIL) { 545*7c478bd9Sstevel@tonic-gate return (1); 546*7c478bd9Sstevel@tonic-gate } 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate do { 549*7c478bd9Sstevel@tonic-gate node = di_parent_node(node); 550*7c478bd9Sstevel@tonic-gate } while ((node != DI_NODE_NIL) && (node != parent)); 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate return (node != DI_NODE_NIL); 553*7c478bd9Sstevel@tonic-gate } 554*7c478bd9Sstevel@tonic-gate 555*7c478bd9Sstevel@tonic-gate /* 556*7c478bd9Sstevel@tonic-gate * Insert list before the first node which is NOT a descendent of parent. 557*7c478bd9Sstevel@tonic-gate * This is needed to reproduce the exact walking order of link generators. 558*7c478bd9Sstevel@tonic-gate */ 559*7c478bd9Sstevel@tonic-gate static void 560*7c478bd9Sstevel@tonic-gate insert_node_list(struct node_list **headp, struct node_list *list, 561*7c478bd9Sstevel@tonic-gate di_node_t parent) 562*7c478bd9Sstevel@tonic-gate { 563*7c478bd9Sstevel@tonic-gate struct node_list *tmp, *tmp1; 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate if (list == NULL) 566*7c478bd9Sstevel@tonic-gate return; 567*7c478bd9Sstevel@tonic-gate 568*7c478bd9Sstevel@tonic-gate tmp = *headp; 569*7c478bd9Sstevel@tonic-gate if (tmp == NULL) { /* a minor optimization */ 570*7c478bd9Sstevel@tonic-gate *headp = list; 571*7c478bd9Sstevel@tonic-gate return; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if (!is_descendant(tmp->node, parent)) { 575*7c478bd9Sstevel@tonic-gate prepend_node_list(headp, list); 576*7c478bd9Sstevel@tonic-gate return; 577*7c478bd9Sstevel@tonic-gate } 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate /* 580*7c478bd9Sstevel@tonic-gate * Find first node which is not a descendant 581*7c478bd9Sstevel@tonic-gate */ 582*7c478bd9Sstevel@tonic-gate while (tmp->next && is_descendant(tmp->next->node, parent)) { 583*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 584*7c478bd9Sstevel@tonic-gate } 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate tmp1 = tmp->next; 587*7c478bd9Sstevel@tonic-gate tmp->next = list; 588*7c478bd9Sstevel@tonic-gate append_node_list(headp, tmp1); 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate /* 592*7c478bd9Sstevel@tonic-gate * Get a linked list of handles of all children 593*7c478bd9Sstevel@tonic-gate */ 594*7c478bd9Sstevel@tonic-gate static struct node_list * 595*7c478bd9Sstevel@tonic-gate get_children(di_node_t node) 596*7c478bd9Sstevel@tonic-gate { 597*7c478bd9Sstevel@tonic-gate di_node_t child; 598*7c478bd9Sstevel@tonic-gate struct node_list *result, *tmp; 599*7c478bd9Sstevel@tonic-gate 600*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "Get children of node %s\n", di_node_name(node))); 601*7c478bd9Sstevel@tonic-gate 602*7c478bd9Sstevel@tonic-gate if ((child = di_child_node(node)) == DI_NODE_NIL) { 603*7c478bd9Sstevel@tonic-gate return (NULL); 604*7c478bd9Sstevel@tonic-gate } 605*7c478bd9Sstevel@tonic-gate 606*7c478bd9Sstevel@tonic-gate if ((result = malloc(sizeof (struct node_list))) == NULL) { 607*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n")); 608*7c478bd9Sstevel@tonic-gate return (NULL); 609*7c478bd9Sstevel@tonic-gate } 610*7c478bd9Sstevel@tonic-gate 611*7c478bd9Sstevel@tonic-gate result->node = child; 612*7c478bd9Sstevel@tonic-gate tmp = result; 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate while ((child = di_sibling_node(tmp->node)) != DI_NODE_NIL) { 615*7c478bd9Sstevel@tonic-gate if ((tmp->next = malloc(sizeof (struct node_list))) == NULL) { 616*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n")); 617*7c478bd9Sstevel@tonic-gate free_node_list(&result); 618*7c478bd9Sstevel@tonic-gate return (NULL); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate tmp = tmp->next; 621*7c478bd9Sstevel@tonic-gate tmp->node = child; 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate tmp->next = NULL; 625*7c478bd9Sstevel@tonic-gate 626*7c478bd9Sstevel@tonic-gate return (result); 627*7c478bd9Sstevel@tonic-gate } 628*7c478bd9Sstevel@tonic-gate 629*7c478bd9Sstevel@tonic-gate /* 630*7c478bd9Sstevel@tonic-gate * Internal library interface: 631*7c478bd9Sstevel@tonic-gate * Delete all siblings of the first node from the node_list, along with 632*7c478bd9Sstevel@tonic-gate * the first node itself. 633*7c478bd9Sstevel@tonic-gate */ 634*7c478bd9Sstevel@tonic-gate static void 635*7c478bd9Sstevel@tonic-gate prune_sib(struct node_list **headp) 636*7c478bd9Sstevel@tonic-gate { 637*7c478bd9Sstevel@tonic-gate di_node_t parent, curr_par, curr_gpar; 638*7c478bd9Sstevel@tonic-gate struct node_list *curr, *prev; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate /* 641*7c478bd9Sstevel@tonic-gate * get handle to parent of first node 642*7c478bd9Sstevel@tonic-gate */ 643*7c478bd9Sstevel@tonic-gate if ((parent = di_parent_node((*headp)->node)) == DI_NODE_NIL) { 644*7c478bd9Sstevel@tonic-gate /* 645*7c478bd9Sstevel@tonic-gate * This must be the root of the snapshot, so can't 646*7c478bd9Sstevel@tonic-gate * have any siblings. 647*7c478bd9Sstevel@tonic-gate * 648*7c478bd9Sstevel@tonic-gate * XXX Put a check here just in case. 649*7c478bd9Sstevel@tonic-gate */ 650*7c478bd9Sstevel@tonic-gate if ((*headp)->next) 651*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "Unexpected err in di_walk_node.\n")); 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate free(*headp); 654*7c478bd9Sstevel@tonic-gate *headp = NULL; 655*7c478bd9Sstevel@tonic-gate return; 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate /* 659*7c478bd9Sstevel@tonic-gate * To be complete, we should also delete the children 660*7c478bd9Sstevel@tonic-gate * of siblings that have already been visited. 661*7c478bd9Sstevel@tonic-gate * This happens for DI_WALK_SIBFIRST when the first node 662*7c478bd9Sstevel@tonic-gate * is NOT the first in the linked list of siblings. 663*7c478bd9Sstevel@tonic-gate * 664*7c478bd9Sstevel@tonic-gate * Hence, we compare parent with BOTH the parent and grandparent 665*7c478bd9Sstevel@tonic-gate * of nodes, and delete node is a match is found. 666*7c478bd9Sstevel@tonic-gate */ 667*7c478bd9Sstevel@tonic-gate prev = *headp; 668*7c478bd9Sstevel@tonic-gate curr = prev->next; 669*7c478bd9Sstevel@tonic-gate while (curr) { 670*7c478bd9Sstevel@tonic-gate if (((curr_par = di_parent_node(curr->node)) != DI_NODE_NIL) && 671*7c478bd9Sstevel@tonic-gate ((curr_par == parent) || ((curr_gpar = 672*7c478bd9Sstevel@tonic-gate di_parent_node(curr_par)) != DI_NODE_NIL) && 673*7c478bd9Sstevel@tonic-gate (curr_gpar == parent))) { 674*7c478bd9Sstevel@tonic-gate /* 675*7c478bd9Sstevel@tonic-gate * match parent/grandparent: delete curr 676*7c478bd9Sstevel@tonic-gate */ 677*7c478bd9Sstevel@tonic-gate prev->next = curr->next; 678*7c478bd9Sstevel@tonic-gate free(curr); 679*7c478bd9Sstevel@tonic-gate curr = prev->next; 680*7c478bd9Sstevel@tonic-gate } else 681*7c478bd9Sstevel@tonic-gate curr = curr->next; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate /* 685*7c478bd9Sstevel@tonic-gate * delete the first node 686*7c478bd9Sstevel@tonic-gate */ 687*7c478bd9Sstevel@tonic-gate curr = *headp; 688*7c478bd9Sstevel@tonic-gate *headp = curr->next; 689*7c478bd9Sstevel@tonic-gate free(curr); 690*7c478bd9Sstevel@tonic-gate } 691*7c478bd9Sstevel@tonic-gate 692*7c478bd9Sstevel@tonic-gate /* 693*7c478bd9Sstevel@tonic-gate * Internal library function: 694*7c478bd9Sstevel@tonic-gate * Update node list based on action (return code from callback) 695*7c478bd9Sstevel@tonic-gate * and flag specifying walking behavior. 696*7c478bd9Sstevel@tonic-gate */ 697*7c478bd9Sstevel@tonic-gate static void 698*7c478bd9Sstevel@tonic-gate update_node_list(int action, uint_t flag, struct node_list **headp) 699*7c478bd9Sstevel@tonic-gate { 700*7c478bd9Sstevel@tonic-gate struct node_list *children, *tmp; 701*7c478bd9Sstevel@tonic-gate di_node_t parent = di_parent_node((*headp)->node); 702*7c478bd9Sstevel@tonic-gate 703*7c478bd9Sstevel@tonic-gate switch (action) { 704*7c478bd9Sstevel@tonic-gate case DI_WALK_TERMINATE: 705*7c478bd9Sstevel@tonic-gate /* 706*7c478bd9Sstevel@tonic-gate * free the node list and be done 707*7c478bd9Sstevel@tonic-gate */ 708*7c478bd9Sstevel@tonic-gate children = NULL; 709*7c478bd9Sstevel@tonic-gate free_node_list(headp); 710*7c478bd9Sstevel@tonic-gate break; 711*7c478bd9Sstevel@tonic-gate 712*7c478bd9Sstevel@tonic-gate case DI_WALK_PRUNESIB: 713*7c478bd9Sstevel@tonic-gate /* 714*7c478bd9Sstevel@tonic-gate * Get list of children and prune siblings 715*7c478bd9Sstevel@tonic-gate */ 716*7c478bd9Sstevel@tonic-gate children = get_children((*headp)->node); 717*7c478bd9Sstevel@tonic-gate prune_sib(headp); 718*7c478bd9Sstevel@tonic-gate break; 719*7c478bd9Sstevel@tonic-gate 720*7c478bd9Sstevel@tonic-gate case DI_WALK_PRUNECHILD: 721*7c478bd9Sstevel@tonic-gate /* 722*7c478bd9Sstevel@tonic-gate * Set children to NULL and pop first node 723*7c478bd9Sstevel@tonic-gate */ 724*7c478bd9Sstevel@tonic-gate children = NULL; 725*7c478bd9Sstevel@tonic-gate tmp = *headp; 726*7c478bd9Sstevel@tonic-gate *headp = tmp->next; 727*7c478bd9Sstevel@tonic-gate free(tmp); 728*7c478bd9Sstevel@tonic-gate break; 729*7c478bd9Sstevel@tonic-gate 730*7c478bd9Sstevel@tonic-gate case DI_WALK_CONTINUE: 731*7c478bd9Sstevel@tonic-gate default: 732*7c478bd9Sstevel@tonic-gate /* 733*7c478bd9Sstevel@tonic-gate * Get list of children and pop first node 734*7c478bd9Sstevel@tonic-gate */ 735*7c478bd9Sstevel@tonic-gate children = get_children((*headp)->node); 736*7c478bd9Sstevel@tonic-gate tmp = *headp; 737*7c478bd9Sstevel@tonic-gate *headp = tmp->next; 738*7c478bd9Sstevel@tonic-gate free(tmp); 739*7c478bd9Sstevel@tonic-gate break; 740*7c478bd9Sstevel@tonic-gate } 741*7c478bd9Sstevel@tonic-gate 742*7c478bd9Sstevel@tonic-gate /* 743*7c478bd9Sstevel@tonic-gate * insert the list of children 744*7c478bd9Sstevel@tonic-gate */ 745*7c478bd9Sstevel@tonic-gate switch (flag) { 746*7c478bd9Sstevel@tonic-gate case DI_WALK_CLDFIRST: 747*7c478bd9Sstevel@tonic-gate prepend_node_list(headp, children); 748*7c478bd9Sstevel@tonic-gate break; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate case DI_WALK_SIBFIRST: 751*7c478bd9Sstevel@tonic-gate append_node_list(headp, children); 752*7c478bd9Sstevel@tonic-gate break; 753*7c478bd9Sstevel@tonic-gate 754*7c478bd9Sstevel@tonic-gate case DI_WALK_LINKGEN: 755*7c478bd9Sstevel@tonic-gate default: 756*7c478bd9Sstevel@tonic-gate insert_node_list(headp, children, parent); 757*7c478bd9Sstevel@tonic-gate break; 758*7c478bd9Sstevel@tonic-gate } 759*7c478bd9Sstevel@tonic-gate } 760*7c478bd9Sstevel@tonic-gate 761*7c478bd9Sstevel@tonic-gate /* 762*7c478bd9Sstevel@tonic-gate * Internal library function: 763*7c478bd9Sstevel@tonic-gate * Invoke callback on one node and update the list of nodes to be walked 764*7c478bd9Sstevel@tonic-gate * based on the flag and return code. 765*7c478bd9Sstevel@tonic-gate */ 766*7c478bd9Sstevel@tonic-gate static void 767*7c478bd9Sstevel@tonic-gate walk_one_node(struct node_list **headp, uint_t flag, void *arg, 768*7c478bd9Sstevel@tonic-gate int (*callback)(di_node_t, void *)) 769*7c478bd9Sstevel@tonic-gate { 770*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Walking node %s\n", di_node_name((*headp)->node))); 771*7c478bd9Sstevel@tonic-gate 772*7c478bd9Sstevel@tonic-gate update_node_list(callback((*headp)->node, arg), 773*7c478bd9Sstevel@tonic-gate flag & DI_WALK_MASK, headp); 774*7c478bd9Sstevel@tonic-gate } 775*7c478bd9Sstevel@tonic-gate 776*7c478bd9Sstevel@tonic-gate int 777*7c478bd9Sstevel@tonic-gate di_walk_node(di_node_t root, uint_t flag, void *arg, 778*7c478bd9Sstevel@tonic-gate int (*node_callback)(di_node_t, void *)) 779*7c478bd9Sstevel@tonic-gate { 780*7c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */ 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate if (root == NULL) { 783*7c478bd9Sstevel@tonic-gate errno = EINVAL; 784*7c478bd9Sstevel@tonic-gate return (-1); 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) { 788*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n")); 789*7c478bd9Sstevel@tonic-gate return (-1); 790*7c478bd9Sstevel@tonic-gate } 791*7c478bd9Sstevel@tonic-gate 792*7c478bd9Sstevel@tonic-gate head->next = NULL; 793*7c478bd9Sstevel@tonic-gate head->node = root; 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start node walking from node %s\n", 796*7c478bd9Sstevel@tonic-gate di_node_name(root))); 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate while (head != NULL) 799*7c478bd9Sstevel@tonic-gate walk_one_node(&head, flag, arg, node_callback); 800*7c478bd9Sstevel@tonic-gate 801*7c478bd9Sstevel@tonic-gate return (0); 802*7c478bd9Sstevel@tonic-gate } 803*7c478bd9Sstevel@tonic-gate 804*7c478bd9Sstevel@tonic-gate /* 805*7c478bd9Sstevel@tonic-gate * Internal library function: 806*7c478bd9Sstevel@tonic-gate * Invoke callback for each minor on the minor list of first node 807*7c478bd9Sstevel@tonic-gate * on node_list headp, and place children of first node on the list. 808*7c478bd9Sstevel@tonic-gate * 809*7c478bd9Sstevel@tonic-gate * This is similar to walk_one_node, except we only walk in child 810*7c478bd9Sstevel@tonic-gate * first mode. 811*7c478bd9Sstevel@tonic-gate */ 812*7c478bd9Sstevel@tonic-gate static void 813*7c478bd9Sstevel@tonic-gate walk_one_minor_list(struct node_list **headp, const char *desired_type, 814*7c478bd9Sstevel@tonic-gate uint_t flag, void *arg, int (*callback)(di_node_t, di_minor_t, void *)) 815*7c478bd9Sstevel@tonic-gate { 816*7c478bd9Sstevel@tonic-gate int ddm_type; 817*7c478bd9Sstevel@tonic-gate int action = DI_WALK_CONTINUE; 818*7c478bd9Sstevel@tonic-gate char *node_type; 819*7c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL; 820*7c478bd9Sstevel@tonic-gate di_node_t node = (*headp)->node; 821*7c478bd9Sstevel@tonic-gate 822*7c478bd9Sstevel@tonic-gate while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 823*7c478bd9Sstevel@tonic-gate ddm_type = di_minor_type(minor); 824*7c478bd9Sstevel@tonic-gate 825*7c478bd9Sstevel@tonic-gate if ((ddm_type == DDM_ALIAS) && !(flag & DI_CHECK_ALIAS)) 826*7c478bd9Sstevel@tonic-gate continue; 827*7c478bd9Sstevel@tonic-gate 828*7c478bd9Sstevel@tonic-gate if ((ddm_type == DDM_INTERNAL_PATH) && 829*7c478bd9Sstevel@tonic-gate !(flag & DI_CHECK_INTERNAL_PATH)) 830*7c478bd9Sstevel@tonic-gate continue; 831*7c478bd9Sstevel@tonic-gate 832*7c478bd9Sstevel@tonic-gate node_type = di_minor_nodetype(minor); 833*7c478bd9Sstevel@tonic-gate if ((desired_type != NULL) && ((node_type == NULL) || 834*7c478bd9Sstevel@tonic-gate strncmp(desired_type, node_type, strlen(desired_type)) 835*7c478bd9Sstevel@tonic-gate != 0)) 836*7c478bd9Sstevel@tonic-gate continue; 837*7c478bd9Sstevel@tonic-gate 838*7c478bd9Sstevel@tonic-gate if ((action = callback(node, minor, arg)) == 839*7c478bd9Sstevel@tonic-gate DI_WALK_TERMINATE) { 840*7c478bd9Sstevel@tonic-gate break; 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate } 843*7c478bd9Sstevel@tonic-gate 844*7c478bd9Sstevel@tonic-gate update_node_list(action, DI_WALK_LINKGEN, headp); 845*7c478bd9Sstevel@tonic-gate } 846*7c478bd9Sstevel@tonic-gate 847*7c478bd9Sstevel@tonic-gate int 848*7c478bd9Sstevel@tonic-gate di_walk_minor(di_node_t root, const char *minor_type, uint_t flag, void *arg, 849*7c478bd9Sstevel@tonic-gate int (*minor_callback)(di_node_t, di_minor_t, void *)) 850*7c478bd9Sstevel@tonic-gate { 851*7c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */ 852*7c478bd9Sstevel@tonic-gate 853*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 854*7c478bd9Sstevel@tonic-gate char *path = di_devfs_path(root); 855*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "walking minor nodes under %s\n", path)); 856*7c478bd9Sstevel@tonic-gate di_devfs_path_free(path); 857*7c478bd9Sstevel@tonic-gate #endif 858*7c478bd9Sstevel@tonic-gate 859*7c478bd9Sstevel@tonic-gate if (root == NULL) { 860*7c478bd9Sstevel@tonic-gate errno = EINVAL; 861*7c478bd9Sstevel@tonic-gate return (-1); 862*7c478bd9Sstevel@tonic-gate } 863*7c478bd9Sstevel@tonic-gate 864*7c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) { 865*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n")); 866*7c478bd9Sstevel@tonic-gate return (-1); 867*7c478bd9Sstevel@tonic-gate } 868*7c478bd9Sstevel@tonic-gate 869*7c478bd9Sstevel@tonic-gate head->next = NULL; 870*7c478bd9Sstevel@tonic-gate head->node = root; 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start minor walking from node %s\n", 873*7c478bd9Sstevel@tonic-gate di_node_name(root))); 874*7c478bd9Sstevel@tonic-gate 875*7c478bd9Sstevel@tonic-gate while (head != NULL) 876*7c478bd9Sstevel@tonic-gate walk_one_minor_list(&head, minor_type, flag, arg, 877*7c478bd9Sstevel@tonic-gate minor_callback); 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate return (0); 880*7c478bd9Sstevel@tonic-gate } 881*7c478bd9Sstevel@tonic-gate 882*7c478bd9Sstevel@tonic-gate /* 883*7c478bd9Sstevel@tonic-gate * generic node parameters 884*7c478bd9Sstevel@tonic-gate * Calling these routines always succeeds. 885*7c478bd9Sstevel@tonic-gate */ 886*7c478bd9Sstevel@tonic-gate char * 887*7c478bd9Sstevel@tonic-gate di_node_name(di_node_t node) 888*7c478bd9Sstevel@tonic-gate { 889*7c478bd9Sstevel@tonic-gate return ((caddr_t)node + DI_NODE(node)->node_name - DI_NODE(node)->self); 890*7c478bd9Sstevel@tonic-gate } 891*7c478bd9Sstevel@tonic-gate 892*7c478bd9Sstevel@tonic-gate /* returns NULL ptr or a valid ptr to non-NULL string */ 893*7c478bd9Sstevel@tonic-gate char * 894*7c478bd9Sstevel@tonic-gate di_bus_addr(di_node_t node) 895*7c478bd9Sstevel@tonic-gate { 896*7c478bd9Sstevel@tonic-gate caddr_t pa = (caddr_t)node - DI_NODE(node)->self; 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->address == 0) 899*7c478bd9Sstevel@tonic-gate return (NULL); 900*7c478bd9Sstevel@tonic-gate 901*7c478bd9Sstevel@tonic-gate return ((char *)(pa + DI_NODE(node)->address)); 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate 904*7c478bd9Sstevel@tonic-gate char * 905*7c478bd9Sstevel@tonic-gate di_binding_name(di_node_t node) 906*7c478bd9Sstevel@tonic-gate { 907*7c478bd9Sstevel@tonic-gate caddr_t pa = (caddr_t)node - DI_NODE(node)->self; 908*7c478bd9Sstevel@tonic-gate 909*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->bind_name == 0) 910*7c478bd9Sstevel@tonic-gate return (NULL); 911*7c478bd9Sstevel@tonic-gate 912*7c478bd9Sstevel@tonic-gate return ((char *)(pa + DI_NODE(node)->bind_name)); 913*7c478bd9Sstevel@tonic-gate } 914*7c478bd9Sstevel@tonic-gate 915*7c478bd9Sstevel@tonic-gate int 916*7c478bd9Sstevel@tonic-gate di_compatible_names(di_node_t node, char **names) 917*7c478bd9Sstevel@tonic-gate { 918*7c478bd9Sstevel@tonic-gate char *c; 919*7c478bd9Sstevel@tonic-gate int len, size, entries = 0; 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->compat_names == 0) { 922*7c478bd9Sstevel@tonic-gate *names = NULL; 923*7c478bd9Sstevel@tonic-gate return (0); 924*7c478bd9Sstevel@tonic-gate } 925*7c478bd9Sstevel@tonic-gate 926*7c478bd9Sstevel@tonic-gate *names = (caddr_t)node + 927*7c478bd9Sstevel@tonic-gate DI_NODE(node)->compat_names - DI_NODE(node)->self; 928*7c478bd9Sstevel@tonic-gate 929*7c478bd9Sstevel@tonic-gate c = *names; 930*7c478bd9Sstevel@tonic-gate len = DI_NODE(node)->compat_length; 931*7c478bd9Sstevel@tonic-gate while (len > 0) { 932*7c478bd9Sstevel@tonic-gate entries++; 933*7c478bd9Sstevel@tonic-gate size = strlen(c) + 1; 934*7c478bd9Sstevel@tonic-gate len -= size; 935*7c478bd9Sstevel@tonic-gate c += size; 936*7c478bd9Sstevel@tonic-gate } 937*7c478bd9Sstevel@tonic-gate 938*7c478bd9Sstevel@tonic-gate return (entries); 939*7c478bd9Sstevel@tonic-gate } 940*7c478bd9Sstevel@tonic-gate 941*7c478bd9Sstevel@tonic-gate int 942*7c478bd9Sstevel@tonic-gate di_instance(di_node_t node) 943*7c478bd9Sstevel@tonic-gate { 944*7c478bd9Sstevel@tonic-gate return (DI_NODE(node)->instance); 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate /* 948*7c478bd9Sstevel@tonic-gate * XXX: emulate the return value of the old implementation 949*7c478bd9Sstevel@tonic-gate * using info from devi_node_class and devi_node_attributes. 950*7c478bd9Sstevel@tonic-gate */ 951*7c478bd9Sstevel@tonic-gate int 952*7c478bd9Sstevel@tonic-gate di_nodeid(di_node_t node) 953*7c478bd9Sstevel@tonic-gate { 954*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->node_class == DDI_NC_PROM) 955*7c478bd9Sstevel@tonic-gate return (DI_PROM_NODEID); 956*7c478bd9Sstevel@tonic-gate 957*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->attributes & DDI_PERSISTENT) 958*7c478bd9Sstevel@tonic-gate return (DI_SID_NODEID); 959*7c478bd9Sstevel@tonic-gate 960*7c478bd9Sstevel@tonic-gate return (DI_PSEUDO_NODEID); 961*7c478bd9Sstevel@tonic-gate } 962*7c478bd9Sstevel@tonic-gate 963*7c478bd9Sstevel@tonic-gate uint_t 964*7c478bd9Sstevel@tonic-gate di_state(di_node_t node) 965*7c478bd9Sstevel@tonic-gate { 966*7c478bd9Sstevel@tonic-gate uint_t result = 0; 967*7c478bd9Sstevel@tonic-gate 968*7c478bd9Sstevel@tonic-gate if (di_node_state(node) < DS_ATTACHED) 969*7c478bd9Sstevel@tonic-gate result |= DI_DRIVER_DETACHED; 970*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_DEVICE_OFFLINE) 971*7c478bd9Sstevel@tonic-gate result |= DI_DEVICE_OFFLINE; 972*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_DEVICE_DOWN) 973*7c478bd9Sstevel@tonic-gate result |= DI_DEVICE_OFFLINE; 974*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_BUS_QUIESCED) 975*7c478bd9Sstevel@tonic-gate result |= DI_BUS_QUIESCED; 976*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_BUS_DOWN) 977*7c478bd9Sstevel@tonic-gate result |= DI_BUS_DOWN; 978*7c478bd9Sstevel@tonic-gate 979*7c478bd9Sstevel@tonic-gate return (result); 980*7c478bd9Sstevel@tonic-gate } 981*7c478bd9Sstevel@tonic-gate 982*7c478bd9Sstevel@tonic-gate ddi_node_state_t 983*7c478bd9Sstevel@tonic-gate di_node_state(di_node_t node) 984*7c478bd9Sstevel@tonic-gate { 985*7c478bd9Sstevel@tonic-gate return (DI_NODE(node)->node_state); 986*7c478bd9Sstevel@tonic-gate } 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate ddi_devid_t 989*7c478bd9Sstevel@tonic-gate di_devid(di_node_t node) 990*7c478bd9Sstevel@tonic-gate { 991*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->devid == 0) 992*7c478bd9Sstevel@tonic-gate return (NULL); 993*7c478bd9Sstevel@tonic-gate 994*7c478bd9Sstevel@tonic-gate return ((ddi_devid_t)((caddr_t)node + 995*7c478bd9Sstevel@tonic-gate DI_NODE(node)->devid - DI_NODE(node)->self)); 996*7c478bd9Sstevel@tonic-gate } 997*7c478bd9Sstevel@tonic-gate 998*7c478bd9Sstevel@tonic-gate int 999*7c478bd9Sstevel@tonic-gate di_driver_major(di_node_t node) 1000*7c478bd9Sstevel@tonic-gate { 1001*7c478bd9Sstevel@tonic-gate int major; 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate major = DI_NODE(node)->drv_major; 1004*7c478bd9Sstevel@tonic-gate if (major < 0) 1005*7c478bd9Sstevel@tonic-gate return (-1); 1006*7c478bd9Sstevel@tonic-gate return (major); 1007*7c478bd9Sstevel@tonic-gate } 1008*7c478bd9Sstevel@tonic-gate 1009*7c478bd9Sstevel@tonic-gate char * 1010*7c478bd9Sstevel@tonic-gate di_driver_name(di_node_t node) 1011*7c478bd9Sstevel@tonic-gate { 1012*7c478bd9Sstevel@tonic-gate int major; 1013*7c478bd9Sstevel@tonic-gate caddr_t pa; 1014*7c478bd9Sstevel@tonic-gate struct di_devnm *devnm; 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate major = DI_NODE(node)->drv_major; 1017*7c478bd9Sstevel@tonic-gate if (major < 0) 1018*7c478bd9Sstevel@tonic-gate return (NULL); 1019*7c478bd9Sstevel@tonic-gate 1020*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1021*7c478bd9Sstevel@tonic-gate devnm = DI_DEVNM(pa + DI_ALL(pa)->devnames); 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate if (devnm[major].name) 1024*7c478bd9Sstevel@tonic-gate return (pa + devnm[major].name); 1025*7c478bd9Sstevel@tonic-gate else 1026*7c478bd9Sstevel@tonic-gate return (NULL); 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate uint_t 1030*7c478bd9Sstevel@tonic-gate di_driver_ops(di_node_t node) 1031*7c478bd9Sstevel@tonic-gate { 1032*7c478bd9Sstevel@tonic-gate int major; 1033*7c478bd9Sstevel@tonic-gate caddr_t pa; 1034*7c478bd9Sstevel@tonic-gate struct di_devnm *devnm; 1035*7c478bd9Sstevel@tonic-gate 1036*7c478bd9Sstevel@tonic-gate major = DI_NODE(node)->drv_major; 1037*7c478bd9Sstevel@tonic-gate if (major < 0) 1038*7c478bd9Sstevel@tonic-gate return (0); 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1041*7c478bd9Sstevel@tonic-gate devnm = DI_DEVNM(pa + DI_ALL(pa)->devnames); 1042*7c478bd9Sstevel@tonic-gate 1043*7c478bd9Sstevel@tonic-gate return (devnm[major].ops); 1044*7c478bd9Sstevel@tonic-gate } 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate /* 1047*7c478bd9Sstevel@tonic-gate * returns the length of the path, caller must free memory 1048*7c478bd9Sstevel@tonic-gate */ 1049*7c478bd9Sstevel@tonic-gate char * 1050*7c478bd9Sstevel@tonic-gate di_devfs_path(di_node_t node) 1051*7c478bd9Sstevel@tonic-gate { 1052*7c478bd9Sstevel@tonic-gate caddr_t pa; 1053*7c478bd9Sstevel@tonic-gate di_node_t parent; 1054*7c478bd9Sstevel@tonic-gate int depth = 0, len = 0; 1055*7c478bd9Sstevel@tonic-gate char *buf, *name[MAX_TREE_DEPTH], *addr[MAX_TREE_DEPTH]; 1056*7c478bd9Sstevel@tonic-gate 1057*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 1058*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1059*7c478bd9Sstevel@tonic-gate return (NULL); 1060*7c478bd9Sstevel@tonic-gate } 1061*7c478bd9Sstevel@tonic-gate 1062*7c478bd9Sstevel@tonic-gate /* 1063*7c478bd9Sstevel@tonic-gate * trace back to root, note the node_name & address 1064*7c478bd9Sstevel@tonic-gate */ 1065*7c478bd9Sstevel@tonic-gate while ((parent = di_parent_node(node)) != DI_NODE_NIL) { 1066*7c478bd9Sstevel@tonic-gate name[depth] = di_node_name(node); 1067*7c478bd9Sstevel@tonic-gate len += strlen(name[depth]) + 1; /* 1 for '/' */ 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate if ((addr[depth] = di_bus_addr(node)) != NULL) 1070*7c478bd9Sstevel@tonic-gate len += strlen(addr[depth]) + 1; /* 1 for '@' */ 1071*7c478bd9Sstevel@tonic-gate 1072*7c478bd9Sstevel@tonic-gate node = parent; 1073*7c478bd9Sstevel@tonic-gate depth++; 1074*7c478bd9Sstevel@tonic-gate } 1075*7c478bd9Sstevel@tonic-gate 1076*7c478bd9Sstevel@tonic-gate /* 1077*7c478bd9Sstevel@tonic-gate * get the path to the root of snapshot 1078*7c478bd9Sstevel@tonic-gate */ 1079*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1080*7c478bd9Sstevel@tonic-gate name[depth] = DI_ALL(pa)->root_path; 1081*7c478bd9Sstevel@tonic-gate len += strlen(name[depth]) + 1; 1082*7c478bd9Sstevel@tonic-gate 1083*7c478bd9Sstevel@tonic-gate /* 1084*7c478bd9Sstevel@tonic-gate * allocate buffer and assemble path 1085*7c478bd9Sstevel@tonic-gate */ 1086*7c478bd9Sstevel@tonic-gate if ((buf = malloc(len)) == NULL) { 1087*7c478bd9Sstevel@tonic-gate return (NULL); 1088*7c478bd9Sstevel@tonic-gate } 1089*7c478bd9Sstevel@tonic-gate 1090*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, name[depth]); 1091*7c478bd9Sstevel@tonic-gate len = strlen(buf); 1092*7c478bd9Sstevel@tonic-gate if (buf[len - 1] == '/') 1093*7c478bd9Sstevel@tonic-gate len--; /* delete trailing '/' */ 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate while (depth) { 1096*7c478bd9Sstevel@tonic-gate depth--; 1097*7c478bd9Sstevel@tonic-gate buf[len] = '/'; 1098*7c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, name[depth]); 1099*7c478bd9Sstevel@tonic-gate len += strlen(name[depth]) + 1; 1100*7c478bd9Sstevel@tonic-gate if (addr[depth] && addr[depth][0] != '\0') { 1101*7c478bd9Sstevel@tonic-gate buf[len] = '@'; 1102*7c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, addr[depth]); 1103*7c478bd9Sstevel@tonic-gate len += strlen(addr[depth]) + 1; 1104*7c478bd9Sstevel@tonic-gate } 1105*7c478bd9Sstevel@tonic-gate } 1106*7c478bd9Sstevel@tonic-gate 1107*7c478bd9Sstevel@tonic-gate return (buf); 1108*7c478bd9Sstevel@tonic-gate } 1109*7c478bd9Sstevel@tonic-gate 1110*7c478bd9Sstevel@tonic-gate char * 1111*7c478bd9Sstevel@tonic-gate di_devfs_minor_path(di_minor_t minor) 1112*7c478bd9Sstevel@tonic-gate { 1113*7c478bd9Sstevel@tonic-gate di_node_t node; 1114*7c478bd9Sstevel@tonic-gate char *full_path, *name, *path; 1115*7c478bd9Sstevel@tonic-gate int full_path_len; 1116*7c478bd9Sstevel@tonic-gate 1117*7c478bd9Sstevel@tonic-gate if (minor == DI_MINOR_NIL) { 1118*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1119*7c478bd9Sstevel@tonic-gate return (NULL); 1120*7c478bd9Sstevel@tonic-gate } 1121*7c478bd9Sstevel@tonic-gate 1122*7c478bd9Sstevel@tonic-gate name = di_minor_name(minor); 1123*7c478bd9Sstevel@tonic-gate node = di_minor_devinfo(minor); 1124*7c478bd9Sstevel@tonic-gate path = di_devfs_path(node); 1125*7c478bd9Sstevel@tonic-gate if (path == NULL) 1126*7c478bd9Sstevel@tonic-gate return (NULL); 1127*7c478bd9Sstevel@tonic-gate 1128*7c478bd9Sstevel@tonic-gate /* make the full path to the device minor node */ 1129*7c478bd9Sstevel@tonic-gate full_path_len = strlen(path) + strlen(name) + 2; 1130*7c478bd9Sstevel@tonic-gate full_path = (char *)calloc(1, full_path_len); 1131*7c478bd9Sstevel@tonic-gate if (full_path != NULL) 1132*7c478bd9Sstevel@tonic-gate (void) snprintf(full_path, full_path_len, "%s:%s", path, name); 1133*7c478bd9Sstevel@tonic-gate 1134*7c478bd9Sstevel@tonic-gate di_devfs_path_free(path); 1135*7c478bd9Sstevel@tonic-gate return (full_path); 1136*7c478bd9Sstevel@tonic-gate } 1137*7c478bd9Sstevel@tonic-gate 1138*7c478bd9Sstevel@tonic-gate void 1139*7c478bd9Sstevel@tonic-gate di_devfs_path_free(char *buf) 1140*7c478bd9Sstevel@tonic-gate { 1141*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 1142*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "di_devfs_path_free NULL arg!\n")); 1143*7c478bd9Sstevel@tonic-gate return; 1144*7c478bd9Sstevel@tonic-gate } 1145*7c478bd9Sstevel@tonic-gate 1146*7c478bd9Sstevel@tonic-gate free(buf); 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate /* minor data access */ 1150*7c478bd9Sstevel@tonic-gate di_minor_t 1151*7c478bd9Sstevel@tonic-gate di_minor_next(di_node_t node, di_minor_t minor) 1152*7c478bd9Sstevel@tonic-gate { 1153*7c478bd9Sstevel@tonic-gate caddr_t pa; 1154*7c478bd9Sstevel@tonic-gate 1155*7c478bd9Sstevel@tonic-gate /* 1156*7c478bd9Sstevel@tonic-gate * paranoid error checking 1157*7c478bd9Sstevel@tonic-gate */ 1158*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 1159*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1160*7c478bd9Sstevel@tonic-gate return (DI_MINOR_NIL); 1161*7c478bd9Sstevel@tonic-gate } 1162*7c478bd9Sstevel@tonic-gate 1163*7c478bd9Sstevel@tonic-gate /* 1164*7c478bd9Sstevel@tonic-gate * minor is not NIL 1165*7c478bd9Sstevel@tonic-gate */ 1166*7c478bd9Sstevel@tonic-gate if (minor != DI_MINOR_NIL) { 1167*7c478bd9Sstevel@tonic-gate if (DI_MINOR(minor)->next != 0) 1168*7c478bd9Sstevel@tonic-gate return ((di_minor_t)((void *)((caddr_t)minor - 1169*7c478bd9Sstevel@tonic-gate DI_MINOR(minor)->self + DI_MINOR(minor)->next))); 1170*7c478bd9Sstevel@tonic-gate else { 1171*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1172*7c478bd9Sstevel@tonic-gate return (DI_MINOR_NIL); 1173*7c478bd9Sstevel@tonic-gate } 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate /* 1177*7c478bd9Sstevel@tonic-gate * minor is NIL-->caller asks for first minor node 1178*7c478bd9Sstevel@tonic-gate */ 1179*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->minor_data != 0) { 1180*7c478bd9Sstevel@tonic-gate return (DI_MINOR((caddr_t)node - DI_NODE(node)->self + 1181*7c478bd9Sstevel@tonic-gate DI_NODE(node)->minor_data)); 1182*7c478bd9Sstevel@tonic-gate } 1183*7c478bd9Sstevel@tonic-gate 1184*7c478bd9Sstevel@tonic-gate /* 1185*7c478bd9Sstevel@tonic-gate * no minor data-->check if snapshot includes minor data 1186*7c478bd9Sstevel@tonic-gate * in order to set the correct errno 1187*7c478bd9Sstevel@tonic-gate */ 1188*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1189*7c478bd9Sstevel@tonic-gate if (DINFOMINOR & DI_ALL(pa)->command) 1190*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1191*7c478bd9Sstevel@tonic-gate else 1192*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1193*7c478bd9Sstevel@tonic-gate 1194*7c478bd9Sstevel@tonic-gate return (DI_MINOR_NIL); 1195*7c478bd9Sstevel@tonic-gate } 1196*7c478bd9Sstevel@tonic-gate 1197*7c478bd9Sstevel@tonic-gate /* private interface for dealing with alias minor link generation */ 1198*7c478bd9Sstevel@tonic-gate di_node_t 1199*7c478bd9Sstevel@tonic-gate di_minor_devinfo(di_minor_t minor) 1200*7c478bd9Sstevel@tonic-gate { 1201*7c478bd9Sstevel@tonic-gate if (minor == DI_MINOR_NIL) { 1202*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1203*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 1204*7c478bd9Sstevel@tonic-gate } 1205*7c478bd9Sstevel@tonic-gate 1206*7c478bd9Sstevel@tonic-gate return (DI_NODE((caddr_t)minor - DI_MINOR(minor)->self + 1207*7c478bd9Sstevel@tonic-gate DI_MINOR(minor)->node)); 1208*7c478bd9Sstevel@tonic-gate } 1209*7c478bd9Sstevel@tonic-gate 1210*7c478bd9Sstevel@tonic-gate ddi_minor_type 1211*7c478bd9Sstevel@tonic-gate di_minor_type(di_minor_t minor) 1212*7c478bd9Sstevel@tonic-gate { 1213*7c478bd9Sstevel@tonic-gate return (DI_MINOR(minor)->type); 1214*7c478bd9Sstevel@tonic-gate } 1215*7c478bd9Sstevel@tonic-gate 1216*7c478bd9Sstevel@tonic-gate char * 1217*7c478bd9Sstevel@tonic-gate di_minor_name(di_minor_t minor) 1218*7c478bd9Sstevel@tonic-gate { 1219*7c478bd9Sstevel@tonic-gate if (DI_MINOR(minor)->name == 0) 1220*7c478bd9Sstevel@tonic-gate return (NULL); 1221*7c478bd9Sstevel@tonic-gate 1222*7c478bd9Sstevel@tonic-gate return ((caddr_t)minor - DI_MINOR(minor)->self + DI_MINOR(minor)->name); 1223*7c478bd9Sstevel@tonic-gate } 1224*7c478bd9Sstevel@tonic-gate 1225*7c478bd9Sstevel@tonic-gate dev_t 1226*7c478bd9Sstevel@tonic-gate di_minor_devt(di_minor_t minor) 1227*7c478bd9Sstevel@tonic-gate { 1228*7c478bd9Sstevel@tonic-gate return (makedev(DI_MINOR(minor)->dev_major, 1229*7c478bd9Sstevel@tonic-gate DI_MINOR(minor)->dev_minor)); 1230*7c478bd9Sstevel@tonic-gate } 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate int 1233*7c478bd9Sstevel@tonic-gate di_minor_spectype(di_minor_t minor) 1234*7c478bd9Sstevel@tonic-gate { 1235*7c478bd9Sstevel@tonic-gate return (DI_MINOR(minor)->spec_type); 1236*7c478bd9Sstevel@tonic-gate } 1237*7c478bd9Sstevel@tonic-gate 1238*7c478bd9Sstevel@tonic-gate char * 1239*7c478bd9Sstevel@tonic-gate di_minor_nodetype(di_minor_t minor) 1240*7c478bd9Sstevel@tonic-gate { 1241*7c478bd9Sstevel@tonic-gate if (DI_MINOR(minor)->node_type == 0) 1242*7c478bd9Sstevel@tonic-gate return (NULL); 1243*7c478bd9Sstevel@tonic-gate 1244*7c478bd9Sstevel@tonic-gate return ((caddr_t)minor - 1245*7c478bd9Sstevel@tonic-gate DI_MINOR(minor)->self + DI_MINOR(minor)->node_type); 1246*7c478bd9Sstevel@tonic-gate } 1247*7c478bd9Sstevel@tonic-gate 1248*7c478bd9Sstevel@tonic-gate /* 1249*7c478bd9Sstevel@tonic-gate * Single public interface for accessing software properties 1250*7c478bd9Sstevel@tonic-gate */ 1251*7c478bd9Sstevel@tonic-gate di_prop_t 1252*7c478bd9Sstevel@tonic-gate di_prop_next(di_node_t node, di_prop_t prop) 1253*7c478bd9Sstevel@tonic-gate { 1254*7c478bd9Sstevel@tonic-gate int list = DI_PROP_DRV_LIST; 1255*7c478bd9Sstevel@tonic-gate 1256*7c478bd9Sstevel@tonic-gate /* 1257*7c478bd9Sstevel@tonic-gate * paranoid check 1258*7c478bd9Sstevel@tonic-gate */ 1259*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 1260*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1261*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1262*7c478bd9Sstevel@tonic-gate } 1263*7c478bd9Sstevel@tonic-gate 1264*7c478bd9Sstevel@tonic-gate /* 1265*7c478bd9Sstevel@tonic-gate * Find which prop list we are at 1266*7c478bd9Sstevel@tonic-gate */ 1267*7c478bd9Sstevel@tonic-gate if (prop != DI_PROP_NIL) 1268*7c478bd9Sstevel@tonic-gate list = DI_PROP(prop)->prop_list; 1269*7c478bd9Sstevel@tonic-gate 1270*7c478bd9Sstevel@tonic-gate do { 1271*7c478bd9Sstevel@tonic-gate switch (list++) { 1272*7c478bd9Sstevel@tonic-gate case DI_PROP_DRV_LIST: 1273*7c478bd9Sstevel@tonic-gate prop = di_prop_drv_next(node, prop); 1274*7c478bd9Sstevel@tonic-gate break; 1275*7c478bd9Sstevel@tonic-gate case DI_PROP_SYS_LIST: 1276*7c478bd9Sstevel@tonic-gate prop = di_prop_sys_next(node, prop); 1277*7c478bd9Sstevel@tonic-gate break; 1278*7c478bd9Sstevel@tonic-gate case DI_PROP_GLB_LIST: 1279*7c478bd9Sstevel@tonic-gate prop = di_prop_global_next(node, prop); 1280*7c478bd9Sstevel@tonic-gate break; 1281*7c478bd9Sstevel@tonic-gate case DI_PROP_HW_LIST: 1282*7c478bd9Sstevel@tonic-gate prop = di_prop_hw_next(node, prop); 1283*7c478bd9Sstevel@tonic-gate break; 1284*7c478bd9Sstevel@tonic-gate default: /* shouldn't happen */ 1285*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1286*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1287*7c478bd9Sstevel@tonic-gate } 1288*7c478bd9Sstevel@tonic-gate } while ((prop == DI_PROP_NIL) && (list <= DI_PROP_HW_LIST)); 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate return (prop); 1291*7c478bd9Sstevel@tonic-gate } 1292*7c478bd9Sstevel@tonic-gate 1293*7c478bd9Sstevel@tonic-gate dev_t 1294*7c478bd9Sstevel@tonic-gate di_prop_devt(di_prop_t prop) 1295*7c478bd9Sstevel@tonic-gate { 1296*7c478bd9Sstevel@tonic-gate return (makedev(DI_PROP(prop)->dev_major, DI_PROP(prop)->dev_minor)); 1297*7c478bd9Sstevel@tonic-gate } 1298*7c478bd9Sstevel@tonic-gate 1299*7c478bd9Sstevel@tonic-gate char * 1300*7c478bd9Sstevel@tonic-gate di_prop_name(di_prop_t prop) 1301*7c478bd9Sstevel@tonic-gate { 1302*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_name == 0) 1303*7c478bd9Sstevel@tonic-gate return (NULL); 1304*7c478bd9Sstevel@tonic-gate 1305*7c478bd9Sstevel@tonic-gate return ((caddr_t)prop - DI_PROP(prop)->self + DI_PROP(prop)->prop_name); 1306*7c478bd9Sstevel@tonic-gate } 1307*7c478bd9Sstevel@tonic-gate 1308*7c478bd9Sstevel@tonic-gate int 1309*7c478bd9Sstevel@tonic-gate di_prop_type(di_prop_t prop) 1310*7c478bd9Sstevel@tonic-gate { 1311*7c478bd9Sstevel@tonic-gate uint_t flags = DI_PROP(prop)->prop_flags; 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_UNDEF_IT) 1314*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNDEF_IT); 1315*7c478bd9Sstevel@tonic-gate 1316*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) 1317*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_BOOLEAN); 1318*7c478bd9Sstevel@tonic-gate 1319*7c478bd9Sstevel@tonic-gate if ((flags & DDI_PROP_TYPE_MASK) == DDI_PROP_TYPE_ANY) 1320*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNKNOWN); 1321*7c478bd9Sstevel@tonic-gate 1322*7c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_INT) 1323*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT); 1324*7c478bd9Sstevel@tonic-gate 1325*7c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_INT64) 1326*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT64); 1327*7c478bd9Sstevel@tonic-gate 1328*7c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_STRING) 1329*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_STRING); 1330*7c478bd9Sstevel@tonic-gate 1331*7c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_BYTE) 1332*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_BYTE); 1333*7c478bd9Sstevel@tonic-gate 1334*7c478bd9Sstevel@tonic-gate /* 1335*7c478bd9Sstevel@tonic-gate * Shouldn't get here. In case we do, return unknown type. 1336*7c478bd9Sstevel@tonic-gate * 1337*7c478bd9Sstevel@tonic-gate * XXX--When DDI_PROP_TYPE_COMPOSITE is implemented, we need 1338*7c478bd9Sstevel@tonic-gate * to add DI_PROP_TYPE_COMPOSITE. 1339*7c478bd9Sstevel@tonic-gate */ 1340*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "Unimplemented property type: 0x%x\n", flags)); 1341*7c478bd9Sstevel@tonic-gate 1342*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNKNOWN); 1343*7c478bd9Sstevel@tonic-gate } 1344*7c478bd9Sstevel@tonic-gate 1345*7c478bd9Sstevel@tonic-gate /* 1346*7c478bd9Sstevel@tonic-gate * Extract type-specific values of an property 1347*7c478bd9Sstevel@tonic-gate */ 1348*7c478bd9Sstevel@tonic-gate extern int di_prop_decode_common(void *prop_data, int len, 1349*7c478bd9Sstevel@tonic-gate int ddi_type, int prom); 1350*7c478bd9Sstevel@tonic-gate 1351*7c478bd9Sstevel@tonic-gate int 1352*7c478bd9Sstevel@tonic-gate di_prop_ints(di_prop_t prop, int **prop_data) 1353*7c478bd9Sstevel@tonic-gate { 1354*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) 1355*7c478bd9Sstevel@tonic-gate return (0); /* boolean property */ 1356*7c478bd9Sstevel@tonic-gate 1357*7c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) || 1358*7c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) { 1359*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1360*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1361*7c478bd9Sstevel@tonic-gate return (-1); 1362*7c478bd9Sstevel@tonic-gate } 1363*7c478bd9Sstevel@tonic-gate 1364*7c478bd9Sstevel@tonic-gate *prop_data = (int *)((void *)((caddr_t)prop - DI_PROP(prop)->self 1365*7c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data)); 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1368*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_INT, 0)); 1369*7c478bd9Sstevel@tonic-gate } 1370*7c478bd9Sstevel@tonic-gate 1371*7c478bd9Sstevel@tonic-gate int 1372*7c478bd9Sstevel@tonic-gate di_prop_int64(di_prop_t prop, int64_t **prop_data) 1373*7c478bd9Sstevel@tonic-gate { 1374*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) 1375*7c478bd9Sstevel@tonic-gate return (0); /* boolean property */ 1376*7c478bd9Sstevel@tonic-gate 1377*7c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) || 1378*7c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) { 1379*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1380*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1381*7c478bd9Sstevel@tonic-gate return (-1); 1382*7c478bd9Sstevel@tonic-gate } 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate *prop_data = (int64_t *)((void *)((caddr_t)prop - DI_PROP(prop)->self 1385*7c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data)); 1386*7c478bd9Sstevel@tonic-gate 1387*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1388*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_INT64, 0)); 1389*7c478bd9Sstevel@tonic-gate } 1390*7c478bd9Sstevel@tonic-gate 1391*7c478bd9Sstevel@tonic-gate int 1392*7c478bd9Sstevel@tonic-gate di_prop_strings(di_prop_t prop, char **prop_data) 1393*7c478bd9Sstevel@tonic-gate { 1394*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) 1395*7c478bd9Sstevel@tonic-gate return (0); /* boolean property */ 1396*7c478bd9Sstevel@tonic-gate 1397*7c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) || 1398*7c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) { 1399*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1400*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1401*7c478bd9Sstevel@tonic-gate return (-1); 1402*7c478bd9Sstevel@tonic-gate } 1403*7c478bd9Sstevel@tonic-gate 1404*7c478bd9Sstevel@tonic-gate *prop_data = (char *)((caddr_t)prop - DI_PROP(prop)->self 1405*7c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data); 1406*7c478bd9Sstevel@tonic-gate 1407*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1408*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_STRING, 0)); 1409*7c478bd9Sstevel@tonic-gate } 1410*7c478bd9Sstevel@tonic-gate 1411*7c478bd9Sstevel@tonic-gate int 1412*7c478bd9Sstevel@tonic-gate di_prop_bytes(di_prop_t prop, uchar_t **prop_data) 1413*7c478bd9Sstevel@tonic-gate { 1414*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) 1415*7c478bd9Sstevel@tonic-gate return (0); /* boolean property */ 1416*7c478bd9Sstevel@tonic-gate 1417*7c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) || 1418*7c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) { 1419*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1420*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1421*7c478bd9Sstevel@tonic-gate return (-1); 1422*7c478bd9Sstevel@tonic-gate } 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate *prop_data = (uchar_t *)((caddr_t)prop - DI_PROP(prop)->self 1425*7c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data); 1426*7c478bd9Sstevel@tonic-gate 1427*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1428*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_BYTE, 0)); 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate /* 1432*7c478bd9Sstevel@tonic-gate * returns 1 for match, 0 for no match 1433*7c478bd9Sstevel@tonic-gate */ 1434*7c478bd9Sstevel@tonic-gate static int 1435*7c478bd9Sstevel@tonic-gate match_prop(di_prop_t prop, dev_t match_dev, const char *name, int type) 1436*7c478bd9Sstevel@tonic-gate { 1437*7c478bd9Sstevel@tonic-gate int prop_type; 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1440*7c478bd9Sstevel@tonic-gate if (di_prop_name(prop) == NULL) { 1441*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "libdevinfo: property has no name!\n")); 1442*7c478bd9Sstevel@tonic-gate return (0); 1443*7c478bd9Sstevel@tonic-gate } 1444*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1445*7c478bd9Sstevel@tonic-gate 1446*7c478bd9Sstevel@tonic-gate if (strcmp(name, di_prop_name(prop)) != 0) 1447*7c478bd9Sstevel@tonic-gate return (0); 1448*7c478bd9Sstevel@tonic-gate 1449*7c478bd9Sstevel@tonic-gate if ((match_dev != DDI_DEV_T_ANY) && (di_prop_devt(prop) != match_dev)) 1450*7c478bd9Sstevel@tonic-gate return (0); 1451*7c478bd9Sstevel@tonic-gate 1452*7c478bd9Sstevel@tonic-gate /* 1453*7c478bd9Sstevel@tonic-gate * XXX prop_type is different from DDI_*. See PSARC 1997/127. 1454*7c478bd9Sstevel@tonic-gate */ 1455*7c478bd9Sstevel@tonic-gate prop_type = di_prop_type(prop); 1456*7c478bd9Sstevel@tonic-gate if ((prop_type != DI_PROP_TYPE_UNKNOWN) && (prop_type != type) && 1457*7c478bd9Sstevel@tonic-gate (prop_type != DI_PROP_TYPE_BOOLEAN)) 1458*7c478bd9Sstevel@tonic-gate return (0); 1459*7c478bd9Sstevel@tonic-gate 1460*7c478bd9Sstevel@tonic-gate return (1); 1461*7c478bd9Sstevel@tonic-gate } 1462*7c478bd9Sstevel@tonic-gate 1463*7c478bd9Sstevel@tonic-gate static di_prop_t 1464*7c478bd9Sstevel@tonic-gate di_prop_search(dev_t match_dev, di_node_t node, const char *name, 1465*7c478bd9Sstevel@tonic-gate int type) 1466*7c478bd9Sstevel@tonic-gate { 1467*7c478bd9Sstevel@tonic-gate di_prop_t prop = DI_PROP_NIL; 1468*7c478bd9Sstevel@tonic-gate 1469*7c478bd9Sstevel@tonic-gate /* 1470*7c478bd9Sstevel@tonic-gate * The check on match_dev follows ddi_prop_lookup_common(). 1471*7c478bd9Sstevel@tonic-gate * Other checks are libdevinfo specific implementation. 1472*7c478bd9Sstevel@tonic-gate */ 1473*7c478bd9Sstevel@tonic-gate if ((node == DI_NODE_NIL) || (name == NULL) || (strlen(name) == 0) || 1474*7c478bd9Sstevel@tonic-gate (match_dev == DDI_DEV_T_NONE) || !DI_PROP_TYPE_VALID(type)) { 1475*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1476*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1477*7c478bd9Sstevel@tonic-gate } 1478*7c478bd9Sstevel@tonic-gate 1479*7c478bd9Sstevel@tonic-gate while ((prop = di_prop_next(node, prop)) != DI_PROP_NIL) { 1480*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "match prop name %s, devt 0x%lx, type %d\n", 1481*7c478bd9Sstevel@tonic-gate di_prop_name(prop), di_prop_devt(prop), 1482*7c478bd9Sstevel@tonic-gate di_prop_type(prop))); 1483*7c478bd9Sstevel@tonic-gate if (match_prop(prop, match_dev, name, type)) 1484*7c478bd9Sstevel@tonic-gate return (prop); 1485*7c478bd9Sstevel@tonic-gate } 1486*7c478bd9Sstevel@tonic-gate 1487*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1488*7c478bd9Sstevel@tonic-gate } 1489*7c478bd9Sstevel@tonic-gate 1490*7c478bd9Sstevel@tonic-gate int 1491*7c478bd9Sstevel@tonic-gate di_prop_lookup_ints(dev_t dev, di_node_t node, const char *prop_name, 1492*7c478bd9Sstevel@tonic-gate int **prop_data) 1493*7c478bd9Sstevel@tonic-gate { 1494*7c478bd9Sstevel@tonic-gate di_prop_t prop; 1495*7c478bd9Sstevel@tonic-gate 1496*7c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name, 1497*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT)) == DI_PROP_NIL) 1498*7c478bd9Sstevel@tonic-gate return (-1); 1499*7c478bd9Sstevel@tonic-gate 1500*7c478bd9Sstevel@tonic-gate return (di_prop_ints(prop, (void *)prop_data)); 1501*7c478bd9Sstevel@tonic-gate } 1502*7c478bd9Sstevel@tonic-gate 1503*7c478bd9Sstevel@tonic-gate int 1504*7c478bd9Sstevel@tonic-gate di_prop_lookup_int64(dev_t dev, di_node_t node, const char *prop_name, 1505*7c478bd9Sstevel@tonic-gate int64_t **prop_data) 1506*7c478bd9Sstevel@tonic-gate { 1507*7c478bd9Sstevel@tonic-gate di_prop_t prop; 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name, 1510*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT64)) == DI_PROP_NIL) 1511*7c478bd9Sstevel@tonic-gate return (-1); 1512*7c478bd9Sstevel@tonic-gate 1513*7c478bd9Sstevel@tonic-gate return (di_prop_int64(prop, (void *)prop_data)); 1514*7c478bd9Sstevel@tonic-gate } 1515*7c478bd9Sstevel@tonic-gate 1516*7c478bd9Sstevel@tonic-gate int 1517*7c478bd9Sstevel@tonic-gate di_prop_lookup_strings(dev_t dev, di_node_t node, const char *prop_name, 1518*7c478bd9Sstevel@tonic-gate char **prop_data) 1519*7c478bd9Sstevel@tonic-gate { 1520*7c478bd9Sstevel@tonic-gate di_prop_t prop; 1521*7c478bd9Sstevel@tonic-gate 1522*7c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name, 1523*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_STRING)) == DI_PROP_NIL) 1524*7c478bd9Sstevel@tonic-gate return (-1); 1525*7c478bd9Sstevel@tonic-gate 1526*7c478bd9Sstevel@tonic-gate return (di_prop_strings(prop, (void *)prop_data)); 1527*7c478bd9Sstevel@tonic-gate } 1528*7c478bd9Sstevel@tonic-gate 1529*7c478bd9Sstevel@tonic-gate int 1530*7c478bd9Sstevel@tonic-gate di_prop_lookup_bytes(dev_t dev, di_node_t node, const char *prop_name, 1531*7c478bd9Sstevel@tonic-gate uchar_t **prop_data) 1532*7c478bd9Sstevel@tonic-gate { 1533*7c478bd9Sstevel@tonic-gate di_prop_t prop; 1534*7c478bd9Sstevel@tonic-gate 1535*7c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name, 1536*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_BYTE)) == DI_PROP_NIL) 1537*7c478bd9Sstevel@tonic-gate return (-1); 1538*7c478bd9Sstevel@tonic-gate 1539*7c478bd9Sstevel@tonic-gate return (di_prop_bytes(prop, (void *)prop_data)); 1540*7c478bd9Sstevel@tonic-gate } 1541*7c478bd9Sstevel@tonic-gate 1542*7c478bd9Sstevel@tonic-gate /* 1543*7c478bd9Sstevel@tonic-gate * Consolidation private property access functions 1544*7c478bd9Sstevel@tonic-gate */ 1545*7c478bd9Sstevel@tonic-gate enum prop_type { 1546*7c478bd9Sstevel@tonic-gate PROP_TYPE_DRV, 1547*7c478bd9Sstevel@tonic-gate PROP_TYPE_SYS, 1548*7c478bd9Sstevel@tonic-gate PROP_TYPE_GLOB, 1549*7c478bd9Sstevel@tonic-gate PROP_TYPE_HW 1550*7c478bd9Sstevel@tonic-gate }; 1551*7c478bd9Sstevel@tonic-gate 1552*7c478bd9Sstevel@tonic-gate static di_prop_t 1553*7c478bd9Sstevel@tonic-gate di_prop_next_common(di_node_t node, di_prop_t prop, int prop_type) 1554*7c478bd9Sstevel@tonic-gate { 1555*7c478bd9Sstevel@tonic-gate caddr_t pa; 1556*7c478bd9Sstevel@tonic-gate di_off_t prop_off = 0; 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate if (prop != DI_PROP_NIL) { 1559*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->next) { 1560*7c478bd9Sstevel@tonic-gate return (DI_PROP((caddr_t)prop - 1561*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->self + DI_PROP(prop)->next)); 1562*7c478bd9Sstevel@tonic-gate } else { 1563*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1564*7c478bd9Sstevel@tonic-gate } 1565*7c478bd9Sstevel@tonic-gate } 1566*7c478bd9Sstevel@tonic-gate 1567*7c478bd9Sstevel@tonic-gate 1568*7c478bd9Sstevel@tonic-gate /* 1569*7c478bd9Sstevel@tonic-gate * prop is NIL, caller asks for first property 1570*7c478bd9Sstevel@tonic-gate */ 1571*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1572*7c478bd9Sstevel@tonic-gate switch (prop_type) { 1573*7c478bd9Sstevel@tonic-gate case PROP_TYPE_DRV: 1574*7c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->drv_prop; 1575*7c478bd9Sstevel@tonic-gate break; 1576*7c478bd9Sstevel@tonic-gate case PROP_TYPE_SYS: 1577*7c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->sys_prop; 1578*7c478bd9Sstevel@tonic-gate break; 1579*7c478bd9Sstevel@tonic-gate case PROP_TYPE_HW: 1580*7c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->hw_prop; 1581*7c478bd9Sstevel@tonic-gate break; 1582*7c478bd9Sstevel@tonic-gate case PROP_TYPE_GLOB: 1583*7c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->glob_prop; 1584*7c478bd9Sstevel@tonic-gate if (prop_off == -1) { 1585*7c478bd9Sstevel@tonic-gate /* no global property */ 1586*7c478bd9Sstevel@tonic-gate prop_off = 0; 1587*7c478bd9Sstevel@tonic-gate } else if ((prop_off == 0) && (DI_NODE(node)->drv_major >= 0)) { 1588*7c478bd9Sstevel@tonic-gate /* refer to devnames array */ 1589*7c478bd9Sstevel@tonic-gate struct di_devnm *devnm = DI_DEVNM(pa + 1590*7c478bd9Sstevel@tonic-gate DI_ALL(pa)->devnames + (DI_NODE(node)->drv_major * 1591*7c478bd9Sstevel@tonic-gate sizeof (struct di_devnm))); 1592*7c478bd9Sstevel@tonic-gate prop_off = devnm->global_prop; 1593*7c478bd9Sstevel@tonic-gate } 1594*7c478bd9Sstevel@tonic-gate break; 1595*7c478bd9Sstevel@tonic-gate } 1596*7c478bd9Sstevel@tonic-gate 1597*7c478bd9Sstevel@tonic-gate if (prop_off) { 1598*7c478bd9Sstevel@tonic-gate return (DI_PROP(pa + prop_off)); 1599*7c478bd9Sstevel@tonic-gate } 1600*7c478bd9Sstevel@tonic-gate 1601*7c478bd9Sstevel@tonic-gate /* 1602*7c478bd9Sstevel@tonic-gate * no prop found. Check the reason for not found 1603*7c478bd9Sstevel@tonic-gate */ 1604*7c478bd9Sstevel@tonic-gate if (DINFOPROP & DI_ALL(pa)->command) 1605*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1606*7c478bd9Sstevel@tonic-gate else 1607*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1608*7c478bd9Sstevel@tonic-gate 1609*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1610*7c478bd9Sstevel@tonic-gate } 1611*7c478bd9Sstevel@tonic-gate 1612*7c478bd9Sstevel@tonic-gate di_prop_t 1613*7c478bd9Sstevel@tonic-gate di_prop_drv_next(di_node_t node, di_prop_t prop) 1614*7c478bd9Sstevel@tonic-gate { 1615*7c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_DRV)); 1616*7c478bd9Sstevel@tonic-gate } 1617*7c478bd9Sstevel@tonic-gate 1618*7c478bd9Sstevel@tonic-gate di_prop_t 1619*7c478bd9Sstevel@tonic-gate di_prop_sys_next(di_node_t node, di_prop_t prop) 1620*7c478bd9Sstevel@tonic-gate { 1621*7c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_SYS)); 1622*7c478bd9Sstevel@tonic-gate } 1623*7c478bd9Sstevel@tonic-gate 1624*7c478bd9Sstevel@tonic-gate di_prop_t 1625*7c478bd9Sstevel@tonic-gate di_prop_global_next(di_node_t node, di_prop_t prop) 1626*7c478bd9Sstevel@tonic-gate { 1627*7c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_GLOB)); 1628*7c478bd9Sstevel@tonic-gate } 1629*7c478bd9Sstevel@tonic-gate 1630*7c478bd9Sstevel@tonic-gate di_prop_t 1631*7c478bd9Sstevel@tonic-gate di_prop_hw_next(di_node_t node, di_prop_t prop) 1632*7c478bd9Sstevel@tonic-gate { 1633*7c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_HW)); 1634*7c478bd9Sstevel@tonic-gate } 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate int 1637*7c478bd9Sstevel@tonic-gate di_prop_rawdata(di_prop_t prop, uchar_t **prop_data) 1638*7c478bd9Sstevel@tonic-gate { 1639*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 1640*7c478bd9Sstevel@tonic-gate if (prop == DI_PROP_NIL) { 1641*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1642*7c478bd9Sstevel@tonic-gate return (-1); 1643*7c478bd9Sstevel@tonic-gate } 1644*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 1645*7c478bd9Sstevel@tonic-gate 1646*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) { 1647*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1648*7c478bd9Sstevel@tonic-gate return (0); 1649*7c478bd9Sstevel@tonic-gate } 1650*7c478bd9Sstevel@tonic-gate 1651*7c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) || 1652*7c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) { 1653*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1654*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1655*7c478bd9Sstevel@tonic-gate return (-1); 1656*7c478bd9Sstevel@tonic-gate } 1657*7c478bd9Sstevel@tonic-gate 1658*7c478bd9Sstevel@tonic-gate /* 1659*7c478bd9Sstevel@tonic-gate * No memory allocation. 1660*7c478bd9Sstevel@tonic-gate */ 1661*7c478bd9Sstevel@tonic-gate *prop_data = (uchar_t *)((caddr_t)prop - DI_PROP(prop)->self + 1662*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_data); 1663*7c478bd9Sstevel@tonic-gate 1664*7c478bd9Sstevel@tonic-gate return (DI_PROP(prop)->prop_len); 1665*7c478bd9Sstevel@tonic-gate } 1666*7c478bd9Sstevel@tonic-gate 1667*7c478bd9Sstevel@tonic-gate /* 1668*7c478bd9Sstevel@tonic-gate * Consolidation private interfaces for accessing I/O multipathing data 1669*7c478bd9Sstevel@tonic-gate */ 1670*7c478bd9Sstevel@tonic-gate di_path_t 1671*7c478bd9Sstevel@tonic-gate di_path_next_client(di_node_t node, di_path_t path) 1672*7c478bd9Sstevel@tonic-gate { 1673*7c478bd9Sstevel@tonic-gate caddr_t pa; 1674*7c478bd9Sstevel@tonic-gate 1675*7c478bd9Sstevel@tonic-gate /* 1676*7c478bd9Sstevel@tonic-gate * path is not NIL 1677*7c478bd9Sstevel@tonic-gate */ 1678*7c478bd9Sstevel@tonic-gate if (path != DI_PATH_NIL) { 1679*7c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_p_link != 0) 1680*7c478bd9Sstevel@tonic-gate return (DI_PATH((void *)((caddr_t)path - 1681*7c478bd9Sstevel@tonic-gate DI_PATH(path)->self + DI_PATH(path)->path_p_link))); 1682*7c478bd9Sstevel@tonic-gate else { 1683*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1684*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1685*7c478bd9Sstevel@tonic-gate } 1686*7c478bd9Sstevel@tonic-gate } 1687*7c478bd9Sstevel@tonic-gate 1688*7c478bd9Sstevel@tonic-gate /* 1689*7c478bd9Sstevel@tonic-gate * Path is NIL; the caller is asking for the first path info node 1690*7c478bd9Sstevel@tonic-gate */ 1691*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->multipath_phci != 0) { 1692*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "phci: returning %p\n", ((caddr_t)node - 1693*7c478bd9Sstevel@tonic-gate DI_NODE(node)->self + DI_NODE(node)->multipath_phci))); 1694*7c478bd9Sstevel@tonic-gate return (DI_PATH((caddr_t)node - DI_NODE(node)->self + 1695*7c478bd9Sstevel@tonic-gate DI_NODE(node)->multipath_phci)); 1696*7c478bd9Sstevel@tonic-gate } 1697*7c478bd9Sstevel@tonic-gate 1698*7c478bd9Sstevel@tonic-gate /* 1699*7c478bd9Sstevel@tonic-gate * No pathing data; check if the snapshot includes path data in order 1700*7c478bd9Sstevel@tonic-gate * to set errno properly. 1701*7c478bd9Sstevel@tonic-gate */ 1702*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1703*7c478bd9Sstevel@tonic-gate if (DINFOPATH & (DI_ALL(pa)->command)) 1704*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1705*7c478bd9Sstevel@tonic-gate else 1706*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1709*7c478bd9Sstevel@tonic-gate } 1710*7c478bd9Sstevel@tonic-gate 1711*7c478bd9Sstevel@tonic-gate di_path_t 1712*7c478bd9Sstevel@tonic-gate di_path_next_phci(di_node_t node, di_path_t path) 1713*7c478bd9Sstevel@tonic-gate { 1714*7c478bd9Sstevel@tonic-gate caddr_t pa; 1715*7c478bd9Sstevel@tonic-gate 1716*7c478bd9Sstevel@tonic-gate /* 1717*7c478bd9Sstevel@tonic-gate * path is not NIL 1718*7c478bd9Sstevel@tonic-gate */ 1719*7c478bd9Sstevel@tonic-gate if (path != DI_PATH_NIL) { 1720*7c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_c_link != 0) 1721*7c478bd9Sstevel@tonic-gate return (DI_PATH((caddr_t)path - DI_PATH(path)->self 1722*7c478bd9Sstevel@tonic-gate + DI_PATH(path)->path_c_link)); 1723*7c478bd9Sstevel@tonic-gate else { 1724*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1725*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1726*7c478bd9Sstevel@tonic-gate } 1727*7c478bd9Sstevel@tonic-gate } 1728*7c478bd9Sstevel@tonic-gate 1729*7c478bd9Sstevel@tonic-gate /* 1730*7c478bd9Sstevel@tonic-gate * Path is NIL; the caller is asking for the first path info node 1731*7c478bd9Sstevel@tonic-gate */ 1732*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->multipath_client != 0) { 1733*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "client: returning %p\n", ((caddr_t)node - 1734*7c478bd9Sstevel@tonic-gate DI_NODE(node)->self + DI_NODE(node)->multipath_client))); 1735*7c478bd9Sstevel@tonic-gate return (DI_PATH((caddr_t)node - DI_NODE(node)->self + 1736*7c478bd9Sstevel@tonic-gate DI_NODE(node)->multipath_client)); 1737*7c478bd9Sstevel@tonic-gate } 1738*7c478bd9Sstevel@tonic-gate 1739*7c478bd9Sstevel@tonic-gate /* 1740*7c478bd9Sstevel@tonic-gate * No pathing data; check if the snapshot includes path data in order 1741*7c478bd9Sstevel@tonic-gate * to set errno properly. 1742*7c478bd9Sstevel@tonic-gate */ 1743*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 1744*7c478bd9Sstevel@tonic-gate if (DINFOPATH & (DI_ALL(pa)->command)) 1745*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1746*7c478bd9Sstevel@tonic-gate else 1747*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1750*7c478bd9Sstevel@tonic-gate } 1751*7c478bd9Sstevel@tonic-gate 1752*7c478bd9Sstevel@tonic-gate /* 1753*7c478bd9Sstevel@tonic-gate * XXX Obsolete wrapper to be removed. Won't work under multilevel. 1754*7c478bd9Sstevel@tonic-gate */ 1755*7c478bd9Sstevel@tonic-gate di_path_t 1756*7c478bd9Sstevel@tonic-gate di_path_next(di_node_t node, di_path_t path) 1757*7c478bd9Sstevel@tonic-gate { 1758*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 1759*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1760*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1761*7c478bd9Sstevel@tonic-gate } 1762*7c478bd9Sstevel@tonic-gate 1763*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->multipath_client) { 1764*7c478bd9Sstevel@tonic-gate return (di_path_next_phci(node, path)); 1765*7c478bd9Sstevel@tonic-gate } else if (DI_NODE(node)->multipath_phci) { 1766*7c478bd9Sstevel@tonic-gate return (di_path_next_client(node, path)); 1767*7c478bd9Sstevel@tonic-gate } else { 1768*7c478bd9Sstevel@tonic-gate /* 1769*7c478bd9Sstevel@tonic-gate * The node had multipathing data but didn't appear to be a 1770*7c478bd9Sstevel@tonic-gate * phci *or* a client; probably a programmer error. 1771*7c478bd9Sstevel@tonic-gate */ 1772*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1773*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1774*7c478bd9Sstevel@tonic-gate } 1775*7c478bd9Sstevel@tonic-gate } 1776*7c478bd9Sstevel@tonic-gate 1777*7c478bd9Sstevel@tonic-gate di_path_state_t 1778*7c478bd9Sstevel@tonic-gate di_path_state(di_path_t path) 1779*7c478bd9Sstevel@tonic-gate { 1780*7c478bd9Sstevel@tonic-gate return ((di_path_state_t)DI_PATH(path)->path_state); 1781*7c478bd9Sstevel@tonic-gate } 1782*7c478bd9Sstevel@tonic-gate 1783*7c478bd9Sstevel@tonic-gate char * 1784*7c478bd9Sstevel@tonic-gate di_path_addr(di_path_t path, char *buf) 1785*7c478bd9Sstevel@tonic-gate { 1786*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 1787*7c478bd9Sstevel@tonic-gate 1788*7c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self; 1789*7c478bd9Sstevel@tonic-gate 1790*7c478bd9Sstevel@tonic-gate (void) strncpy(buf, (char *)(pa + DI_PATH(path)->path_addr), 1791*7c478bd9Sstevel@tonic-gate MAXPATHLEN); 1792*7c478bd9Sstevel@tonic-gate return (buf); 1793*7c478bd9Sstevel@tonic-gate } 1794*7c478bd9Sstevel@tonic-gate 1795*7c478bd9Sstevel@tonic-gate di_node_t 1796*7c478bd9Sstevel@tonic-gate di_path_client_node(di_path_t path) 1797*7c478bd9Sstevel@tonic-gate { 1798*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 1799*7c478bd9Sstevel@tonic-gate 1800*7c478bd9Sstevel@tonic-gate if (path == DI_PATH_NIL) { 1801*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1802*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1803*7c478bd9Sstevel@tonic-gate } 1804*7c478bd9Sstevel@tonic-gate 1805*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get client node for path %p\n", path)); 1806*7c478bd9Sstevel@tonic-gate 1807*7c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self; 1808*7c478bd9Sstevel@tonic-gate 1809*7c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_client) { 1810*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_PATH(path)->path_client)); 1811*7c478bd9Sstevel@tonic-gate } 1812*7c478bd9Sstevel@tonic-gate 1813*7c478bd9Sstevel@tonic-gate /* 1814*7c478bd9Sstevel@tonic-gate * Deal with error condition: 1815*7c478bd9Sstevel@tonic-gate * If parent doesn't exist and node is not the root, 1816*7c478bd9Sstevel@tonic-gate * set errno to ENOTSUP. Otherwise, set errno to ENXIO. 1817*7c478bd9Sstevel@tonic-gate */ 1818*7c478bd9Sstevel@tonic-gate if ((DI_PATH(path)->path_snap_state & DI_PATH_SNAP_NOCLIENT) == 0) 1819*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1820*7c478bd9Sstevel@tonic-gate else 1821*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1822*7c478bd9Sstevel@tonic-gate 1823*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 1824*7c478bd9Sstevel@tonic-gate } 1825*7c478bd9Sstevel@tonic-gate 1826*7c478bd9Sstevel@tonic-gate di_node_t 1827*7c478bd9Sstevel@tonic-gate di_path_phci_node(di_path_t path) 1828*7c478bd9Sstevel@tonic-gate { 1829*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 1830*7c478bd9Sstevel@tonic-gate 1831*7c478bd9Sstevel@tonic-gate if (path == DI_PATH_NIL) { 1832*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1833*7c478bd9Sstevel@tonic-gate return (DI_PATH_NIL); 1834*7c478bd9Sstevel@tonic-gate } 1835*7c478bd9Sstevel@tonic-gate 1836*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get phci node for path %p\n", path)); 1837*7c478bd9Sstevel@tonic-gate 1838*7c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self; 1839*7c478bd9Sstevel@tonic-gate 1840*7c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_phci) { 1841*7c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_PATH(path)->path_phci)); 1842*7c478bd9Sstevel@tonic-gate } 1843*7c478bd9Sstevel@tonic-gate 1844*7c478bd9Sstevel@tonic-gate /* 1845*7c478bd9Sstevel@tonic-gate * Deal with error condition: 1846*7c478bd9Sstevel@tonic-gate * If parent doesn't exist and node is not the root, 1847*7c478bd9Sstevel@tonic-gate * set errno to ENOTSUP. Otherwise, set errno to ENXIO. 1848*7c478bd9Sstevel@tonic-gate */ 1849*7c478bd9Sstevel@tonic-gate if ((DI_PATH(path)->path_snap_state & DI_PATH_SNAP_NOPHCI) == 0) 1850*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1851*7c478bd9Sstevel@tonic-gate else 1852*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1853*7c478bd9Sstevel@tonic-gate 1854*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 1855*7c478bd9Sstevel@tonic-gate } 1856*7c478bd9Sstevel@tonic-gate 1857*7c478bd9Sstevel@tonic-gate di_path_prop_t 1858*7c478bd9Sstevel@tonic-gate di_path_prop_next(di_path_t path, di_path_prop_t prop) 1859*7c478bd9Sstevel@tonic-gate { 1860*7c478bd9Sstevel@tonic-gate caddr_t pa; 1861*7c478bd9Sstevel@tonic-gate 1862*7c478bd9Sstevel@tonic-gate if (path == DI_PATH_NIL) { 1863*7c478bd9Sstevel@tonic-gate errno = EINVAL; 1864*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1865*7c478bd9Sstevel@tonic-gate } 1866*7c478bd9Sstevel@tonic-gate 1867*7c478bd9Sstevel@tonic-gate /* 1868*7c478bd9Sstevel@tonic-gate * prop is not NIL 1869*7c478bd9Sstevel@tonic-gate */ 1870*7c478bd9Sstevel@tonic-gate if (prop != DI_PROP_NIL) { 1871*7c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->next != 0) 1872*7c478bd9Sstevel@tonic-gate return (DI_PATHPROP((caddr_t)prop - 1873*7c478bd9Sstevel@tonic-gate DI_PROP(prop)->self + DI_PROP(prop)->next)); 1874*7c478bd9Sstevel@tonic-gate else { 1875*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1876*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1877*7c478bd9Sstevel@tonic-gate } 1878*7c478bd9Sstevel@tonic-gate } 1879*7c478bd9Sstevel@tonic-gate 1880*7c478bd9Sstevel@tonic-gate /* 1881*7c478bd9Sstevel@tonic-gate * prop is NIL-->caller asks for first property 1882*7c478bd9Sstevel@tonic-gate */ 1883*7c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self; 1884*7c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_prop != 0) { 1885*7c478bd9Sstevel@tonic-gate return (DI_PATHPROP(pa + DI_PATH(path)->path_prop)); 1886*7c478bd9Sstevel@tonic-gate } 1887*7c478bd9Sstevel@tonic-gate 1888*7c478bd9Sstevel@tonic-gate /* 1889*7c478bd9Sstevel@tonic-gate * no property data-->check if snapshot includes props 1890*7c478bd9Sstevel@tonic-gate * in order to set the correct errno 1891*7c478bd9Sstevel@tonic-gate */ 1892*7c478bd9Sstevel@tonic-gate if (DINFOPROP & (DI_ALL(pa)->command)) 1893*7c478bd9Sstevel@tonic-gate errno = ENXIO; 1894*7c478bd9Sstevel@tonic-gate else 1895*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 1896*7c478bd9Sstevel@tonic-gate 1897*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 1898*7c478bd9Sstevel@tonic-gate } 1899*7c478bd9Sstevel@tonic-gate 1900*7c478bd9Sstevel@tonic-gate char * 1901*7c478bd9Sstevel@tonic-gate di_path_prop_name(di_path_prop_t prop) 1902*7c478bd9Sstevel@tonic-gate { 1903*7c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */ 1904*7c478bd9Sstevel@tonic-gate pa = (caddr_t)prop - DI_PATHPROP(prop)->self; 1905*7c478bd9Sstevel@tonic-gate return ((char *)(pa + DI_PATHPROP(prop)->prop_name)); 1906*7c478bd9Sstevel@tonic-gate } 1907*7c478bd9Sstevel@tonic-gate 1908*7c478bd9Sstevel@tonic-gate int 1909*7c478bd9Sstevel@tonic-gate di_path_prop_len(di_path_prop_t prop) 1910*7c478bd9Sstevel@tonic-gate { 1911*7c478bd9Sstevel@tonic-gate return (DI_PATHPROP(prop)->prop_len); 1912*7c478bd9Sstevel@tonic-gate } 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate int 1915*7c478bd9Sstevel@tonic-gate di_path_prop_type(di_path_prop_t prop) 1916*7c478bd9Sstevel@tonic-gate { 1917*7c478bd9Sstevel@tonic-gate switch (DI_PATHPROP(prop)->prop_type) { 1918*7c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT: 1919*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT); 1920*7c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT64: 1921*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT64); 1922*7c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_BYTE: 1923*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_BYTE); 1924*7c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_STRING: 1925*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_STRING); 1926*7c478bd9Sstevel@tonic-gate } 1927*7c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNKNOWN); 1928*7c478bd9Sstevel@tonic-gate } 1929*7c478bd9Sstevel@tonic-gate 1930*7c478bd9Sstevel@tonic-gate int 1931*7c478bd9Sstevel@tonic-gate di_path_prop_bytes(di_path_prop_t prop, uchar_t **prop_data) 1932*7c478bd9Sstevel@tonic-gate { 1933*7c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) || 1934*7c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) { 1935*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1936*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1937*7c478bd9Sstevel@tonic-gate return (-1); 1938*7c478bd9Sstevel@tonic-gate } 1939*7c478bd9Sstevel@tonic-gate 1940*7c478bd9Sstevel@tonic-gate *prop_data = (uchar_t *)((caddr_t)prop - DI_PATHPROP(prop)->self 1941*7c478bd9Sstevel@tonic-gate + DI_PATHPROP(prop)->prop_data); 1942*7c478bd9Sstevel@tonic-gate 1943*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1944*7c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_BYTE, 0)); 1945*7c478bd9Sstevel@tonic-gate } 1946*7c478bd9Sstevel@tonic-gate 1947*7c478bd9Sstevel@tonic-gate int 1948*7c478bd9Sstevel@tonic-gate di_path_prop_ints(di_path_prop_t prop, int **prop_data) 1949*7c478bd9Sstevel@tonic-gate { 1950*7c478bd9Sstevel@tonic-gate if (DI_PATHPROP(prop)->prop_len == 0) 1951*7c478bd9Sstevel@tonic-gate return (0); 1952*7c478bd9Sstevel@tonic-gate 1953*7c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) || 1954*7c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) { 1955*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1956*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1957*7c478bd9Sstevel@tonic-gate return (-1); 1958*7c478bd9Sstevel@tonic-gate } 1959*7c478bd9Sstevel@tonic-gate 1960*7c478bd9Sstevel@tonic-gate *prop_data = (int *)((void *)((caddr_t)prop - DI_PATHPROP(prop)->self 1961*7c478bd9Sstevel@tonic-gate + DI_PATHPROP(prop)->prop_data)); 1962*7c478bd9Sstevel@tonic-gate 1963*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1964*7c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_INT, 0)); 1965*7c478bd9Sstevel@tonic-gate } 1966*7c478bd9Sstevel@tonic-gate 1967*7c478bd9Sstevel@tonic-gate int 1968*7c478bd9Sstevel@tonic-gate di_path_prop_int64s(di_path_prop_t prop, int64_t **prop_data) 1969*7c478bd9Sstevel@tonic-gate { 1970*7c478bd9Sstevel@tonic-gate if (DI_PATHPROP(prop)->prop_len == 0) 1971*7c478bd9Sstevel@tonic-gate return (0); 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) || 1974*7c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) { 1975*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1976*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1977*7c478bd9Sstevel@tonic-gate return (-1); 1978*7c478bd9Sstevel@tonic-gate } 1979*7c478bd9Sstevel@tonic-gate 1980*7c478bd9Sstevel@tonic-gate *prop_data = (int64_t *)((void *)((caddr_t)prop - 1981*7c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->self + DI_PATHPROP(prop)->prop_data)); 1982*7c478bd9Sstevel@tonic-gate 1983*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 1984*7c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_INT64, 0)); 1985*7c478bd9Sstevel@tonic-gate } 1986*7c478bd9Sstevel@tonic-gate 1987*7c478bd9Sstevel@tonic-gate int 1988*7c478bd9Sstevel@tonic-gate di_path_prop_strings(di_path_prop_t prop, char **prop_data) 1989*7c478bd9Sstevel@tonic-gate { 1990*7c478bd9Sstevel@tonic-gate if (DI_PATHPROP(prop)->prop_len == 0) 1991*7c478bd9Sstevel@tonic-gate return (0); 1992*7c478bd9Sstevel@tonic-gate 1993*7c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) || 1994*7c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) { 1995*7c478bd9Sstevel@tonic-gate errno = EFAULT; 1996*7c478bd9Sstevel@tonic-gate *prop_data = NULL; 1997*7c478bd9Sstevel@tonic-gate return (-1); 1998*7c478bd9Sstevel@tonic-gate } 1999*7c478bd9Sstevel@tonic-gate 2000*7c478bd9Sstevel@tonic-gate *prop_data = (char *)((caddr_t)prop - DI_PATHPROP(prop)->self 2001*7c478bd9Sstevel@tonic-gate + DI_PATHPROP(prop)->prop_data); 2002*7c478bd9Sstevel@tonic-gate 2003*7c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data, 2004*7c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_STRING, 0)); 2005*7c478bd9Sstevel@tonic-gate } 2006*7c478bd9Sstevel@tonic-gate 2007*7c478bd9Sstevel@tonic-gate static di_path_prop_t 2008*7c478bd9Sstevel@tonic-gate di_path_prop_search(di_path_t path, const char *name, int type) 2009*7c478bd9Sstevel@tonic-gate { 2010*7c478bd9Sstevel@tonic-gate di_path_prop_t prop = DI_PROP_NIL; 2011*7c478bd9Sstevel@tonic-gate 2012*7c478bd9Sstevel@tonic-gate /* 2013*7c478bd9Sstevel@tonic-gate * Sanity check arguments 2014*7c478bd9Sstevel@tonic-gate */ 2015*7c478bd9Sstevel@tonic-gate if ((path == DI_PATH_NIL) || (name == NULL) || (strlen(name) == 0) || 2016*7c478bd9Sstevel@tonic-gate !DI_PROP_TYPE_VALID(type)) { 2017*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2018*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 2019*7c478bd9Sstevel@tonic-gate } 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate while ((prop = di_path_prop_next(path, prop)) != DI_PROP_NIL) { 2022*7c478bd9Sstevel@tonic-gate int prop_type = di_path_prop_type(prop); 2023*7c478bd9Sstevel@tonic-gate 2024*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "match path prop name %s, type %d\n", 2025*7c478bd9Sstevel@tonic-gate di_path_prop_name(prop), prop_type)); 2026*7c478bd9Sstevel@tonic-gate 2027*7c478bd9Sstevel@tonic-gate if (strcmp(name, di_path_prop_name(prop)) != 0) 2028*7c478bd9Sstevel@tonic-gate continue; 2029*7c478bd9Sstevel@tonic-gate 2030*7c478bd9Sstevel@tonic-gate if ((prop_type != DI_PROP_TYPE_UNKNOWN) && (prop_type != type)) 2031*7c478bd9Sstevel@tonic-gate continue; 2032*7c478bd9Sstevel@tonic-gate 2033*7c478bd9Sstevel@tonic-gate return (prop); 2034*7c478bd9Sstevel@tonic-gate } 2035*7c478bd9Sstevel@tonic-gate 2036*7c478bd9Sstevel@tonic-gate return (DI_PROP_NIL); 2037*7c478bd9Sstevel@tonic-gate } 2038*7c478bd9Sstevel@tonic-gate 2039*7c478bd9Sstevel@tonic-gate int 2040*7c478bd9Sstevel@tonic-gate di_path_prop_lookup_bytes(di_path_t path, const char *prop_name, 2041*7c478bd9Sstevel@tonic-gate uchar_t **prop_data) 2042*7c478bd9Sstevel@tonic-gate { 2043*7c478bd9Sstevel@tonic-gate di_path_prop_t prop; 2044*7c478bd9Sstevel@tonic-gate 2045*7c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name, 2046*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_BYTE)) == DI_PROP_NIL) 2047*7c478bd9Sstevel@tonic-gate return (-1); 2048*7c478bd9Sstevel@tonic-gate 2049*7c478bd9Sstevel@tonic-gate return (di_path_prop_bytes(prop, prop_data)); 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate int 2053*7c478bd9Sstevel@tonic-gate di_path_prop_lookup_ints(di_path_t path, const char *prop_name, 2054*7c478bd9Sstevel@tonic-gate int **prop_data) 2055*7c478bd9Sstevel@tonic-gate { 2056*7c478bd9Sstevel@tonic-gate di_path_prop_t prop; 2057*7c478bd9Sstevel@tonic-gate 2058*7c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name, 2059*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT)) == DI_PROP_NIL) 2060*7c478bd9Sstevel@tonic-gate return (-1); 2061*7c478bd9Sstevel@tonic-gate 2062*7c478bd9Sstevel@tonic-gate return (di_path_prop_ints(prop, prop_data)); 2063*7c478bd9Sstevel@tonic-gate } 2064*7c478bd9Sstevel@tonic-gate 2065*7c478bd9Sstevel@tonic-gate int 2066*7c478bd9Sstevel@tonic-gate di_path_prop_lookup_int64s(di_path_t path, const char *prop_name, 2067*7c478bd9Sstevel@tonic-gate int64_t **prop_data) 2068*7c478bd9Sstevel@tonic-gate { 2069*7c478bd9Sstevel@tonic-gate di_path_prop_t prop; 2070*7c478bd9Sstevel@tonic-gate 2071*7c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name, 2072*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT64)) == DI_PROP_NIL) 2073*7c478bd9Sstevel@tonic-gate return (-1); 2074*7c478bd9Sstevel@tonic-gate 2075*7c478bd9Sstevel@tonic-gate return (di_path_prop_int64s(prop, prop_data)); 2076*7c478bd9Sstevel@tonic-gate } 2077*7c478bd9Sstevel@tonic-gate 2078*7c478bd9Sstevel@tonic-gate int di_path_prop_lookup_strings(di_path_t path, const char *prop_name, 2079*7c478bd9Sstevel@tonic-gate char **prop_data) 2080*7c478bd9Sstevel@tonic-gate { 2081*7c478bd9Sstevel@tonic-gate di_path_prop_t prop; 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name, 2084*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_STRING)) == DI_PROP_NIL) 2085*7c478bd9Sstevel@tonic-gate return (-1); 2086*7c478bd9Sstevel@tonic-gate 2087*7c478bd9Sstevel@tonic-gate return (di_path_prop_strings(prop, prop_data)); 2088*7c478bd9Sstevel@tonic-gate } 2089*7c478bd9Sstevel@tonic-gate 2090*7c478bd9Sstevel@tonic-gate 2091*7c478bd9Sstevel@tonic-gate /* 2092*7c478bd9Sstevel@tonic-gate * Consolidation private interfaces for private data 2093*7c478bd9Sstevel@tonic-gate */ 2094*7c478bd9Sstevel@tonic-gate void * 2095*7c478bd9Sstevel@tonic-gate di_parent_private_data(di_node_t node) 2096*7c478bd9Sstevel@tonic-gate { 2097*7c478bd9Sstevel@tonic-gate caddr_t pa; 2098*7c478bd9Sstevel@tonic-gate 2099*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent_data == 0) { 2100*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2101*7c478bd9Sstevel@tonic-gate return (NULL); 2102*7c478bd9Sstevel@tonic-gate } 2103*7c478bd9Sstevel@tonic-gate 2104*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent_data == (di_off_t)-1) { 2105*7c478bd9Sstevel@tonic-gate /* 2106*7c478bd9Sstevel@tonic-gate * Private data requested, but not obtained due to a memory 2107*7c478bd9Sstevel@tonic-gate * error (e.g. wrong format specified) 2108*7c478bd9Sstevel@tonic-gate */ 2109*7c478bd9Sstevel@tonic-gate errno = EFAULT; 2110*7c478bd9Sstevel@tonic-gate return (NULL); 2111*7c478bd9Sstevel@tonic-gate } 2112*7c478bd9Sstevel@tonic-gate 2113*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 2114*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent_data) 2115*7c478bd9Sstevel@tonic-gate return (pa + DI_NODE(node)->parent_data); 2116*7c478bd9Sstevel@tonic-gate 2117*7c478bd9Sstevel@tonic-gate if (DI_ALL(pa)->command & DINFOPRIVDATA) 2118*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2119*7c478bd9Sstevel@tonic-gate else 2120*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2121*7c478bd9Sstevel@tonic-gate 2122*7c478bd9Sstevel@tonic-gate return (NULL); 2123*7c478bd9Sstevel@tonic-gate } 2124*7c478bd9Sstevel@tonic-gate 2125*7c478bd9Sstevel@tonic-gate void * 2126*7c478bd9Sstevel@tonic-gate di_driver_private_data(di_node_t node) 2127*7c478bd9Sstevel@tonic-gate { 2128*7c478bd9Sstevel@tonic-gate caddr_t pa; 2129*7c478bd9Sstevel@tonic-gate 2130*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->driver_data == 0) { 2131*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2132*7c478bd9Sstevel@tonic-gate return (NULL); 2133*7c478bd9Sstevel@tonic-gate } 2134*7c478bd9Sstevel@tonic-gate 2135*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->driver_data == (di_off_t)-1) { 2136*7c478bd9Sstevel@tonic-gate /* 2137*7c478bd9Sstevel@tonic-gate * Private data requested, but not obtained due to a memory 2138*7c478bd9Sstevel@tonic-gate * error (e.g. wrong format specified) 2139*7c478bd9Sstevel@tonic-gate */ 2140*7c478bd9Sstevel@tonic-gate errno = EFAULT; 2141*7c478bd9Sstevel@tonic-gate return (NULL); 2142*7c478bd9Sstevel@tonic-gate } 2143*7c478bd9Sstevel@tonic-gate 2144*7c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self; 2145*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->driver_data) 2146*7c478bd9Sstevel@tonic-gate return (pa + DI_NODE(node)->driver_data); 2147*7c478bd9Sstevel@tonic-gate 2148*7c478bd9Sstevel@tonic-gate if (DI_ALL(pa)->command & DINFOPRIVDATA) 2149*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2150*7c478bd9Sstevel@tonic-gate else 2151*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2152*7c478bd9Sstevel@tonic-gate 2153*7c478bd9Sstevel@tonic-gate return (NULL); 2154*7c478bd9Sstevel@tonic-gate } 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate /* 2157*7c478bd9Sstevel@tonic-gate * PROM property access 2158*7c478bd9Sstevel@tonic-gate */ 2159*7c478bd9Sstevel@tonic-gate 2160*7c478bd9Sstevel@tonic-gate /* 2161*7c478bd9Sstevel@tonic-gate * openprom driver stuff: 2162*7c478bd9Sstevel@tonic-gate * The maximum property length depends on the buffer size. We use 2163*7c478bd9Sstevel@tonic-gate * OPROMMAXPARAM defined in <sys/openpromio.h> 2164*7c478bd9Sstevel@tonic-gate * 2165*7c478bd9Sstevel@tonic-gate * MAXNAMESZ is max property name. obpdefs.h defines it as 32 based on 1275 2166*7c478bd9Sstevel@tonic-gate * MAXVALSZ is maximum value size, which is whatever space left in buf 2167*7c478bd9Sstevel@tonic-gate */ 2168*7c478bd9Sstevel@tonic-gate 2169*7c478bd9Sstevel@tonic-gate #define OBP_MAXBUF OPROMMAXPARAM - sizeof (int) 2170*7c478bd9Sstevel@tonic-gate #define OBP_MAXPROPLEN OBP_MAXBUF - OBP_MAXPROPNAME; 2171*7c478bd9Sstevel@tonic-gate 2172*7c478bd9Sstevel@tonic-gate struct di_prom_prop { 2173*7c478bd9Sstevel@tonic-gate char *name; 2174*7c478bd9Sstevel@tonic-gate int len; 2175*7c478bd9Sstevel@tonic-gate uchar_t *data; 2176*7c478bd9Sstevel@tonic-gate struct di_prom_prop *next; /* form a linked list */ 2177*7c478bd9Sstevel@tonic-gate }; 2178*7c478bd9Sstevel@tonic-gate 2179*7c478bd9Sstevel@tonic-gate struct di_prom_handle { /* handle to prom */ 2180*7c478bd9Sstevel@tonic-gate mutex_t lock; /* synchronize access to openprom fd */ 2181*7c478bd9Sstevel@tonic-gate int fd; /* /dev/openprom file descriptor */ 2182*7c478bd9Sstevel@tonic-gate struct di_prom_prop *list; /* linked list of prop */ 2183*7c478bd9Sstevel@tonic-gate union { 2184*7c478bd9Sstevel@tonic-gate char buf[OPROMMAXPARAM]; 2185*7c478bd9Sstevel@tonic-gate struct openpromio opp; 2186*7c478bd9Sstevel@tonic-gate } oppbuf; 2187*7c478bd9Sstevel@tonic-gate }; 2188*7c478bd9Sstevel@tonic-gate 2189*7c478bd9Sstevel@tonic-gate di_prom_handle_t 2190*7c478bd9Sstevel@tonic-gate di_prom_init() 2191*7c478bd9Sstevel@tonic-gate { 2192*7c478bd9Sstevel@tonic-gate struct di_prom_handle *p; 2193*7c478bd9Sstevel@tonic-gate 2194*7c478bd9Sstevel@tonic-gate if ((p = malloc(sizeof (struct di_prom_handle))) == NULL) 2195*7c478bd9Sstevel@tonic-gate return (DI_PROM_HANDLE_NIL); 2196*7c478bd9Sstevel@tonic-gate 2197*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_prom_init: get prom handle 0x%p\n", p)); 2198*7c478bd9Sstevel@tonic-gate 2199*7c478bd9Sstevel@tonic-gate (void) mutex_init(&p->lock, USYNC_THREAD, NULL); 2200*7c478bd9Sstevel@tonic-gate if ((p->fd = open("/dev/openprom", O_RDONLY)) < 0) { 2201*7c478bd9Sstevel@tonic-gate free(p); 2202*7c478bd9Sstevel@tonic-gate return (DI_PROM_HANDLE_NIL); 2203*7c478bd9Sstevel@tonic-gate } 2204*7c478bd9Sstevel@tonic-gate p->list = NULL; 2205*7c478bd9Sstevel@tonic-gate 2206*7c478bd9Sstevel@tonic-gate return ((di_prom_handle_t)p); 2207*7c478bd9Sstevel@tonic-gate } 2208*7c478bd9Sstevel@tonic-gate 2209*7c478bd9Sstevel@tonic-gate static void 2210*7c478bd9Sstevel@tonic-gate di_prom_prop_free(struct di_prom_prop *list) 2211*7c478bd9Sstevel@tonic-gate { 2212*7c478bd9Sstevel@tonic-gate struct di_prom_prop *tmp = list; 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate while (tmp != NULL) { 2215*7c478bd9Sstevel@tonic-gate list = tmp->next; 2216*7c478bd9Sstevel@tonic-gate if (tmp->name != NULL) { 2217*7c478bd9Sstevel@tonic-gate free(tmp->name); 2218*7c478bd9Sstevel@tonic-gate } 2219*7c478bd9Sstevel@tonic-gate if (tmp->data != NULL) { 2220*7c478bd9Sstevel@tonic-gate free(tmp->data); 2221*7c478bd9Sstevel@tonic-gate } 2222*7c478bd9Sstevel@tonic-gate free(tmp); 2223*7c478bd9Sstevel@tonic-gate tmp = list; 2224*7c478bd9Sstevel@tonic-gate } 2225*7c478bd9Sstevel@tonic-gate } 2226*7c478bd9Sstevel@tonic-gate 2227*7c478bd9Sstevel@tonic-gate void 2228*7c478bd9Sstevel@tonic-gate di_prom_fini(di_prom_handle_t ph) 2229*7c478bd9Sstevel@tonic-gate { 2230*7c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph; 2231*7c478bd9Sstevel@tonic-gate 2232*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_prom_fini: free prom handle 0x%p\n", p)); 2233*7c478bd9Sstevel@tonic-gate 2234*7c478bd9Sstevel@tonic-gate (void) close(p->fd); 2235*7c478bd9Sstevel@tonic-gate (void) mutex_destroy(&p->lock); 2236*7c478bd9Sstevel@tonic-gate di_prom_prop_free(p->list); 2237*7c478bd9Sstevel@tonic-gate 2238*7c478bd9Sstevel@tonic-gate free(p); 2239*7c478bd9Sstevel@tonic-gate } 2240*7c478bd9Sstevel@tonic-gate 2241*7c478bd9Sstevel@tonic-gate /* 2242*7c478bd9Sstevel@tonic-gate * Internal library interface for locating the property 2243*7c478bd9Sstevel@tonic-gate * XXX: ph->lock must be held for the duration of call. 2244*7c478bd9Sstevel@tonic-gate */ 2245*7c478bd9Sstevel@tonic-gate static di_prom_prop_t 2246*7c478bd9Sstevel@tonic-gate di_prom_prop_found(di_prom_handle_t ph, int nodeid, 2247*7c478bd9Sstevel@tonic-gate di_prom_prop_t prom_prop) 2248*7c478bd9Sstevel@tonic-gate { 2249*7c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph; 2250*7c478bd9Sstevel@tonic-gate struct openpromio *opp = &p->oppbuf.opp; 2251*7c478bd9Sstevel@tonic-gate int *ip = (int *)((void *)opp->oprom_array); 2252*7c478bd9Sstevel@tonic-gate struct di_prom_prop *prop = (struct di_prom_prop *)prom_prop; 2253*7c478bd9Sstevel@tonic-gate 2254*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "Looking for nodeid 0x%x\n", nodeid)); 2255*7c478bd9Sstevel@tonic-gate 2256*7c478bd9Sstevel@tonic-gate /* 2257*7c478bd9Sstevel@tonic-gate * Set "current" nodeid in the openprom driver 2258*7c478bd9Sstevel@tonic-gate */ 2259*7c478bd9Sstevel@tonic-gate opp->oprom_size = sizeof (int); 2260*7c478bd9Sstevel@tonic-gate *ip = nodeid; 2261*7c478bd9Sstevel@tonic-gate if (ioctl(p->fd, OPROMSETNODEID, opp) < 0) { 2262*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "*** Nodeid not found 0x%x\n", nodeid)); 2263*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2264*7c478bd9Sstevel@tonic-gate } 2265*7c478bd9Sstevel@tonic-gate 2266*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Found nodeid 0x%x\n", nodeid)); 2267*7c478bd9Sstevel@tonic-gate 2268*7c478bd9Sstevel@tonic-gate bzero(opp, OBP_MAXBUF); 2269*7c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPNAME; 2270*7c478bd9Sstevel@tonic-gate if (prom_prop != DI_PROM_PROP_NIL) 2271*7c478bd9Sstevel@tonic-gate (void) strcpy(opp->oprom_array, prop->name); 2272*7c478bd9Sstevel@tonic-gate 2273*7c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMNXTPROP, opp) < 0) || (opp->oprom_size == 0)) 2274*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2275*7c478bd9Sstevel@tonic-gate 2276*7c478bd9Sstevel@tonic-gate /* 2277*7c478bd9Sstevel@tonic-gate * Prom property found. Allocate struct for storing prop 2278*7c478bd9Sstevel@tonic-gate * (reuse variable prop) 2279*7c478bd9Sstevel@tonic-gate */ 2280*7c478bd9Sstevel@tonic-gate if ((prop = malloc(sizeof (struct di_prom_prop))) == NULL) 2281*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2282*7c478bd9Sstevel@tonic-gate 2283*7c478bd9Sstevel@tonic-gate /* 2284*7c478bd9Sstevel@tonic-gate * Get a copy of property name 2285*7c478bd9Sstevel@tonic-gate */ 2286*7c478bd9Sstevel@tonic-gate if ((prop->name = strdup(opp->oprom_array)) == NULL) { 2287*7c478bd9Sstevel@tonic-gate free(prop); 2288*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2289*7c478bd9Sstevel@tonic-gate } 2290*7c478bd9Sstevel@tonic-gate 2291*7c478bd9Sstevel@tonic-gate /* 2292*7c478bd9Sstevel@tonic-gate * get property value and length 2293*7c478bd9Sstevel@tonic-gate */ 2294*7c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPLEN; 2295*7c478bd9Sstevel@tonic-gate 2296*7c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMGETPROP, opp) < 0) || 2297*7c478bd9Sstevel@tonic-gate (opp->oprom_size == (uint_t)-1)) { 2298*7c478bd9Sstevel@tonic-gate free(prop->name); 2299*7c478bd9Sstevel@tonic-gate free(prop); 2300*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2301*7c478bd9Sstevel@tonic-gate } 2302*7c478bd9Sstevel@tonic-gate 2303*7c478bd9Sstevel@tonic-gate /* 2304*7c478bd9Sstevel@tonic-gate * make a copy of the property value 2305*7c478bd9Sstevel@tonic-gate */ 2306*7c478bd9Sstevel@tonic-gate prop->len = opp->oprom_size; 2307*7c478bd9Sstevel@tonic-gate 2308*7c478bd9Sstevel@tonic-gate if (prop->len == 0) 2309*7c478bd9Sstevel@tonic-gate prop->data = NULL; 2310*7c478bd9Sstevel@tonic-gate else if ((prop->data = malloc(prop->len)) == NULL) { 2311*7c478bd9Sstevel@tonic-gate free(prop->name); 2312*7c478bd9Sstevel@tonic-gate free(prop); 2313*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2314*7c478bd9Sstevel@tonic-gate } 2315*7c478bd9Sstevel@tonic-gate 2316*7c478bd9Sstevel@tonic-gate bcopy(opp->oprom_array, prop->data, prop->len); 2317*7c478bd9Sstevel@tonic-gate 2318*7c478bd9Sstevel@tonic-gate /* 2319*7c478bd9Sstevel@tonic-gate * Prepend prop to list in prom handle 2320*7c478bd9Sstevel@tonic-gate */ 2321*7c478bd9Sstevel@tonic-gate prop->next = p->list; 2322*7c478bd9Sstevel@tonic-gate p->list = prop; 2323*7c478bd9Sstevel@tonic-gate 2324*7c478bd9Sstevel@tonic-gate return ((di_prom_prop_t)prop); 2325*7c478bd9Sstevel@tonic-gate } 2326*7c478bd9Sstevel@tonic-gate 2327*7c478bd9Sstevel@tonic-gate di_prom_prop_t 2328*7c478bd9Sstevel@tonic-gate di_prom_prop_next(di_prom_handle_t ph, di_node_t node, di_prom_prop_t prom_prop) 2329*7c478bd9Sstevel@tonic-gate { 2330*7c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph; 2331*7c478bd9Sstevel@tonic-gate 2332*7c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "Search next prop for node 0x%p with ph 0x%p\n", 2333*7c478bd9Sstevel@tonic-gate node, p)); 2334*7c478bd9Sstevel@tonic-gate 2335*7c478bd9Sstevel@tonic-gate /* 2336*7c478bd9Sstevel@tonic-gate * paranoid check 2337*7c478bd9Sstevel@tonic-gate */ 2338*7c478bd9Sstevel@tonic-gate if ((ph == DI_PROM_HANDLE_NIL) || (node == DI_NODE_NIL)) { 2339*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2340*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2341*7c478bd9Sstevel@tonic-gate } 2342*7c478bd9Sstevel@tonic-gate 2343*7c478bd9Sstevel@tonic-gate if (di_nodeid(node) != DI_PROM_NODEID) { 2344*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2345*7c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL); 2346*7c478bd9Sstevel@tonic-gate } 2347*7c478bd9Sstevel@tonic-gate 2348*7c478bd9Sstevel@tonic-gate /* 2349*7c478bd9Sstevel@tonic-gate * synchronize access to prom file descriptor 2350*7c478bd9Sstevel@tonic-gate */ 2351*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&p->lock); 2352*7c478bd9Sstevel@tonic-gate 2353*7c478bd9Sstevel@tonic-gate /* 2354*7c478bd9Sstevel@tonic-gate * look for next property 2355*7c478bd9Sstevel@tonic-gate */ 2356*7c478bd9Sstevel@tonic-gate prom_prop = di_prom_prop_found(ph, DI_NODE(node)->nodeid, prom_prop); 2357*7c478bd9Sstevel@tonic-gate 2358*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2359*7c478bd9Sstevel@tonic-gate 2360*7c478bd9Sstevel@tonic-gate return (prom_prop); 2361*7c478bd9Sstevel@tonic-gate } 2362*7c478bd9Sstevel@tonic-gate 2363*7c478bd9Sstevel@tonic-gate char * 2364*7c478bd9Sstevel@tonic-gate di_prom_prop_name(di_prom_prop_t prom_prop) 2365*7c478bd9Sstevel@tonic-gate { 2366*7c478bd9Sstevel@tonic-gate /* 2367*7c478bd9Sstevel@tonic-gate * paranoid check 2368*7c478bd9Sstevel@tonic-gate */ 2369*7c478bd9Sstevel@tonic-gate if (prom_prop == DI_PROM_PROP_NIL) { 2370*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2371*7c478bd9Sstevel@tonic-gate return (NULL); 2372*7c478bd9Sstevel@tonic-gate } 2373*7c478bd9Sstevel@tonic-gate 2374*7c478bd9Sstevel@tonic-gate return (((struct di_prom_prop *)prom_prop)->name); 2375*7c478bd9Sstevel@tonic-gate } 2376*7c478bd9Sstevel@tonic-gate 2377*7c478bd9Sstevel@tonic-gate int 2378*7c478bd9Sstevel@tonic-gate di_prom_prop_data(di_prom_prop_t prom_prop, uchar_t **prom_prop_data) 2379*7c478bd9Sstevel@tonic-gate { 2380*7c478bd9Sstevel@tonic-gate /* 2381*7c478bd9Sstevel@tonic-gate * paranoid check 2382*7c478bd9Sstevel@tonic-gate */ 2383*7c478bd9Sstevel@tonic-gate if (prom_prop == DI_PROM_PROP_NIL) { 2384*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2385*7c478bd9Sstevel@tonic-gate return (NULL); 2386*7c478bd9Sstevel@tonic-gate } 2387*7c478bd9Sstevel@tonic-gate 2388*7c478bd9Sstevel@tonic-gate *prom_prop_data = ((struct di_prom_prop *)prom_prop)->data; 2389*7c478bd9Sstevel@tonic-gate 2390*7c478bd9Sstevel@tonic-gate return (((struct di_prom_prop *)prom_prop)->len); 2391*7c478bd9Sstevel@tonic-gate } 2392*7c478bd9Sstevel@tonic-gate 2393*7c478bd9Sstevel@tonic-gate /* 2394*7c478bd9Sstevel@tonic-gate * Internal library interface for locating the property 2395*7c478bd9Sstevel@tonic-gate * Returns length if found, -1 if prop doesn't exist. 2396*7c478bd9Sstevel@tonic-gate */ 2397*7c478bd9Sstevel@tonic-gate static struct di_prom_prop * 2398*7c478bd9Sstevel@tonic-gate di_prom_prop_lookup_common(di_prom_handle_t ph, di_node_t node, 2399*7c478bd9Sstevel@tonic-gate const char *prom_prop_name) 2400*7c478bd9Sstevel@tonic-gate { 2401*7c478bd9Sstevel@tonic-gate struct openpromio *opp; 2402*7c478bd9Sstevel@tonic-gate struct di_prom_prop *prop; 2403*7c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph; 2404*7c478bd9Sstevel@tonic-gate 2405*7c478bd9Sstevel@tonic-gate /* 2406*7c478bd9Sstevel@tonic-gate * paranoid check 2407*7c478bd9Sstevel@tonic-gate */ 2408*7c478bd9Sstevel@tonic-gate if ((ph == DI_PROM_HANDLE_NIL) || (node == DI_NODE_NIL)) { 2409*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2410*7c478bd9Sstevel@tonic-gate return (NULL); 2411*7c478bd9Sstevel@tonic-gate } 2412*7c478bd9Sstevel@tonic-gate 2413*7c478bd9Sstevel@tonic-gate if (di_nodeid(node) != DI_PROM_NODEID) { 2414*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2415*7c478bd9Sstevel@tonic-gate return (NULL); 2416*7c478bd9Sstevel@tonic-gate } 2417*7c478bd9Sstevel@tonic-gate 2418*7c478bd9Sstevel@tonic-gate opp = &p->oppbuf.opp; 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate (void) mutex_lock(&p->lock); 2421*7c478bd9Sstevel@tonic-gate 2422*7c478bd9Sstevel@tonic-gate opp->oprom_size = sizeof (int); 2423*7c478bd9Sstevel@tonic-gate opp->oprom_node = DI_NODE(node)->nodeid; 2424*7c478bd9Sstevel@tonic-gate if (ioctl(p->fd, OPROMSETNODEID, opp) < 0) { 2425*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2426*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "*** Nodeid not found 0x%x\n", 2427*7c478bd9Sstevel@tonic-gate DI_NODE(node)->nodeid)); 2428*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2429*7c478bd9Sstevel@tonic-gate return (NULL); 2430*7c478bd9Sstevel@tonic-gate } 2431*7c478bd9Sstevel@tonic-gate 2432*7c478bd9Sstevel@tonic-gate /* 2433*7c478bd9Sstevel@tonic-gate * get property length 2434*7c478bd9Sstevel@tonic-gate */ 2435*7c478bd9Sstevel@tonic-gate bzero(opp, OBP_MAXBUF); 2436*7c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPLEN; 2437*7c478bd9Sstevel@tonic-gate (void) strcpy(opp->oprom_array, prom_prop_name); 2438*7c478bd9Sstevel@tonic-gate 2439*7c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMGETPROPLEN, opp) < 0) || 2440*7c478bd9Sstevel@tonic-gate (opp->oprom_len == -1)) { 2441*7c478bd9Sstevel@tonic-gate /* no such property */ 2442*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2443*7c478bd9Sstevel@tonic-gate return (NULL); 2444*7c478bd9Sstevel@tonic-gate } 2445*7c478bd9Sstevel@tonic-gate 2446*7c478bd9Sstevel@tonic-gate /* 2447*7c478bd9Sstevel@tonic-gate * Prom property found. Allocate struct for storing prop 2448*7c478bd9Sstevel@tonic-gate */ 2449*7c478bd9Sstevel@tonic-gate if ((prop = malloc(sizeof (struct di_prom_prop))) == NULL) { 2450*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2451*7c478bd9Sstevel@tonic-gate return (NULL); 2452*7c478bd9Sstevel@tonic-gate } 2453*7c478bd9Sstevel@tonic-gate prop->name = NULL; /* we don't need the name */ 2454*7c478bd9Sstevel@tonic-gate prop->len = opp->oprom_len; 2455*7c478bd9Sstevel@tonic-gate 2456*7c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */ 2457*7c478bd9Sstevel@tonic-gate prop->data = NULL; 2458*7c478bd9Sstevel@tonic-gate prop->next = p->list; 2459*7c478bd9Sstevel@tonic-gate p->list = prop; 2460*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2461*7c478bd9Sstevel@tonic-gate return (prop); 2462*7c478bd9Sstevel@tonic-gate } 2463*7c478bd9Sstevel@tonic-gate 2464*7c478bd9Sstevel@tonic-gate /* 2465*7c478bd9Sstevel@tonic-gate * retrieve the property value 2466*7c478bd9Sstevel@tonic-gate */ 2467*7c478bd9Sstevel@tonic-gate bzero(opp, OBP_MAXBUF); 2468*7c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPLEN; 2469*7c478bd9Sstevel@tonic-gate (void) strcpy(opp->oprom_array, prom_prop_name); 2470*7c478bd9Sstevel@tonic-gate 2471*7c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMGETPROP, opp) < 0) || 2472*7c478bd9Sstevel@tonic-gate (opp->oprom_size == (uint_t)-1)) { 2473*7c478bd9Sstevel@tonic-gate /* error retrieving property value */ 2474*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2475*7c478bd9Sstevel@tonic-gate free(prop); 2476*7c478bd9Sstevel@tonic-gate return (NULL); 2477*7c478bd9Sstevel@tonic-gate } 2478*7c478bd9Sstevel@tonic-gate 2479*7c478bd9Sstevel@tonic-gate /* 2480*7c478bd9Sstevel@tonic-gate * make a copy of the property value, stick in ph->list 2481*7c478bd9Sstevel@tonic-gate */ 2482*7c478bd9Sstevel@tonic-gate if ((prop->data = malloc(prop->len)) == NULL) { 2483*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2484*7c478bd9Sstevel@tonic-gate free(prop); 2485*7c478bd9Sstevel@tonic-gate return (NULL); 2486*7c478bd9Sstevel@tonic-gate } 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate bcopy(opp->oprom_array, prop->data, prop->len); 2489*7c478bd9Sstevel@tonic-gate 2490*7c478bd9Sstevel@tonic-gate prop->next = p->list; 2491*7c478bd9Sstevel@tonic-gate p->list = prop; 2492*7c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock); 2493*7c478bd9Sstevel@tonic-gate 2494*7c478bd9Sstevel@tonic-gate return (prop); 2495*7c478bd9Sstevel@tonic-gate } 2496*7c478bd9Sstevel@tonic-gate 2497*7c478bd9Sstevel@tonic-gate int 2498*7c478bd9Sstevel@tonic-gate di_prom_prop_lookup_ints(di_prom_handle_t ph, di_node_t node, 2499*7c478bd9Sstevel@tonic-gate const char *prom_prop_name, int **prom_prop_data) 2500*7c478bd9Sstevel@tonic-gate { 2501*7c478bd9Sstevel@tonic-gate int len; 2502*7c478bd9Sstevel@tonic-gate struct di_prom_prop *prop; 2503*7c478bd9Sstevel@tonic-gate 2504*7c478bd9Sstevel@tonic-gate prop = di_prom_prop_lookup_common(ph, node, prom_prop_name); 2505*7c478bd9Sstevel@tonic-gate 2506*7c478bd9Sstevel@tonic-gate if (prop == NULL) { 2507*7c478bd9Sstevel@tonic-gate *prom_prop_data = NULL; 2508*7c478bd9Sstevel@tonic-gate return (-1); 2509*7c478bd9Sstevel@tonic-gate } 2510*7c478bd9Sstevel@tonic-gate 2511*7c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */ 2512*7c478bd9Sstevel@tonic-gate *prom_prop_data = NULL; 2513*7c478bd9Sstevel@tonic-gate return (0); 2514*7c478bd9Sstevel@tonic-gate } 2515*7c478bd9Sstevel@tonic-gate 2516*7c478bd9Sstevel@tonic-gate len = di_prop_decode_common((void *)&prop->data, prop->len, 2517*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT, 1); 2518*7c478bd9Sstevel@tonic-gate *prom_prop_data = (int *)((void *)prop->data); 2519*7c478bd9Sstevel@tonic-gate 2520*7c478bd9Sstevel@tonic-gate return (len); 2521*7c478bd9Sstevel@tonic-gate } 2522*7c478bd9Sstevel@tonic-gate 2523*7c478bd9Sstevel@tonic-gate int 2524*7c478bd9Sstevel@tonic-gate di_prom_prop_lookup_strings(di_prom_handle_t ph, di_node_t node, 2525*7c478bd9Sstevel@tonic-gate const char *prom_prop_name, char **prom_prop_data) 2526*7c478bd9Sstevel@tonic-gate { 2527*7c478bd9Sstevel@tonic-gate int len; 2528*7c478bd9Sstevel@tonic-gate struct di_prom_prop *prop; 2529*7c478bd9Sstevel@tonic-gate 2530*7c478bd9Sstevel@tonic-gate prop = di_prom_prop_lookup_common(ph, node, prom_prop_name); 2531*7c478bd9Sstevel@tonic-gate 2532*7c478bd9Sstevel@tonic-gate if (prop == NULL) { 2533*7c478bd9Sstevel@tonic-gate *prom_prop_data = NULL; 2534*7c478bd9Sstevel@tonic-gate return (-1); 2535*7c478bd9Sstevel@tonic-gate } 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */ 2538*7c478bd9Sstevel@tonic-gate *prom_prop_data = NULL; 2539*7c478bd9Sstevel@tonic-gate return (0); 2540*7c478bd9Sstevel@tonic-gate } 2541*7c478bd9Sstevel@tonic-gate 2542*7c478bd9Sstevel@tonic-gate /* 2543*7c478bd9Sstevel@tonic-gate * Fix an openprom bug (OBP string not NULL terminated). 2544*7c478bd9Sstevel@tonic-gate * XXX This should really be fixed in promif. 2545*7c478bd9Sstevel@tonic-gate */ 2546*7c478bd9Sstevel@tonic-gate if (((char *)prop->data)[prop->len - 1] != '\0') { 2547*7c478bd9Sstevel@tonic-gate uchar_t *tmp; 2548*7c478bd9Sstevel@tonic-gate prop->len++; 2549*7c478bd9Sstevel@tonic-gate if ((tmp = realloc(prop->data, prop->len)) == NULL) 2550*7c478bd9Sstevel@tonic-gate return (-1); 2551*7c478bd9Sstevel@tonic-gate 2552*7c478bd9Sstevel@tonic-gate prop->data = tmp; 2553*7c478bd9Sstevel@tonic-gate ((char *)prop->data)[prop->len - 1] = '\0'; 2554*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "OBP string not NULL terminated: " 2555*7c478bd9Sstevel@tonic-gate "node=%s, prop=%s, val=%s\n", 2556*7c478bd9Sstevel@tonic-gate di_node_name(node), prom_prop_name, prop->data)); 2557*7c478bd9Sstevel@tonic-gate } 2558*7c478bd9Sstevel@tonic-gate 2559*7c478bd9Sstevel@tonic-gate len = di_prop_decode_common((void *)&prop->data, prop->len, 2560*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_STRING, 1); 2561*7c478bd9Sstevel@tonic-gate *prom_prop_data = (char *)prop->data; 2562*7c478bd9Sstevel@tonic-gate 2563*7c478bd9Sstevel@tonic-gate return (len); 2564*7c478bd9Sstevel@tonic-gate } 2565*7c478bd9Sstevel@tonic-gate 2566*7c478bd9Sstevel@tonic-gate int 2567*7c478bd9Sstevel@tonic-gate di_prom_prop_lookup_bytes(di_prom_handle_t ph, di_node_t node, 2568*7c478bd9Sstevel@tonic-gate const char *prom_prop_name, uchar_t **prom_prop_data) 2569*7c478bd9Sstevel@tonic-gate { 2570*7c478bd9Sstevel@tonic-gate int len; 2571*7c478bd9Sstevel@tonic-gate struct di_prom_prop *prop; 2572*7c478bd9Sstevel@tonic-gate 2573*7c478bd9Sstevel@tonic-gate prop = di_prom_prop_lookup_common(ph, node, prom_prop_name); 2574*7c478bd9Sstevel@tonic-gate 2575*7c478bd9Sstevel@tonic-gate if (prop == NULL) { 2576*7c478bd9Sstevel@tonic-gate *prom_prop_data = NULL; 2577*7c478bd9Sstevel@tonic-gate return (-1); 2578*7c478bd9Sstevel@tonic-gate } 2579*7c478bd9Sstevel@tonic-gate 2580*7c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */ 2581*7c478bd9Sstevel@tonic-gate *prom_prop_data = NULL; 2582*7c478bd9Sstevel@tonic-gate return (0); 2583*7c478bd9Sstevel@tonic-gate } 2584*7c478bd9Sstevel@tonic-gate 2585*7c478bd9Sstevel@tonic-gate len = di_prop_decode_common((void *)&prop->data, prop->len, 2586*7c478bd9Sstevel@tonic-gate DI_PROP_TYPE_BYTE, 1); 2587*7c478bd9Sstevel@tonic-gate *prom_prop_data = prop->data; 2588*7c478bd9Sstevel@tonic-gate 2589*7c478bd9Sstevel@tonic-gate return (len); 2590*7c478bd9Sstevel@tonic-gate } 2591*7c478bd9Sstevel@tonic-gate 2592*7c478bd9Sstevel@tonic-gate di_lnode_t 2593*7c478bd9Sstevel@tonic-gate di_link_to_lnode(di_link_t link, uint_t endpoint) 2594*7c478bd9Sstevel@tonic-gate { 2595*7c478bd9Sstevel@tonic-gate struct di_all *di_all; 2596*7c478bd9Sstevel@tonic-gate 2597*7c478bd9Sstevel@tonic-gate if ((link == DI_LINK_NIL) || 2598*7c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) { 2599*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2600*7c478bd9Sstevel@tonic-gate return (DI_LNODE_NIL); 2601*7c478bd9Sstevel@tonic-gate } 2602*7c478bd9Sstevel@tonic-gate 2603*7c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)link - DI_LINK(link)->self); 2604*7c478bd9Sstevel@tonic-gate 2605*7c478bd9Sstevel@tonic-gate if (endpoint == DI_LINK_SRC) { 2606*7c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all + DI_LINK(link)->src_lnode)); 2607*7c478bd9Sstevel@tonic-gate } else { 2608*7c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all + DI_LINK(link)->tgt_lnode)); 2609*7c478bd9Sstevel@tonic-gate } 2610*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2611*7c478bd9Sstevel@tonic-gate } 2612*7c478bd9Sstevel@tonic-gate 2613*7c478bd9Sstevel@tonic-gate char * 2614*7c478bd9Sstevel@tonic-gate di_lnode_name(di_lnode_t lnode) 2615*7c478bd9Sstevel@tonic-gate { 2616*7c478bd9Sstevel@tonic-gate return (di_driver_name(di_lnode_devinfo(lnode))); 2617*7c478bd9Sstevel@tonic-gate } 2618*7c478bd9Sstevel@tonic-gate 2619*7c478bd9Sstevel@tonic-gate di_node_t 2620*7c478bd9Sstevel@tonic-gate di_lnode_devinfo(di_lnode_t lnode) 2621*7c478bd9Sstevel@tonic-gate { 2622*7c478bd9Sstevel@tonic-gate struct di_all *di_all; 2623*7c478bd9Sstevel@tonic-gate 2624*7c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)lnode - DI_LNODE(lnode)->self); 2625*7c478bd9Sstevel@tonic-gate return (DI_NODE((caddr_t)di_all + DI_LNODE(lnode)->node)); 2626*7c478bd9Sstevel@tonic-gate } 2627*7c478bd9Sstevel@tonic-gate 2628*7c478bd9Sstevel@tonic-gate int 2629*7c478bd9Sstevel@tonic-gate di_lnode_devt(di_lnode_t lnode, dev_t *devt) 2630*7c478bd9Sstevel@tonic-gate { 2631*7c478bd9Sstevel@tonic-gate if ((lnode == DI_LNODE_NIL) || (devt == NULL)) { 2632*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2633*7c478bd9Sstevel@tonic-gate return (-1); 2634*7c478bd9Sstevel@tonic-gate } 2635*7c478bd9Sstevel@tonic-gate if ((DI_LNODE(lnode)->dev_major == (major_t)-1) && 2636*7c478bd9Sstevel@tonic-gate (DI_LNODE(lnode)->dev_minor == (minor_t)-1)) 2637*7c478bd9Sstevel@tonic-gate return (-1); 2638*7c478bd9Sstevel@tonic-gate 2639*7c478bd9Sstevel@tonic-gate *devt = makedev(DI_LNODE(lnode)->dev_major, DI_LNODE(lnode)->dev_minor); 2640*7c478bd9Sstevel@tonic-gate return (0); 2641*7c478bd9Sstevel@tonic-gate } 2642*7c478bd9Sstevel@tonic-gate 2643*7c478bd9Sstevel@tonic-gate int 2644*7c478bd9Sstevel@tonic-gate di_link_spectype(di_link_t link) 2645*7c478bd9Sstevel@tonic-gate { 2646*7c478bd9Sstevel@tonic-gate return (DI_LINK(link)->spec_type); 2647*7c478bd9Sstevel@tonic-gate } 2648*7c478bd9Sstevel@tonic-gate 2649*7c478bd9Sstevel@tonic-gate void 2650*7c478bd9Sstevel@tonic-gate di_minor_private_set(di_minor_t minor, void *data) 2651*7c478bd9Sstevel@tonic-gate { 2652*7c478bd9Sstevel@tonic-gate DI_MINOR(minor)->user_private_data = (uintptr_t)data; 2653*7c478bd9Sstevel@tonic-gate } 2654*7c478bd9Sstevel@tonic-gate 2655*7c478bd9Sstevel@tonic-gate void * 2656*7c478bd9Sstevel@tonic-gate di_minor_private_get(di_minor_t minor) 2657*7c478bd9Sstevel@tonic-gate { 2658*7c478bd9Sstevel@tonic-gate return ((void *)DI_MINOR(minor)->user_private_data); 2659*7c478bd9Sstevel@tonic-gate } 2660*7c478bd9Sstevel@tonic-gate 2661*7c478bd9Sstevel@tonic-gate void 2662*7c478bd9Sstevel@tonic-gate di_node_private_set(di_node_t node, void *data) 2663*7c478bd9Sstevel@tonic-gate { 2664*7c478bd9Sstevel@tonic-gate DI_NODE(node)->user_private_data = (uintptr_t)data; 2665*7c478bd9Sstevel@tonic-gate } 2666*7c478bd9Sstevel@tonic-gate 2667*7c478bd9Sstevel@tonic-gate void * 2668*7c478bd9Sstevel@tonic-gate di_node_private_get(di_node_t node) 2669*7c478bd9Sstevel@tonic-gate { 2670*7c478bd9Sstevel@tonic-gate return ((void *)DI_NODE(node)->user_private_data); 2671*7c478bd9Sstevel@tonic-gate } 2672*7c478bd9Sstevel@tonic-gate 2673*7c478bd9Sstevel@tonic-gate void 2674*7c478bd9Sstevel@tonic-gate di_lnode_private_set(di_lnode_t lnode, void *data) 2675*7c478bd9Sstevel@tonic-gate { 2676*7c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->user_private_data = (uintptr_t)data; 2677*7c478bd9Sstevel@tonic-gate } 2678*7c478bd9Sstevel@tonic-gate 2679*7c478bd9Sstevel@tonic-gate void * 2680*7c478bd9Sstevel@tonic-gate di_lnode_private_get(di_lnode_t lnode) 2681*7c478bd9Sstevel@tonic-gate { 2682*7c478bd9Sstevel@tonic-gate return ((void *)DI_LNODE(lnode)->user_private_data); 2683*7c478bd9Sstevel@tonic-gate } 2684*7c478bd9Sstevel@tonic-gate 2685*7c478bd9Sstevel@tonic-gate void 2686*7c478bd9Sstevel@tonic-gate di_link_private_set(di_link_t link, void *data) 2687*7c478bd9Sstevel@tonic-gate { 2688*7c478bd9Sstevel@tonic-gate DI_LINK(link)->user_private_data = (uintptr_t)data; 2689*7c478bd9Sstevel@tonic-gate } 2690*7c478bd9Sstevel@tonic-gate 2691*7c478bd9Sstevel@tonic-gate void * 2692*7c478bd9Sstevel@tonic-gate di_link_private_get(di_link_t link) 2693*7c478bd9Sstevel@tonic-gate { 2694*7c478bd9Sstevel@tonic-gate return ((void *)DI_LINK(link)->user_private_data); 2695*7c478bd9Sstevel@tonic-gate } 2696*7c478bd9Sstevel@tonic-gate 2697*7c478bd9Sstevel@tonic-gate di_lnode_t 2698*7c478bd9Sstevel@tonic-gate di_lnode_next(di_node_t node, di_lnode_t lnode) 2699*7c478bd9Sstevel@tonic-gate { 2700*7c478bd9Sstevel@tonic-gate struct di_all *di_all; 2701*7c478bd9Sstevel@tonic-gate 2702*7c478bd9Sstevel@tonic-gate /* 2703*7c478bd9Sstevel@tonic-gate * paranoid error checking 2704*7c478bd9Sstevel@tonic-gate */ 2705*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 2706*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2707*7c478bd9Sstevel@tonic-gate return (DI_LNODE_NIL); 2708*7c478bd9Sstevel@tonic-gate } 2709*7c478bd9Sstevel@tonic-gate 2710*7c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)node - DI_NODE(node)->self); 2711*7c478bd9Sstevel@tonic-gate 2712*7c478bd9Sstevel@tonic-gate if (lnode == DI_NODE_NIL) { 2713*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->lnodes != NULL) 2714*7c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all + 2715*7c478bd9Sstevel@tonic-gate DI_NODE(node)->lnodes)); 2716*7c478bd9Sstevel@tonic-gate } else { 2717*7c478bd9Sstevel@tonic-gate if (DI_LNODE(lnode)->node_next != NULL) 2718*7c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all + 2719*7c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->node_next)); 2720*7c478bd9Sstevel@tonic-gate } 2721*7c478bd9Sstevel@tonic-gate 2722*7c478bd9Sstevel@tonic-gate if (DINFOLYR & DI_ALL(di_all)->command) 2723*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2724*7c478bd9Sstevel@tonic-gate else 2725*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2726*7c478bd9Sstevel@tonic-gate 2727*7c478bd9Sstevel@tonic-gate return (DI_LNODE_NIL); 2728*7c478bd9Sstevel@tonic-gate } 2729*7c478bd9Sstevel@tonic-gate 2730*7c478bd9Sstevel@tonic-gate di_link_t 2731*7c478bd9Sstevel@tonic-gate di_link_next_by_node(di_node_t node, di_link_t link, uint_t endpoint) 2732*7c478bd9Sstevel@tonic-gate { 2733*7c478bd9Sstevel@tonic-gate struct di_all *di_all; 2734*7c478bd9Sstevel@tonic-gate 2735*7c478bd9Sstevel@tonic-gate /* 2736*7c478bd9Sstevel@tonic-gate * paranoid error checking 2737*7c478bd9Sstevel@tonic-gate */ 2738*7c478bd9Sstevel@tonic-gate if ((node == DI_NODE_NIL) || 2739*7c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) { 2740*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2741*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2742*7c478bd9Sstevel@tonic-gate } 2743*7c478bd9Sstevel@tonic-gate 2744*7c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)node - DI_NODE(node)->self); 2745*7c478bd9Sstevel@tonic-gate 2746*7c478bd9Sstevel@tonic-gate if (endpoint == DI_LINK_SRC) { 2747*7c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) { 2748*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->src_links != NULL) 2749*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2750*7c478bd9Sstevel@tonic-gate DI_NODE(node)->src_links)); 2751*7c478bd9Sstevel@tonic-gate } else { 2752*7c478bd9Sstevel@tonic-gate if (DI_LINK(link)->src_node_next != NULL) 2753*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2754*7c478bd9Sstevel@tonic-gate DI_LINK(link)->src_node_next)); 2755*7c478bd9Sstevel@tonic-gate } 2756*7c478bd9Sstevel@tonic-gate } else { 2757*7c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) { 2758*7c478bd9Sstevel@tonic-gate if (DI_NODE(node)->tgt_links != NULL) 2759*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2760*7c478bd9Sstevel@tonic-gate DI_NODE(node)->tgt_links)); 2761*7c478bd9Sstevel@tonic-gate } else { 2762*7c478bd9Sstevel@tonic-gate if (DI_LINK(link)->tgt_node_next != NULL) 2763*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2764*7c478bd9Sstevel@tonic-gate DI_LINK(link)->tgt_node_next)); 2765*7c478bd9Sstevel@tonic-gate } 2766*7c478bd9Sstevel@tonic-gate } 2767*7c478bd9Sstevel@tonic-gate 2768*7c478bd9Sstevel@tonic-gate if (DINFOLYR & DI_ALL(di_all)->command) 2769*7c478bd9Sstevel@tonic-gate errno = ENXIO; 2770*7c478bd9Sstevel@tonic-gate else 2771*7c478bd9Sstevel@tonic-gate errno = ENOTSUP; 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2774*7c478bd9Sstevel@tonic-gate } 2775*7c478bd9Sstevel@tonic-gate 2776*7c478bd9Sstevel@tonic-gate di_link_t 2777*7c478bd9Sstevel@tonic-gate di_link_next_by_lnode(di_lnode_t lnode, di_link_t link, uint_t endpoint) 2778*7c478bd9Sstevel@tonic-gate { 2779*7c478bd9Sstevel@tonic-gate struct di_all *di_all; 2780*7c478bd9Sstevel@tonic-gate 2781*7c478bd9Sstevel@tonic-gate /* 2782*7c478bd9Sstevel@tonic-gate * paranoid error checking 2783*7c478bd9Sstevel@tonic-gate */ 2784*7c478bd9Sstevel@tonic-gate if ((lnode == DI_LNODE_NIL) || 2785*7c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) { 2786*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2787*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2788*7c478bd9Sstevel@tonic-gate } 2789*7c478bd9Sstevel@tonic-gate 2790*7c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)lnode - DI_LNODE(lnode)->self); 2791*7c478bd9Sstevel@tonic-gate 2792*7c478bd9Sstevel@tonic-gate if (endpoint == DI_LINK_SRC) { 2793*7c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) { 2794*7c478bd9Sstevel@tonic-gate if (DI_LNODE(lnode)->link_out == NULL) 2795*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2796*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2797*7c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->link_out)); 2798*7c478bd9Sstevel@tonic-gate } else { 2799*7c478bd9Sstevel@tonic-gate if (DI_LINK(link)->src_link_next == NULL) 2800*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2801*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2802*7c478bd9Sstevel@tonic-gate DI_LINK(link)->src_link_next)); 2803*7c478bd9Sstevel@tonic-gate } 2804*7c478bd9Sstevel@tonic-gate } else { 2805*7c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) { 2806*7c478bd9Sstevel@tonic-gate if (DI_LNODE(lnode)->link_in == NULL) 2807*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2808*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2809*7c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->link_in)); 2810*7c478bd9Sstevel@tonic-gate } else { 2811*7c478bd9Sstevel@tonic-gate if (DI_LINK(link)->tgt_link_next == NULL) 2812*7c478bd9Sstevel@tonic-gate return (DI_LINK_NIL); 2813*7c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all + 2814*7c478bd9Sstevel@tonic-gate DI_LINK(link)->tgt_link_next)); 2815*7c478bd9Sstevel@tonic-gate } 2816*7c478bd9Sstevel@tonic-gate } 2817*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 2818*7c478bd9Sstevel@tonic-gate } 2819*7c478bd9Sstevel@tonic-gate 2820*7c478bd9Sstevel@tonic-gate /* 2821*7c478bd9Sstevel@tonic-gate * Internal library function: 2822*7c478bd9Sstevel@tonic-gate * Invoke callback for each link data on the link list of first node 2823*7c478bd9Sstevel@tonic-gate * on node_list headp, and place children of first node on the list. 2824*7c478bd9Sstevel@tonic-gate * 2825*7c478bd9Sstevel@tonic-gate * This is similar to walk_one_node, except we only walk in child 2826*7c478bd9Sstevel@tonic-gate * first mode. 2827*7c478bd9Sstevel@tonic-gate */ 2828*7c478bd9Sstevel@tonic-gate static void 2829*7c478bd9Sstevel@tonic-gate walk_one_link(struct node_list **headp, uint_t ep, 2830*7c478bd9Sstevel@tonic-gate void *arg, int (*callback)(di_link_t link, void *arg)) 2831*7c478bd9Sstevel@tonic-gate { 2832*7c478bd9Sstevel@tonic-gate int action = DI_WALK_CONTINUE; 2833*7c478bd9Sstevel@tonic-gate di_link_t link = DI_LINK_NIL; 2834*7c478bd9Sstevel@tonic-gate di_node_t node = (*headp)->node; 2835*7c478bd9Sstevel@tonic-gate 2836*7c478bd9Sstevel@tonic-gate while ((link = di_link_next_by_node(node, link, ep)) != DI_LINK_NIL) { 2837*7c478bd9Sstevel@tonic-gate action = callback(link, arg); 2838*7c478bd9Sstevel@tonic-gate if (action == DI_WALK_TERMINATE) { 2839*7c478bd9Sstevel@tonic-gate break; 2840*7c478bd9Sstevel@tonic-gate } 2841*7c478bd9Sstevel@tonic-gate } 2842*7c478bd9Sstevel@tonic-gate 2843*7c478bd9Sstevel@tonic-gate update_node_list(action, DI_WALK_LINKGEN, headp); 2844*7c478bd9Sstevel@tonic-gate } 2845*7c478bd9Sstevel@tonic-gate 2846*7c478bd9Sstevel@tonic-gate int 2847*7c478bd9Sstevel@tonic-gate di_walk_link(di_node_t root, uint_t flag, uint_t endpoint, void *arg, 2848*7c478bd9Sstevel@tonic-gate int (*link_callback)(di_link_t link, void *arg)) 2849*7c478bd9Sstevel@tonic-gate { 2850*7c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */ 2851*7c478bd9Sstevel@tonic-gate 2852*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2853*7c478bd9Sstevel@tonic-gate char *path = di_devfs_path(root); 2854*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "walking %s link data under %s\n", 2855*7c478bd9Sstevel@tonic-gate (endpoint == DI_LINK_SRC) ? "src" : "tgt", path)); 2856*7c478bd9Sstevel@tonic-gate di_devfs_path_free(path); 2857*7c478bd9Sstevel@tonic-gate #endif 2858*7c478bd9Sstevel@tonic-gate 2859*7c478bd9Sstevel@tonic-gate /* 2860*7c478bd9Sstevel@tonic-gate * paranoid error checking 2861*7c478bd9Sstevel@tonic-gate */ 2862*7c478bd9Sstevel@tonic-gate if ((root == DI_NODE_NIL) || (link_callback == NULL) || (flag != 0) || 2863*7c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) { 2864*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2865*7c478bd9Sstevel@tonic-gate return (-1); 2866*7c478bd9Sstevel@tonic-gate } 2867*7c478bd9Sstevel@tonic-gate 2868*7c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) { 2869*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n")); 2870*7c478bd9Sstevel@tonic-gate return (-1); 2871*7c478bd9Sstevel@tonic-gate } 2872*7c478bd9Sstevel@tonic-gate 2873*7c478bd9Sstevel@tonic-gate head->next = NULL; 2874*7c478bd9Sstevel@tonic-gate head->node = root; 2875*7c478bd9Sstevel@tonic-gate 2876*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start link data walking from node %s\n", 2877*7c478bd9Sstevel@tonic-gate di_node_name(root))); 2878*7c478bd9Sstevel@tonic-gate 2879*7c478bd9Sstevel@tonic-gate while (head != NULL) 2880*7c478bd9Sstevel@tonic-gate walk_one_link(&head, endpoint, arg, link_callback); 2881*7c478bd9Sstevel@tonic-gate 2882*7c478bd9Sstevel@tonic-gate return (0); 2883*7c478bd9Sstevel@tonic-gate } 2884*7c478bd9Sstevel@tonic-gate 2885*7c478bd9Sstevel@tonic-gate /* 2886*7c478bd9Sstevel@tonic-gate * Internal library function: 2887*7c478bd9Sstevel@tonic-gate * Invoke callback for each link data on the link list of first node 2888*7c478bd9Sstevel@tonic-gate * on node_list headp, and place children of first node on the list. 2889*7c478bd9Sstevel@tonic-gate * 2890*7c478bd9Sstevel@tonic-gate * This is similar to walk_one_node, except we only walk in child 2891*7c478bd9Sstevel@tonic-gate * first mode. 2892*7c478bd9Sstevel@tonic-gate */ 2893*7c478bd9Sstevel@tonic-gate static void 2894*7c478bd9Sstevel@tonic-gate walk_one_lnode(struct node_list **headp, void *arg, 2895*7c478bd9Sstevel@tonic-gate int (*callback)(di_lnode_t lnode, void *arg)) 2896*7c478bd9Sstevel@tonic-gate { 2897*7c478bd9Sstevel@tonic-gate int action = DI_WALK_CONTINUE; 2898*7c478bd9Sstevel@tonic-gate di_lnode_t lnode = DI_LNODE_NIL; 2899*7c478bd9Sstevel@tonic-gate di_node_t node = (*headp)->node; 2900*7c478bd9Sstevel@tonic-gate 2901*7c478bd9Sstevel@tonic-gate while ((lnode = di_lnode_next(node, lnode)) != DI_LNODE_NIL) { 2902*7c478bd9Sstevel@tonic-gate action = callback(lnode, arg); 2903*7c478bd9Sstevel@tonic-gate if (action == DI_WALK_TERMINATE) { 2904*7c478bd9Sstevel@tonic-gate break; 2905*7c478bd9Sstevel@tonic-gate } 2906*7c478bd9Sstevel@tonic-gate } 2907*7c478bd9Sstevel@tonic-gate 2908*7c478bd9Sstevel@tonic-gate update_node_list(action, DI_WALK_LINKGEN, headp); 2909*7c478bd9Sstevel@tonic-gate } 2910*7c478bd9Sstevel@tonic-gate 2911*7c478bd9Sstevel@tonic-gate int 2912*7c478bd9Sstevel@tonic-gate di_walk_lnode(di_node_t root, uint_t flag, void *arg, 2913*7c478bd9Sstevel@tonic-gate int (*lnode_callback)(di_lnode_t lnode, void *arg)) 2914*7c478bd9Sstevel@tonic-gate { 2915*7c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */ 2916*7c478bd9Sstevel@tonic-gate 2917*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 2918*7c478bd9Sstevel@tonic-gate char *path = di_devfs_path(root); 2919*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "walking lnode data under %s\n", path)); 2920*7c478bd9Sstevel@tonic-gate di_devfs_path_free(path); 2921*7c478bd9Sstevel@tonic-gate #endif 2922*7c478bd9Sstevel@tonic-gate 2923*7c478bd9Sstevel@tonic-gate /* 2924*7c478bd9Sstevel@tonic-gate * paranoid error checking 2925*7c478bd9Sstevel@tonic-gate */ 2926*7c478bd9Sstevel@tonic-gate if ((root == DI_NODE_NIL) || (lnode_callback == NULL) || (flag != 0)) { 2927*7c478bd9Sstevel@tonic-gate errno = EINVAL; 2928*7c478bd9Sstevel@tonic-gate return (-1); 2929*7c478bd9Sstevel@tonic-gate } 2930*7c478bd9Sstevel@tonic-gate 2931*7c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) { 2932*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n")); 2933*7c478bd9Sstevel@tonic-gate return (-1); 2934*7c478bd9Sstevel@tonic-gate } 2935*7c478bd9Sstevel@tonic-gate 2936*7c478bd9Sstevel@tonic-gate head->next = NULL; 2937*7c478bd9Sstevel@tonic-gate head->node = root; 2938*7c478bd9Sstevel@tonic-gate 2939*7c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start lnode data walking from node %s\n", 2940*7c478bd9Sstevel@tonic-gate di_node_name(root))); 2941*7c478bd9Sstevel@tonic-gate 2942*7c478bd9Sstevel@tonic-gate while (head != NULL) 2943*7c478bd9Sstevel@tonic-gate walk_one_lnode(&head, arg, lnode_callback); 2944*7c478bd9Sstevel@tonic-gate 2945*7c478bd9Sstevel@tonic-gate return (0); 2946*7c478bd9Sstevel@tonic-gate } 2947*7c478bd9Sstevel@tonic-gate 2948*7c478bd9Sstevel@tonic-gate di_node_t 2949*7c478bd9Sstevel@tonic-gate di_lookup_node(di_node_t root, char *path) 2950*7c478bd9Sstevel@tonic-gate { 2951*7c478bd9Sstevel@tonic-gate struct di_all *dap; 2952*7c478bd9Sstevel@tonic-gate di_node_t node; 2953*7c478bd9Sstevel@tonic-gate char copy[MAXPATHLEN]; 2954*7c478bd9Sstevel@tonic-gate char *slash, *pname, *paddr; 2955*7c478bd9Sstevel@tonic-gate 2956*7c478bd9Sstevel@tonic-gate /* 2957*7c478bd9Sstevel@tonic-gate * Path must be absolute and musn't have duplicate slashes 2958*7c478bd9Sstevel@tonic-gate */ 2959*7c478bd9Sstevel@tonic-gate if (*path != '/' || strstr(path, "//")) { 2960*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "Invalid path: %s\n", path)); 2961*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 2962*7c478bd9Sstevel@tonic-gate } 2963*7c478bd9Sstevel@tonic-gate 2964*7c478bd9Sstevel@tonic-gate if (root == DI_NODE_NIL) { 2965*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "root node is DI_NODE_NIL\n")); 2966*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 2967*7c478bd9Sstevel@tonic-gate } 2968*7c478bd9Sstevel@tonic-gate 2969*7c478bd9Sstevel@tonic-gate dap = DI_ALL((caddr_t)root - DI_NODE(root)->self); 2970*7c478bd9Sstevel@tonic-gate if (strcmp(dap->root_path, "/") != 0) { 2971*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "snapshot root not / : %s\n", dap->root_path)); 2972*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 2973*7c478bd9Sstevel@tonic-gate } 2974*7c478bd9Sstevel@tonic-gate 2975*7c478bd9Sstevel@tonic-gate if (strlcpy(copy, path, sizeof (copy)) >= sizeof (copy)) { 2976*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "path too long: %s\n", path)); 2977*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 2978*7c478bd9Sstevel@tonic-gate } 2979*7c478bd9Sstevel@tonic-gate 2980*7c478bd9Sstevel@tonic-gate for (slash = copy, node = root; slash; ) { 2981*7c478bd9Sstevel@tonic-gate 2982*7c478bd9Sstevel@tonic-gate /* 2983*7c478bd9Sstevel@tonic-gate * Handle path = "/" case as well as trailing '/' 2984*7c478bd9Sstevel@tonic-gate */ 2985*7c478bd9Sstevel@tonic-gate if (*(slash + 1) == '\0') 2986*7c478bd9Sstevel@tonic-gate break; 2987*7c478bd9Sstevel@tonic-gate 2988*7c478bd9Sstevel@tonic-gate /* 2989*7c478bd9Sstevel@tonic-gate * More path-components exist. Deal with the next one 2990*7c478bd9Sstevel@tonic-gate */ 2991*7c478bd9Sstevel@tonic-gate pname = slash + 1; 2992*7c478bd9Sstevel@tonic-gate node = di_child_node(node); 2993*7c478bd9Sstevel@tonic-gate 2994*7c478bd9Sstevel@tonic-gate if (slash = strchr(pname, '/')) 2995*7c478bd9Sstevel@tonic-gate *slash = '\0'; 2996*7c478bd9Sstevel@tonic-gate if (paddr = strchr(pname, '@')) 2997*7c478bd9Sstevel@tonic-gate *paddr++ = '\0'; 2998*7c478bd9Sstevel@tonic-gate 2999*7c478bd9Sstevel@tonic-gate for (; node != DI_NODE_NIL; node = di_sibling_node(node)) { 3000*7c478bd9Sstevel@tonic-gate char *name, *baddr; 3001*7c478bd9Sstevel@tonic-gate 3002*7c478bd9Sstevel@tonic-gate name = di_node_name(node); 3003*7c478bd9Sstevel@tonic-gate baddr = di_bus_addr(node); 3004*7c478bd9Sstevel@tonic-gate 3005*7c478bd9Sstevel@tonic-gate if (strcmp(pname, name) != 0) 3006*7c478bd9Sstevel@tonic-gate continue; 3007*7c478bd9Sstevel@tonic-gate 3008*7c478bd9Sstevel@tonic-gate /* 3009*7c478bd9Sstevel@tonic-gate * Mappings between a "path-address" and bus-addr 3010*7c478bd9Sstevel@tonic-gate * 3011*7c478bd9Sstevel@tonic-gate * paddr baddr 3012*7c478bd9Sstevel@tonic-gate * --------------------- 3013*7c478bd9Sstevel@tonic-gate * NULL NULL 3014*7c478bd9Sstevel@tonic-gate * NULL "" 3015*7c478bd9Sstevel@tonic-gate * "" N/A (invalid paddr) 3016*7c478bd9Sstevel@tonic-gate */ 3017*7c478bd9Sstevel@tonic-gate if (paddr && baddr && strcmp(paddr, baddr) == 0) 3018*7c478bd9Sstevel@tonic-gate break; 3019*7c478bd9Sstevel@tonic-gate if (paddr == NULL && (baddr == NULL || *baddr == '\0')) 3020*7c478bd9Sstevel@tonic-gate break; 3021*7c478bd9Sstevel@tonic-gate } 3022*7c478bd9Sstevel@tonic-gate 3023*7c478bd9Sstevel@tonic-gate /* 3024*7c478bd9Sstevel@tonic-gate * No nodes in the sibling list or there was no match 3025*7c478bd9Sstevel@tonic-gate */ 3026*7c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) { 3027*7c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "%s@%s: no node\n", pname, paddr)); 3028*7c478bd9Sstevel@tonic-gate return (DI_NODE_NIL); 3029*7c478bd9Sstevel@tonic-gate } 3030*7c478bd9Sstevel@tonic-gate } 3031*7c478bd9Sstevel@tonic-gate 3032*7c478bd9Sstevel@tonic-gate assert(node != DI_NODE_NIL); 3033*7c478bd9Sstevel@tonic-gate return (node); 3034*7c478bd9Sstevel@tonic-gate } 3035*7c478bd9Sstevel@tonic-gate 3036*7c478bd9Sstevel@tonic-gate static char * 3037*7c478bd9Sstevel@tonic-gate msglevel2str(di_debug_t msglevel) 3038*7c478bd9Sstevel@tonic-gate { 3039*7c478bd9Sstevel@tonic-gate switch (msglevel) { 3040*7c478bd9Sstevel@tonic-gate case DI_ERR: 3041*7c478bd9Sstevel@tonic-gate return ("ERROR"); 3042*7c478bd9Sstevel@tonic-gate case DI_INFO: 3043*7c478bd9Sstevel@tonic-gate return ("Info"); 3044*7c478bd9Sstevel@tonic-gate case DI_TRACE: 3045*7c478bd9Sstevel@tonic-gate return ("Trace"); 3046*7c478bd9Sstevel@tonic-gate case DI_TRACE1: 3047*7c478bd9Sstevel@tonic-gate return ("Trace1"); 3048*7c478bd9Sstevel@tonic-gate case DI_TRACE2: 3049*7c478bd9Sstevel@tonic-gate return ("Trace2"); 3050*7c478bd9Sstevel@tonic-gate default: 3051*7c478bd9Sstevel@tonic-gate return ("UNKNOWN"); 3052*7c478bd9Sstevel@tonic-gate } 3053*7c478bd9Sstevel@tonic-gate } 3054*7c478bd9Sstevel@tonic-gate 3055*7c478bd9Sstevel@tonic-gate void 3056*7c478bd9Sstevel@tonic-gate dprint(di_debug_t msglevel, const char *fmt, ...) 3057*7c478bd9Sstevel@tonic-gate { 3058*7c478bd9Sstevel@tonic-gate va_list ap; 3059*7c478bd9Sstevel@tonic-gate char *estr; 3060*7c478bd9Sstevel@tonic-gate 3061*7c478bd9Sstevel@tonic-gate if (di_debug <= DI_QUIET) 3062*7c478bd9Sstevel@tonic-gate return; 3063*7c478bd9Sstevel@tonic-gate 3064*7c478bd9Sstevel@tonic-gate if (di_debug < msglevel) 3065*7c478bd9Sstevel@tonic-gate return; 3066*7c478bd9Sstevel@tonic-gate 3067*7c478bd9Sstevel@tonic-gate estr = msglevel2str(msglevel); 3068*7c478bd9Sstevel@tonic-gate 3069*7c478bd9Sstevel@tonic-gate assert(estr); 3070*7c478bd9Sstevel@tonic-gate 3071*7c478bd9Sstevel@tonic-gate va_start(ap, fmt); 3072*7c478bd9Sstevel@tonic-gate 3073*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libdevinfo[%lu]: %s: ", 3074*7c478bd9Sstevel@tonic-gate (ulong_t)getpid(), estr); 3075*7c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap); 3076*7c478bd9Sstevel@tonic-gate 3077*7c478bd9Sstevel@tonic-gate va_end(ap); 3078*7c478bd9Sstevel@tonic-gate } 3079*7c478bd9Sstevel@tonic-gate 3080*7c478bd9Sstevel@tonic-gate /* end of devinfo.c */ 3081