17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
53ebafc43Sjveta * Common Development and Distribution License (the "License").
63ebafc43Sjveta * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
2294c894bbSVikram Hegde * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
23*02cb2d76SToomas Soome * Copyright 2024 MNX Cloud, Inc.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * Interfaces for getting device configuration data from kernel
287c478bd9Sstevel@tonic-gate * through the devinfo driver.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <string.h>
347c478bd9Sstevel@tonic-gate #include <strings.h>
357c478bd9Sstevel@tonic-gate #include <stropts.h>
367c478bd9Sstevel@tonic-gate #include <fcntl.h>
377c478bd9Sstevel@tonic-gate #include <poll.h>
387c478bd9Sstevel@tonic-gate #include <synch.h>
397c478bd9Sstevel@tonic-gate #include <unistd.h>
407c478bd9Sstevel@tonic-gate #include <sys/mkdev.h>
417c478bd9Sstevel@tonic-gate #include <sys/obpdefs.h>
427c478bd9Sstevel@tonic-gate #include <sys/stat.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/time.h>
457c478bd9Sstevel@tonic-gate #include <sys/autoconf.h>
467c478bd9Sstevel@tonic-gate #include <stdarg.h>
4726947304SEvan Yan #include <sys/ddi_hp.h>
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate #define NDEBUG 1
507c478bd9Sstevel@tonic-gate #include <assert.h>
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate #include "libdevinfo.h"
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate * Debug message levels
567c478bd9Sstevel@tonic-gate */
577c478bd9Sstevel@tonic-gate typedef enum {
587c478bd9Sstevel@tonic-gate DI_QUIET = 0, /* No debug messages - the default */
597c478bd9Sstevel@tonic-gate DI_ERR = 1,
607c478bd9Sstevel@tonic-gate DI_INFO,
617c478bd9Sstevel@tonic-gate DI_TRACE,
627c478bd9Sstevel@tonic-gate DI_TRACE1,
637c478bd9Sstevel@tonic-gate DI_TRACE2
647c478bd9Sstevel@tonic-gate } di_debug_t;
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate int di_debug = DI_QUIET;
677c478bd9Sstevel@tonic-gate
687c478bd9Sstevel@tonic-gate #define DPRINTF(args) { if (di_debug != DI_QUIET) dprint args; }
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate void dprint(di_debug_t msglevel, const char *fmt, ...);
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate
737c478bd9Sstevel@tonic-gate #pragma init(_libdevinfo_init)
747c478bd9Sstevel@tonic-gate
757c478bd9Sstevel@tonic-gate void
_libdevinfo_init()767c478bd9Sstevel@tonic-gate _libdevinfo_init()
777c478bd9Sstevel@tonic-gate {
787c478bd9Sstevel@tonic-gate char *debug_str = getenv("_LIBDEVINFO_DEBUG");
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate if (debug_str) {
817c478bd9Sstevel@tonic-gate errno = 0;
827c478bd9Sstevel@tonic-gate di_debug = atoi(debug_str);
837c478bd9Sstevel@tonic-gate if (errno || di_debug < DI_QUIET)
847c478bd9Sstevel@tonic-gate di_debug = DI_QUIET;
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate di_node_t
di_init(const char * phys_path,uint_t flag)897c478bd9Sstevel@tonic-gate di_init(const char *phys_path, uint_t flag)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate return (di_init_impl(phys_path, flag, NULL));
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate * We use blocking_open() to guarantee access to the devinfo device, if open()
967c478bd9Sstevel@tonic-gate * is failing with EAGAIN.
977c478bd9Sstevel@tonic-gate */
987c478bd9Sstevel@tonic-gate static int
blocking_open(const char * path,int oflag)997c478bd9Sstevel@tonic-gate blocking_open(const char *path, int oflag)
1007c478bd9Sstevel@tonic-gate {
1017c478bd9Sstevel@tonic-gate int fd;
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate while ((fd = open(path, oflag)) == -1 && errno == EAGAIN)
1047c478bd9Sstevel@tonic-gate (void) poll(NULL, 0, 1 * MILLISEC);
1057c478bd9Sstevel@tonic-gate
1067c478bd9Sstevel@tonic-gate return (fd);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate
1097c478bd9Sstevel@tonic-gate /* private interface */
1107c478bd9Sstevel@tonic-gate di_node_t
di_init_driver(const char * drv_name,uint_t flag)1117c478bd9Sstevel@tonic-gate di_init_driver(const char *drv_name, uint_t flag)
1127c478bd9Sstevel@tonic-gate {
1137c478bd9Sstevel@tonic-gate int fd;
1147c478bd9Sstevel@tonic-gate char driver[MAXPATHLEN];
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate * Don't allow drv_name to exceed MAXPATHLEN - 1, or 1023,
1187c478bd9Sstevel@tonic-gate * which should be sufficient for any sensible programmer.
1197c478bd9Sstevel@tonic-gate */
1207c478bd9Sstevel@tonic-gate if ((drv_name == NULL) || (strlen(drv_name) >= MAXPATHLEN)) {
1217c478bd9Sstevel@tonic-gate errno = EINVAL;
1227c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate (void) strcpy(driver, drv_name);
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * open the devinfo driver
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate if ((fd = blocking_open("/devices/pseudo/devinfo@0:devinfo",
1307c478bd9Sstevel@tonic-gate O_RDONLY)) == -1) {
1317c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo open failed: errno = %d\n", errno));
1327c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
1337c478bd9Sstevel@tonic-gate }
1347c478bd9Sstevel@tonic-gate
1357c478bd9Sstevel@tonic-gate if (ioctl(fd, DINFOLODRV, driver) != 0) {
1367c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "failed to load driver %s\n", driver));
1377c478bd9Sstevel@tonic-gate (void) close(fd);
1387c478bd9Sstevel@tonic-gate errno = ENXIO;
1397c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate (void) close(fd);
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate /*
1447c478bd9Sstevel@tonic-gate * Driver load succeeded, return a snapshot
1457c478bd9Sstevel@tonic-gate */
1467c478bd9Sstevel@tonic-gate return (di_init("/", flag));
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate di_node_t
di_init_impl(const char * phys_path,uint_t flag,struct di_priv_data * priv)1507c478bd9Sstevel@tonic-gate di_init_impl(const char *phys_path, uint_t flag,
1517c478bd9Sstevel@tonic-gate struct di_priv_data *priv)
1527c478bd9Sstevel@tonic-gate {
1537c478bd9Sstevel@tonic-gate caddr_t pa;
1547c478bd9Sstevel@tonic-gate int fd, map_size;
1557c478bd9Sstevel@tonic-gate struct di_all *dap;
1567c478bd9Sstevel@tonic-gate struct dinfo_io dinfo_io;
1577c478bd9Sstevel@tonic-gate
1587c478bd9Sstevel@tonic-gate uint_t pageoffset = sysconf(_SC_PAGESIZE) - 1;
1597c478bd9Sstevel@tonic-gate uint_t pagemask = ~pageoffset;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_init: taking a snapshot\n"));
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate * Make sure there is no minor name in the path
1657c478bd9Sstevel@tonic-gate * and the path do not start with /devices....
1667c478bd9Sstevel@tonic-gate */
167*02cb2d76SToomas Soome if (phys_path == NULL ||
168*02cb2d76SToomas Soome strchr(phys_path, ':') ||
1697c478bd9Sstevel@tonic-gate (strncmp(phys_path, "/devices", 8) == 0) ||
1707c478bd9Sstevel@tonic-gate (strlen(phys_path) > MAXPATHLEN)) {
1717c478bd9Sstevel@tonic-gate errno = EINVAL;
1727c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate
1757c478bd9Sstevel@tonic-gate if (strlen(phys_path) == 0)
1767c478bd9Sstevel@tonic-gate (void) sprintf(dinfo_io.root_path, "/");
1777c478bd9Sstevel@tonic-gate else if (*phys_path != '/')
1787c478bd9Sstevel@tonic-gate (void) snprintf(dinfo_io.root_path, sizeof (dinfo_io.root_path),
1797c478bd9Sstevel@tonic-gate "/%s", phys_path);
1807c478bd9Sstevel@tonic-gate else
1817c478bd9Sstevel@tonic-gate (void) snprintf(dinfo_io.root_path, sizeof (dinfo_io.root_path),
1827c478bd9Sstevel@tonic-gate "%s", phys_path);
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate * If private data is requested, copy the format specification
1867c478bd9Sstevel@tonic-gate */
1877c478bd9Sstevel@tonic-gate if (flag & DINFOPRIVDATA & 0xff) {
1887c478bd9Sstevel@tonic-gate if (priv)
1897c478bd9Sstevel@tonic-gate bcopy(priv, &dinfo_io.priv,
1907c478bd9Sstevel@tonic-gate sizeof (struct di_priv_data));
1917c478bd9Sstevel@tonic-gate else {
1927c478bd9Sstevel@tonic-gate errno = EINVAL;
1937c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
1947c478bd9Sstevel@tonic-gate }
1957c478bd9Sstevel@tonic-gate }
1967c478bd9Sstevel@tonic-gate
1977c478bd9Sstevel@tonic-gate /*
1987c478bd9Sstevel@tonic-gate * Attempt to open the devinfo driver. Make a second attempt at the
1997c478bd9Sstevel@tonic-gate * read-only minor node if we don't have privileges to open the full
2007c478bd9Sstevel@tonic-gate * version _and_ if we're not requesting operations that the read-only
2017c478bd9Sstevel@tonic-gate * node can't perform. (Setgid processes would fail an access() test,
2027c478bd9Sstevel@tonic-gate * of course.)
2037c478bd9Sstevel@tonic-gate */
2047c478bd9Sstevel@tonic-gate if ((fd = blocking_open("/devices/pseudo/devinfo@0:devinfo",
2057c478bd9Sstevel@tonic-gate O_RDONLY)) == -1) {
2067c478bd9Sstevel@tonic-gate if ((flag & DINFOFORCE) == DINFOFORCE ||
2077c478bd9Sstevel@tonic-gate (flag & DINFOPRIVDATA) == DINFOPRIVDATA) {
2087c478bd9Sstevel@tonic-gate /*
2097c478bd9Sstevel@tonic-gate * We wanted to perform a privileged operation, but the
2107c478bd9Sstevel@tonic-gate * privileged node isn't available. Don't modify errno
2117c478bd9Sstevel@tonic-gate * on our way out (but display it if we're running with
2127c478bd9Sstevel@tonic-gate * di_debug set).
2137c478bd9Sstevel@tonic-gate */
2147c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo open failed: errno = %d\n",
2157c478bd9Sstevel@tonic-gate errno));
2167c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate
2197c478bd9Sstevel@tonic-gate if ((fd = blocking_open("/devices/pseudo/devinfo@0:devinfo,ro",
2207c478bd9Sstevel@tonic-gate O_RDONLY)) == -1) {
2217c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo open failed: errno = %d\n",
2227c478bd9Sstevel@tonic-gate errno));
2237c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate /*
2287c478bd9Sstevel@tonic-gate * Verify that there is no major conflict, i.e., we are indeed opening
2297c478bd9Sstevel@tonic-gate * the devinfo driver.
2307c478bd9Sstevel@tonic-gate */
2317c478bd9Sstevel@tonic-gate if (ioctl(fd, DINFOIDENT, NULL) != DI_MAGIC) {
2327c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR,
2337c478bd9Sstevel@tonic-gate "driver ID failed; check for major conflict\n"));
2347c478bd9Sstevel@tonic-gate (void) close(fd);
2357c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate
2387c478bd9Sstevel@tonic-gate /*
2397c478bd9Sstevel@tonic-gate * create snapshot
2407c478bd9Sstevel@tonic-gate */
2417c478bd9Sstevel@tonic-gate if ((map_size = ioctl(fd, flag, &dinfo_io)) < 0) {
2427c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "devinfo ioctl failed with "
2437c478bd9Sstevel@tonic-gate "error: %d\n", errno));
2447c478bd9Sstevel@tonic-gate (void) close(fd);
2457c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2467c478bd9Sstevel@tonic-gate } else if (map_size == 0) {
2477c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "%s not found\n", phys_path));
2487c478bd9Sstevel@tonic-gate errno = ENXIO;
2497c478bd9Sstevel@tonic-gate (void) close(fd);
2507c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate /*
2547c478bd9Sstevel@tonic-gate * copy snapshot to userland
2557c478bd9Sstevel@tonic-gate */
2567c478bd9Sstevel@tonic-gate map_size = (map_size + pageoffset) & pagemask;
2577c478bd9Sstevel@tonic-gate if ((pa = valloc(map_size)) == NULL) {
2587c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "valloc failed for snapshot\n"));
2597c478bd9Sstevel@tonic-gate (void) close(fd);
2607c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2617c478bd9Sstevel@tonic-gate }
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate if (ioctl(fd, DINFOUSRLD, pa) != map_size) {
2647c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "failed to copy snapshot to usrld\n"));
2657c478bd9Sstevel@tonic-gate (void) close(fd);
2667c478bd9Sstevel@tonic-gate free(pa);
2677c478bd9Sstevel@tonic-gate errno = EFAULT;
2687c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate (void) close(fd);
2727c478bd9Sstevel@tonic-gate
2737c478bd9Sstevel@tonic-gate dap = DI_ALL(pa);
2743e2676e0Svikram if (dap->version != DI_SNAPSHOT_VERSION) {
2753e2676e0Svikram DPRINTF((DI_ERR, "wrong snapshot version "
2763e2676e0Svikram "(expected=%d, actual=%d)\n",
2773e2676e0Svikram DI_SNAPSHOT_VERSION, dap->version));
2783e2676e0Svikram free(pa);
2793e2676e0Svikram errno = ESTALE;
2803e2676e0Svikram return (DI_NODE_NIL);
2813e2676e0Svikram }
2827c478bd9Sstevel@tonic-gate if (dap->top_devinfo == 0) { /* phys_path not found */
2837c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "%s not found\n", phys_path));
2847c478bd9Sstevel@tonic-gate free(pa);
2857c478bd9Sstevel@tonic-gate errno = EINVAL;
2867c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate return (DI_NODE(pa + dap->top_devinfo));
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate void
di_fini(di_node_t root)2937c478bd9Sstevel@tonic-gate di_fini(di_node_t root)
2947c478bd9Sstevel@tonic-gate {
2957c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_fini: freeing a snapshot\n"));
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /*
3007c478bd9Sstevel@tonic-gate * paranoid checking
3017c478bd9Sstevel@tonic-gate */
3027c478bd9Sstevel@tonic-gate if (root == DI_NODE_NIL) {
3037c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "di_fini called with NIL arg\n"));
3047c478bd9Sstevel@tonic-gate return;
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /*
3087c478bd9Sstevel@tonic-gate * The root contains its own offset--self.
3097c478bd9Sstevel@tonic-gate * Subtracting it from root address, we get the starting addr.
3107c478bd9Sstevel@tonic-gate * The map_size is stored at the beginning of snapshot.
3117c478bd9Sstevel@tonic-gate * Once we have starting address and size, we can free().
3127c478bd9Sstevel@tonic-gate */
3137c478bd9Sstevel@tonic-gate pa = (caddr_t)root - DI_NODE(root)->self;
3147c478bd9Sstevel@tonic-gate
3157c478bd9Sstevel@tonic-gate free(pa);
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate di_node_t
di_parent_node(di_node_t node)3197c478bd9Sstevel@tonic-gate di_parent_node(di_node_t node)
3207c478bd9Sstevel@tonic-gate {
3217c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
3227c478bd9Sstevel@tonic-gate
3237c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
3247c478bd9Sstevel@tonic-gate errno = EINVAL;
3257c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get parent of node %s\n", di_node_name(node)));
3297c478bd9Sstevel@tonic-gate
3307c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent) {
3337c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->parent));
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate
3367c478bd9Sstevel@tonic-gate /*
3377c478bd9Sstevel@tonic-gate * Deal with error condition:
3387c478bd9Sstevel@tonic-gate * If parent doesn't exist and node is not the root,
3397c478bd9Sstevel@tonic-gate * set errno to ENOTSUP. Otherwise, set errno to ENXIO.
3407c478bd9Sstevel@tonic-gate */
3417c478bd9Sstevel@tonic-gate if (strcmp(DI_ALL(pa)->root_path, "/") != 0)
3427c478bd9Sstevel@tonic-gate errno = ENOTSUP;
3437c478bd9Sstevel@tonic-gate else
3447c478bd9Sstevel@tonic-gate errno = ENXIO;
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate di_node_t
di_sibling_node(di_node_t node)3507c478bd9Sstevel@tonic-gate di_sibling_node(di_node_t node)
3517c478bd9Sstevel@tonic-gate {
3527c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
3537c478bd9Sstevel@tonic-gate
3547c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
3557c478bd9Sstevel@tonic-gate errno = EINVAL;
3567c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
3577c478bd9Sstevel@tonic-gate }
3587c478bd9Sstevel@tonic-gate
3597c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get sibling of node %s\n", di_node_name(node)));
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate if (DI_NODE(node)->sibling) {
3647c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->sibling));
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate
3677c478bd9Sstevel@tonic-gate /*
3687c478bd9Sstevel@tonic-gate * Deal with error condition:
3697c478bd9Sstevel@tonic-gate * Sibling doesn't exist, figure out if ioctl command
3707c478bd9Sstevel@tonic-gate * has DINFOSUBTREE set. If it doesn't, set errno to
3717c478bd9Sstevel@tonic-gate * ENOTSUP.
3727c478bd9Sstevel@tonic-gate */
3737c478bd9Sstevel@tonic-gate if (!(DI_ALL(pa)->command & DINFOSUBTREE))
3747c478bd9Sstevel@tonic-gate errno = ENOTSUP;
3757c478bd9Sstevel@tonic-gate else
3767c478bd9Sstevel@tonic-gate errno = ENXIO;
3777c478bd9Sstevel@tonic-gate
3787c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate di_node_t
di_child_node(di_node_t node)3827c478bd9Sstevel@tonic-gate di_child_node(di_node_t node)
3837c478bd9Sstevel@tonic-gate {
3847c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get child of node %s\n", di_node_name(node)));
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
3897c478bd9Sstevel@tonic-gate errno = EINVAL;
3907c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate if (DI_NODE(node)->child) {
3967c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->child));
3977c478bd9Sstevel@tonic-gate }
3987c478bd9Sstevel@tonic-gate
3997c478bd9Sstevel@tonic-gate /*
4007c478bd9Sstevel@tonic-gate * Deal with error condition:
4017c478bd9Sstevel@tonic-gate * Child doesn't exist, figure out if DINFOSUBTREE is set.
4027c478bd9Sstevel@tonic-gate * If it isn't, set errno to ENOTSUP.
4037c478bd9Sstevel@tonic-gate */
4047c478bd9Sstevel@tonic-gate if (!(DI_ALL(pa)->command & DINFOSUBTREE))
4057c478bd9Sstevel@tonic-gate errno = ENOTSUP;
4067c478bd9Sstevel@tonic-gate else
4077c478bd9Sstevel@tonic-gate errno = ENXIO;
4087c478bd9Sstevel@tonic-gate
4097c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate di_node_t
di_drv_first_node(const char * drv_name,di_node_t root)4137c478bd9Sstevel@tonic-gate di_drv_first_node(const char *drv_name, di_node_t root)
4147c478bd9Sstevel@tonic-gate {
4157c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
4167c478bd9Sstevel@tonic-gate int major, devcnt;
4177c478bd9Sstevel@tonic-gate struct di_devnm *devnm;
4187c478bd9Sstevel@tonic-gate
4197c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Get first node of driver %s\n", drv_name));
4207c478bd9Sstevel@tonic-gate
4217c478bd9Sstevel@tonic-gate if (root == DI_NODE_NIL) {
4227c478bd9Sstevel@tonic-gate errno = EINVAL;
4237c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate
4267c478bd9Sstevel@tonic-gate /*
4277c478bd9Sstevel@tonic-gate * get major number of driver
4287c478bd9Sstevel@tonic-gate */
4297c478bd9Sstevel@tonic-gate pa = (caddr_t)root - DI_NODE(root)->self;
4307c478bd9Sstevel@tonic-gate devcnt = DI_ALL(pa)->devcnt;
4317c478bd9Sstevel@tonic-gate devnm = DI_DEVNM(pa + DI_ALL(pa)->devnames);
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate for (major = 0; major < devcnt; major++)
4347c478bd9Sstevel@tonic-gate if (devnm[major].name && (strcmp(drv_name,
4357c478bd9Sstevel@tonic-gate (char *)(pa + devnm[major].name)) == 0))
4367c478bd9Sstevel@tonic-gate break;
4377c478bd9Sstevel@tonic-gate
4387c478bd9Sstevel@tonic-gate if (major >= devcnt) {
4397c478bd9Sstevel@tonic-gate errno = EINVAL;
4407c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4417c478bd9Sstevel@tonic-gate }
4427c478bd9Sstevel@tonic-gate
4437c478bd9Sstevel@tonic-gate if (!(devnm[major].head)) {
4447c478bd9Sstevel@tonic-gate errno = ENXIO;
4457c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate
4487c478bd9Sstevel@tonic-gate return (DI_NODE(pa + devnm[major].head));
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate
4517c478bd9Sstevel@tonic-gate di_node_t
di_drv_next_node(di_node_t node)4527c478bd9Sstevel@tonic-gate di_drv_next_node(di_node_t node)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
4577c478bd9Sstevel@tonic-gate errno = EINVAL;
4587c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4597c478bd9Sstevel@tonic-gate }
4607c478bd9Sstevel@tonic-gate
4617c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "next node on per driver list:"
4627c478bd9Sstevel@tonic-gate " current=%s, driver=%s\n",
4637c478bd9Sstevel@tonic-gate di_node_name(node), di_driver_name(node)));
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate if (DI_NODE(node)->next == (di_off_t)-1) {
4667c478bd9Sstevel@tonic-gate errno = ENOTSUP;
4677c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate
4707c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
4717c478bd9Sstevel@tonic-gate
472f00128d8SToomas Soome if (DI_NODE(node)->next == 0) {
4737c478bd9Sstevel@tonic-gate errno = ENXIO;
4747c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate
4777c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_NODE(node)->next));
4787c478bd9Sstevel@tonic-gate }
4797c478bd9Sstevel@tonic-gate
4807c478bd9Sstevel@tonic-gate /*
4817c478bd9Sstevel@tonic-gate * Internal library interfaces:
4827c478bd9Sstevel@tonic-gate * node_list etc. for node walking
4837c478bd9Sstevel@tonic-gate */
4847c478bd9Sstevel@tonic-gate struct node_list {
4857c478bd9Sstevel@tonic-gate struct node_list *next;
4867c478bd9Sstevel@tonic-gate di_node_t node;
4877c478bd9Sstevel@tonic-gate };
4887c478bd9Sstevel@tonic-gate
4897c478bd9Sstevel@tonic-gate static void
free_node_list(struct node_list ** headp)4907c478bd9Sstevel@tonic-gate free_node_list(struct node_list **headp)
4917c478bd9Sstevel@tonic-gate {
4927c478bd9Sstevel@tonic-gate struct node_list *tmp;
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate while (*headp) {
4957c478bd9Sstevel@tonic-gate tmp = *headp;
4967c478bd9Sstevel@tonic-gate *headp = (*headp)->next;
4977c478bd9Sstevel@tonic-gate free(tmp);
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate
5017c478bd9Sstevel@tonic-gate static void
append_node_list(struct node_list ** headp,struct node_list * list)5027c478bd9Sstevel@tonic-gate append_node_list(struct node_list **headp, struct node_list *list)
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate struct node_list *tmp;
5057c478bd9Sstevel@tonic-gate
5067c478bd9Sstevel@tonic-gate if (*headp == NULL) {
5077c478bd9Sstevel@tonic-gate *headp = list;
5087c478bd9Sstevel@tonic-gate return;
5097c478bd9Sstevel@tonic-gate }
5107c478bd9Sstevel@tonic-gate
5117c478bd9Sstevel@tonic-gate if (list == NULL) /* a minor optimization */
5127c478bd9Sstevel@tonic-gate return;
5137c478bd9Sstevel@tonic-gate
5147c478bd9Sstevel@tonic-gate tmp = *headp;
5157c478bd9Sstevel@tonic-gate while (tmp->next)
5167c478bd9Sstevel@tonic-gate tmp = tmp->next;
5177c478bd9Sstevel@tonic-gate
5187c478bd9Sstevel@tonic-gate tmp->next = list;
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate static void
prepend_node_list(struct node_list ** headp,struct node_list * list)5227c478bd9Sstevel@tonic-gate prepend_node_list(struct node_list **headp, struct node_list *list)
5237c478bd9Sstevel@tonic-gate {
5247c478bd9Sstevel@tonic-gate struct node_list *tmp;
5257c478bd9Sstevel@tonic-gate
5267c478bd9Sstevel@tonic-gate if (list == NULL)
5277c478bd9Sstevel@tonic-gate return;
5287c478bd9Sstevel@tonic-gate
5297c478bd9Sstevel@tonic-gate tmp = *headp;
5307c478bd9Sstevel@tonic-gate *headp = list;
5317c478bd9Sstevel@tonic-gate
5327c478bd9Sstevel@tonic-gate if (tmp == NULL) /* a minor optimization */
5337c478bd9Sstevel@tonic-gate return;
5347c478bd9Sstevel@tonic-gate
5357c478bd9Sstevel@tonic-gate while (list->next)
5367c478bd9Sstevel@tonic-gate list = list->next;
5377c478bd9Sstevel@tonic-gate
5387c478bd9Sstevel@tonic-gate list->next = tmp;
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate /*
5427c478bd9Sstevel@tonic-gate * returns 1 if node is a descendant of parent, 0 otherwise
5437c478bd9Sstevel@tonic-gate */
5447c478bd9Sstevel@tonic-gate static int
is_descendant(di_node_t node,di_node_t parent)5457c478bd9Sstevel@tonic-gate is_descendant(di_node_t node, di_node_t parent)
5467c478bd9Sstevel@tonic-gate {
5477c478bd9Sstevel@tonic-gate /*
5487c478bd9Sstevel@tonic-gate * DI_NODE_NIL is parent of root, so it is
5497c478bd9Sstevel@tonic-gate * the parent of all nodes.
5507c478bd9Sstevel@tonic-gate */
5517c478bd9Sstevel@tonic-gate if (parent == DI_NODE_NIL) {
5527c478bd9Sstevel@tonic-gate return (1);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate
5557c478bd9Sstevel@tonic-gate do {
5567c478bd9Sstevel@tonic-gate node = di_parent_node(node);
5577c478bd9Sstevel@tonic-gate } while ((node != DI_NODE_NIL) && (node != parent));
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate return (node != DI_NODE_NIL);
5607c478bd9Sstevel@tonic-gate }
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate * Insert list before the first node which is NOT a descendent of parent.
5647c478bd9Sstevel@tonic-gate * This is needed to reproduce the exact walking order of link generators.
5657c478bd9Sstevel@tonic-gate */
5667c478bd9Sstevel@tonic-gate static void
insert_node_list(struct node_list ** headp,struct node_list * list,di_node_t parent)5677c478bd9Sstevel@tonic-gate insert_node_list(struct node_list **headp, struct node_list *list,
5687c478bd9Sstevel@tonic-gate di_node_t parent)
5697c478bd9Sstevel@tonic-gate {
5707c478bd9Sstevel@tonic-gate struct node_list *tmp, *tmp1;
5717c478bd9Sstevel@tonic-gate
5727c478bd9Sstevel@tonic-gate if (list == NULL)
5737c478bd9Sstevel@tonic-gate return;
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate tmp = *headp;
5767c478bd9Sstevel@tonic-gate if (tmp == NULL) { /* a minor optimization */
5777c478bd9Sstevel@tonic-gate *headp = list;
5787c478bd9Sstevel@tonic-gate return;
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate
5817c478bd9Sstevel@tonic-gate if (!is_descendant(tmp->node, parent)) {
5827c478bd9Sstevel@tonic-gate prepend_node_list(headp, list);
5837c478bd9Sstevel@tonic-gate return;
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * Find first node which is not a descendant
5887c478bd9Sstevel@tonic-gate */
5897c478bd9Sstevel@tonic-gate while (tmp->next && is_descendant(tmp->next->node, parent)) {
5907c478bd9Sstevel@tonic-gate tmp = tmp->next;
5917c478bd9Sstevel@tonic-gate }
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate tmp1 = tmp->next;
5947c478bd9Sstevel@tonic-gate tmp->next = list;
5957c478bd9Sstevel@tonic-gate append_node_list(headp, tmp1);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate * Get a linked list of handles of all children
6007c478bd9Sstevel@tonic-gate */
6017c478bd9Sstevel@tonic-gate static struct node_list *
get_children(di_node_t node)6027c478bd9Sstevel@tonic-gate get_children(di_node_t node)
6037c478bd9Sstevel@tonic-gate {
6047c478bd9Sstevel@tonic-gate di_node_t child;
6057c478bd9Sstevel@tonic-gate struct node_list *result, *tmp;
6067c478bd9Sstevel@tonic-gate
6077c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "Get children of node %s\n", di_node_name(node)));
6087c478bd9Sstevel@tonic-gate
6097c478bd9Sstevel@tonic-gate if ((child = di_child_node(node)) == DI_NODE_NIL) {
6107c478bd9Sstevel@tonic-gate return (NULL);
6117c478bd9Sstevel@tonic-gate }
6127c478bd9Sstevel@tonic-gate
6137c478bd9Sstevel@tonic-gate if ((result = malloc(sizeof (struct node_list))) == NULL) {
6147c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n"));
6157c478bd9Sstevel@tonic-gate return (NULL);
6167c478bd9Sstevel@tonic-gate }
6177c478bd9Sstevel@tonic-gate
6187c478bd9Sstevel@tonic-gate result->node = child;
6197c478bd9Sstevel@tonic-gate tmp = result;
6207c478bd9Sstevel@tonic-gate
6217c478bd9Sstevel@tonic-gate while ((child = di_sibling_node(tmp->node)) != DI_NODE_NIL) {
6227c478bd9Sstevel@tonic-gate if ((tmp->next = malloc(sizeof (struct node_list))) == NULL) {
6237c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n"));
6247c478bd9Sstevel@tonic-gate free_node_list(&result);
6257c478bd9Sstevel@tonic-gate return (NULL);
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate tmp = tmp->next;
6287c478bd9Sstevel@tonic-gate tmp->node = child;
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate
6317c478bd9Sstevel@tonic-gate tmp->next = NULL;
6327c478bd9Sstevel@tonic-gate
6337c478bd9Sstevel@tonic-gate return (result);
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate
6367c478bd9Sstevel@tonic-gate /*
6377c478bd9Sstevel@tonic-gate * Internal library interface:
6387c478bd9Sstevel@tonic-gate * Delete all siblings of the first node from the node_list, along with
6397c478bd9Sstevel@tonic-gate * the first node itself.
6407c478bd9Sstevel@tonic-gate */
6417c478bd9Sstevel@tonic-gate static void
prune_sib(struct node_list ** headp)6427c478bd9Sstevel@tonic-gate prune_sib(struct node_list **headp)
6437c478bd9Sstevel@tonic-gate {
6447c478bd9Sstevel@tonic-gate di_node_t parent, curr_par, curr_gpar;
6457c478bd9Sstevel@tonic-gate struct node_list *curr, *prev;
6467c478bd9Sstevel@tonic-gate
6477c478bd9Sstevel@tonic-gate /*
6487c478bd9Sstevel@tonic-gate * get handle to parent of first node
6497c478bd9Sstevel@tonic-gate */
6507c478bd9Sstevel@tonic-gate if ((parent = di_parent_node((*headp)->node)) == DI_NODE_NIL) {
6517c478bd9Sstevel@tonic-gate /*
6527c478bd9Sstevel@tonic-gate * This must be the root of the snapshot, so can't
6537c478bd9Sstevel@tonic-gate * have any siblings.
6547c478bd9Sstevel@tonic-gate *
6557c478bd9Sstevel@tonic-gate * XXX Put a check here just in case.
6567c478bd9Sstevel@tonic-gate */
6577c478bd9Sstevel@tonic-gate if ((*headp)->next)
6587c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "Unexpected err in di_walk_node.\n"));
6597c478bd9Sstevel@tonic-gate
6607c478bd9Sstevel@tonic-gate free(*headp);
6617c478bd9Sstevel@tonic-gate *headp = NULL;
6627c478bd9Sstevel@tonic-gate return;
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate /*
6667c478bd9Sstevel@tonic-gate * To be complete, we should also delete the children
6677c478bd9Sstevel@tonic-gate * of siblings that have already been visited.
6687c478bd9Sstevel@tonic-gate * This happens for DI_WALK_SIBFIRST when the first node
6697c478bd9Sstevel@tonic-gate * is NOT the first in the linked list of siblings.
6707c478bd9Sstevel@tonic-gate *
6717c478bd9Sstevel@tonic-gate * Hence, we compare parent with BOTH the parent and grandparent
6727c478bd9Sstevel@tonic-gate * of nodes, and delete node is a match is found.
6737c478bd9Sstevel@tonic-gate */
6747c478bd9Sstevel@tonic-gate prev = *headp;
6757c478bd9Sstevel@tonic-gate curr = prev->next;
6767c478bd9Sstevel@tonic-gate while (curr) {
6777c478bd9Sstevel@tonic-gate if (((curr_par = di_parent_node(curr->node)) != DI_NODE_NIL) &&
6787c478bd9Sstevel@tonic-gate ((curr_par == parent) || ((curr_gpar =
6797c478bd9Sstevel@tonic-gate di_parent_node(curr_par)) != DI_NODE_NIL) &&
6807c478bd9Sstevel@tonic-gate (curr_gpar == parent))) {
6817c478bd9Sstevel@tonic-gate /*
6827c478bd9Sstevel@tonic-gate * match parent/grandparent: delete curr
6837c478bd9Sstevel@tonic-gate */
6847c478bd9Sstevel@tonic-gate prev->next = curr->next;
6857c478bd9Sstevel@tonic-gate free(curr);
6867c478bd9Sstevel@tonic-gate curr = prev->next;
6877c478bd9Sstevel@tonic-gate } else
6887c478bd9Sstevel@tonic-gate curr = curr->next;
6897c478bd9Sstevel@tonic-gate }
6907c478bd9Sstevel@tonic-gate
6917c478bd9Sstevel@tonic-gate /*
6927c478bd9Sstevel@tonic-gate * delete the first node
6937c478bd9Sstevel@tonic-gate */
6947c478bd9Sstevel@tonic-gate curr = *headp;
6957c478bd9Sstevel@tonic-gate *headp = curr->next;
6967c478bd9Sstevel@tonic-gate free(curr);
6977c478bd9Sstevel@tonic-gate }
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate * Internal library function:
7017c478bd9Sstevel@tonic-gate * Update node list based on action (return code from callback)
7027c478bd9Sstevel@tonic-gate * and flag specifying walking behavior.
7037c478bd9Sstevel@tonic-gate */
7047c478bd9Sstevel@tonic-gate static void
update_node_list(int action,uint_t flag,struct node_list ** headp)7057c478bd9Sstevel@tonic-gate update_node_list(int action, uint_t flag, struct node_list **headp)
7067c478bd9Sstevel@tonic-gate {
7077c478bd9Sstevel@tonic-gate struct node_list *children, *tmp;
7087c478bd9Sstevel@tonic-gate di_node_t parent = di_parent_node((*headp)->node);
7097c478bd9Sstevel@tonic-gate
7107c478bd9Sstevel@tonic-gate switch (action) {
7117c478bd9Sstevel@tonic-gate case DI_WALK_TERMINATE:
7127c478bd9Sstevel@tonic-gate /*
7137c478bd9Sstevel@tonic-gate * free the node list and be done
7147c478bd9Sstevel@tonic-gate */
7157c478bd9Sstevel@tonic-gate children = NULL;
7167c478bd9Sstevel@tonic-gate free_node_list(headp);
7177c478bd9Sstevel@tonic-gate break;
7187c478bd9Sstevel@tonic-gate
7197c478bd9Sstevel@tonic-gate case DI_WALK_PRUNESIB:
7207c478bd9Sstevel@tonic-gate /*
7217c478bd9Sstevel@tonic-gate * Get list of children and prune siblings
7227c478bd9Sstevel@tonic-gate */
7237c478bd9Sstevel@tonic-gate children = get_children((*headp)->node);
7247c478bd9Sstevel@tonic-gate prune_sib(headp);
7257c478bd9Sstevel@tonic-gate break;
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate case DI_WALK_PRUNECHILD:
7287c478bd9Sstevel@tonic-gate /*
7297c478bd9Sstevel@tonic-gate * Set children to NULL and pop first node
7307c478bd9Sstevel@tonic-gate */
7317c478bd9Sstevel@tonic-gate children = NULL;
7327c478bd9Sstevel@tonic-gate tmp = *headp;
7337c478bd9Sstevel@tonic-gate *headp = tmp->next;
7347c478bd9Sstevel@tonic-gate free(tmp);
7357c478bd9Sstevel@tonic-gate break;
7367c478bd9Sstevel@tonic-gate
7377c478bd9Sstevel@tonic-gate case DI_WALK_CONTINUE:
7387c478bd9Sstevel@tonic-gate default:
7397c478bd9Sstevel@tonic-gate /*
7407c478bd9Sstevel@tonic-gate * Get list of children and pop first node
7417c478bd9Sstevel@tonic-gate */
7427c478bd9Sstevel@tonic-gate children = get_children((*headp)->node);
7437c478bd9Sstevel@tonic-gate tmp = *headp;
7447c478bd9Sstevel@tonic-gate *headp = tmp->next;
7457c478bd9Sstevel@tonic-gate free(tmp);
7467c478bd9Sstevel@tonic-gate break;
7477c478bd9Sstevel@tonic-gate }
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate /*
7507c478bd9Sstevel@tonic-gate * insert the list of children
7517c478bd9Sstevel@tonic-gate */
7527c478bd9Sstevel@tonic-gate switch (flag) {
7537c478bd9Sstevel@tonic-gate case DI_WALK_CLDFIRST:
7547c478bd9Sstevel@tonic-gate prepend_node_list(headp, children);
7557c478bd9Sstevel@tonic-gate break;
7567c478bd9Sstevel@tonic-gate
7577c478bd9Sstevel@tonic-gate case DI_WALK_SIBFIRST:
7587c478bd9Sstevel@tonic-gate append_node_list(headp, children);
7597c478bd9Sstevel@tonic-gate break;
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate case DI_WALK_LINKGEN:
7627c478bd9Sstevel@tonic-gate default:
7637c478bd9Sstevel@tonic-gate insert_node_list(headp, children, parent);
7647c478bd9Sstevel@tonic-gate break;
7657c478bd9Sstevel@tonic-gate }
7667c478bd9Sstevel@tonic-gate }
7677c478bd9Sstevel@tonic-gate
7687c478bd9Sstevel@tonic-gate /*
7697c478bd9Sstevel@tonic-gate * Internal library function:
7707c478bd9Sstevel@tonic-gate * Invoke callback on one node and update the list of nodes to be walked
7717c478bd9Sstevel@tonic-gate * based on the flag and return code.
7727c478bd9Sstevel@tonic-gate */
7737c478bd9Sstevel@tonic-gate static void
walk_one_node(struct node_list ** headp,uint_t flag,void * arg,int (* callback)(di_node_t,void *))7747c478bd9Sstevel@tonic-gate walk_one_node(struct node_list **headp, uint_t flag, void *arg,
7757c478bd9Sstevel@tonic-gate int (*callback)(di_node_t, void *))
7767c478bd9Sstevel@tonic-gate {
7777c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Walking node %s\n", di_node_name((*headp)->node)));
7787c478bd9Sstevel@tonic-gate
7797c478bd9Sstevel@tonic-gate update_node_list(callback((*headp)->node, arg),
7807c478bd9Sstevel@tonic-gate flag & DI_WALK_MASK, headp);
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate
7837c478bd9Sstevel@tonic-gate int
di_walk_node(di_node_t root,uint_t flag,void * arg,int (* node_callback)(di_node_t,void *))7847c478bd9Sstevel@tonic-gate di_walk_node(di_node_t root, uint_t flag, void *arg,
7857c478bd9Sstevel@tonic-gate int (*node_callback)(di_node_t, void *))
7867c478bd9Sstevel@tonic-gate {
7877c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate if (root == NULL) {
7907c478bd9Sstevel@tonic-gate errno = EINVAL;
7917c478bd9Sstevel@tonic-gate return (-1);
7927c478bd9Sstevel@tonic-gate }
7937c478bd9Sstevel@tonic-gate
7947c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) {
7957c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n"));
7967c478bd9Sstevel@tonic-gate return (-1);
7977c478bd9Sstevel@tonic-gate }
7987c478bd9Sstevel@tonic-gate
7997c478bd9Sstevel@tonic-gate head->next = NULL;
8007c478bd9Sstevel@tonic-gate head->node = root;
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start node walking from node %s\n",
8037c478bd9Sstevel@tonic-gate di_node_name(root)));
8047c478bd9Sstevel@tonic-gate
8057c478bd9Sstevel@tonic-gate while (head != NULL)
8067c478bd9Sstevel@tonic-gate walk_one_node(&head, flag, arg, node_callback);
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate return (0);
8097c478bd9Sstevel@tonic-gate }
8107c478bd9Sstevel@tonic-gate
8117c478bd9Sstevel@tonic-gate /*
8127c478bd9Sstevel@tonic-gate * Internal library function:
8137c478bd9Sstevel@tonic-gate * Invoke callback for each minor on the minor list of first node
8147c478bd9Sstevel@tonic-gate * on node_list headp, and place children of first node on the list.
8157c478bd9Sstevel@tonic-gate *
8167c478bd9Sstevel@tonic-gate * This is similar to walk_one_node, except we only walk in child
8177c478bd9Sstevel@tonic-gate * first mode.
8187c478bd9Sstevel@tonic-gate */
8197c478bd9Sstevel@tonic-gate static void
walk_one_minor_list(struct node_list ** headp,const char * desired_type,uint_t flag,void * arg,int (* callback)(di_node_t,di_minor_t,void *))8207c478bd9Sstevel@tonic-gate walk_one_minor_list(struct node_list **headp, const char *desired_type,
8217c478bd9Sstevel@tonic-gate uint_t flag, void *arg, int (*callback)(di_node_t, di_minor_t, void *))
8227c478bd9Sstevel@tonic-gate {
8237c478bd9Sstevel@tonic-gate int ddm_type;
8247c478bd9Sstevel@tonic-gate int action = DI_WALK_CONTINUE;
8257c478bd9Sstevel@tonic-gate char *node_type;
8267c478bd9Sstevel@tonic-gate di_minor_t minor = DI_MINOR_NIL;
8277c478bd9Sstevel@tonic-gate di_node_t node = (*headp)->node;
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
8307c478bd9Sstevel@tonic-gate ddm_type = di_minor_type(minor);
8317c478bd9Sstevel@tonic-gate
8327c478bd9Sstevel@tonic-gate if ((ddm_type == DDM_ALIAS) && !(flag & DI_CHECK_ALIAS))
8337c478bd9Sstevel@tonic-gate continue;
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate if ((ddm_type == DDM_INTERNAL_PATH) &&
8367c478bd9Sstevel@tonic-gate !(flag & DI_CHECK_INTERNAL_PATH))
8377c478bd9Sstevel@tonic-gate continue;
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate node_type = di_minor_nodetype(minor);
8407c478bd9Sstevel@tonic-gate if ((desired_type != NULL) && ((node_type == NULL) ||
8417c478bd9Sstevel@tonic-gate strncmp(desired_type, node_type, strlen(desired_type))
8427c478bd9Sstevel@tonic-gate != 0))
8437c478bd9Sstevel@tonic-gate continue;
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate if ((action = callback(node, minor, arg)) ==
8467c478bd9Sstevel@tonic-gate DI_WALK_TERMINATE) {
8477c478bd9Sstevel@tonic-gate break;
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate update_node_list(action, DI_WALK_LINKGEN, headp);
8527c478bd9Sstevel@tonic-gate }
8537c478bd9Sstevel@tonic-gate
8547c478bd9Sstevel@tonic-gate int
di_walk_minor(di_node_t root,const char * minor_type,uint_t flag,void * arg,int (* minor_callback)(di_node_t,di_minor_t,void *))8557c478bd9Sstevel@tonic-gate di_walk_minor(di_node_t root, const char *minor_type, uint_t flag, void *arg,
8567c478bd9Sstevel@tonic-gate int (*minor_callback)(di_node_t, di_minor_t, void *))
8577c478bd9Sstevel@tonic-gate {
8587c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate #ifdef DEBUG
861602ca9eaScth char *devfspath = di_devfs_path(root);
862602ca9eaScth DPRINTF((DI_INFO, "walking minor nodes under %s\n", devfspath));
863602ca9eaScth di_devfs_path_free(devfspath);
8647c478bd9Sstevel@tonic-gate #endif
8657c478bd9Sstevel@tonic-gate
8667c478bd9Sstevel@tonic-gate if (root == NULL) {
8677c478bd9Sstevel@tonic-gate errno = EINVAL;
8687c478bd9Sstevel@tonic-gate return (-1);
8697c478bd9Sstevel@tonic-gate }
8707c478bd9Sstevel@tonic-gate
8717c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) {
8727c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n"));
8737c478bd9Sstevel@tonic-gate return (-1);
8747c478bd9Sstevel@tonic-gate }
8757c478bd9Sstevel@tonic-gate
8767c478bd9Sstevel@tonic-gate head->next = NULL;
8777c478bd9Sstevel@tonic-gate head->node = root;
8787c478bd9Sstevel@tonic-gate
8797c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start minor walking from node %s\n",
8807c478bd9Sstevel@tonic-gate di_node_name(root)));
8817c478bd9Sstevel@tonic-gate
8827c478bd9Sstevel@tonic-gate while (head != NULL)
8837c478bd9Sstevel@tonic-gate walk_one_minor_list(&head, minor_type, flag, arg,
8847c478bd9Sstevel@tonic-gate minor_callback);
8857c478bd9Sstevel@tonic-gate
8867c478bd9Sstevel@tonic-gate return (0);
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate /*
8907c478bd9Sstevel@tonic-gate * generic node parameters
8917c478bd9Sstevel@tonic-gate * Calling these routines always succeeds.
8927c478bd9Sstevel@tonic-gate */
8937c478bd9Sstevel@tonic-gate char *
di_node_name(di_node_t node)8947c478bd9Sstevel@tonic-gate di_node_name(di_node_t node)
8957c478bd9Sstevel@tonic-gate {
8967c478bd9Sstevel@tonic-gate return ((caddr_t)node + DI_NODE(node)->node_name - DI_NODE(node)->self);
8977c478bd9Sstevel@tonic-gate }
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate /* returns NULL ptr or a valid ptr to non-NULL string */
9007c478bd9Sstevel@tonic-gate char *
di_bus_addr(di_node_t node)9017c478bd9Sstevel@tonic-gate di_bus_addr(di_node_t node)
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate caddr_t pa = (caddr_t)node - DI_NODE(node)->self;
9047c478bd9Sstevel@tonic-gate
9057c478bd9Sstevel@tonic-gate if (DI_NODE(node)->address == 0)
9067c478bd9Sstevel@tonic-gate return (NULL);
9077c478bd9Sstevel@tonic-gate
9087c478bd9Sstevel@tonic-gate return ((char *)(pa + DI_NODE(node)->address));
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate
9117c478bd9Sstevel@tonic-gate char *
di_binding_name(di_node_t node)9127c478bd9Sstevel@tonic-gate di_binding_name(di_node_t node)
9137c478bd9Sstevel@tonic-gate {
9147c478bd9Sstevel@tonic-gate caddr_t pa = (caddr_t)node - DI_NODE(node)->self;
9157c478bd9Sstevel@tonic-gate
9167c478bd9Sstevel@tonic-gate if (DI_NODE(node)->bind_name == 0)
9177c478bd9Sstevel@tonic-gate return (NULL);
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate return ((char *)(pa + DI_NODE(node)->bind_name));
9207c478bd9Sstevel@tonic-gate }
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate int
di_compatible_names(di_node_t node,char ** names)9237c478bd9Sstevel@tonic-gate di_compatible_names(di_node_t node, char **names)
9247c478bd9Sstevel@tonic-gate {
9257c478bd9Sstevel@tonic-gate char *c;
9267c478bd9Sstevel@tonic-gate int len, size, entries = 0;
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate if (DI_NODE(node)->compat_names == 0) {
9297c478bd9Sstevel@tonic-gate *names = NULL;
9307c478bd9Sstevel@tonic-gate return (0);
9317c478bd9Sstevel@tonic-gate }
9327c478bd9Sstevel@tonic-gate
9337c478bd9Sstevel@tonic-gate *names = (caddr_t)node +
9347c478bd9Sstevel@tonic-gate DI_NODE(node)->compat_names - DI_NODE(node)->self;
9357c478bd9Sstevel@tonic-gate
9367c478bd9Sstevel@tonic-gate c = *names;
9377c478bd9Sstevel@tonic-gate len = DI_NODE(node)->compat_length;
9387c478bd9Sstevel@tonic-gate while (len > 0) {
9397c478bd9Sstevel@tonic-gate entries++;
9407c478bd9Sstevel@tonic-gate size = strlen(c) + 1;
9417c478bd9Sstevel@tonic-gate len -= size;
9427c478bd9Sstevel@tonic-gate c += size;
9437c478bd9Sstevel@tonic-gate }
9447c478bd9Sstevel@tonic-gate
9457c478bd9Sstevel@tonic-gate return (entries);
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate int
di_instance(di_node_t node)9497c478bd9Sstevel@tonic-gate di_instance(di_node_t node)
9507c478bd9Sstevel@tonic-gate {
9517c478bd9Sstevel@tonic-gate return (DI_NODE(node)->instance);
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate
9547c478bd9Sstevel@tonic-gate /*
9557c478bd9Sstevel@tonic-gate * XXX: emulate the return value of the old implementation
9567c478bd9Sstevel@tonic-gate * using info from devi_node_class and devi_node_attributes.
9577c478bd9Sstevel@tonic-gate */
9587c478bd9Sstevel@tonic-gate int
di_nodeid(di_node_t node)9597c478bd9Sstevel@tonic-gate di_nodeid(di_node_t node)
9607c478bd9Sstevel@tonic-gate {
9617c478bd9Sstevel@tonic-gate if (DI_NODE(node)->node_class == DDI_NC_PROM)
9627c478bd9Sstevel@tonic-gate return (DI_PROM_NODEID);
9637c478bd9Sstevel@tonic-gate
9647c478bd9Sstevel@tonic-gate if (DI_NODE(node)->attributes & DDI_PERSISTENT)
9657c478bd9Sstevel@tonic-gate return (DI_SID_NODEID);
9667c478bd9Sstevel@tonic-gate
9677c478bd9Sstevel@tonic-gate return (DI_PSEUDO_NODEID);
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate
9707c478bd9Sstevel@tonic-gate uint_t
di_state(di_node_t node)9717c478bd9Sstevel@tonic-gate di_state(di_node_t node)
9727c478bd9Sstevel@tonic-gate {
9737c478bd9Sstevel@tonic-gate uint_t result = 0;
9747c478bd9Sstevel@tonic-gate
9757c478bd9Sstevel@tonic-gate if (di_node_state(node) < DS_ATTACHED)
9767c478bd9Sstevel@tonic-gate result |= DI_DRIVER_DETACHED;
9777c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_DEVICE_OFFLINE)
9787c478bd9Sstevel@tonic-gate result |= DI_DEVICE_OFFLINE;
9797c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_DEVICE_DOWN)
9804c06356bSdh142964 result |= DI_DEVICE_DOWN;
98125c6ff4bSstephh if (DI_NODE(node)->state & DEVI_DEVICE_DEGRADED)
98225c6ff4bSstephh result |= DI_DEVICE_DEGRADED;
9834c06356bSdh142964 if (DI_NODE(node)->state & DEVI_DEVICE_REMOVED)
9844c06356bSdh142964 result |= DI_DEVICE_REMOVED;
9857c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_BUS_QUIESCED)
9867c478bd9Sstevel@tonic-gate result |= DI_BUS_QUIESCED;
9877c478bd9Sstevel@tonic-gate if (DI_NODE(node)->state & DEVI_BUS_DOWN)
9887c478bd9Sstevel@tonic-gate result |= DI_BUS_DOWN;
9897c478bd9Sstevel@tonic-gate
9907c478bd9Sstevel@tonic-gate return (result);
9917c478bd9Sstevel@tonic-gate }
9927c478bd9Sstevel@tonic-gate
9937c478bd9Sstevel@tonic-gate ddi_node_state_t
di_node_state(di_node_t node)9947c478bd9Sstevel@tonic-gate di_node_state(di_node_t node)
9957c478bd9Sstevel@tonic-gate {
9967c478bd9Sstevel@tonic-gate return (DI_NODE(node)->node_state);
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate
9993e2676e0Svikram uint_t
di_flags(di_node_t node)10003e2676e0Svikram di_flags(di_node_t node)
10013e2676e0Svikram {
10023e2676e0Svikram return (DI_NODE(node)->flags);
10033e2676e0Svikram }
10043e2676e0Svikram
100525e8c5aaSvikram uint_t
di_retired(di_node_t node)100625e8c5aaSvikram di_retired(di_node_t node)
100725e8c5aaSvikram {
100825e8c5aaSvikram return (di_flags(node) & DEVI_RETIRED);
100925e8c5aaSvikram }
101025e8c5aaSvikram
10117c478bd9Sstevel@tonic-gate ddi_devid_t
di_devid(di_node_t node)10127c478bd9Sstevel@tonic-gate di_devid(di_node_t node)
10137c478bd9Sstevel@tonic-gate {
10147c478bd9Sstevel@tonic-gate if (DI_NODE(node)->devid == 0)
10157c478bd9Sstevel@tonic-gate return (NULL);
10167c478bd9Sstevel@tonic-gate
10177c478bd9Sstevel@tonic-gate return ((ddi_devid_t)((caddr_t)node +
10187c478bd9Sstevel@tonic-gate DI_NODE(node)->devid - DI_NODE(node)->self));
10197c478bd9Sstevel@tonic-gate }
10207c478bd9Sstevel@tonic-gate
10217c478bd9Sstevel@tonic-gate int
di_driver_major(di_node_t node)10227c478bd9Sstevel@tonic-gate di_driver_major(di_node_t node)
10237c478bd9Sstevel@tonic-gate {
10247c478bd9Sstevel@tonic-gate int major;
10257c478bd9Sstevel@tonic-gate
10267c478bd9Sstevel@tonic-gate major = DI_NODE(node)->drv_major;
10277c478bd9Sstevel@tonic-gate if (major < 0)
10287c478bd9Sstevel@tonic-gate return (-1);
10297c478bd9Sstevel@tonic-gate return (major);
10307c478bd9Sstevel@tonic-gate }
10317c478bd9Sstevel@tonic-gate
10327c478bd9Sstevel@tonic-gate char *
di_driver_name(di_node_t node)10337c478bd9Sstevel@tonic-gate di_driver_name(di_node_t node)
10347c478bd9Sstevel@tonic-gate {
10357c478bd9Sstevel@tonic-gate int major;
10367c478bd9Sstevel@tonic-gate caddr_t pa;
10377c478bd9Sstevel@tonic-gate struct di_devnm *devnm;
10387c478bd9Sstevel@tonic-gate
10397c478bd9Sstevel@tonic-gate major = DI_NODE(node)->drv_major;
10407c478bd9Sstevel@tonic-gate if (major < 0)
10417c478bd9Sstevel@tonic-gate return (NULL);
10427c478bd9Sstevel@tonic-gate
10437c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
10447c478bd9Sstevel@tonic-gate devnm = DI_DEVNM(pa + DI_ALL(pa)->devnames);
10457c478bd9Sstevel@tonic-gate
10467c478bd9Sstevel@tonic-gate if (devnm[major].name)
10477c478bd9Sstevel@tonic-gate return (pa + devnm[major].name);
10487c478bd9Sstevel@tonic-gate else
10497c478bd9Sstevel@tonic-gate return (NULL);
10507c478bd9Sstevel@tonic-gate }
10517c478bd9Sstevel@tonic-gate
10527c478bd9Sstevel@tonic-gate uint_t
di_driver_ops(di_node_t node)10537c478bd9Sstevel@tonic-gate di_driver_ops(di_node_t node)
10547c478bd9Sstevel@tonic-gate {
10557c478bd9Sstevel@tonic-gate int major;
10567c478bd9Sstevel@tonic-gate caddr_t pa;
10577c478bd9Sstevel@tonic-gate struct di_devnm *devnm;
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate major = DI_NODE(node)->drv_major;
10607c478bd9Sstevel@tonic-gate if (major < 0)
10617c478bd9Sstevel@tonic-gate return (0);
10627c478bd9Sstevel@tonic-gate
10637c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
10647c478bd9Sstevel@tonic-gate devnm = DI_DEVNM(pa + DI_ALL(pa)->devnames);
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate return (devnm[major].ops);
10677c478bd9Sstevel@tonic-gate }
10687c478bd9Sstevel@tonic-gate
10697c478bd9Sstevel@tonic-gate /*
107025d35568SYuri Pankov * Returns pointer to the allocated string, which must be freed by the caller.
10717c478bd9Sstevel@tonic-gate */
10727c478bd9Sstevel@tonic-gate char *
di_devfs_path(di_node_t node)10737c478bd9Sstevel@tonic-gate di_devfs_path(di_node_t node)
10747c478bd9Sstevel@tonic-gate {
10757c478bd9Sstevel@tonic-gate caddr_t pa;
10767c478bd9Sstevel@tonic-gate di_node_t parent;
10777c478bd9Sstevel@tonic-gate int depth = 0, len = 0;
10787c478bd9Sstevel@tonic-gate char *buf, *name[MAX_TREE_DEPTH], *addr[MAX_TREE_DEPTH];
10797c478bd9Sstevel@tonic-gate
10807c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
10817c478bd9Sstevel@tonic-gate errno = EINVAL;
10827c478bd9Sstevel@tonic-gate return (NULL);
10837c478bd9Sstevel@tonic-gate }
10847c478bd9Sstevel@tonic-gate
10857c478bd9Sstevel@tonic-gate /*
10867c478bd9Sstevel@tonic-gate * trace back to root, note the node_name & address
10877c478bd9Sstevel@tonic-gate */
10887c478bd9Sstevel@tonic-gate while ((parent = di_parent_node(node)) != DI_NODE_NIL) {
10897c478bd9Sstevel@tonic-gate name[depth] = di_node_name(node);
10907c478bd9Sstevel@tonic-gate len += strlen(name[depth]) + 1; /* 1 for '/' */
10917c478bd9Sstevel@tonic-gate
10927c478bd9Sstevel@tonic-gate if ((addr[depth] = di_bus_addr(node)) != NULL)
10937c478bd9Sstevel@tonic-gate len += strlen(addr[depth]) + 1; /* 1 for '@' */
10947c478bd9Sstevel@tonic-gate
10957c478bd9Sstevel@tonic-gate node = parent;
10967c478bd9Sstevel@tonic-gate depth++;
10977c478bd9Sstevel@tonic-gate }
10987c478bd9Sstevel@tonic-gate
10997c478bd9Sstevel@tonic-gate /*
11007c478bd9Sstevel@tonic-gate * get the path to the root of snapshot
11017c478bd9Sstevel@tonic-gate */
11027c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
11037c478bd9Sstevel@tonic-gate name[depth] = DI_ALL(pa)->root_path;
11047c478bd9Sstevel@tonic-gate len += strlen(name[depth]) + 1;
11057c478bd9Sstevel@tonic-gate
11067c478bd9Sstevel@tonic-gate /*
11077c478bd9Sstevel@tonic-gate * allocate buffer and assemble path
11087c478bd9Sstevel@tonic-gate */
11097c478bd9Sstevel@tonic-gate if ((buf = malloc(len)) == NULL) {
11107c478bd9Sstevel@tonic-gate return (NULL);
11117c478bd9Sstevel@tonic-gate }
11127c478bd9Sstevel@tonic-gate
11137c478bd9Sstevel@tonic-gate (void) strcpy(buf, name[depth]);
11147c478bd9Sstevel@tonic-gate len = strlen(buf);
11157c478bd9Sstevel@tonic-gate if (buf[len - 1] == '/')
11167c478bd9Sstevel@tonic-gate len--; /* delete trailing '/' */
11177c478bd9Sstevel@tonic-gate
11187c478bd9Sstevel@tonic-gate while (depth) {
11197c478bd9Sstevel@tonic-gate depth--;
11207c478bd9Sstevel@tonic-gate buf[len] = '/';
11217c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, name[depth]);
11227c478bd9Sstevel@tonic-gate len += strlen(name[depth]) + 1;
11237c478bd9Sstevel@tonic-gate if (addr[depth] && addr[depth][0] != '\0') {
11247c478bd9Sstevel@tonic-gate buf[len] = '@';
11257c478bd9Sstevel@tonic-gate (void) strcpy(buf + len + 1, addr[depth]);
11267c478bd9Sstevel@tonic-gate len += strlen(addr[depth]) + 1;
11277c478bd9Sstevel@tonic-gate }
11287c478bd9Sstevel@tonic-gate }
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate return (buf);
11317c478bd9Sstevel@tonic-gate }
11327c478bd9Sstevel@tonic-gate
11337c478bd9Sstevel@tonic-gate char *
di_devfs_minor_path(di_minor_t minor)11347c478bd9Sstevel@tonic-gate di_devfs_minor_path(di_minor_t minor)
11357c478bd9Sstevel@tonic-gate {
11367c478bd9Sstevel@tonic-gate di_node_t node;
1137602ca9eaScth char *full_path, *name, *devfspath;
11387c478bd9Sstevel@tonic-gate int full_path_len;
11397c478bd9Sstevel@tonic-gate
11407c478bd9Sstevel@tonic-gate if (minor == DI_MINOR_NIL) {
11417c478bd9Sstevel@tonic-gate errno = EINVAL;
11427c478bd9Sstevel@tonic-gate return (NULL);
11437c478bd9Sstevel@tonic-gate }
11447c478bd9Sstevel@tonic-gate
11457c478bd9Sstevel@tonic-gate name = di_minor_name(minor);
11467c478bd9Sstevel@tonic-gate node = di_minor_devinfo(minor);
1147602ca9eaScth devfspath = di_devfs_path(node);
1148602ca9eaScth if (devfspath == NULL)
11497c478bd9Sstevel@tonic-gate return (NULL);
11507c478bd9Sstevel@tonic-gate
11517c478bd9Sstevel@tonic-gate /* make the full path to the device minor node */
1152602ca9eaScth full_path_len = strlen(devfspath) + strlen(name) + 2;
11537c478bd9Sstevel@tonic-gate full_path = (char *)calloc(1, full_path_len);
11547c478bd9Sstevel@tonic-gate if (full_path != NULL)
1155602ca9eaScth (void) snprintf(full_path, full_path_len, "%s:%s",
1156602ca9eaScth devfspath, name);
11577c478bd9Sstevel@tonic-gate
1158602ca9eaScth di_devfs_path_free(devfspath);
11597c478bd9Sstevel@tonic-gate return (full_path);
11607c478bd9Sstevel@tonic-gate }
11617c478bd9Sstevel@tonic-gate
1162602ca9eaScth /*
1163602ca9eaScth * Produce a string representation of path to di_path_t (pathinfo node). This
1164602ca9eaScth * string is identical to di_devfs_path had the device been enumerated under
1165602ca9eaScth * the pHCI: it has a base path to pHCI, then uses node_name of client, and
1166602ca9eaScth * device unit-address of pathinfo node.
1167602ca9eaScth */
1168602ca9eaScth char *
di_path_devfs_path(di_path_t path)1169602ca9eaScth di_path_devfs_path(di_path_t path)
1170602ca9eaScth {
1171602ca9eaScth di_node_t phci_node;
1172602ca9eaScth char *phci_path, *path_name, *path_addr;
1173602ca9eaScth char *full_path;
1174602ca9eaScth int full_path_len;
1175602ca9eaScth
1176602ca9eaScth if (path == DI_PATH_NIL) {
1177602ca9eaScth errno = EINVAL;
1178602ca9eaScth return (NULL);
1179602ca9eaScth }
1180602ca9eaScth
1181602ca9eaScth /* get name@addr for path */
1182602ca9eaScth path_name = di_path_node_name(path);
1183602ca9eaScth path_addr = di_path_bus_addr(path);
1184602ca9eaScth if ((path_name == NULL) || (path_addr == NULL))
1185602ca9eaScth return (NULL);
1186602ca9eaScth
1187602ca9eaScth /* base path to pHCI devinfo node */
1188602ca9eaScth phci_node = di_path_phci_node(path);
1189602ca9eaScth if (phci_node == NULL)
1190602ca9eaScth return (NULL);
1191602ca9eaScth phci_path = di_devfs_path(phci_node);
1192602ca9eaScth if (phci_path == NULL)
1193602ca9eaScth return (NULL);
1194602ca9eaScth
1195602ca9eaScth /* make the full string representation of path */
1196602ca9eaScth full_path_len = strlen(phci_path) + 1 + strlen(path_name) +
1197602ca9eaScth 1 + strlen(path_addr) + 1;
1198602ca9eaScth full_path = (char *)calloc(1, full_path_len);
1199602ca9eaScth
1200602ca9eaScth if (full_path != NULL)
1201602ca9eaScth (void) snprintf(full_path, full_path_len, "%s/%s@%s",
1202602ca9eaScth phci_path, path_name, path_addr);
1203602ca9eaScth di_devfs_path_free(phci_path);
1204602ca9eaScth return (full_path);
1205602ca9eaScth }
1206602ca9eaScth
1207602ca9eaScth char *
di_path_client_devfs_path(di_path_t path)1208602ca9eaScth di_path_client_devfs_path(di_path_t path)
1209602ca9eaScth {
1210602ca9eaScth return (di_devfs_path(di_path_client_node(path)));
1211602ca9eaScth }
1212602ca9eaScth
12137c478bd9Sstevel@tonic-gate void
di_devfs_path_free(char * buf)12147c478bd9Sstevel@tonic-gate di_devfs_path_free(char *buf)
12157c478bd9Sstevel@tonic-gate {
12167c478bd9Sstevel@tonic-gate if (buf == NULL) {
12177c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "di_devfs_path_free NULL arg!\n"));
12187c478bd9Sstevel@tonic-gate return;
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate free(buf);
12227c478bd9Sstevel@tonic-gate }
12237c478bd9Sstevel@tonic-gate
1224602ca9eaScth /*
1225602ca9eaScth * Return 1 if name is a IEEE-1275 generic name. If new generic
1226602ca9eaScth * names are defined, they should be added to this table
1227602ca9eaScth */
1228602ca9eaScth static int
is_generic(const char * name,int len)1229602ca9eaScth is_generic(const char *name, int len)
1230602ca9eaScth {
1231602ca9eaScth const char **gp;
1232602ca9eaScth
1233602ca9eaScth /* from IEEE-1275 recommended practices section 3 */
1234602ca9eaScth static const char *generic_names[] = {
1235602ca9eaScth "atm",
1236602ca9eaScth "disk",
1237602ca9eaScth "display",
1238602ca9eaScth "dma-controller",
1239602ca9eaScth "ethernet",
1240602ca9eaScth "fcs",
1241602ca9eaScth "fdc",
1242602ca9eaScth "fddi",
1243602ca9eaScth "fibre-channel",
1244602ca9eaScth "ide",
1245602ca9eaScth "interrupt-controller",
1246602ca9eaScth "isa",
1247602ca9eaScth "keyboard",
1248602ca9eaScth "memory",
1249602ca9eaScth "mouse",
1250602ca9eaScth "nvram",
1251602ca9eaScth "pc-card",
1252602ca9eaScth "pci",
1253602ca9eaScth "printer",
1254602ca9eaScth "rtc",
1255602ca9eaScth "sbus",
1256602ca9eaScth "scanner",
1257602ca9eaScth "scsi",
1258602ca9eaScth "serial",
1259602ca9eaScth "sound",
1260602ca9eaScth "ssa",
1261602ca9eaScth "tape",
1262602ca9eaScth "timer",
1263602ca9eaScth "token-ring",
1264602ca9eaScth "vme",
1265602ca9eaScth 0
1266602ca9eaScth };
1267602ca9eaScth
1268602ca9eaScth for (gp = generic_names; *gp; gp++) {
1269602ca9eaScth if ((strncmp(*gp, name, len) == 0) &&
1270602ca9eaScth (strlen(*gp) == len))
1271602ca9eaScth return (1);
1272602ca9eaScth }
1273602ca9eaScth return (0);
1274602ca9eaScth }
1275602ca9eaScth
1276602ca9eaScth /*
1277602ca9eaScth * Determine if two paths below /devices refer to the same device, ignoring
1278602ca9eaScth * any generic .vs. non-generic 'name' issues in "[[/]name[@addr[:minor]]]*".
1279602ca9eaScth * Return 1 if the paths match.
1280602ca9eaScth */
1281602ca9eaScth int
di_devfs_path_match(const char * dp1,const char * dp2)1282602ca9eaScth di_devfs_path_match(const char *dp1, const char *dp2)
1283602ca9eaScth {
1284602ca9eaScth const char *p1, *p2;
1285602ca9eaScth const char *ec1, *ec2;
1286602ca9eaScth const char *at1, *at2;
1287602ca9eaScth char nc;
1288602ca9eaScth int g1, g2;
1289602ca9eaScth
1290602ca9eaScth /* progress through both strings */
1291602ca9eaScth for (p1 = dp1, p2 = dp2; (*p1 == *p2) && *p1; p1++, p2++) {
1292602ca9eaScth /* require match until the start of a component */
1293602ca9eaScth if (*p1 != '/')
1294602ca9eaScth continue;
1295602ca9eaScth
1296602ca9eaScth /* advance p1 and p2 to start of 'name' in component */
1297602ca9eaScth nc = *(p1 + 1);
1298602ca9eaScth if ((nc == '\0') || (nc == '/'))
1299602ca9eaScth continue; /* skip trash */
1300602ca9eaScth p1++;
1301602ca9eaScth p2++;
1302602ca9eaScth
1303602ca9eaScth /*
1304602ca9eaScth * Both p1 and p2 point to beginning of 'name' in component.
1305602ca9eaScth * Determine where current component ends: next '/' or '\0'.
1306602ca9eaScth */
1307602ca9eaScth ec1 = strchr(p1, '/');
1308602ca9eaScth if (ec1 == NULL)
1309602ca9eaScth ec1 = p1 + strlen(p1);
1310602ca9eaScth ec2 = strchr(p2, '/');
1311602ca9eaScth if (ec2 == NULL)
1312602ca9eaScth ec2 = p2 + strlen(p2);
1313602ca9eaScth
1314602ca9eaScth /* Determine where name ends based on whether '@' exists */
1315602ca9eaScth at1 = strchr(p1, '@');
1316602ca9eaScth at2 = strchr(p2, '@');
1317602ca9eaScth if (at1 && (at1 < ec1))
1318602ca9eaScth ec1 = at1;
1319602ca9eaScth if (at2 && (at2 < ec2))
1320602ca9eaScth ec2 = at2;
1321602ca9eaScth
1322602ca9eaScth /*
1323602ca9eaScth * At this point p[12] point to beginning of name and
1324602ca9eaScth * ec[12] point to character past the end of name. Determine
1325602ca9eaScth * if the names are generic.
1326602ca9eaScth */
1327602ca9eaScth g1 = is_generic(p1, ec1 - p1);
1328602ca9eaScth g2 = is_generic(p2, ec2 - p2);
1329602ca9eaScth
1330602ca9eaScth if (g1 != g2) {
1331602ca9eaScth /*
1332602ca9eaScth * one generic and one non-generic
1333602ca9eaScth * skip past the names in the match.
1334602ca9eaScth */
1335602ca9eaScth p1 = ec1;
1336602ca9eaScth p2 = ec2;
1337602ca9eaScth } else {
1338602ca9eaScth if (*p1 != *p2)
1339602ca9eaScth break;
1340602ca9eaScth }
1341602ca9eaScth }
1342602ca9eaScth
1343602ca9eaScth return ((*p1 == *p2) ? 1 : 0);
1344602ca9eaScth }
1345602ca9eaScth
13467c478bd9Sstevel@tonic-gate /* minor data access */
13477c478bd9Sstevel@tonic-gate di_minor_t
di_minor_next(di_node_t node,di_minor_t minor)13487c478bd9Sstevel@tonic-gate di_minor_next(di_node_t node, di_minor_t minor)
13497c478bd9Sstevel@tonic-gate {
13507c478bd9Sstevel@tonic-gate caddr_t pa;
13517c478bd9Sstevel@tonic-gate
13527c478bd9Sstevel@tonic-gate /*
13537c478bd9Sstevel@tonic-gate * paranoid error checking
13547c478bd9Sstevel@tonic-gate */
13557c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
13567c478bd9Sstevel@tonic-gate errno = EINVAL;
13577c478bd9Sstevel@tonic-gate return (DI_MINOR_NIL);
13587c478bd9Sstevel@tonic-gate }
13597c478bd9Sstevel@tonic-gate
13607c478bd9Sstevel@tonic-gate /*
13617c478bd9Sstevel@tonic-gate * minor is not NIL
13627c478bd9Sstevel@tonic-gate */
13637c478bd9Sstevel@tonic-gate if (minor != DI_MINOR_NIL) {
13647c478bd9Sstevel@tonic-gate if (DI_MINOR(minor)->next != 0)
13657c478bd9Sstevel@tonic-gate return ((di_minor_t)((void *)((caddr_t)minor -
13667c478bd9Sstevel@tonic-gate DI_MINOR(minor)->self + DI_MINOR(minor)->next)));
13677c478bd9Sstevel@tonic-gate else {
13687c478bd9Sstevel@tonic-gate errno = ENXIO;
13697c478bd9Sstevel@tonic-gate return (DI_MINOR_NIL);
13707c478bd9Sstevel@tonic-gate }
13717c478bd9Sstevel@tonic-gate }
13727c478bd9Sstevel@tonic-gate
13737c478bd9Sstevel@tonic-gate /*
13747c478bd9Sstevel@tonic-gate * minor is NIL-->caller asks for first minor node
13757c478bd9Sstevel@tonic-gate */
13767c478bd9Sstevel@tonic-gate if (DI_NODE(node)->minor_data != 0) {
13777c478bd9Sstevel@tonic-gate return (DI_MINOR((caddr_t)node - DI_NODE(node)->self +
13787c478bd9Sstevel@tonic-gate DI_NODE(node)->minor_data));
13797c478bd9Sstevel@tonic-gate }
13807c478bd9Sstevel@tonic-gate
13817c478bd9Sstevel@tonic-gate /*
13827c478bd9Sstevel@tonic-gate * no minor data-->check if snapshot includes minor data
13837c478bd9Sstevel@tonic-gate * in order to set the correct errno
13847c478bd9Sstevel@tonic-gate */
13857c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
13867c478bd9Sstevel@tonic-gate if (DINFOMINOR & DI_ALL(pa)->command)
13877c478bd9Sstevel@tonic-gate errno = ENXIO;
13887c478bd9Sstevel@tonic-gate else
13897c478bd9Sstevel@tonic-gate errno = ENOTSUP;
13907c478bd9Sstevel@tonic-gate
13917c478bd9Sstevel@tonic-gate return (DI_MINOR_NIL);
13927c478bd9Sstevel@tonic-gate }
13937c478bd9Sstevel@tonic-gate
13947c478bd9Sstevel@tonic-gate /* private interface for dealing with alias minor link generation */
13957c478bd9Sstevel@tonic-gate di_node_t
di_minor_devinfo(di_minor_t minor)13967c478bd9Sstevel@tonic-gate di_minor_devinfo(di_minor_t minor)
13977c478bd9Sstevel@tonic-gate {
13987c478bd9Sstevel@tonic-gate if (minor == DI_MINOR_NIL) {
13997c478bd9Sstevel@tonic-gate errno = EINVAL;
14007c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
14017c478bd9Sstevel@tonic-gate }
14027c478bd9Sstevel@tonic-gate
14037c478bd9Sstevel@tonic-gate return (DI_NODE((caddr_t)minor - DI_MINOR(minor)->self +
14047c478bd9Sstevel@tonic-gate DI_MINOR(minor)->node));
14057c478bd9Sstevel@tonic-gate }
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate ddi_minor_type
di_minor_type(di_minor_t minor)14087c478bd9Sstevel@tonic-gate di_minor_type(di_minor_t minor)
14097c478bd9Sstevel@tonic-gate {
14107c478bd9Sstevel@tonic-gate return (DI_MINOR(minor)->type);
14117c478bd9Sstevel@tonic-gate }
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate char *
di_minor_name(di_minor_t minor)14147c478bd9Sstevel@tonic-gate di_minor_name(di_minor_t minor)
14157c478bd9Sstevel@tonic-gate {
14167c478bd9Sstevel@tonic-gate if (DI_MINOR(minor)->name == 0)
14177c478bd9Sstevel@tonic-gate return (NULL);
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate return ((caddr_t)minor - DI_MINOR(minor)->self + DI_MINOR(minor)->name);
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate
14227c478bd9Sstevel@tonic-gate dev_t
di_minor_devt(di_minor_t minor)14237c478bd9Sstevel@tonic-gate di_minor_devt(di_minor_t minor)
14247c478bd9Sstevel@tonic-gate {
14257c478bd9Sstevel@tonic-gate return (makedev(DI_MINOR(minor)->dev_major,
14267c478bd9Sstevel@tonic-gate DI_MINOR(minor)->dev_minor));
14277c478bd9Sstevel@tonic-gate }
14287c478bd9Sstevel@tonic-gate
14297c478bd9Sstevel@tonic-gate int
di_minor_spectype(di_minor_t minor)14307c478bd9Sstevel@tonic-gate di_minor_spectype(di_minor_t minor)
14317c478bd9Sstevel@tonic-gate {
14327c478bd9Sstevel@tonic-gate return (DI_MINOR(minor)->spec_type);
14337c478bd9Sstevel@tonic-gate }
14347c478bd9Sstevel@tonic-gate
14357c478bd9Sstevel@tonic-gate char *
di_minor_nodetype(di_minor_t minor)14367c478bd9Sstevel@tonic-gate di_minor_nodetype(di_minor_t minor)
14377c478bd9Sstevel@tonic-gate {
14387c478bd9Sstevel@tonic-gate if (DI_MINOR(minor)->node_type == 0)
14397c478bd9Sstevel@tonic-gate return (NULL);
14407c478bd9Sstevel@tonic-gate
14417c478bd9Sstevel@tonic-gate return ((caddr_t)minor -
14427c478bd9Sstevel@tonic-gate DI_MINOR(minor)->self + DI_MINOR(minor)->node_type);
14437c478bd9Sstevel@tonic-gate }
14447c478bd9Sstevel@tonic-gate
14457c478bd9Sstevel@tonic-gate /*
14467c478bd9Sstevel@tonic-gate * Single public interface for accessing software properties
14477c478bd9Sstevel@tonic-gate */
14487c478bd9Sstevel@tonic-gate di_prop_t
di_prop_next(di_node_t node,di_prop_t prop)14497c478bd9Sstevel@tonic-gate di_prop_next(di_node_t node, di_prop_t prop)
14507c478bd9Sstevel@tonic-gate {
14517c478bd9Sstevel@tonic-gate int list = DI_PROP_DRV_LIST;
14527c478bd9Sstevel@tonic-gate
14537c478bd9Sstevel@tonic-gate /*
14547c478bd9Sstevel@tonic-gate * paranoid check
14557c478bd9Sstevel@tonic-gate */
14567c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
14577c478bd9Sstevel@tonic-gate errno = EINVAL;
14587c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate
14617c478bd9Sstevel@tonic-gate /*
14627c478bd9Sstevel@tonic-gate * Find which prop list we are at
14637c478bd9Sstevel@tonic-gate */
14647c478bd9Sstevel@tonic-gate if (prop != DI_PROP_NIL)
14657c478bd9Sstevel@tonic-gate list = DI_PROP(prop)->prop_list;
14667c478bd9Sstevel@tonic-gate
14677c478bd9Sstevel@tonic-gate do {
14687c478bd9Sstevel@tonic-gate switch (list++) {
14697c478bd9Sstevel@tonic-gate case DI_PROP_DRV_LIST:
14707c478bd9Sstevel@tonic-gate prop = di_prop_drv_next(node, prop);
14717c478bd9Sstevel@tonic-gate break;
14727c478bd9Sstevel@tonic-gate case DI_PROP_SYS_LIST:
14737c478bd9Sstevel@tonic-gate prop = di_prop_sys_next(node, prop);
14747c478bd9Sstevel@tonic-gate break;
14757c478bd9Sstevel@tonic-gate case DI_PROP_GLB_LIST:
14767c478bd9Sstevel@tonic-gate prop = di_prop_global_next(node, prop);
14777c478bd9Sstevel@tonic-gate break;
14787c478bd9Sstevel@tonic-gate case DI_PROP_HW_LIST:
14797c478bd9Sstevel@tonic-gate prop = di_prop_hw_next(node, prop);
14807c478bd9Sstevel@tonic-gate break;
14817c478bd9Sstevel@tonic-gate default: /* shouldn't happen */
14827c478bd9Sstevel@tonic-gate errno = EFAULT;
14837c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
14847c478bd9Sstevel@tonic-gate }
14857c478bd9Sstevel@tonic-gate } while ((prop == DI_PROP_NIL) && (list <= DI_PROP_HW_LIST));
14867c478bd9Sstevel@tonic-gate
14877c478bd9Sstevel@tonic-gate return (prop);
14887c478bd9Sstevel@tonic-gate }
14897c478bd9Sstevel@tonic-gate
14907c478bd9Sstevel@tonic-gate dev_t
di_prop_devt(di_prop_t prop)14917c478bd9Sstevel@tonic-gate di_prop_devt(di_prop_t prop)
14927c478bd9Sstevel@tonic-gate {
14937c478bd9Sstevel@tonic-gate return (makedev(DI_PROP(prop)->dev_major, DI_PROP(prop)->dev_minor));
14947c478bd9Sstevel@tonic-gate }
14957c478bd9Sstevel@tonic-gate
14967c478bd9Sstevel@tonic-gate char *
di_prop_name(di_prop_t prop)14977c478bd9Sstevel@tonic-gate di_prop_name(di_prop_t prop)
14987c478bd9Sstevel@tonic-gate {
14997c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_name == 0)
15007c478bd9Sstevel@tonic-gate return (NULL);
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate return ((caddr_t)prop - DI_PROP(prop)->self + DI_PROP(prop)->prop_name);
15037c478bd9Sstevel@tonic-gate }
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate int
di_prop_type(di_prop_t prop)15067c478bd9Sstevel@tonic-gate di_prop_type(di_prop_t prop)
15077c478bd9Sstevel@tonic-gate {
15087c478bd9Sstevel@tonic-gate uint_t flags = DI_PROP(prop)->prop_flags;
15097c478bd9Sstevel@tonic-gate
15107c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_UNDEF_IT)
15117c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNDEF_IT);
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0)
15147c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_BOOLEAN);
15157c478bd9Sstevel@tonic-gate
15167c478bd9Sstevel@tonic-gate if ((flags & DDI_PROP_TYPE_MASK) == DDI_PROP_TYPE_ANY)
15177c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNKNOWN);
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_INT)
15207c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT);
15217c478bd9Sstevel@tonic-gate
15227c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_INT64)
15237c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT64);
15247c478bd9Sstevel@tonic-gate
15257c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_STRING)
15267c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_STRING);
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate if (flags & DDI_PROP_TYPE_BYTE)
15297c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_BYTE);
15307c478bd9Sstevel@tonic-gate
15317c478bd9Sstevel@tonic-gate /*
15327c478bd9Sstevel@tonic-gate * Shouldn't get here. In case we do, return unknown type.
15337c478bd9Sstevel@tonic-gate *
15347c478bd9Sstevel@tonic-gate * XXX--When DDI_PROP_TYPE_COMPOSITE is implemented, we need
15357c478bd9Sstevel@tonic-gate * to add DI_PROP_TYPE_COMPOSITE.
15367c478bd9Sstevel@tonic-gate */
15377c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "Unimplemented property type: 0x%x\n", flags));
15387c478bd9Sstevel@tonic-gate
15397c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNKNOWN);
15407c478bd9Sstevel@tonic-gate }
15417c478bd9Sstevel@tonic-gate
15427c478bd9Sstevel@tonic-gate /*
15437c478bd9Sstevel@tonic-gate * Extract type-specific values of an property
15447c478bd9Sstevel@tonic-gate */
15457c478bd9Sstevel@tonic-gate extern int di_prop_decode_common(void *prop_data, int len,
15467c478bd9Sstevel@tonic-gate int ddi_type, int prom);
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate int
di_prop_ints(di_prop_t prop,int ** prop_data)15497c478bd9Sstevel@tonic-gate di_prop_ints(di_prop_t prop, int **prop_data)
15507c478bd9Sstevel@tonic-gate {
15517c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0)
15527c478bd9Sstevel@tonic-gate return (0); /* boolean property */
15537c478bd9Sstevel@tonic-gate
15547c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) ||
15557c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) {
15567c478bd9Sstevel@tonic-gate errno = EFAULT;
15577c478bd9Sstevel@tonic-gate *prop_data = NULL;
15587c478bd9Sstevel@tonic-gate return (-1);
15597c478bd9Sstevel@tonic-gate }
15607c478bd9Sstevel@tonic-gate
15617c478bd9Sstevel@tonic-gate *prop_data = (int *)((void *)((caddr_t)prop - DI_PROP(prop)->self
15627c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data));
15637c478bd9Sstevel@tonic-gate
15647c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
15657c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_INT, 0));
15667c478bd9Sstevel@tonic-gate }
15677c478bd9Sstevel@tonic-gate
15687c478bd9Sstevel@tonic-gate int
di_prop_int64(di_prop_t prop,int64_t ** prop_data)15697c478bd9Sstevel@tonic-gate di_prop_int64(di_prop_t prop, int64_t **prop_data)
15707c478bd9Sstevel@tonic-gate {
15717c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0)
15727c478bd9Sstevel@tonic-gate return (0); /* boolean property */
15737c478bd9Sstevel@tonic-gate
15747c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) ||
15757c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) {
15767c478bd9Sstevel@tonic-gate errno = EFAULT;
15777c478bd9Sstevel@tonic-gate *prop_data = NULL;
15787c478bd9Sstevel@tonic-gate return (-1);
15797c478bd9Sstevel@tonic-gate }
15807c478bd9Sstevel@tonic-gate
15817c478bd9Sstevel@tonic-gate *prop_data = (int64_t *)((void *)((caddr_t)prop - DI_PROP(prop)->self
15827c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data));
15837c478bd9Sstevel@tonic-gate
15847c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
15857c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_INT64, 0));
15867c478bd9Sstevel@tonic-gate }
15877c478bd9Sstevel@tonic-gate
15887c478bd9Sstevel@tonic-gate int
di_prop_strings(di_prop_t prop,char ** prop_data)15897c478bd9Sstevel@tonic-gate di_prop_strings(di_prop_t prop, char **prop_data)
15907c478bd9Sstevel@tonic-gate {
15917c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0)
15927c478bd9Sstevel@tonic-gate return (0); /* boolean property */
15937c478bd9Sstevel@tonic-gate
15947c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) ||
15957c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) {
15967c478bd9Sstevel@tonic-gate errno = EFAULT;
15977c478bd9Sstevel@tonic-gate *prop_data = NULL;
15987c478bd9Sstevel@tonic-gate return (-1);
15997c478bd9Sstevel@tonic-gate }
16007c478bd9Sstevel@tonic-gate
16017c478bd9Sstevel@tonic-gate *prop_data = (char *)((caddr_t)prop - DI_PROP(prop)->self
16027c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data);
16037c478bd9Sstevel@tonic-gate
16047c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
16057c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_STRING, 0));
16067c478bd9Sstevel@tonic-gate }
16077c478bd9Sstevel@tonic-gate
16087c478bd9Sstevel@tonic-gate int
di_prop_bytes(di_prop_t prop,uchar_t ** prop_data)16097c478bd9Sstevel@tonic-gate di_prop_bytes(di_prop_t prop, uchar_t **prop_data)
16107c478bd9Sstevel@tonic-gate {
16117c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0)
16127c478bd9Sstevel@tonic-gate return (0); /* boolean property */
16137c478bd9Sstevel@tonic-gate
16147c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) ||
16157c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) {
16167c478bd9Sstevel@tonic-gate errno = EFAULT;
16177c478bd9Sstevel@tonic-gate *prop_data = NULL;
16187c478bd9Sstevel@tonic-gate return (-1);
16197c478bd9Sstevel@tonic-gate }
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate *prop_data = (uchar_t *)((caddr_t)prop - DI_PROP(prop)->self
16227c478bd9Sstevel@tonic-gate + DI_PROP(prop)->prop_data);
16237c478bd9Sstevel@tonic-gate
16247c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
16257c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_len, DI_PROP_TYPE_BYTE, 0));
16267c478bd9Sstevel@tonic-gate }
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gate /*
16297c478bd9Sstevel@tonic-gate * returns 1 for match, 0 for no match
16307c478bd9Sstevel@tonic-gate */
16317c478bd9Sstevel@tonic-gate static int
match_prop(di_prop_t prop,dev_t match_dev,const char * name,int type)16327c478bd9Sstevel@tonic-gate match_prop(di_prop_t prop, dev_t match_dev, const char *name, int type)
16337c478bd9Sstevel@tonic-gate {
16347c478bd9Sstevel@tonic-gate int prop_type;
16357c478bd9Sstevel@tonic-gate
16367c478bd9Sstevel@tonic-gate #ifdef DEBUG
16377c478bd9Sstevel@tonic-gate if (di_prop_name(prop) == NULL) {
16387c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "libdevinfo: property has no name!\n"));
16397c478bd9Sstevel@tonic-gate return (0);
16407c478bd9Sstevel@tonic-gate }
16417c478bd9Sstevel@tonic-gate #endif /* DEBUG */
16427c478bd9Sstevel@tonic-gate
16437c478bd9Sstevel@tonic-gate if (strcmp(name, di_prop_name(prop)) != 0)
16447c478bd9Sstevel@tonic-gate return (0);
16457c478bd9Sstevel@tonic-gate
16467c478bd9Sstevel@tonic-gate if ((match_dev != DDI_DEV_T_ANY) && (di_prop_devt(prop) != match_dev))
16477c478bd9Sstevel@tonic-gate return (0);
16487c478bd9Sstevel@tonic-gate
16497c478bd9Sstevel@tonic-gate /*
16507c478bd9Sstevel@tonic-gate * XXX prop_type is different from DDI_*. See PSARC 1997/127.
16517c478bd9Sstevel@tonic-gate */
16527c478bd9Sstevel@tonic-gate prop_type = di_prop_type(prop);
16537c478bd9Sstevel@tonic-gate if ((prop_type != DI_PROP_TYPE_UNKNOWN) && (prop_type != type) &&
16547c478bd9Sstevel@tonic-gate (prop_type != DI_PROP_TYPE_BOOLEAN))
16557c478bd9Sstevel@tonic-gate return (0);
16567c478bd9Sstevel@tonic-gate
16577c478bd9Sstevel@tonic-gate return (1);
16587c478bd9Sstevel@tonic-gate }
16597c478bd9Sstevel@tonic-gate
16607c478bd9Sstevel@tonic-gate static di_prop_t
di_prop_search(dev_t match_dev,di_node_t node,const char * name,int type)16617c478bd9Sstevel@tonic-gate di_prop_search(dev_t match_dev, di_node_t node, const char *name,
16627c478bd9Sstevel@tonic-gate int type)
16637c478bd9Sstevel@tonic-gate {
16647c478bd9Sstevel@tonic-gate di_prop_t prop = DI_PROP_NIL;
16657c478bd9Sstevel@tonic-gate
16667c478bd9Sstevel@tonic-gate /*
16677c478bd9Sstevel@tonic-gate * The check on match_dev follows ddi_prop_lookup_common().
16687c478bd9Sstevel@tonic-gate * Other checks are libdevinfo specific implementation.
16697c478bd9Sstevel@tonic-gate */
16707c478bd9Sstevel@tonic-gate if ((node == DI_NODE_NIL) || (name == NULL) || (strlen(name) == 0) ||
16717c478bd9Sstevel@tonic-gate (match_dev == DDI_DEV_T_NONE) || !DI_PROP_TYPE_VALID(type)) {
16727c478bd9Sstevel@tonic-gate errno = EINVAL;
16737c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
16747c478bd9Sstevel@tonic-gate }
16757c478bd9Sstevel@tonic-gate
16767c478bd9Sstevel@tonic-gate while ((prop = di_prop_next(node, prop)) != DI_PROP_NIL) {
16777c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "match prop name %s, devt 0x%lx, type %d\n",
16787c478bd9Sstevel@tonic-gate di_prop_name(prop), di_prop_devt(prop),
16797c478bd9Sstevel@tonic-gate di_prop_type(prop)));
16807c478bd9Sstevel@tonic-gate if (match_prop(prop, match_dev, name, type))
16817c478bd9Sstevel@tonic-gate return (prop);
16827c478bd9Sstevel@tonic-gate }
16837c478bd9Sstevel@tonic-gate
16847c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate
16873ebafc43Sjveta di_prop_t
di_prop_find(dev_t match_dev,di_node_t node,const char * name)16883ebafc43Sjveta di_prop_find(dev_t match_dev, di_node_t node, const char *name)
16893ebafc43Sjveta {
16903ebafc43Sjveta di_prop_t prop = DI_PROP_NIL;
16913ebafc43Sjveta
16923ebafc43Sjveta if ((node == DI_NODE_NIL) || (name == NULL) || (strlen(name) == 0) ||
16933ebafc43Sjveta (match_dev == DDI_DEV_T_NONE)) {
16943ebafc43Sjveta errno = EINVAL;
16953ebafc43Sjveta return (DI_PROP_NIL);
16963ebafc43Sjveta }
16973ebafc43Sjveta
16983ebafc43Sjveta while ((prop = di_prop_next(node, prop)) != DI_PROP_NIL) {
16993ebafc43Sjveta DPRINTF((DI_TRACE1, "found prop name %s, devt 0x%lx, type %d\n",
17003ebafc43Sjveta di_prop_name(prop), di_prop_devt(prop),
17013ebafc43Sjveta di_prop_type(prop)));
17023ebafc43Sjveta
17033ebafc43Sjveta if (strcmp(name, di_prop_name(prop)) == 0 &&
17043ebafc43Sjveta (match_dev == DDI_DEV_T_ANY ||
17053ebafc43Sjveta di_prop_devt(prop) == match_dev))
17063ebafc43Sjveta return (prop);
17073ebafc43Sjveta }
17083ebafc43Sjveta
17093ebafc43Sjveta return (DI_PROP_NIL);
17103ebafc43Sjveta }
17113ebafc43Sjveta
17127c478bd9Sstevel@tonic-gate int
di_prop_lookup_ints(dev_t dev,di_node_t node,const char * prop_name,int ** prop_data)17137c478bd9Sstevel@tonic-gate di_prop_lookup_ints(dev_t dev, di_node_t node, const char *prop_name,
17147c478bd9Sstevel@tonic-gate int **prop_data)
17157c478bd9Sstevel@tonic-gate {
17167c478bd9Sstevel@tonic-gate di_prop_t prop;
17177c478bd9Sstevel@tonic-gate
17187c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name,
17197c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT)) == DI_PROP_NIL)
17207c478bd9Sstevel@tonic-gate return (-1);
17217c478bd9Sstevel@tonic-gate
17227c478bd9Sstevel@tonic-gate return (di_prop_ints(prop, (void *)prop_data));
17237c478bd9Sstevel@tonic-gate }
17247c478bd9Sstevel@tonic-gate
17257c478bd9Sstevel@tonic-gate int
di_prop_lookup_int64(dev_t dev,di_node_t node,const char * prop_name,int64_t ** prop_data)17267c478bd9Sstevel@tonic-gate di_prop_lookup_int64(dev_t dev, di_node_t node, const char *prop_name,
17277c478bd9Sstevel@tonic-gate int64_t **prop_data)
17287c478bd9Sstevel@tonic-gate {
17297c478bd9Sstevel@tonic-gate di_prop_t prop;
17307c478bd9Sstevel@tonic-gate
17317c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name,
17327c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT64)) == DI_PROP_NIL)
17337c478bd9Sstevel@tonic-gate return (-1);
17347c478bd9Sstevel@tonic-gate
17357c478bd9Sstevel@tonic-gate return (di_prop_int64(prop, (void *)prop_data));
17367c478bd9Sstevel@tonic-gate }
17377c478bd9Sstevel@tonic-gate
17387c478bd9Sstevel@tonic-gate int
di_prop_lookup_strings(dev_t dev,di_node_t node,const char * prop_name,char ** prop_data)17397c478bd9Sstevel@tonic-gate di_prop_lookup_strings(dev_t dev, di_node_t node, const char *prop_name,
17407c478bd9Sstevel@tonic-gate char **prop_data)
17417c478bd9Sstevel@tonic-gate {
17427c478bd9Sstevel@tonic-gate di_prop_t prop;
17437c478bd9Sstevel@tonic-gate
17447c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name,
17457c478bd9Sstevel@tonic-gate DI_PROP_TYPE_STRING)) == DI_PROP_NIL)
17467c478bd9Sstevel@tonic-gate return (-1);
17477c478bd9Sstevel@tonic-gate
17487c478bd9Sstevel@tonic-gate return (di_prop_strings(prop, (void *)prop_data));
17497c478bd9Sstevel@tonic-gate }
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate int
di_prop_lookup_bytes(dev_t dev,di_node_t node,const char * prop_name,uchar_t ** prop_data)17527c478bd9Sstevel@tonic-gate di_prop_lookup_bytes(dev_t dev, di_node_t node, const char *prop_name,
17537c478bd9Sstevel@tonic-gate uchar_t **prop_data)
17547c478bd9Sstevel@tonic-gate {
17557c478bd9Sstevel@tonic-gate di_prop_t prop;
17567c478bd9Sstevel@tonic-gate
17577c478bd9Sstevel@tonic-gate if ((prop = di_prop_search(dev, node, prop_name,
17587c478bd9Sstevel@tonic-gate DI_PROP_TYPE_BYTE)) == DI_PROP_NIL)
17597c478bd9Sstevel@tonic-gate return (-1);
17607c478bd9Sstevel@tonic-gate
17617c478bd9Sstevel@tonic-gate return (di_prop_bytes(prop, (void *)prop_data));
17627c478bd9Sstevel@tonic-gate }
17637c478bd9Sstevel@tonic-gate
17647c478bd9Sstevel@tonic-gate /*
17657c478bd9Sstevel@tonic-gate * Consolidation private property access functions
17667c478bd9Sstevel@tonic-gate */
17677c478bd9Sstevel@tonic-gate enum prop_type {
17687c478bd9Sstevel@tonic-gate PROP_TYPE_DRV,
17697c478bd9Sstevel@tonic-gate PROP_TYPE_SYS,
17707c478bd9Sstevel@tonic-gate PROP_TYPE_GLOB,
17717c478bd9Sstevel@tonic-gate PROP_TYPE_HW
17727c478bd9Sstevel@tonic-gate };
17737c478bd9Sstevel@tonic-gate
17747c478bd9Sstevel@tonic-gate static di_prop_t
di_prop_next_common(di_node_t node,di_prop_t prop,int prop_type)17757c478bd9Sstevel@tonic-gate di_prop_next_common(di_node_t node, di_prop_t prop, int prop_type)
17767c478bd9Sstevel@tonic-gate {
17777c478bd9Sstevel@tonic-gate caddr_t pa;
17787c478bd9Sstevel@tonic-gate di_off_t prop_off = 0;
17797c478bd9Sstevel@tonic-gate
17807c478bd9Sstevel@tonic-gate if (prop != DI_PROP_NIL) {
17817c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->next) {
17827c478bd9Sstevel@tonic-gate return (DI_PROP((caddr_t)prop -
17837c478bd9Sstevel@tonic-gate DI_PROP(prop)->self + DI_PROP(prop)->next));
17847c478bd9Sstevel@tonic-gate } else {
17857c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
17867c478bd9Sstevel@tonic-gate }
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate
17897c478bd9Sstevel@tonic-gate
17907c478bd9Sstevel@tonic-gate /*
17917c478bd9Sstevel@tonic-gate * prop is NIL, caller asks for first property
17927c478bd9Sstevel@tonic-gate */
17937c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
17947c478bd9Sstevel@tonic-gate switch (prop_type) {
17957c478bd9Sstevel@tonic-gate case PROP_TYPE_DRV:
17967c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->drv_prop;
17977c478bd9Sstevel@tonic-gate break;
17987c478bd9Sstevel@tonic-gate case PROP_TYPE_SYS:
17997c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->sys_prop;
18007c478bd9Sstevel@tonic-gate break;
18017c478bd9Sstevel@tonic-gate case PROP_TYPE_HW:
18027c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->hw_prop;
18037c478bd9Sstevel@tonic-gate break;
18047c478bd9Sstevel@tonic-gate case PROP_TYPE_GLOB:
18057c478bd9Sstevel@tonic-gate prop_off = DI_NODE(node)->glob_prop;
18067c478bd9Sstevel@tonic-gate if (prop_off == -1) {
18077c478bd9Sstevel@tonic-gate /* no global property */
18087c478bd9Sstevel@tonic-gate prop_off = 0;
18097c478bd9Sstevel@tonic-gate } else if ((prop_off == 0) && (DI_NODE(node)->drv_major >= 0)) {
18107c478bd9Sstevel@tonic-gate /* refer to devnames array */
18117c478bd9Sstevel@tonic-gate struct di_devnm *devnm = DI_DEVNM(pa +
18127c478bd9Sstevel@tonic-gate DI_ALL(pa)->devnames + (DI_NODE(node)->drv_major *
18137c478bd9Sstevel@tonic-gate sizeof (struct di_devnm)));
18147c478bd9Sstevel@tonic-gate prop_off = devnm->global_prop;
18157c478bd9Sstevel@tonic-gate }
18167c478bd9Sstevel@tonic-gate break;
18177c478bd9Sstevel@tonic-gate }
18187c478bd9Sstevel@tonic-gate
18197c478bd9Sstevel@tonic-gate if (prop_off) {
18207c478bd9Sstevel@tonic-gate return (DI_PROP(pa + prop_off));
18217c478bd9Sstevel@tonic-gate }
18227c478bd9Sstevel@tonic-gate
18237c478bd9Sstevel@tonic-gate /*
18247c478bd9Sstevel@tonic-gate * no prop found. Check the reason for not found
18257c478bd9Sstevel@tonic-gate */
18267c478bd9Sstevel@tonic-gate if (DINFOPROP & DI_ALL(pa)->command)
18277c478bd9Sstevel@tonic-gate errno = ENXIO;
18287c478bd9Sstevel@tonic-gate else
18297c478bd9Sstevel@tonic-gate errno = ENOTSUP;
18307c478bd9Sstevel@tonic-gate
18317c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
18327c478bd9Sstevel@tonic-gate }
18337c478bd9Sstevel@tonic-gate
18347c478bd9Sstevel@tonic-gate di_prop_t
di_prop_drv_next(di_node_t node,di_prop_t prop)18357c478bd9Sstevel@tonic-gate di_prop_drv_next(di_node_t node, di_prop_t prop)
18367c478bd9Sstevel@tonic-gate {
18377c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_DRV));
18387c478bd9Sstevel@tonic-gate }
18397c478bd9Sstevel@tonic-gate
18407c478bd9Sstevel@tonic-gate di_prop_t
di_prop_sys_next(di_node_t node,di_prop_t prop)18417c478bd9Sstevel@tonic-gate di_prop_sys_next(di_node_t node, di_prop_t prop)
18427c478bd9Sstevel@tonic-gate {
18437c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_SYS));
18447c478bd9Sstevel@tonic-gate }
18457c478bd9Sstevel@tonic-gate
18467c478bd9Sstevel@tonic-gate di_prop_t
di_prop_global_next(di_node_t node,di_prop_t prop)18477c478bd9Sstevel@tonic-gate di_prop_global_next(di_node_t node, di_prop_t prop)
18487c478bd9Sstevel@tonic-gate {
18497c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_GLOB));
18507c478bd9Sstevel@tonic-gate }
18517c478bd9Sstevel@tonic-gate
18527c478bd9Sstevel@tonic-gate di_prop_t
di_prop_hw_next(di_node_t node,di_prop_t prop)18537c478bd9Sstevel@tonic-gate di_prop_hw_next(di_node_t node, di_prop_t prop)
18547c478bd9Sstevel@tonic-gate {
18557c478bd9Sstevel@tonic-gate return (di_prop_next_common(node, prop, PROP_TYPE_HW));
18567c478bd9Sstevel@tonic-gate }
18577c478bd9Sstevel@tonic-gate
18587c478bd9Sstevel@tonic-gate int
di_prop_rawdata(di_prop_t prop,uchar_t ** prop_data)18597c478bd9Sstevel@tonic-gate di_prop_rawdata(di_prop_t prop, uchar_t **prop_data)
18607c478bd9Sstevel@tonic-gate {
18617c478bd9Sstevel@tonic-gate #ifdef DEBUG
18627c478bd9Sstevel@tonic-gate if (prop == DI_PROP_NIL) {
18637c478bd9Sstevel@tonic-gate errno = EINVAL;
18647c478bd9Sstevel@tonic-gate return (-1);
18657c478bd9Sstevel@tonic-gate }
18667c478bd9Sstevel@tonic-gate #endif /* DEBUG */
18677c478bd9Sstevel@tonic-gate
18687c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->prop_len == 0) {
18697c478bd9Sstevel@tonic-gate *prop_data = NULL;
18707c478bd9Sstevel@tonic-gate return (0);
18717c478bd9Sstevel@tonic-gate }
18727c478bd9Sstevel@tonic-gate
18737c478bd9Sstevel@tonic-gate if ((DI_PROP(prop)->prop_data == 0) ||
18747c478bd9Sstevel@tonic-gate (DI_PROP(prop)->prop_data == (di_off_t)-1)) {
18757c478bd9Sstevel@tonic-gate errno = EFAULT;
18767c478bd9Sstevel@tonic-gate *prop_data = NULL;
18777c478bd9Sstevel@tonic-gate return (-1);
18787c478bd9Sstevel@tonic-gate }
18797c478bd9Sstevel@tonic-gate
18807c478bd9Sstevel@tonic-gate /*
18817c478bd9Sstevel@tonic-gate * No memory allocation.
18827c478bd9Sstevel@tonic-gate */
18837c478bd9Sstevel@tonic-gate *prop_data = (uchar_t *)((caddr_t)prop - DI_PROP(prop)->self +
18847c478bd9Sstevel@tonic-gate DI_PROP(prop)->prop_data);
18857c478bd9Sstevel@tonic-gate
18867c478bd9Sstevel@tonic-gate return (DI_PROP(prop)->prop_len);
18877c478bd9Sstevel@tonic-gate }
18887c478bd9Sstevel@tonic-gate
18897c478bd9Sstevel@tonic-gate /*
18907c478bd9Sstevel@tonic-gate * Consolidation private interfaces for accessing I/O multipathing data
18917c478bd9Sstevel@tonic-gate */
18927c478bd9Sstevel@tonic-gate di_path_t
di_path_phci_next_path(di_node_t node,di_path_t path)1893602ca9eaScth di_path_phci_next_path(di_node_t node, di_path_t path)
18947c478bd9Sstevel@tonic-gate {
18957c478bd9Sstevel@tonic-gate caddr_t pa;
18967c478bd9Sstevel@tonic-gate
18977c478bd9Sstevel@tonic-gate /*
18987c478bd9Sstevel@tonic-gate * path is not NIL
18997c478bd9Sstevel@tonic-gate */
19007c478bd9Sstevel@tonic-gate if (path != DI_PATH_NIL) {
19017c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_p_link != 0)
19027c478bd9Sstevel@tonic-gate return (DI_PATH((void *)((caddr_t)path -
19037c478bd9Sstevel@tonic-gate DI_PATH(path)->self + DI_PATH(path)->path_p_link)));
19047c478bd9Sstevel@tonic-gate else {
19057c478bd9Sstevel@tonic-gate errno = ENXIO;
19067c478bd9Sstevel@tonic-gate return (DI_PATH_NIL);
19077c478bd9Sstevel@tonic-gate }
19087c478bd9Sstevel@tonic-gate }
19097c478bd9Sstevel@tonic-gate
19107c478bd9Sstevel@tonic-gate /*
19117c478bd9Sstevel@tonic-gate * Path is NIL; the caller is asking for the first path info node
19127c478bd9Sstevel@tonic-gate */
19137c478bd9Sstevel@tonic-gate if (DI_NODE(node)->multipath_phci != 0) {
1914602ca9eaScth DPRINTF((DI_INFO, "phci_next_path: returning %p\n",
1915602ca9eaScth ((caddr_t)node -
19167c478bd9Sstevel@tonic-gate DI_NODE(node)->self + DI_NODE(node)->multipath_phci)));
19177c478bd9Sstevel@tonic-gate return (DI_PATH((caddr_t)node - DI_NODE(node)->self +
19187c478bd9Sstevel@tonic-gate DI_NODE(node)->multipath_phci));
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate
19217c478bd9Sstevel@tonic-gate /*
19227c478bd9Sstevel@tonic-gate * No pathing data; check if the snapshot includes path data in order
19237c478bd9Sstevel@tonic-gate * to set errno properly.
19247c478bd9Sstevel@tonic-gate */
19257c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
19267c478bd9Sstevel@tonic-gate if (DINFOPATH & (DI_ALL(pa)->command))
19277c478bd9Sstevel@tonic-gate errno = ENXIO;
19287c478bd9Sstevel@tonic-gate else
19297c478bd9Sstevel@tonic-gate errno = ENOTSUP;
19307c478bd9Sstevel@tonic-gate
19317c478bd9Sstevel@tonic-gate return (DI_PATH_NIL);
19327c478bd9Sstevel@tonic-gate }
19337c478bd9Sstevel@tonic-gate
19347c478bd9Sstevel@tonic-gate di_path_t
di_path_client_next_path(di_node_t node,di_path_t path)1935602ca9eaScth di_path_client_next_path(di_node_t node, di_path_t path)
19367c478bd9Sstevel@tonic-gate {
19377c478bd9Sstevel@tonic-gate caddr_t pa;
19387c478bd9Sstevel@tonic-gate
19397c478bd9Sstevel@tonic-gate /*
19407c478bd9Sstevel@tonic-gate * path is not NIL
19417c478bd9Sstevel@tonic-gate */
19427c478bd9Sstevel@tonic-gate if (path != DI_PATH_NIL) {
19437c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_c_link != 0)
19447c478bd9Sstevel@tonic-gate return (DI_PATH((caddr_t)path - DI_PATH(path)->self
19457c478bd9Sstevel@tonic-gate + DI_PATH(path)->path_c_link));
19467c478bd9Sstevel@tonic-gate else {
19477c478bd9Sstevel@tonic-gate errno = ENXIO;
19487c478bd9Sstevel@tonic-gate return (DI_PATH_NIL);
19497c478bd9Sstevel@tonic-gate }
19507c478bd9Sstevel@tonic-gate }
19517c478bd9Sstevel@tonic-gate
19527c478bd9Sstevel@tonic-gate /*
19537c478bd9Sstevel@tonic-gate * Path is NIL; the caller is asking for the first path info node
19547c478bd9Sstevel@tonic-gate */
19557c478bd9Sstevel@tonic-gate if (DI_NODE(node)->multipath_client != 0) {
1956602ca9eaScth DPRINTF((DI_INFO, "client_next_path: returning %p\n",
1957602ca9eaScth ((caddr_t)node -
19587c478bd9Sstevel@tonic-gate DI_NODE(node)->self + DI_NODE(node)->multipath_client)));
19597c478bd9Sstevel@tonic-gate return (DI_PATH((caddr_t)node - DI_NODE(node)->self +
19607c478bd9Sstevel@tonic-gate DI_NODE(node)->multipath_client));
19617c478bd9Sstevel@tonic-gate }
19627c478bd9Sstevel@tonic-gate
19637c478bd9Sstevel@tonic-gate /*
19647c478bd9Sstevel@tonic-gate * No pathing data; check if the snapshot includes path data in order
19657c478bd9Sstevel@tonic-gate * to set errno properly.
19667c478bd9Sstevel@tonic-gate */
19677c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
19687c478bd9Sstevel@tonic-gate if (DINFOPATH & (DI_ALL(pa)->command))
19697c478bd9Sstevel@tonic-gate errno = ENXIO;
19707c478bd9Sstevel@tonic-gate else
19717c478bd9Sstevel@tonic-gate errno = ENOTSUP;
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate return (DI_PATH_NIL);
19747c478bd9Sstevel@tonic-gate }
19757c478bd9Sstevel@tonic-gate
19767c478bd9Sstevel@tonic-gate /*
1977602ca9eaScth * XXX Remove the private di_path_(addr,next,next_phci,next_client) interfaces
1978602ca9eaScth * below after NWS consolidation switches to using di_path_bus_addr,
1979602ca9eaScth * di_path_phci_next_path, and di_path_client_next_path per CR6638521.
19807c478bd9Sstevel@tonic-gate */
19817c478bd9Sstevel@tonic-gate char *
di_path_addr(di_path_t path,char * buf)19827c478bd9Sstevel@tonic-gate di_path_addr(di_path_t path, char *buf)
19837c478bd9Sstevel@tonic-gate {
19847c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
19857c478bd9Sstevel@tonic-gate
19867c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self;
19877c478bd9Sstevel@tonic-gate
19887c478bd9Sstevel@tonic-gate (void) strncpy(buf, (char *)(pa + DI_PATH(path)->path_addr),
19897c478bd9Sstevel@tonic-gate MAXPATHLEN);
19907c478bd9Sstevel@tonic-gate return (buf);
19917c478bd9Sstevel@tonic-gate }
1992602ca9eaScth di_path_t
di_path_next(di_node_t node,di_path_t path)1993602ca9eaScth di_path_next(di_node_t node, di_path_t path)
1994602ca9eaScth {
1995602ca9eaScth if (node == DI_NODE_NIL) {
1996602ca9eaScth errno = EINVAL;
1997602ca9eaScth return (DI_PATH_NIL);
1998602ca9eaScth }
1999602ca9eaScth
2000602ca9eaScth if (DI_NODE(node)->multipath_client) {
2001602ca9eaScth return (di_path_client_next_path(node, path));
2002602ca9eaScth } else if (DI_NODE(node)->multipath_phci) {
2003602ca9eaScth return (di_path_phci_next_path(node, path));
2004602ca9eaScth } else {
2005602ca9eaScth /*
2006602ca9eaScth * The node had multipathing data but didn't appear to be a
2007602ca9eaScth * phci *or* a client; probably a programmer error.
2008602ca9eaScth */
2009602ca9eaScth errno = EINVAL;
2010602ca9eaScth return (DI_PATH_NIL);
2011602ca9eaScth }
2012602ca9eaScth }
2013602ca9eaScth di_path_t
di_path_next_phci(di_node_t node,di_path_t path)2014602ca9eaScth di_path_next_phci(di_node_t node, di_path_t path)
2015602ca9eaScth {
2016602ca9eaScth return (di_path_client_next_path(node, path));
2017602ca9eaScth }
2018602ca9eaScth di_path_t
di_path_next_client(di_node_t node,di_path_t path)2019602ca9eaScth di_path_next_client(di_node_t node, di_path_t path)
2020602ca9eaScth {
2021602ca9eaScth return (di_path_phci_next_path(node, path));
2022602ca9eaScth }
2023602ca9eaScth
2024602ca9eaScth
2025602ca9eaScth
2026602ca9eaScth
2027602ca9eaScth di_path_state_t
di_path_state(di_path_t path)2028602ca9eaScth di_path_state(di_path_t path)
2029602ca9eaScth {
2030602ca9eaScth return ((di_path_state_t)DI_PATH(path)->path_state);
2031602ca9eaScth }
2032602ca9eaScth
20334c06356bSdh142964 uint_t
di_path_flags(di_path_t path)20344c06356bSdh142964 di_path_flags(di_path_t path)
20354c06356bSdh142964 {
20364c06356bSdh142964 return (DI_PATH(path)->path_flags);
20374c06356bSdh142964 }
20384c06356bSdh142964
2039602ca9eaScth char *
di_path_node_name(di_path_t path)2040602ca9eaScth di_path_node_name(di_path_t path)
2041602ca9eaScth {
2042602ca9eaScth di_node_t client_node;
2043602ca9eaScth
2044602ca9eaScth /* pathinfo gets node_name from client */
2045602ca9eaScth if ((client_node = di_path_client_node(path)) == NULL)
2046602ca9eaScth return (NULL);
2047602ca9eaScth return (di_node_name(client_node));
2048602ca9eaScth }
2049602ca9eaScth
2050602ca9eaScth char *
di_path_bus_addr(di_path_t path)2051602ca9eaScth di_path_bus_addr(di_path_t path)
2052602ca9eaScth {
2053602ca9eaScth caddr_t pa = (caddr_t)path - DI_PATH(path)->self;
2054602ca9eaScth
2055602ca9eaScth if (DI_PATH(path)->path_addr == 0)
2056602ca9eaScth return (NULL);
2057602ca9eaScth
2058602ca9eaScth return ((char *)(pa + DI_PATH(path)->path_addr));
2059602ca9eaScth }
2060602ca9eaScth
2061602ca9eaScth int
di_path_instance(di_path_t path)2062602ca9eaScth di_path_instance(di_path_t path)
2063602ca9eaScth {
2064602ca9eaScth return (DI_PATH(path)->path_instance);
2065602ca9eaScth }
20667c478bd9Sstevel@tonic-gate
20677c478bd9Sstevel@tonic-gate di_node_t
di_path_client_node(di_path_t path)20687c478bd9Sstevel@tonic-gate di_path_client_node(di_path_t path)
20697c478bd9Sstevel@tonic-gate {
20707c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
20717c478bd9Sstevel@tonic-gate
20727c478bd9Sstevel@tonic-gate if (path == DI_PATH_NIL) {
20737c478bd9Sstevel@tonic-gate errno = EINVAL;
20747c478bd9Sstevel@tonic-gate return (DI_PATH_NIL);
20757c478bd9Sstevel@tonic-gate }
20767c478bd9Sstevel@tonic-gate
20777c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get client node for path %p\n", path));
20787c478bd9Sstevel@tonic-gate
20797c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self;
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_client) {
20827c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_PATH(path)->path_client));
20837c478bd9Sstevel@tonic-gate }
20847c478bd9Sstevel@tonic-gate
20857c478bd9Sstevel@tonic-gate /*
20867c478bd9Sstevel@tonic-gate * Deal with error condition:
20877c478bd9Sstevel@tonic-gate * If parent doesn't exist and node is not the root,
20887c478bd9Sstevel@tonic-gate * set errno to ENOTSUP. Otherwise, set errno to ENXIO.
20897c478bd9Sstevel@tonic-gate */
20907c478bd9Sstevel@tonic-gate if ((DI_PATH(path)->path_snap_state & DI_PATH_SNAP_NOCLIENT) == 0)
20917c478bd9Sstevel@tonic-gate errno = ENOTSUP;
20927c478bd9Sstevel@tonic-gate else
20937c478bd9Sstevel@tonic-gate errno = ENXIO;
20947c478bd9Sstevel@tonic-gate
20957c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
20967c478bd9Sstevel@tonic-gate }
20977c478bd9Sstevel@tonic-gate
20987c478bd9Sstevel@tonic-gate di_node_t
di_path_phci_node(di_path_t path)20997c478bd9Sstevel@tonic-gate di_path_phci_node(di_path_t path)
21007c478bd9Sstevel@tonic-gate {
21017c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
21027c478bd9Sstevel@tonic-gate
21037c478bd9Sstevel@tonic-gate if (path == DI_PATH_NIL) {
21047c478bd9Sstevel@tonic-gate errno = EINVAL;
21057c478bd9Sstevel@tonic-gate return (DI_PATH_NIL);
21067c478bd9Sstevel@tonic-gate }
21077c478bd9Sstevel@tonic-gate
21087c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Get phci node for path %p\n", path));
21097c478bd9Sstevel@tonic-gate
21107c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self;
21117c478bd9Sstevel@tonic-gate
21127c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_phci) {
21137c478bd9Sstevel@tonic-gate return (DI_NODE(pa + DI_PATH(path)->path_phci));
21147c478bd9Sstevel@tonic-gate }
21157c478bd9Sstevel@tonic-gate
21167c478bd9Sstevel@tonic-gate /*
21177c478bd9Sstevel@tonic-gate * Deal with error condition:
21187c478bd9Sstevel@tonic-gate * If parent doesn't exist and node is not the root,
21197c478bd9Sstevel@tonic-gate * set errno to ENOTSUP. Otherwise, set errno to ENXIO.
21207c478bd9Sstevel@tonic-gate */
21217c478bd9Sstevel@tonic-gate if ((DI_PATH(path)->path_snap_state & DI_PATH_SNAP_NOPHCI) == 0)
21227c478bd9Sstevel@tonic-gate errno = ENOTSUP;
21237c478bd9Sstevel@tonic-gate else
21247c478bd9Sstevel@tonic-gate errno = ENXIO;
21257c478bd9Sstevel@tonic-gate
21267c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
21277c478bd9Sstevel@tonic-gate }
21287c478bd9Sstevel@tonic-gate
21297c478bd9Sstevel@tonic-gate di_path_prop_t
di_path_prop_next(di_path_t path,di_path_prop_t prop)21307c478bd9Sstevel@tonic-gate di_path_prop_next(di_path_t path, di_path_prop_t prop)
21317c478bd9Sstevel@tonic-gate {
21327c478bd9Sstevel@tonic-gate caddr_t pa;
21337c478bd9Sstevel@tonic-gate
21347c478bd9Sstevel@tonic-gate if (path == DI_PATH_NIL) {
21357c478bd9Sstevel@tonic-gate errno = EINVAL;
21367c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
21377c478bd9Sstevel@tonic-gate }
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate /*
21407c478bd9Sstevel@tonic-gate * prop is not NIL
21417c478bd9Sstevel@tonic-gate */
21427c478bd9Sstevel@tonic-gate if (prop != DI_PROP_NIL) {
21437c478bd9Sstevel@tonic-gate if (DI_PROP(prop)->next != 0)
21447c478bd9Sstevel@tonic-gate return (DI_PATHPROP((caddr_t)prop -
21457c478bd9Sstevel@tonic-gate DI_PROP(prop)->self + DI_PROP(prop)->next));
21467c478bd9Sstevel@tonic-gate else {
21477c478bd9Sstevel@tonic-gate errno = ENXIO;
21487c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
21497c478bd9Sstevel@tonic-gate }
21507c478bd9Sstevel@tonic-gate }
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate /*
21537c478bd9Sstevel@tonic-gate * prop is NIL-->caller asks for first property
21547c478bd9Sstevel@tonic-gate */
21557c478bd9Sstevel@tonic-gate pa = (caddr_t)path - DI_PATH(path)->self;
21567c478bd9Sstevel@tonic-gate if (DI_PATH(path)->path_prop != 0) {
21577c478bd9Sstevel@tonic-gate return (DI_PATHPROP(pa + DI_PATH(path)->path_prop));
21587c478bd9Sstevel@tonic-gate }
21597c478bd9Sstevel@tonic-gate
21607c478bd9Sstevel@tonic-gate /*
21617c478bd9Sstevel@tonic-gate * no property data-->check if snapshot includes props
21627c478bd9Sstevel@tonic-gate * in order to set the correct errno
21637c478bd9Sstevel@tonic-gate */
21647c478bd9Sstevel@tonic-gate if (DINFOPROP & (DI_ALL(pa)->command))
21657c478bd9Sstevel@tonic-gate errno = ENXIO;
21667c478bd9Sstevel@tonic-gate else
21677c478bd9Sstevel@tonic-gate errno = ENOTSUP;
21687c478bd9Sstevel@tonic-gate
21697c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
21707c478bd9Sstevel@tonic-gate }
21717c478bd9Sstevel@tonic-gate
21727c478bd9Sstevel@tonic-gate char *
di_path_prop_name(di_path_prop_t prop)21737c478bd9Sstevel@tonic-gate di_path_prop_name(di_path_prop_t prop)
21747c478bd9Sstevel@tonic-gate {
21757c478bd9Sstevel@tonic-gate caddr_t pa; /* starting address of map */
21767c478bd9Sstevel@tonic-gate pa = (caddr_t)prop - DI_PATHPROP(prop)->self;
21777c478bd9Sstevel@tonic-gate return ((char *)(pa + DI_PATHPROP(prop)->prop_name));
21787c478bd9Sstevel@tonic-gate }
21797c478bd9Sstevel@tonic-gate
21807c478bd9Sstevel@tonic-gate int
di_path_prop_len(di_path_prop_t prop)21817c478bd9Sstevel@tonic-gate di_path_prop_len(di_path_prop_t prop)
21827c478bd9Sstevel@tonic-gate {
21837c478bd9Sstevel@tonic-gate return (DI_PATHPROP(prop)->prop_len);
21847c478bd9Sstevel@tonic-gate }
21857c478bd9Sstevel@tonic-gate
21867c478bd9Sstevel@tonic-gate int
di_path_prop_type(di_path_prop_t prop)21877c478bd9Sstevel@tonic-gate di_path_prop_type(di_path_prop_t prop)
21887c478bd9Sstevel@tonic-gate {
21897c478bd9Sstevel@tonic-gate switch (DI_PATHPROP(prop)->prop_type) {
21907c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT:
21917c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT);
21927c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_INT64:
21937c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_INT64);
21947c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_BYTE:
21957c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_BYTE);
21967c478bd9Sstevel@tonic-gate case DDI_PROP_TYPE_STRING:
21977c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_STRING);
21987c478bd9Sstevel@tonic-gate }
21997c478bd9Sstevel@tonic-gate return (DI_PROP_TYPE_UNKNOWN);
22007c478bd9Sstevel@tonic-gate }
22017c478bd9Sstevel@tonic-gate
22027c478bd9Sstevel@tonic-gate int
di_path_prop_bytes(di_path_prop_t prop,uchar_t ** prop_data)22037c478bd9Sstevel@tonic-gate di_path_prop_bytes(di_path_prop_t prop, uchar_t **prop_data)
22047c478bd9Sstevel@tonic-gate {
22057c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) ||
22067c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) {
22077c478bd9Sstevel@tonic-gate errno = EFAULT;
22087c478bd9Sstevel@tonic-gate *prop_data = NULL;
22097c478bd9Sstevel@tonic-gate return (-1);
22107c478bd9Sstevel@tonic-gate }
22117c478bd9Sstevel@tonic-gate
22127c478bd9Sstevel@tonic-gate *prop_data = (uchar_t *)((caddr_t)prop - DI_PATHPROP(prop)->self
22137c478bd9Sstevel@tonic-gate + DI_PATHPROP(prop)->prop_data);
22147c478bd9Sstevel@tonic-gate
22157c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
22167c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_BYTE, 0));
22177c478bd9Sstevel@tonic-gate }
22187c478bd9Sstevel@tonic-gate
22197c478bd9Sstevel@tonic-gate int
di_path_prop_ints(di_path_prop_t prop,int ** prop_data)22207c478bd9Sstevel@tonic-gate di_path_prop_ints(di_path_prop_t prop, int **prop_data)
22217c478bd9Sstevel@tonic-gate {
22227c478bd9Sstevel@tonic-gate if (DI_PATHPROP(prop)->prop_len == 0)
22237c478bd9Sstevel@tonic-gate return (0);
22247c478bd9Sstevel@tonic-gate
22257c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) ||
22267c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) {
22277c478bd9Sstevel@tonic-gate errno = EFAULT;
22287c478bd9Sstevel@tonic-gate *prop_data = NULL;
22297c478bd9Sstevel@tonic-gate return (-1);
22307c478bd9Sstevel@tonic-gate }
22317c478bd9Sstevel@tonic-gate
22327c478bd9Sstevel@tonic-gate *prop_data = (int *)((void *)((caddr_t)prop - DI_PATHPROP(prop)->self
22337c478bd9Sstevel@tonic-gate + DI_PATHPROP(prop)->prop_data));
22347c478bd9Sstevel@tonic-gate
22357c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
22367c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_INT, 0));
22377c478bd9Sstevel@tonic-gate }
22387c478bd9Sstevel@tonic-gate
22397c478bd9Sstevel@tonic-gate int
di_path_prop_int64s(di_path_prop_t prop,int64_t ** prop_data)22407c478bd9Sstevel@tonic-gate di_path_prop_int64s(di_path_prop_t prop, int64_t **prop_data)
22417c478bd9Sstevel@tonic-gate {
22427c478bd9Sstevel@tonic-gate if (DI_PATHPROP(prop)->prop_len == 0)
22437c478bd9Sstevel@tonic-gate return (0);
22447c478bd9Sstevel@tonic-gate
22457c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) ||
22467c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) {
22477c478bd9Sstevel@tonic-gate errno = EFAULT;
22487c478bd9Sstevel@tonic-gate *prop_data = NULL;
22497c478bd9Sstevel@tonic-gate return (-1);
22507c478bd9Sstevel@tonic-gate }
22517c478bd9Sstevel@tonic-gate
22527c478bd9Sstevel@tonic-gate *prop_data = (int64_t *)((void *)((caddr_t)prop -
22537c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->self + DI_PATHPROP(prop)->prop_data));
22547c478bd9Sstevel@tonic-gate
22557c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
22567c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_INT64, 0));
22577c478bd9Sstevel@tonic-gate }
22587c478bd9Sstevel@tonic-gate
22597c478bd9Sstevel@tonic-gate int
di_path_prop_strings(di_path_prop_t prop,char ** prop_data)22607c478bd9Sstevel@tonic-gate di_path_prop_strings(di_path_prop_t prop, char **prop_data)
22617c478bd9Sstevel@tonic-gate {
22627c478bd9Sstevel@tonic-gate if (DI_PATHPROP(prop)->prop_len == 0)
22637c478bd9Sstevel@tonic-gate return (0);
22647c478bd9Sstevel@tonic-gate
22657c478bd9Sstevel@tonic-gate if ((DI_PATHPROP(prop)->prop_data == 0) ||
22667c478bd9Sstevel@tonic-gate (DI_PATHPROP(prop)->prop_data == (di_off_t)-1)) {
22677c478bd9Sstevel@tonic-gate errno = EFAULT;
22687c478bd9Sstevel@tonic-gate *prop_data = NULL;
22697c478bd9Sstevel@tonic-gate return (-1);
22707c478bd9Sstevel@tonic-gate }
22717c478bd9Sstevel@tonic-gate
22727c478bd9Sstevel@tonic-gate *prop_data = (char *)((caddr_t)prop - DI_PATHPROP(prop)->self
22737c478bd9Sstevel@tonic-gate + DI_PATHPROP(prop)->prop_data);
22747c478bd9Sstevel@tonic-gate
22757c478bd9Sstevel@tonic-gate return (di_prop_decode_common((void *)prop_data,
22767c478bd9Sstevel@tonic-gate DI_PATHPROP(prop)->prop_len, DI_PROP_TYPE_STRING, 0));
22777c478bd9Sstevel@tonic-gate }
22787c478bd9Sstevel@tonic-gate
22797c478bd9Sstevel@tonic-gate static di_path_prop_t
di_path_prop_search(di_path_t path,const char * name,int type)22807c478bd9Sstevel@tonic-gate di_path_prop_search(di_path_t path, const char *name, int type)
22817c478bd9Sstevel@tonic-gate {
22827c478bd9Sstevel@tonic-gate di_path_prop_t prop = DI_PROP_NIL;
22837c478bd9Sstevel@tonic-gate
22847c478bd9Sstevel@tonic-gate /*
22857c478bd9Sstevel@tonic-gate * Sanity check arguments
22867c478bd9Sstevel@tonic-gate */
22877c478bd9Sstevel@tonic-gate if ((path == DI_PATH_NIL) || (name == NULL) || (strlen(name) == 0) ||
22887c478bd9Sstevel@tonic-gate !DI_PROP_TYPE_VALID(type)) {
22897c478bd9Sstevel@tonic-gate errno = EINVAL;
22907c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
22917c478bd9Sstevel@tonic-gate }
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate while ((prop = di_path_prop_next(path, prop)) != DI_PROP_NIL) {
22947c478bd9Sstevel@tonic-gate int prop_type = di_path_prop_type(prop);
22957c478bd9Sstevel@tonic-gate
22967c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "match path prop name %s, type %d\n",
22977c478bd9Sstevel@tonic-gate di_path_prop_name(prop), prop_type));
22987c478bd9Sstevel@tonic-gate
22997c478bd9Sstevel@tonic-gate if (strcmp(name, di_path_prop_name(prop)) != 0)
23007c478bd9Sstevel@tonic-gate continue;
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate if ((prop_type != DI_PROP_TYPE_UNKNOWN) && (prop_type != type))
23037c478bd9Sstevel@tonic-gate continue;
23047c478bd9Sstevel@tonic-gate
23057c478bd9Sstevel@tonic-gate return (prop);
23067c478bd9Sstevel@tonic-gate }
23077c478bd9Sstevel@tonic-gate
23087c478bd9Sstevel@tonic-gate return (DI_PROP_NIL);
23097c478bd9Sstevel@tonic-gate }
23107c478bd9Sstevel@tonic-gate
23117c478bd9Sstevel@tonic-gate int
di_path_prop_lookup_bytes(di_path_t path,const char * prop_name,uchar_t ** prop_data)23127c478bd9Sstevel@tonic-gate di_path_prop_lookup_bytes(di_path_t path, const char *prop_name,
23137c478bd9Sstevel@tonic-gate uchar_t **prop_data)
23147c478bd9Sstevel@tonic-gate {
23157c478bd9Sstevel@tonic-gate di_path_prop_t prop;
23167c478bd9Sstevel@tonic-gate
23177c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name,
23187c478bd9Sstevel@tonic-gate DI_PROP_TYPE_BYTE)) == DI_PROP_NIL)
23197c478bd9Sstevel@tonic-gate return (-1);
23207c478bd9Sstevel@tonic-gate
23217c478bd9Sstevel@tonic-gate return (di_path_prop_bytes(prop, prop_data));
23227c478bd9Sstevel@tonic-gate }
23237c478bd9Sstevel@tonic-gate
23247c478bd9Sstevel@tonic-gate int
di_path_prop_lookup_ints(di_path_t path,const char * prop_name,int ** prop_data)23257c478bd9Sstevel@tonic-gate di_path_prop_lookup_ints(di_path_t path, const char *prop_name,
23267c478bd9Sstevel@tonic-gate int **prop_data)
23277c478bd9Sstevel@tonic-gate {
23287c478bd9Sstevel@tonic-gate di_path_prop_t prop;
23297c478bd9Sstevel@tonic-gate
23307c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name,
23317c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT)) == DI_PROP_NIL)
23327c478bd9Sstevel@tonic-gate return (-1);
23337c478bd9Sstevel@tonic-gate
23347c478bd9Sstevel@tonic-gate return (di_path_prop_ints(prop, prop_data));
23357c478bd9Sstevel@tonic-gate }
23367c478bd9Sstevel@tonic-gate
23377c478bd9Sstevel@tonic-gate int
di_path_prop_lookup_int64s(di_path_t path,const char * prop_name,int64_t ** prop_data)23387c478bd9Sstevel@tonic-gate di_path_prop_lookup_int64s(di_path_t path, const char *prop_name,
23397c478bd9Sstevel@tonic-gate int64_t **prop_data)
23407c478bd9Sstevel@tonic-gate {
23417c478bd9Sstevel@tonic-gate di_path_prop_t prop;
23427c478bd9Sstevel@tonic-gate
23437c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name,
23447c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT64)) == DI_PROP_NIL)
23457c478bd9Sstevel@tonic-gate return (-1);
23467c478bd9Sstevel@tonic-gate
23477c478bd9Sstevel@tonic-gate return (di_path_prop_int64s(prop, prop_data));
23487c478bd9Sstevel@tonic-gate }
23497c478bd9Sstevel@tonic-gate
di_path_prop_lookup_strings(di_path_t path,const char * prop_name,char ** prop_data)23507c478bd9Sstevel@tonic-gate int di_path_prop_lookup_strings(di_path_t path, const char *prop_name,
23517c478bd9Sstevel@tonic-gate char **prop_data)
23527c478bd9Sstevel@tonic-gate {
23537c478bd9Sstevel@tonic-gate di_path_prop_t prop;
23547c478bd9Sstevel@tonic-gate
23557c478bd9Sstevel@tonic-gate if ((prop = di_path_prop_search(path, prop_name,
23567c478bd9Sstevel@tonic-gate DI_PROP_TYPE_STRING)) == DI_PROP_NIL)
23577c478bd9Sstevel@tonic-gate return (-1);
23587c478bd9Sstevel@tonic-gate
23597c478bd9Sstevel@tonic-gate return (di_path_prop_strings(prop, prop_data));
23607c478bd9Sstevel@tonic-gate }
23617c478bd9Sstevel@tonic-gate
23628c4f8890Srs135747 /*
23638c4f8890Srs135747 * Consolidation private interfaces for traversing vhci nodes.
23648c4f8890Srs135747 */
23658c4f8890Srs135747 di_node_t
di_vhci_first_node(di_node_t root)23668c4f8890Srs135747 di_vhci_first_node(di_node_t root)
23678c4f8890Srs135747 {
23688c4f8890Srs135747 struct di_all *dap;
23698c4f8890Srs135747 caddr_t pa; /* starting address of map */
23708c4f8890Srs135747
23718c4f8890Srs135747 DPRINTF((DI_INFO, "Get first vhci node\n"));
23728c4f8890Srs135747
23738c4f8890Srs135747 if (root == DI_NODE_NIL) {
23748c4f8890Srs135747 errno = EINVAL;
23758c4f8890Srs135747 return (DI_NODE_NIL);
23768c4f8890Srs135747 }
23778c4f8890Srs135747
23788c4f8890Srs135747 pa = (caddr_t)root - DI_NODE(root)->self;
23798c4f8890Srs135747 dap = DI_ALL(pa);
23808c4f8890Srs135747
2381f00128d8SToomas Soome if (dap->top_vhci_devinfo == 0) {
23828c4f8890Srs135747 errno = ENXIO;
23838c4f8890Srs135747 return (DI_NODE_NIL);
23848c4f8890Srs135747 }
23858c4f8890Srs135747
23868c4f8890Srs135747 return (DI_NODE(pa + dap->top_vhci_devinfo));
23878c4f8890Srs135747 }
23888c4f8890Srs135747
23898c4f8890Srs135747 di_node_t
di_vhci_next_node(di_node_t node)23908c4f8890Srs135747 di_vhci_next_node(di_node_t node)
23918c4f8890Srs135747 {
23928c4f8890Srs135747 caddr_t pa; /* starting address of map */
23938c4f8890Srs135747
23948c4f8890Srs135747 if (node == DI_NODE_NIL) {
23958c4f8890Srs135747 errno = EINVAL;
23968c4f8890Srs135747 return (DI_NODE_NIL);
23978c4f8890Srs135747 }
23988c4f8890Srs135747
23998c4f8890Srs135747 DPRINTF((DI_TRACE, "next vhci node on the snap shot:"
24008c4f8890Srs135747 " current=%s\n", di_node_name(node)));
24018c4f8890Srs135747
2402f00128d8SToomas Soome if (DI_NODE(node)->next_vhci == 0) {
24038c4f8890Srs135747 errno = ENXIO;
24048c4f8890Srs135747 return (DI_NODE_NIL);
24058c4f8890Srs135747 }
24068c4f8890Srs135747
24078c4f8890Srs135747 pa = (caddr_t)node - DI_NODE(node)->self;
24088c4f8890Srs135747
24098c4f8890Srs135747 return (DI_NODE(pa + DI_NODE(node)->next_vhci));
24108c4f8890Srs135747 }
24118c4f8890Srs135747
24128c4f8890Srs135747 /*
24138c4f8890Srs135747 * Consolidation private interfaces for traversing phci nodes.
24148c4f8890Srs135747 */
24158c4f8890Srs135747 di_node_t
di_phci_first_node(di_node_t vhci_node)24168c4f8890Srs135747 di_phci_first_node(di_node_t vhci_node)
24178c4f8890Srs135747 {
24188c4f8890Srs135747 caddr_t pa; /* starting address of map */
24198c4f8890Srs135747
24208c4f8890Srs135747 DPRINTF((DI_INFO, "Get first phci node:\n"
24218c4f8890Srs135747 " current=%s", di_node_name(vhci_node)));
24228c4f8890Srs135747
24238c4f8890Srs135747 if (vhci_node == DI_NODE_NIL) {
24248c4f8890Srs135747 errno = EINVAL;
24258c4f8890Srs135747 return (DI_NODE_NIL);
24268c4f8890Srs135747 }
24278c4f8890Srs135747
24288c4f8890Srs135747 pa = (caddr_t)vhci_node - DI_NODE(vhci_node)->self;
24298c4f8890Srs135747
2430f00128d8SToomas Soome if (DI_NODE(vhci_node)->top_phci == 0) {
24318c4f8890Srs135747 errno = ENXIO;
24328c4f8890Srs135747 return (DI_NODE_NIL);
24338c4f8890Srs135747 }
24348c4f8890Srs135747
24358c4f8890Srs135747 return (DI_NODE(pa + DI_NODE(vhci_node)->top_phci));
24368c4f8890Srs135747 }
24378c4f8890Srs135747
24388c4f8890Srs135747 di_node_t
di_phci_next_node(di_node_t node)24398c4f8890Srs135747 di_phci_next_node(di_node_t node)
24408c4f8890Srs135747 {
24418c4f8890Srs135747 caddr_t pa; /* starting address of map */
24428c4f8890Srs135747
24438c4f8890Srs135747 if (node == DI_NODE_NIL) {
24448c4f8890Srs135747 errno = EINVAL;
24458c4f8890Srs135747 return (DI_NODE_NIL);
24468c4f8890Srs135747 }
24478c4f8890Srs135747
24488c4f8890Srs135747 DPRINTF((DI_TRACE, "next phci node on the snap shot:"
24498c4f8890Srs135747 " current=%s\n", di_node_name(node)));
24508c4f8890Srs135747
2451f00128d8SToomas Soome if (DI_NODE(node)->next_phci == 0) {
24528c4f8890Srs135747 errno = ENXIO;
24538c4f8890Srs135747 return (DI_NODE_NIL);
24548c4f8890Srs135747 }
24558c4f8890Srs135747
24568c4f8890Srs135747 pa = (caddr_t)node - DI_NODE(node)->self;
24578c4f8890Srs135747
24588c4f8890Srs135747 return (DI_NODE(pa + DI_NODE(node)->next_phci));
24598c4f8890Srs135747 }
24607c478bd9Sstevel@tonic-gate
24617c478bd9Sstevel@tonic-gate /*
24627c478bd9Sstevel@tonic-gate * Consolidation private interfaces for private data
24637c478bd9Sstevel@tonic-gate */
24647c478bd9Sstevel@tonic-gate void *
di_parent_private_data(di_node_t node)24657c478bd9Sstevel@tonic-gate di_parent_private_data(di_node_t node)
24667c478bd9Sstevel@tonic-gate {
24677c478bd9Sstevel@tonic-gate caddr_t pa;
24687c478bd9Sstevel@tonic-gate
24697c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent_data == 0) {
24707c478bd9Sstevel@tonic-gate errno = ENXIO;
24717c478bd9Sstevel@tonic-gate return (NULL);
24727c478bd9Sstevel@tonic-gate }
24737c478bd9Sstevel@tonic-gate
24747c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent_data == (di_off_t)-1) {
24757c478bd9Sstevel@tonic-gate /*
24767c478bd9Sstevel@tonic-gate * Private data requested, but not obtained due to a memory
24777c478bd9Sstevel@tonic-gate * error (e.g. wrong format specified)
24787c478bd9Sstevel@tonic-gate */
24797c478bd9Sstevel@tonic-gate errno = EFAULT;
24807c478bd9Sstevel@tonic-gate return (NULL);
24817c478bd9Sstevel@tonic-gate }
24827c478bd9Sstevel@tonic-gate
24837c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
24847c478bd9Sstevel@tonic-gate if (DI_NODE(node)->parent_data)
24857c478bd9Sstevel@tonic-gate return (pa + DI_NODE(node)->parent_data);
24867c478bd9Sstevel@tonic-gate
24877c478bd9Sstevel@tonic-gate if (DI_ALL(pa)->command & DINFOPRIVDATA)
24887c478bd9Sstevel@tonic-gate errno = ENXIO;
24897c478bd9Sstevel@tonic-gate else
24907c478bd9Sstevel@tonic-gate errno = ENOTSUP;
24917c478bd9Sstevel@tonic-gate
24927c478bd9Sstevel@tonic-gate return (NULL);
24937c478bd9Sstevel@tonic-gate }
24947c478bd9Sstevel@tonic-gate
24957c478bd9Sstevel@tonic-gate void *
di_driver_private_data(di_node_t node)24967c478bd9Sstevel@tonic-gate di_driver_private_data(di_node_t node)
24977c478bd9Sstevel@tonic-gate {
24987c478bd9Sstevel@tonic-gate caddr_t pa;
24997c478bd9Sstevel@tonic-gate
25007c478bd9Sstevel@tonic-gate if (DI_NODE(node)->driver_data == 0) {
25017c478bd9Sstevel@tonic-gate errno = ENXIO;
25027c478bd9Sstevel@tonic-gate return (NULL);
25037c478bd9Sstevel@tonic-gate }
25047c478bd9Sstevel@tonic-gate
25057c478bd9Sstevel@tonic-gate if (DI_NODE(node)->driver_data == (di_off_t)-1) {
25067c478bd9Sstevel@tonic-gate /*
25077c478bd9Sstevel@tonic-gate * Private data requested, but not obtained due to a memory
25087c478bd9Sstevel@tonic-gate * error (e.g. wrong format specified)
25097c478bd9Sstevel@tonic-gate */
25107c478bd9Sstevel@tonic-gate errno = EFAULT;
25117c478bd9Sstevel@tonic-gate return (NULL);
25127c478bd9Sstevel@tonic-gate }
25137c478bd9Sstevel@tonic-gate
25147c478bd9Sstevel@tonic-gate pa = (caddr_t)node - DI_NODE(node)->self;
25157c478bd9Sstevel@tonic-gate if (DI_NODE(node)->driver_data)
25167c478bd9Sstevel@tonic-gate return (pa + DI_NODE(node)->driver_data);
25177c478bd9Sstevel@tonic-gate
25187c478bd9Sstevel@tonic-gate if (DI_ALL(pa)->command & DINFOPRIVDATA)
25197c478bd9Sstevel@tonic-gate errno = ENXIO;
25207c478bd9Sstevel@tonic-gate else
25217c478bd9Sstevel@tonic-gate errno = ENOTSUP;
25227c478bd9Sstevel@tonic-gate
25237c478bd9Sstevel@tonic-gate return (NULL);
25247c478bd9Sstevel@tonic-gate }
25257c478bd9Sstevel@tonic-gate
25267c478bd9Sstevel@tonic-gate /*
252726947304SEvan Yan * Hotplug information access
252826947304SEvan Yan */
252926947304SEvan Yan
253026947304SEvan Yan typedef struct {
253126947304SEvan Yan void *arg;
253226947304SEvan Yan const char *type;
253326947304SEvan Yan uint_t flag;
253426947304SEvan Yan int (*hp_callback)(di_node_t, di_hp_t, void *);
253526947304SEvan Yan } di_walk_hp_arg_t;
253626947304SEvan Yan
253726947304SEvan Yan static int
di_walk_hp_callback(di_node_t node,void * argp)253826947304SEvan Yan di_walk_hp_callback(di_node_t node, void *argp)
253926947304SEvan Yan {
254026947304SEvan Yan di_walk_hp_arg_t *arg = (di_walk_hp_arg_t *)argp;
254126947304SEvan Yan di_hp_t hp;
254226947304SEvan Yan char *type_str;
254326947304SEvan Yan
254426947304SEvan Yan for (hp = DI_HP_NIL; (hp = di_hp_next(node, hp)) != DI_HP_NIL; ) {
254526947304SEvan Yan
254626947304SEvan Yan /* Exclude non-matching types if a type filter is specified */
254726947304SEvan Yan if (arg->type != NULL) {
254826947304SEvan Yan type_str = di_hp_description(hp);
254926947304SEvan Yan if (type_str && (strcmp(arg->type, type_str) != 0))
255026947304SEvan Yan continue;
255126947304SEvan Yan }
255226947304SEvan Yan
255326947304SEvan Yan /* Exclude ports if DI_HP_PORT flag not specified */
255426947304SEvan Yan if (!(arg->flag & DI_HP_PORT) &&
255526947304SEvan Yan (di_hp_type(hp) == DDI_HP_CN_TYPE_VIRTUAL_PORT))
255626947304SEvan Yan continue;
255726947304SEvan Yan
255826947304SEvan Yan /* Exclude connectors if DI_HP_CONNECTOR flag not specified */
255926947304SEvan Yan if (!(arg->flag & DI_HP_CONNECTOR) &&
256026947304SEvan Yan !(di_hp_type(hp) == DDI_HP_CN_TYPE_VIRTUAL_PORT))
256126947304SEvan Yan continue;
256226947304SEvan Yan
256326947304SEvan Yan /* Perform callback */
256426947304SEvan Yan if (arg->hp_callback(node, hp, arg->arg) != DI_WALK_CONTINUE)
256526947304SEvan Yan return (DI_WALK_TERMINATE);
256626947304SEvan Yan }
256726947304SEvan Yan
256826947304SEvan Yan return (DI_WALK_CONTINUE);
256926947304SEvan Yan }
257026947304SEvan Yan
257126947304SEvan Yan int
di_walk_hp(di_node_t node,const char * type,uint_t flag,void * arg,int (* hp_callback)(di_node_t node,di_hp_t hp,void * arg))257226947304SEvan Yan di_walk_hp(di_node_t node, const char *type, uint_t flag, void *arg,
257326947304SEvan Yan int (*hp_callback)(di_node_t node, di_hp_t hp, void *arg))
257426947304SEvan Yan {
257526947304SEvan Yan di_walk_hp_arg_t walk_arg;
257626947304SEvan Yan caddr_t pa;
257726947304SEvan Yan
257826947304SEvan Yan #ifdef DEBUG
257926947304SEvan Yan char *devfspath = di_devfs_path(node);
258026947304SEvan Yan DPRINTF((DI_INFO, "walking hotplug nodes under %s\n", devfspath));
258126947304SEvan Yan di_devfs_path_free(devfspath);
258226947304SEvan Yan #endif
258326947304SEvan Yan /*
258426947304SEvan Yan * paranoid error checking
258526947304SEvan Yan */
258626947304SEvan Yan if ((node == DI_NODE_NIL) || (hp_callback == NULL)) {
258726947304SEvan Yan errno = EINVAL;
258826947304SEvan Yan return (-1);
258926947304SEvan Yan }
259026947304SEvan Yan
259126947304SEvan Yan /* check if hotplug data is included in snapshot */
259226947304SEvan Yan pa = (caddr_t)node - DI_NODE(node)->self;
259326947304SEvan Yan if (!(DI_ALL(pa)->command & DINFOHP)) {
259426947304SEvan Yan errno = ENOTSUP;
259526947304SEvan Yan return (-1);
259626947304SEvan Yan }
259726947304SEvan Yan
259826947304SEvan Yan walk_arg.arg = arg;
259926947304SEvan Yan walk_arg.type = type;
260026947304SEvan Yan walk_arg.flag = flag;
260126947304SEvan Yan walk_arg.hp_callback = hp_callback;
260226947304SEvan Yan return (di_walk_node(node, DI_WALK_CLDFIRST, &walk_arg,
260326947304SEvan Yan di_walk_hp_callback));
260426947304SEvan Yan }
260526947304SEvan Yan
260626947304SEvan Yan di_hp_t
di_hp_next(di_node_t node,di_hp_t hp)260726947304SEvan Yan di_hp_next(di_node_t node, di_hp_t hp)
260826947304SEvan Yan {
260926947304SEvan Yan caddr_t pa;
261026947304SEvan Yan
261126947304SEvan Yan /*
261226947304SEvan Yan * paranoid error checking
261326947304SEvan Yan */
261426947304SEvan Yan if (node == DI_NODE_NIL) {
261526947304SEvan Yan errno = EINVAL;
261626947304SEvan Yan return (DI_HP_NIL);
261726947304SEvan Yan }
261826947304SEvan Yan
261926947304SEvan Yan /*
262026947304SEvan Yan * hotplug node is not NIL
262126947304SEvan Yan */
262226947304SEvan Yan if (hp != DI_HP_NIL) {
262326947304SEvan Yan if (DI_HP(hp)->next != 0)
262426947304SEvan Yan return (DI_HP((caddr_t)hp - hp->self + hp->next));
262526947304SEvan Yan else {
262626947304SEvan Yan errno = ENXIO;
262726947304SEvan Yan return (DI_HP_NIL);
262826947304SEvan Yan }
262926947304SEvan Yan }
263026947304SEvan Yan
263126947304SEvan Yan /*
263226947304SEvan Yan * hotplug node is NIL-->caller asks for first hotplug node
263326947304SEvan Yan */
263426947304SEvan Yan if (DI_NODE(node)->hp_data != 0) {
263526947304SEvan Yan return (DI_HP((caddr_t)node - DI_NODE(node)->self +
263626947304SEvan Yan DI_NODE(node)->hp_data));
263726947304SEvan Yan }
263826947304SEvan Yan
263926947304SEvan Yan /*
264026947304SEvan Yan * no hotplug data-->check if snapshot includes hotplug data
264126947304SEvan Yan * in order to set the correct errno
264226947304SEvan Yan */
264326947304SEvan Yan pa = (caddr_t)node - DI_NODE(node)->self;
264426947304SEvan Yan if (DINFOHP & DI_ALL(pa)->command)
264526947304SEvan Yan errno = ENXIO;
264626947304SEvan Yan else
264726947304SEvan Yan errno = ENOTSUP;
264826947304SEvan Yan
264926947304SEvan Yan return (DI_HP_NIL);
265026947304SEvan Yan }
265126947304SEvan Yan
265226947304SEvan Yan char *
di_hp_name(di_hp_t hp)265326947304SEvan Yan di_hp_name(di_hp_t hp)
265426947304SEvan Yan {
265526947304SEvan Yan caddr_t pa;
265626947304SEvan Yan
265726947304SEvan Yan /*
265826947304SEvan Yan * paranoid error checking
265926947304SEvan Yan */
266026947304SEvan Yan if (hp == DI_HP_NIL) {
266126947304SEvan Yan errno = EINVAL;
266226947304SEvan Yan return (NULL);
266326947304SEvan Yan }
266426947304SEvan Yan
266526947304SEvan Yan pa = (caddr_t)hp - DI_HP(hp)->self;
266626947304SEvan Yan
266726947304SEvan Yan if (DI_HP(hp)->hp_name == 0) {
266826947304SEvan Yan errno = ENXIO;
266926947304SEvan Yan return (NULL);
267026947304SEvan Yan }
267126947304SEvan Yan
267226947304SEvan Yan return ((char *)(pa + DI_HP(hp)->hp_name));
267326947304SEvan Yan }
267426947304SEvan Yan
267526947304SEvan Yan int
di_hp_connection(di_hp_t hp)267626947304SEvan Yan di_hp_connection(di_hp_t hp)
267726947304SEvan Yan {
267826947304SEvan Yan /*
267926947304SEvan Yan * paranoid error checking
268026947304SEvan Yan */
268126947304SEvan Yan if (hp == DI_HP_NIL) {
268226947304SEvan Yan errno = EINVAL;
268326947304SEvan Yan return (-1);
268426947304SEvan Yan }
268526947304SEvan Yan
268626947304SEvan Yan if (DI_HP(hp)->hp_connection == -1)
268726947304SEvan Yan errno = ENOENT;
268826947304SEvan Yan
268926947304SEvan Yan return (DI_HP(hp)->hp_connection);
269026947304SEvan Yan }
269126947304SEvan Yan
269226947304SEvan Yan int
di_hp_depends_on(di_hp_t hp)269326947304SEvan Yan di_hp_depends_on(di_hp_t hp)
269426947304SEvan Yan {
269526947304SEvan Yan /*
269626947304SEvan Yan * paranoid error checking
269726947304SEvan Yan */
269826947304SEvan Yan if (hp == DI_HP_NIL) {
269926947304SEvan Yan errno = EINVAL;
270026947304SEvan Yan return (-1);
270126947304SEvan Yan }
270226947304SEvan Yan
270326947304SEvan Yan if (DI_HP(hp)->hp_depends_on == -1)
270426947304SEvan Yan errno = ENOENT;
270526947304SEvan Yan
270626947304SEvan Yan return (DI_HP(hp)->hp_depends_on);
270726947304SEvan Yan }
270826947304SEvan Yan
270926947304SEvan Yan int
di_hp_state(di_hp_t hp)271026947304SEvan Yan di_hp_state(di_hp_t hp)
271126947304SEvan Yan {
271226947304SEvan Yan /*
271326947304SEvan Yan * paranoid error checking
271426947304SEvan Yan */
271526947304SEvan Yan if (hp == DI_HP_NIL) {
271626947304SEvan Yan errno = EINVAL;
271726947304SEvan Yan return (-1);
271826947304SEvan Yan }
271926947304SEvan Yan
272026947304SEvan Yan return (DI_HP(hp)->hp_state);
272126947304SEvan Yan }
272226947304SEvan Yan
272326947304SEvan Yan int
di_hp_type(di_hp_t hp)272426947304SEvan Yan di_hp_type(di_hp_t hp)
272526947304SEvan Yan {
272626947304SEvan Yan /*
272726947304SEvan Yan * paranoid error checking
272826947304SEvan Yan */
272926947304SEvan Yan if (hp == DI_HP_NIL) {
273026947304SEvan Yan errno = EINVAL;
273126947304SEvan Yan return (-1);
273226947304SEvan Yan }
273326947304SEvan Yan
273426947304SEvan Yan return (DI_HP(hp)->hp_type);
273526947304SEvan Yan }
273626947304SEvan Yan
273726947304SEvan Yan char *
di_hp_description(di_hp_t hp)273826947304SEvan Yan di_hp_description(di_hp_t hp)
273926947304SEvan Yan {
274026947304SEvan Yan caddr_t pa;
274126947304SEvan Yan
274226947304SEvan Yan /*
274326947304SEvan Yan * paranoid error checking
274426947304SEvan Yan */
274526947304SEvan Yan if (hp == DI_HP_NIL) {
274626947304SEvan Yan errno = EINVAL;
274726947304SEvan Yan return (NULL);
274826947304SEvan Yan }
274926947304SEvan Yan
275026947304SEvan Yan pa = (caddr_t)hp - DI_HP(hp)->self;
275126947304SEvan Yan
275226947304SEvan Yan if (DI_HP(hp)->hp_type_str == 0)
275326947304SEvan Yan return (NULL);
275426947304SEvan Yan
275526947304SEvan Yan return ((char *)(pa + DI_HP(hp)->hp_type_str));
275626947304SEvan Yan }
275726947304SEvan Yan
275826947304SEvan Yan di_node_t
di_hp_child(di_hp_t hp)275926947304SEvan Yan di_hp_child(di_hp_t hp)
276026947304SEvan Yan {
276126947304SEvan Yan caddr_t pa; /* starting address of map */
276226947304SEvan Yan
276326947304SEvan Yan /*
276426947304SEvan Yan * paranoid error checking
276526947304SEvan Yan */
276626947304SEvan Yan if (hp == DI_HP_NIL) {
276726947304SEvan Yan errno = EINVAL;
276826947304SEvan Yan return (DI_NODE_NIL);
276926947304SEvan Yan }
277026947304SEvan Yan
277126947304SEvan Yan pa = (caddr_t)hp - DI_HP(hp)->self;
277226947304SEvan Yan
277326947304SEvan Yan if (DI_HP(hp)->hp_child > 0) {
277426947304SEvan Yan return (DI_NODE(pa + DI_HP(hp)->hp_child));
277526947304SEvan Yan }
277626947304SEvan Yan
277726947304SEvan Yan /*
277826947304SEvan Yan * Deal with error condition:
277926947304SEvan Yan * Child doesn't exist, figure out if DINFOSUBTREE is set.
278026947304SEvan Yan * If it isn't, set errno to ENOTSUP.
278126947304SEvan Yan */
278226947304SEvan Yan if (!(DINFOSUBTREE & DI_ALL(pa)->command))
278326947304SEvan Yan errno = ENOTSUP;
278426947304SEvan Yan else
278526947304SEvan Yan errno = ENXIO;
278626947304SEvan Yan
278726947304SEvan Yan return (DI_NODE_NIL);
278826947304SEvan Yan }
278926947304SEvan Yan
279026947304SEvan Yan time_t
di_hp_last_change(di_hp_t hp)279126947304SEvan Yan di_hp_last_change(di_hp_t hp)
279226947304SEvan Yan {
279326947304SEvan Yan /*
279426947304SEvan Yan * paranoid error checking
279526947304SEvan Yan */
279626947304SEvan Yan if (hp == DI_HP_NIL) {
279726947304SEvan Yan errno = EINVAL;
279826947304SEvan Yan return ((time_t)0);
279926947304SEvan Yan }
280026947304SEvan Yan
280126947304SEvan Yan return ((time_t)DI_HP(hp)->hp_last_change);
280226947304SEvan Yan }
280326947304SEvan Yan
280426947304SEvan Yan /*
28057c478bd9Sstevel@tonic-gate * PROM property access
28067c478bd9Sstevel@tonic-gate */
28077c478bd9Sstevel@tonic-gate
28087c478bd9Sstevel@tonic-gate /*
28097c478bd9Sstevel@tonic-gate * openprom driver stuff:
28107c478bd9Sstevel@tonic-gate * The maximum property length depends on the buffer size. We use
28117c478bd9Sstevel@tonic-gate * OPROMMAXPARAM defined in <sys/openpromio.h>
28127c478bd9Sstevel@tonic-gate *
28137c478bd9Sstevel@tonic-gate * MAXNAMESZ is max property name. obpdefs.h defines it as 32 based on 1275
28147c478bd9Sstevel@tonic-gate * MAXVALSZ is maximum value size, which is whatever space left in buf
28157c478bd9Sstevel@tonic-gate */
28167c478bd9Sstevel@tonic-gate
28177c478bd9Sstevel@tonic-gate #define OBP_MAXBUF OPROMMAXPARAM - sizeof (int)
28187c478bd9Sstevel@tonic-gate #define OBP_MAXPROPLEN OBP_MAXBUF - OBP_MAXPROPNAME;
28197c478bd9Sstevel@tonic-gate
28207c478bd9Sstevel@tonic-gate struct di_prom_prop {
28217c478bd9Sstevel@tonic-gate char *name;
28227c478bd9Sstevel@tonic-gate int len;
28237c478bd9Sstevel@tonic-gate uchar_t *data;
28247c478bd9Sstevel@tonic-gate struct di_prom_prop *next; /* form a linked list */
28257c478bd9Sstevel@tonic-gate };
28267c478bd9Sstevel@tonic-gate
28277c478bd9Sstevel@tonic-gate struct di_prom_handle { /* handle to prom */
28287c478bd9Sstevel@tonic-gate mutex_t lock; /* synchronize access to openprom fd */
28297c478bd9Sstevel@tonic-gate int fd; /* /dev/openprom file descriptor */
28307c478bd9Sstevel@tonic-gate struct di_prom_prop *list; /* linked list of prop */
28317c478bd9Sstevel@tonic-gate union {
28327c478bd9Sstevel@tonic-gate char buf[OPROMMAXPARAM];
28337c478bd9Sstevel@tonic-gate struct openpromio opp;
28347c478bd9Sstevel@tonic-gate } oppbuf;
28357c478bd9Sstevel@tonic-gate };
28367c478bd9Sstevel@tonic-gate
28377c478bd9Sstevel@tonic-gate di_prom_handle_t
di_prom_init()28387c478bd9Sstevel@tonic-gate di_prom_init()
28397c478bd9Sstevel@tonic-gate {
28407c478bd9Sstevel@tonic-gate struct di_prom_handle *p;
28417c478bd9Sstevel@tonic-gate
28427c478bd9Sstevel@tonic-gate if ((p = malloc(sizeof (struct di_prom_handle))) == NULL)
28437c478bd9Sstevel@tonic-gate return (DI_PROM_HANDLE_NIL);
28447c478bd9Sstevel@tonic-gate
28457c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_prom_init: get prom handle 0x%p\n", p));
28467c478bd9Sstevel@tonic-gate
28477c478bd9Sstevel@tonic-gate (void) mutex_init(&p->lock, USYNC_THREAD, NULL);
28487c478bd9Sstevel@tonic-gate if ((p->fd = open("/dev/openprom", O_RDONLY)) < 0) {
28497c478bd9Sstevel@tonic-gate free(p);
28507c478bd9Sstevel@tonic-gate return (DI_PROM_HANDLE_NIL);
28517c478bd9Sstevel@tonic-gate }
28527c478bd9Sstevel@tonic-gate p->list = NULL;
28537c478bd9Sstevel@tonic-gate
28547c478bd9Sstevel@tonic-gate return ((di_prom_handle_t)p);
28557c478bd9Sstevel@tonic-gate }
28567c478bd9Sstevel@tonic-gate
28577c478bd9Sstevel@tonic-gate static void
di_prom_prop_free(struct di_prom_prop * list)28587c478bd9Sstevel@tonic-gate di_prom_prop_free(struct di_prom_prop *list)
28597c478bd9Sstevel@tonic-gate {
28607c478bd9Sstevel@tonic-gate struct di_prom_prop *tmp = list;
28617c478bd9Sstevel@tonic-gate
28627c478bd9Sstevel@tonic-gate while (tmp != NULL) {
28637c478bd9Sstevel@tonic-gate list = tmp->next;
28647c478bd9Sstevel@tonic-gate if (tmp->name != NULL) {
28657c478bd9Sstevel@tonic-gate free(tmp->name);
28667c478bd9Sstevel@tonic-gate }
28677c478bd9Sstevel@tonic-gate if (tmp->data != NULL) {
28687c478bd9Sstevel@tonic-gate free(tmp->data);
28697c478bd9Sstevel@tonic-gate }
28707c478bd9Sstevel@tonic-gate free(tmp);
28717c478bd9Sstevel@tonic-gate tmp = list;
28727c478bd9Sstevel@tonic-gate }
28737c478bd9Sstevel@tonic-gate }
28747c478bd9Sstevel@tonic-gate
28757c478bd9Sstevel@tonic-gate void
di_prom_fini(di_prom_handle_t ph)28767c478bd9Sstevel@tonic-gate di_prom_fini(di_prom_handle_t ph)
28777c478bd9Sstevel@tonic-gate {
28787c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph;
28797c478bd9Sstevel@tonic-gate
28807c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "di_prom_fini: free prom handle 0x%p\n", p));
28817c478bd9Sstevel@tonic-gate
28827c478bd9Sstevel@tonic-gate (void) close(p->fd);
28837c478bd9Sstevel@tonic-gate (void) mutex_destroy(&p->lock);
28847c478bd9Sstevel@tonic-gate di_prom_prop_free(p->list);
28857c478bd9Sstevel@tonic-gate
28867c478bd9Sstevel@tonic-gate free(p);
28877c478bd9Sstevel@tonic-gate }
28887c478bd9Sstevel@tonic-gate
28897c478bd9Sstevel@tonic-gate /*
28907c478bd9Sstevel@tonic-gate * Internal library interface for locating the property
28917c478bd9Sstevel@tonic-gate * XXX: ph->lock must be held for the duration of call.
28927c478bd9Sstevel@tonic-gate */
28937c478bd9Sstevel@tonic-gate static di_prom_prop_t
di_prom_prop_found(di_prom_handle_t ph,int nodeid,di_prom_prop_t prom_prop)28947c478bd9Sstevel@tonic-gate di_prom_prop_found(di_prom_handle_t ph, int nodeid,
28957c478bd9Sstevel@tonic-gate di_prom_prop_t prom_prop)
28967c478bd9Sstevel@tonic-gate {
28977c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph;
28987c478bd9Sstevel@tonic-gate struct openpromio *opp = &p->oppbuf.opp;
28997c478bd9Sstevel@tonic-gate int *ip = (int *)((void *)opp->oprom_array);
29007c478bd9Sstevel@tonic-gate struct di_prom_prop *prop = (struct di_prom_prop *)prom_prop;
29017c478bd9Sstevel@tonic-gate
29027c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "Looking for nodeid 0x%x\n", nodeid));
29037c478bd9Sstevel@tonic-gate
29047c478bd9Sstevel@tonic-gate /*
29057c478bd9Sstevel@tonic-gate * Set "current" nodeid in the openprom driver
29067c478bd9Sstevel@tonic-gate */
29077c478bd9Sstevel@tonic-gate opp->oprom_size = sizeof (int);
29087c478bd9Sstevel@tonic-gate *ip = nodeid;
29097c478bd9Sstevel@tonic-gate if (ioctl(p->fd, OPROMSETNODEID, opp) < 0) {
29107c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "*** Nodeid not found 0x%x\n", nodeid));
29117c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29127c478bd9Sstevel@tonic-gate }
29137c478bd9Sstevel@tonic-gate
29147c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE, "Found nodeid 0x%x\n", nodeid));
29157c478bd9Sstevel@tonic-gate
29167c478bd9Sstevel@tonic-gate bzero(opp, OBP_MAXBUF);
29177c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPNAME;
29187c478bd9Sstevel@tonic-gate if (prom_prop != DI_PROM_PROP_NIL)
29197c478bd9Sstevel@tonic-gate (void) strcpy(opp->oprom_array, prop->name);
29207c478bd9Sstevel@tonic-gate
29217c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMNXTPROP, opp) < 0) || (opp->oprom_size == 0))
29227c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29237c478bd9Sstevel@tonic-gate
29247c478bd9Sstevel@tonic-gate /*
29257c478bd9Sstevel@tonic-gate * Prom property found. Allocate struct for storing prop
29267c478bd9Sstevel@tonic-gate * (reuse variable prop)
29277c478bd9Sstevel@tonic-gate */
29287c478bd9Sstevel@tonic-gate if ((prop = malloc(sizeof (struct di_prom_prop))) == NULL)
29297c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29307c478bd9Sstevel@tonic-gate
29317c478bd9Sstevel@tonic-gate /*
29327c478bd9Sstevel@tonic-gate * Get a copy of property name
29337c478bd9Sstevel@tonic-gate */
29347c478bd9Sstevel@tonic-gate if ((prop->name = strdup(opp->oprom_array)) == NULL) {
29357c478bd9Sstevel@tonic-gate free(prop);
29367c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29377c478bd9Sstevel@tonic-gate }
29387c478bd9Sstevel@tonic-gate
29397c478bd9Sstevel@tonic-gate /*
29407c478bd9Sstevel@tonic-gate * get property value and length
29417c478bd9Sstevel@tonic-gate */
29427c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPLEN;
29437c478bd9Sstevel@tonic-gate
29447c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMGETPROP, opp) < 0) ||
29457c478bd9Sstevel@tonic-gate (opp->oprom_size == (uint_t)-1)) {
29467c478bd9Sstevel@tonic-gate free(prop->name);
29477c478bd9Sstevel@tonic-gate free(prop);
29487c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29497c478bd9Sstevel@tonic-gate }
29507c478bd9Sstevel@tonic-gate
29517c478bd9Sstevel@tonic-gate /*
29527c478bd9Sstevel@tonic-gate * make a copy of the property value
29537c478bd9Sstevel@tonic-gate */
29547c478bd9Sstevel@tonic-gate prop->len = opp->oprom_size;
29557c478bd9Sstevel@tonic-gate
29567c478bd9Sstevel@tonic-gate if (prop->len == 0)
29577c478bd9Sstevel@tonic-gate prop->data = NULL;
29587c478bd9Sstevel@tonic-gate else if ((prop->data = malloc(prop->len)) == NULL) {
29597c478bd9Sstevel@tonic-gate free(prop->name);
29607c478bd9Sstevel@tonic-gate free(prop);
29617c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29627c478bd9Sstevel@tonic-gate }
29637c478bd9Sstevel@tonic-gate
29647c478bd9Sstevel@tonic-gate bcopy(opp->oprom_array, prop->data, prop->len);
29657c478bd9Sstevel@tonic-gate
29667c478bd9Sstevel@tonic-gate /*
29677c478bd9Sstevel@tonic-gate * Prepend prop to list in prom handle
29687c478bd9Sstevel@tonic-gate */
29697c478bd9Sstevel@tonic-gate prop->next = p->list;
29707c478bd9Sstevel@tonic-gate p->list = prop;
29717c478bd9Sstevel@tonic-gate
29727c478bd9Sstevel@tonic-gate return ((di_prom_prop_t)prop);
29737c478bd9Sstevel@tonic-gate }
29747c478bd9Sstevel@tonic-gate
29757c478bd9Sstevel@tonic-gate di_prom_prop_t
di_prom_prop_next(di_prom_handle_t ph,di_node_t node,di_prom_prop_t prom_prop)29767c478bd9Sstevel@tonic-gate di_prom_prop_next(di_prom_handle_t ph, di_node_t node, di_prom_prop_t prom_prop)
29777c478bd9Sstevel@tonic-gate {
29787c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph;
29797c478bd9Sstevel@tonic-gate
29807c478bd9Sstevel@tonic-gate DPRINTF((DI_TRACE1, "Search next prop for node 0x%p with ph 0x%p\n",
29817c478bd9Sstevel@tonic-gate node, p));
29827c478bd9Sstevel@tonic-gate
29837c478bd9Sstevel@tonic-gate /*
29847c478bd9Sstevel@tonic-gate * paranoid check
29857c478bd9Sstevel@tonic-gate */
29867c478bd9Sstevel@tonic-gate if ((ph == DI_PROM_HANDLE_NIL) || (node == DI_NODE_NIL)) {
29877c478bd9Sstevel@tonic-gate errno = EINVAL;
29887c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29897c478bd9Sstevel@tonic-gate }
29907c478bd9Sstevel@tonic-gate
29917c478bd9Sstevel@tonic-gate if (di_nodeid(node) != DI_PROM_NODEID) {
29927c478bd9Sstevel@tonic-gate errno = ENXIO;
29937c478bd9Sstevel@tonic-gate return (DI_PROM_PROP_NIL);
29947c478bd9Sstevel@tonic-gate }
29957c478bd9Sstevel@tonic-gate
29967c478bd9Sstevel@tonic-gate /*
29977c478bd9Sstevel@tonic-gate * synchronize access to prom file descriptor
29987c478bd9Sstevel@tonic-gate */
29997c478bd9Sstevel@tonic-gate (void) mutex_lock(&p->lock);
30007c478bd9Sstevel@tonic-gate
30017c478bd9Sstevel@tonic-gate /*
30027c478bd9Sstevel@tonic-gate * look for next property
30037c478bd9Sstevel@tonic-gate */
30047c478bd9Sstevel@tonic-gate prom_prop = di_prom_prop_found(ph, DI_NODE(node)->nodeid, prom_prop);
30057c478bd9Sstevel@tonic-gate
30067c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
30077c478bd9Sstevel@tonic-gate
30087c478bd9Sstevel@tonic-gate return (prom_prop);
30097c478bd9Sstevel@tonic-gate }
30107c478bd9Sstevel@tonic-gate
30117c478bd9Sstevel@tonic-gate char *
di_prom_prop_name(di_prom_prop_t prom_prop)30127c478bd9Sstevel@tonic-gate di_prom_prop_name(di_prom_prop_t prom_prop)
30137c478bd9Sstevel@tonic-gate {
30147c478bd9Sstevel@tonic-gate /*
30157c478bd9Sstevel@tonic-gate * paranoid check
30167c478bd9Sstevel@tonic-gate */
30177c478bd9Sstevel@tonic-gate if (prom_prop == DI_PROM_PROP_NIL) {
30187c478bd9Sstevel@tonic-gate errno = EINVAL;
30197c478bd9Sstevel@tonic-gate return (NULL);
30207c478bd9Sstevel@tonic-gate }
30217c478bd9Sstevel@tonic-gate
30227c478bd9Sstevel@tonic-gate return (((struct di_prom_prop *)prom_prop)->name);
30237c478bd9Sstevel@tonic-gate }
30247c478bd9Sstevel@tonic-gate
30257c478bd9Sstevel@tonic-gate int
di_prom_prop_data(di_prom_prop_t prom_prop,uchar_t ** prom_prop_data)30267c478bd9Sstevel@tonic-gate di_prom_prop_data(di_prom_prop_t prom_prop, uchar_t **prom_prop_data)
30277c478bd9Sstevel@tonic-gate {
30287c478bd9Sstevel@tonic-gate /*
30297c478bd9Sstevel@tonic-gate * paranoid check
30307c478bd9Sstevel@tonic-gate */
30317c478bd9Sstevel@tonic-gate if (prom_prop == DI_PROM_PROP_NIL) {
30327c478bd9Sstevel@tonic-gate errno = EINVAL;
3033f00128d8SToomas Soome return (0);
30347c478bd9Sstevel@tonic-gate }
30357c478bd9Sstevel@tonic-gate
30367c478bd9Sstevel@tonic-gate *prom_prop_data = ((struct di_prom_prop *)prom_prop)->data;
30377c478bd9Sstevel@tonic-gate
30387c478bd9Sstevel@tonic-gate return (((struct di_prom_prop *)prom_prop)->len);
30397c478bd9Sstevel@tonic-gate }
30407c478bd9Sstevel@tonic-gate
30417c478bd9Sstevel@tonic-gate /*
30427c478bd9Sstevel@tonic-gate * Internal library interface for locating the property
30437c478bd9Sstevel@tonic-gate * Returns length if found, -1 if prop doesn't exist.
30447c478bd9Sstevel@tonic-gate */
30457c478bd9Sstevel@tonic-gate static struct di_prom_prop *
di_prom_prop_lookup_common(di_prom_handle_t ph,di_node_t node,const char * prom_prop_name)30467c478bd9Sstevel@tonic-gate di_prom_prop_lookup_common(di_prom_handle_t ph, di_node_t node,
30477c478bd9Sstevel@tonic-gate const char *prom_prop_name)
30487c478bd9Sstevel@tonic-gate {
30497c478bd9Sstevel@tonic-gate struct openpromio *opp;
30507c478bd9Sstevel@tonic-gate struct di_prom_prop *prop;
30517c478bd9Sstevel@tonic-gate struct di_prom_handle *p = (struct di_prom_handle *)ph;
30527c478bd9Sstevel@tonic-gate
30537c478bd9Sstevel@tonic-gate /*
30547c478bd9Sstevel@tonic-gate * paranoid check
30557c478bd9Sstevel@tonic-gate */
30567c478bd9Sstevel@tonic-gate if ((ph == DI_PROM_HANDLE_NIL) || (node == DI_NODE_NIL)) {
30577c478bd9Sstevel@tonic-gate errno = EINVAL;
30587c478bd9Sstevel@tonic-gate return (NULL);
30597c478bd9Sstevel@tonic-gate }
30607c478bd9Sstevel@tonic-gate
30617c478bd9Sstevel@tonic-gate if (di_nodeid(node) != DI_PROM_NODEID) {
30627c478bd9Sstevel@tonic-gate errno = ENXIO;
30637c478bd9Sstevel@tonic-gate return (NULL);
30647c478bd9Sstevel@tonic-gate }
30657c478bd9Sstevel@tonic-gate
30667c478bd9Sstevel@tonic-gate opp = &p->oppbuf.opp;
30677c478bd9Sstevel@tonic-gate
30687c478bd9Sstevel@tonic-gate (void) mutex_lock(&p->lock);
30697c478bd9Sstevel@tonic-gate
30707c478bd9Sstevel@tonic-gate opp->oprom_size = sizeof (int);
30717c478bd9Sstevel@tonic-gate opp->oprom_node = DI_NODE(node)->nodeid;
30727c478bd9Sstevel@tonic-gate if (ioctl(p->fd, OPROMSETNODEID, opp) < 0) {
30737c478bd9Sstevel@tonic-gate errno = ENXIO;
30747c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "*** Nodeid not found 0x%x\n",
30757c478bd9Sstevel@tonic-gate DI_NODE(node)->nodeid));
30767c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
30777c478bd9Sstevel@tonic-gate return (NULL);
30787c478bd9Sstevel@tonic-gate }
30797c478bd9Sstevel@tonic-gate
30807c478bd9Sstevel@tonic-gate /*
30817c478bd9Sstevel@tonic-gate * get property length
30827c478bd9Sstevel@tonic-gate */
30837c478bd9Sstevel@tonic-gate bzero(opp, OBP_MAXBUF);
30847c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPLEN;
30857c478bd9Sstevel@tonic-gate (void) strcpy(opp->oprom_array, prom_prop_name);
30867c478bd9Sstevel@tonic-gate
30877c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMGETPROPLEN, opp) < 0) ||
30887c478bd9Sstevel@tonic-gate (opp->oprom_len == -1)) {
30897c478bd9Sstevel@tonic-gate /* no such property */
30907c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
30917c478bd9Sstevel@tonic-gate return (NULL);
30927c478bd9Sstevel@tonic-gate }
30937c478bd9Sstevel@tonic-gate
30947c478bd9Sstevel@tonic-gate /*
30957c478bd9Sstevel@tonic-gate * Prom property found. Allocate struct for storing prop
30967c478bd9Sstevel@tonic-gate */
30977c478bd9Sstevel@tonic-gate if ((prop = malloc(sizeof (struct di_prom_prop))) == NULL) {
30987c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
30997c478bd9Sstevel@tonic-gate return (NULL);
31007c478bd9Sstevel@tonic-gate }
31017c478bd9Sstevel@tonic-gate prop->name = NULL; /* we don't need the name */
31027c478bd9Sstevel@tonic-gate prop->len = opp->oprom_len;
31037c478bd9Sstevel@tonic-gate
31047c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */
31057c478bd9Sstevel@tonic-gate prop->data = NULL;
31067c478bd9Sstevel@tonic-gate prop->next = p->list;
31077c478bd9Sstevel@tonic-gate p->list = prop;
31087c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
31097c478bd9Sstevel@tonic-gate return (prop);
31107c478bd9Sstevel@tonic-gate }
31117c478bd9Sstevel@tonic-gate
31127c478bd9Sstevel@tonic-gate /*
31137c478bd9Sstevel@tonic-gate * retrieve the property value
31147c478bd9Sstevel@tonic-gate */
31157c478bd9Sstevel@tonic-gate bzero(opp, OBP_MAXBUF);
31167c478bd9Sstevel@tonic-gate opp->oprom_size = OBP_MAXPROPLEN;
31177c478bd9Sstevel@tonic-gate (void) strcpy(opp->oprom_array, prom_prop_name);
31187c478bd9Sstevel@tonic-gate
31197c478bd9Sstevel@tonic-gate if ((ioctl(p->fd, OPROMGETPROP, opp) < 0) ||
31207c478bd9Sstevel@tonic-gate (opp->oprom_size == (uint_t)-1)) {
31217c478bd9Sstevel@tonic-gate /* error retrieving property value */
31227c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
31237c478bd9Sstevel@tonic-gate free(prop);
31247c478bd9Sstevel@tonic-gate return (NULL);
31257c478bd9Sstevel@tonic-gate }
31267c478bd9Sstevel@tonic-gate
31277c478bd9Sstevel@tonic-gate /*
31287c478bd9Sstevel@tonic-gate * make a copy of the property value, stick in ph->list
31297c478bd9Sstevel@tonic-gate */
31307c478bd9Sstevel@tonic-gate if ((prop->data = malloc(prop->len)) == NULL) {
31317c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
31327c478bd9Sstevel@tonic-gate free(prop);
31337c478bd9Sstevel@tonic-gate return (NULL);
31347c478bd9Sstevel@tonic-gate }
31357c478bd9Sstevel@tonic-gate
31367c478bd9Sstevel@tonic-gate bcopy(opp->oprom_array, prop->data, prop->len);
31377c478bd9Sstevel@tonic-gate
31387c478bd9Sstevel@tonic-gate prop->next = p->list;
31397c478bd9Sstevel@tonic-gate p->list = prop;
31407c478bd9Sstevel@tonic-gate (void) mutex_unlock(&p->lock);
31417c478bd9Sstevel@tonic-gate
31427c478bd9Sstevel@tonic-gate return (prop);
31437c478bd9Sstevel@tonic-gate }
31447c478bd9Sstevel@tonic-gate
31457c478bd9Sstevel@tonic-gate int
di_prom_prop_lookup_ints(di_prom_handle_t ph,di_node_t node,const char * prom_prop_name,int ** prom_prop_data)31467c478bd9Sstevel@tonic-gate di_prom_prop_lookup_ints(di_prom_handle_t ph, di_node_t node,
31477c478bd9Sstevel@tonic-gate const char *prom_prop_name, int **prom_prop_data)
31487c478bd9Sstevel@tonic-gate {
31497c478bd9Sstevel@tonic-gate int len;
31507c478bd9Sstevel@tonic-gate struct di_prom_prop *prop;
31517c478bd9Sstevel@tonic-gate
31527c478bd9Sstevel@tonic-gate prop = di_prom_prop_lookup_common(ph, node, prom_prop_name);
31537c478bd9Sstevel@tonic-gate
31547c478bd9Sstevel@tonic-gate if (prop == NULL) {
31557c478bd9Sstevel@tonic-gate *prom_prop_data = NULL;
31567c478bd9Sstevel@tonic-gate return (-1);
31577c478bd9Sstevel@tonic-gate }
31587c478bd9Sstevel@tonic-gate
31597c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */
31607c478bd9Sstevel@tonic-gate *prom_prop_data = NULL;
31617c478bd9Sstevel@tonic-gate return (0);
31627c478bd9Sstevel@tonic-gate }
31637c478bd9Sstevel@tonic-gate
31647c478bd9Sstevel@tonic-gate len = di_prop_decode_common((void *)&prop->data, prop->len,
31657c478bd9Sstevel@tonic-gate DI_PROP_TYPE_INT, 1);
31667c478bd9Sstevel@tonic-gate *prom_prop_data = (int *)((void *)prop->data);
31677c478bd9Sstevel@tonic-gate
31687c478bd9Sstevel@tonic-gate return (len);
31697c478bd9Sstevel@tonic-gate }
31707c478bd9Sstevel@tonic-gate
31717c478bd9Sstevel@tonic-gate int
di_prom_prop_lookup_strings(di_prom_handle_t ph,di_node_t node,const char * prom_prop_name,char ** prom_prop_data)31727c478bd9Sstevel@tonic-gate di_prom_prop_lookup_strings(di_prom_handle_t ph, di_node_t node,
31737c478bd9Sstevel@tonic-gate const char *prom_prop_name, char **prom_prop_data)
31747c478bd9Sstevel@tonic-gate {
31757c478bd9Sstevel@tonic-gate int len;
31767c478bd9Sstevel@tonic-gate struct di_prom_prop *prop;
31777c478bd9Sstevel@tonic-gate
31787c478bd9Sstevel@tonic-gate prop = di_prom_prop_lookup_common(ph, node, prom_prop_name);
31797c478bd9Sstevel@tonic-gate
31807c478bd9Sstevel@tonic-gate if (prop == NULL) {
31817c478bd9Sstevel@tonic-gate *prom_prop_data = NULL;
31827c478bd9Sstevel@tonic-gate return (-1);
31837c478bd9Sstevel@tonic-gate }
31847c478bd9Sstevel@tonic-gate
31857c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */
31867c478bd9Sstevel@tonic-gate *prom_prop_data = NULL;
31877c478bd9Sstevel@tonic-gate return (0);
31887c478bd9Sstevel@tonic-gate }
31897c478bd9Sstevel@tonic-gate
31907c478bd9Sstevel@tonic-gate /*
31917c478bd9Sstevel@tonic-gate * Fix an openprom bug (OBP string not NULL terminated).
31927c478bd9Sstevel@tonic-gate * XXX This should really be fixed in promif.
31937c478bd9Sstevel@tonic-gate */
31947c478bd9Sstevel@tonic-gate if (((char *)prop->data)[prop->len - 1] != '\0') {
31957c478bd9Sstevel@tonic-gate uchar_t *tmp;
31967c478bd9Sstevel@tonic-gate prop->len++;
31977c478bd9Sstevel@tonic-gate if ((tmp = realloc(prop->data, prop->len)) == NULL)
31987c478bd9Sstevel@tonic-gate return (-1);
31997c478bd9Sstevel@tonic-gate
32007c478bd9Sstevel@tonic-gate prop->data = tmp;
32017c478bd9Sstevel@tonic-gate ((char *)prop->data)[prop->len - 1] = '\0';
32027c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "OBP string not NULL terminated: "
32037c478bd9Sstevel@tonic-gate "node=%s, prop=%s, val=%s\n",
32047c478bd9Sstevel@tonic-gate di_node_name(node), prom_prop_name, prop->data));
32057c478bd9Sstevel@tonic-gate }
32067c478bd9Sstevel@tonic-gate
32077c478bd9Sstevel@tonic-gate len = di_prop_decode_common((void *)&prop->data, prop->len,
32087c478bd9Sstevel@tonic-gate DI_PROP_TYPE_STRING, 1);
32097c478bd9Sstevel@tonic-gate *prom_prop_data = (char *)prop->data;
32107c478bd9Sstevel@tonic-gate
32117c478bd9Sstevel@tonic-gate return (len);
32127c478bd9Sstevel@tonic-gate }
32137c478bd9Sstevel@tonic-gate
32147c478bd9Sstevel@tonic-gate int
di_prom_prop_lookup_bytes(di_prom_handle_t ph,di_node_t node,const char * prom_prop_name,uchar_t ** prom_prop_data)32157c478bd9Sstevel@tonic-gate di_prom_prop_lookup_bytes(di_prom_handle_t ph, di_node_t node,
32167c478bd9Sstevel@tonic-gate const char *prom_prop_name, uchar_t **prom_prop_data)
32177c478bd9Sstevel@tonic-gate {
32187c478bd9Sstevel@tonic-gate int len;
32197c478bd9Sstevel@tonic-gate struct di_prom_prop *prop;
32207c478bd9Sstevel@tonic-gate
32217c478bd9Sstevel@tonic-gate prop = di_prom_prop_lookup_common(ph, node, prom_prop_name);
32227c478bd9Sstevel@tonic-gate
32237c478bd9Sstevel@tonic-gate if (prop == NULL) {
32247c478bd9Sstevel@tonic-gate *prom_prop_data = NULL;
32257c478bd9Sstevel@tonic-gate return (-1);
32267c478bd9Sstevel@tonic-gate }
32277c478bd9Sstevel@tonic-gate
32287c478bd9Sstevel@tonic-gate if (prop->len == 0) { /* boolean property */
32297c478bd9Sstevel@tonic-gate *prom_prop_data = NULL;
32307c478bd9Sstevel@tonic-gate return (0);
32317c478bd9Sstevel@tonic-gate }
32327c478bd9Sstevel@tonic-gate
32337c478bd9Sstevel@tonic-gate len = di_prop_decode_common((void *)&prop->data, prop->len,
32347c478bd9Sstevel@tonic-gate DI_PROP_TYPE_BYTE, 1);
32357c478bd9Sstevel@tonic-gate *prom_prop_data = prop->data;
32367c478bd9Sstevel@tonic-gate
32377c478bd9Sstevel@tonic-gate return (len);
32387c478bd9Sstevel@tonic-gate }
32397c478bd9Sstevel@tonic-gate
32403ebafc43Sjveta /*
32413ebafc43Sjveta * returns an allocated array through <prop_data> only when its count > 0
32423ebafc43Sjveta * and the number of entries (count) as the function return value;
32433ebafc43Sjveta * use di_slot_names_free() to free the array
32443ebafc43Sjveta */
32453ebafc43Sjveta int
di_prop_slot_names(di_prop_t prop,di_slot_name_t ** prop_data)32463ebafc43Sjveta di_prop_slot_names(di_prop_t prop, di_slot_name_t **prop_data)
32473ebafc43Sjveta {
32483ebafc43Sjveta int rawlen, count;
32493ebafc43Sjveta uchar_t *rawdata;
32503ebafc43Sjveta char *nm = di_prop_name(prop);
32513ebafc43Sjveta
32523ebafc43Sjveta if (nm == NULL || strcmp(DI_PROP_SLOT_NAMES, nm) != 0)
32533ebafc43Sjveta goto ERROUT;
32543ebafc43Sjveta
32553ebafc43Sjveta rawlen = di_prop_rawdata(prop, &rawdata);
32563ebafc43Sjveta if (rawlen <= 0 || rawdata == NULL)
32573ebafc43Sjveta goto ERROUT;
32583ebafc43Sjveta
32593ebafc43Sjveta count = di_slot_names_decode(rawdata, rawlen, prop_data);
32603ebafc43Sjveta if (count < 0 || *prop_data == NULL)
32613ebafc43Sjveta goto ERROUT;
32623ebafc43Sjveta
32633ebafc43Sjveta return (count);
32643ebafc43Sjveta /*NOTREACHED*/
32653ebafc43Sjveta ERROUT:
32663ebafc43Sjveta errno = EFAULT;
32673ebafc43Sjveta *prop_data = NULL;
32683ebafc43Sjveta return (-1);
32693ebafc43Sjveta }
32703ebafc43Sjveta
32713ebafc43Sjveta int
di_prop_lookup_slot_names(dev_t dev,di_node_t node,di_slot_name_t ** prop_data)32723ebafc43Sjveta di_prop_lookup_slot_names(dev_t dev, di_node_t node,
32733ebafc43Sjveta di_slot_name_t **prop_data)
32743ebafc43Sjveta {
32753ebafc43Sjveta di_prop_t prop;
32763ebafc43Sjveta
32773ebafc43Sjveta /*
32783ebafc43Sjveta * change this if and when DI_PROP_TYPE_COMPOSITE is implemented
32793ebafc43Sjveta * and slot-names is properly flagged as such
32803ebafc43Sjveta */
32813ebafc43Sjveta if ((prop = di_prop_find(dev, node, DI_PROP_SLOT_NAMES)) ==
32823ebafc43Sjveta DI_PROP_NIL) {
32833ebafc43Sjveta *prop_data = NULL;
32843ebafc43Sjveta return (-1);
32853ebafc43Sjveta }
32863ebafc43Sjveta
32873ebafc43Sjveta return (di_prop_slot_names(prop, (void *)prop_data));
32883ebafc43Sjveta }
32893ebafc43Sjveta
32903ebafc43Sjveta /*
32913ebafc43Sjveta * returns an allocated array through <prop_data> only when its count > 0
32923ebafc43Sjveta * and the number of entries (count) as the function return value;
32933ebafc43Sjveta * use di_slot_names_free() to free the array
32943ebafc43Sjveta */
32953ebafc43Sjveta int
di_prom_prop_slot_names(di_prom_prop_t prom_prop,di_slot_name_t ** prop_data)32963ebafc43Sjveta di_prom_prop_slot_names(di_prom_prop_t prom_prop, di_slot_name_t **prop_data)
32973ebafc43Sjveta {
32983ebafc43Sjveta int rawlen, count;
32993ebafc43Sjveta uchar_t *rawdata;
33003ebafc43Sjveta
33013ebafc43Sjveta rawlen = di_prom_prop_data(prom_prop, &rawdata);
33023ebafc43Sjveta if (rawlen <= 0 || rawdata == NULL)
33033ebafc43Sjveta goto ERROUT;
33043ebafc43Sjveta
33053ebafc43Sjveta count = di_slot_names_decode(rawdata, rawlen, prop_data);
33063ebafc43Sjveta if (count < 0 || *prop_data == NULL)
33073ebafc43Sjveta goto ERROUT;
33083ebafc43Sjveta
33093ebafc43Sjveta return (count);
33103ebafc43Sjveta /*NOTREACHED*/
33113ebafc43Sjveta ERROUT:
33123ebafc43Sjveta errno = EFAULT;
33133ebafc43Sjveta *prop_data = NULL;
33143ebafc43Sjveta return (-1);
33153ebafc43Sjveta }
33163ebafc43Sjveta
33173ebafc43Sjveta int
di_prom_prop_lookup_slot_names(di_prom_handle_t ph,di_node_t node,di_slot_name_t ** prop_data)33183ebafc43Sjveta di_prom_prop_lookup_slot_names(di_prom_handle_t ph, di_node_t node,
33193ebafc43Sjveta di_slot_name_t **prop_data)
33203ebafc43Sjveta {
33213ebafc43Sjveta struct di_prom_prop *prom_prop;
33223ebafc43Sjveta
33233ebafc43Sjveta prom_prop = di_prom_prop_lookup_common(ph, node, DI_PROP_SLOT_NAMES);
33243ebafc43Sjveta if (prom_prop == NULL) {
33253ebafc43Sjveta *prop_data = NULL;
33263ebafc43Sjveta return (-1);
33273ebafc43Sjveta }
33283ebafc43Sjveta
33293ebafc43Sjveta return (di_prom_prop_slot_names(prom_prop, prop_data));
33303ebafc43Sjveta }
33313ebafc43Sjveta
33327c478bd9Sstevel@tonic-gate di_lnode_t
di_link_to_lnode(di_link_t link,uint_t endpoint)33337c478bd9Sstevel@tonic-gate di_link_to_lnode(di_link_t link, uint_t endpoint)
33347c478bd9Sstevel@tonic-gate {
33357c478bd9Sstevel@tonic-gate struct di_all *di_all;
33367c478bd9Sstevel@tonic-gate
33377c478bd9Sstevel@tonic-gate if ((link == DI_LINK_NIL) ||
33387c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) {
33397c478bd9Sstevel@tonic-gate errno = EINVAL;
33407c478bd9Sstevel@tonic-gate return (DI_LNODE_NIL);
33417c478bd9Sstevel@tonic-gate }
33427c478bd9Sstevel@tonic-gate
33437c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)link - DI_LINK(link)->self);
33447c478bd9Sstevel@tonic-gate
33457c478bd9Sstevel@tonic-gate if (endpoint == DI_LINK_SRC) {
33467c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all + DI_LINK(link)->src_lnode));
33477c478bd9Sstevel@tonic-gate } else {
33487c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all + DI_LINK(link)->tgt_lnode));
33497c478bd9Sstevel@tonic-gate }
33507c478bd9Sstevel@tonic-gate /* NOTREACHED */
33517c478bd9Sstevel@tonic-gate }
33527c478bd9Sstevel@tonic-gate
33537c478bd9Sstevel@tonic-gate char *
di_lnode_name(di_lnode_t lnode)33547c478bd9Sstevel@tonic-gate di_lnode_name(di_lnode_t lnode)
33557c478bd9Sstevel@tonic-gate {
33567c478bd9Sstevel@tonic-gate return (di_driver_name(di_lnode_devinfo(lnode)));
33577c478bd9Sstevel@tonic-gate }
33587c478bd9Sstevel@tonic-gate
33597c478bd9Sstevel@tonic-gate di_node_t
di_lnode_devinfo(di_lnode_t lnode)33607c478bd9Sstevel@tonic-gate di_lnode_devinfo(di_lnode_t lnode)
33617c478bd9Sstevel@tonic-gate {
33627c478bd9Sstevel@tonic-gate struct di_all *di_all;
33637c478bd9Sstevel@tonic-gate
33647c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)lnode - DI_LNODE(lnode)->self);
33657c478bd9Sstevel@tonic-gate return (DI_NODE((caddr_t)di_all + DI_LNODE(lnode)->node));
33667c478bd9Sstevel@tonic-gate }
33677c478bd9Sstevel@tonic-gate
33687c478bd9Sstevel@tonic-gate int
di_lnode_devt(di_lnode_t lnode,dev_t * devt)33697c478bd9Sstevel@tonic-gate di_lnode_devt(di_lnode_t lnode, dev_t *devt)
33707c478bd9Sstevel@tonic-gate {
33717c478bd9Sstevel@tonic-gate if ((lnode == DI_LNODE_NIL) || (devt == NULL)) {
33727c478bd9Sstevel@tonic-gate errno = EINVAL;
33737c478bd9Sstevel@tonic-gate return (-1);
33747c478bd9Sstevel@tonic-gate }
33757c478bd9Sstevel@tonic-gate if ((DI_LNODE(lnode)->dev_major == (major_t)-1) &&
33767c478bd9Sstevel@tonic-gate (DI_LNODE(lnode)->dev_minor == (minor_t)-1))
33777c478bd9Sstevel@tonic-gate return (-1);
33787c478bd9Sstevel@tonic-gate
33797c478bd9Sstevel@tonic-gate *devt = makedev(DI_LNODE(lnode)->dev_major, DI_LNODE(lnode)->dev_minor);
33807c478bd9Sstevel@tonic-gate return (0);
33817c478bd9Sstevel@tonic-gate }
33827c478bd9Sstevel@tonic-gate
33837c478bd9Sstevel@tonic-gate int
di_link_spectype(di_link_t link)33847c478bd9Sstevel@tonic-gate di_link_spectype(di_link_t link)
33857c478bd9Sstevel@tonic-gate {
33867c478bd9Sstevel@tonic-gate return (DI_LINK(link)->spec_type);
33877c478bd9Sstevel@tonic-gate }
33887c478bd9Sstevel@tonic-gate
33897c478bd9Sstevel@tonic-gate void
di_minor_private_set(di_minor_t minor,void * data)33907c478bd9Sstevel@tonic-gate di_minor_private_set(di_minor_t minor, void *data)
33917c478bd9Sstevel@tonic-gate {
33927c478bd9Sstevel@tonic-gate DI_MINOR(minor)->user_private_data = (uintptr_t)data;
33937c478bd9Sstevel@tonic-gate }
33947c478bd9Sstevel@tonic-gate
33957c478bd9Sstevel@tonic-gate void *
di_minor_private_get(di_minor_t minor)33967c478bd9Sstevel@tonic-gate di_minor_private_get(di_minor_t minor)
33977c478bd9Sstevel@tonic-gate {
33988309866bSanish return ((void *)(uintptr_t)DI_MINOR(minor)->user_private_data);
33997c478bd9Sstevel@tonic-gate }
34007c478bd9Sstevel@tonic-gate
34017c478bd9Sstevel@tonic-gate void
di_node_private_set(di_node_t node,void * data)34027c478bd9Sstevel@tonic-gate di_node_private_set(di_node_t node, void *data)
34037c478bd9Sstevel@tonic-gate {
34047c478bd9Sstevel@tonic-gate DI_NODE(node)->user_private_data = (uintptr_t)data;
34057c478bd9Sstevel@tonic-gate }
34067c478bd9Sstevel@tonic-gate
34077c478bd9Sstevel@tonic-gate void *
di_node_private_get(di_node_t node)34087c478bd9Sstevel@tonic-gate di_node_private_get(di_node_t node)
34097c478bd9Sstevel@tonic-gate {
34108309866bSanish return ((void *)(uintptr_t)DI_NODE(node)->user_private_data);
34117c478bd9Sstevel@tonic-gate }
34127c478bd9Sstevel@tonic-gate
34137c478bd9Sstevel@tonic-gate void
di_path_private_set(di_path_t path,void * data)3414602ca9eaScth di_path_private_set(di_path_t path, void *data)
3415602ca9eaScth {
3416602ca9eaScth DI_PATH(path)->user_private_data = (uintptr_t)data;
3417602ca9eaScth }
3418602ca9eaScth
3419602ca9eaScth void *
di_path_private_get(di_path_t path)3420602ca9eaScth di_path_private_get(di_path_t path)
3421602ca9eaScth {
3422602ca9eaScth return ((void *)(uintptr_t)DI_PATH(path)->user_private_data);
3423602ca9eaScth }
3424602ca9eaScth
3425602ca9eaScth void
di_lnode_private_set(di_lnode_t lnode,void * data)34267c478bd9Sstevel@tonic-gate di_lnode_private_set(di_lnode_t lnode, void *data)
34277c478bd9Sstevel@tonic-gate {
34287c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->user_private_data = (uintptr_t)data;
34297c478bd9Sstevel@tonic-gate }
34307c478bd9Sstevel@tonic-gate
34317c478bd9Sstevel@tonic-gate void *
di_lnode_private_get(di_lnode_t lnode)34327c478bd9Sstevel@tonic-gate di_lnode_private_get(di_lnode_t lnode)
34337c478bd9Sstevel@tonic-gate {
34348309866bSanish return ((void *)(uintptr_t)DI_LNODE(lnode)->user_private_data);
34357c478bd9Sstevel@tonic-gate }
34367c478bd9Sstevel@tonic-gate
34377c478bd9Sstevel@tonic-gate void
di_link_private_set(di_link_t link,void * data)34387c478bd9Sstevel@tonic-gate di_link_private_set(di_link_t link, void *data)
34397c478bd9Sstevel@tonic-gate {
34407c478bd9Sstevel@tonic-gate DI_LINK(link)->user_private_data = (uintptr_t)data;
34417c478bd9Sstevel@tonic-gate }
34427c478bd9Sstevel@tonic-gate
34437c478bd9Sstevel@tonic-gate void *
di_link_private_get(di_link_t link)34447c478bd9Sstevel@tonic-gate di_link_private_get(di_link_t link)
34457c478bd9Sstevel@tonic-gate {
34468309866bSanish return ((void *)(uintptr_t)DI_LINK(link)->user_private_data);
34477c478bd9Sstevel@tonic-gate }
34487c478bd9Sstevel@tonic-gate
34497c478bd9Sstevel@tonic-gate di_lnode_t
di_lnode_next(di_node_t node,di_lnode_t lnode)34507c478bd9Sstevel@tonic-gate di_lnode_next(di_node_t node, di_lnode_t lnode)
34517c478bd9Sstevel@tonic-gate {
34527c478bd9Sstevel@tonic-gate struct di_all *di_all;
34537c478bd9Sstevel@tonic-gate
34547c478bd9Sstevel@tonic-gate /*
34557c478bd9Sstevel@tonic-gate * paranoid error checking
34567c478bd9Sstevel@tonic-gate */
34577c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
34587c478bd9Sstevel@tonic-gate errno = EINVAL;
34597c478bd9Sstevel@tonic-gate return (DI_LNODE_NIL);
34607c478bd9Sstevel@tonic-gate }
34617c478bd9Sstevel@tonic-gate
34627c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)node - DI_NODE(node)->self);
34637c478bd9Sstevel@tonic-gate
34647c478bd9Sstevel@tonic-gate if (lnode == DI_NODE_NIL) {
3465f00128d8SToomas Soome if (DI_NODE(node)->lnodes != 0)
34667c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all +
34677c478bd9Sstevel@tonic-gate DI_NODE(node)->lnodes));
34687c478bd9Sstevel@tonic-gate } else {
3469f00128d8SToomas Soome if (DI_LNODE(lnode)->node_next != 0)
34707c478bd9Sstevel@tonic-gate return (DI_LNODE((caddr_t)di_all +
34717c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->node_next));
34727c478bd9Sstevel@tonic-gate }
34737c478bd9Sstevel@tonic-gate
34747c478bd9Sstevel@tonic-gate if (DINFOLYR & DI_ALL(di_all)->command)
34757c478bd9Sstevel@tonic-gate errno = ENXIO;
34767c478bd9Sstevel@tonic-gate else
34777c478bd9Sstevel@tonic-gate errno = ENOTSUP;
34787c478bd9Sstevel@tonic-gate
34797c478bd9Sstevel@tonic-gate return (DI_LNODE_NIL);
34807c478bd9Sstevel@tonic-gate }
34817c478bd9Sstevel@tonic-gate
34827c478bd9Sstevel@tonic-gate di_link_t
di_link_next_by_node(di_node_t node,di_link_t link,uint_t endpoint)34837c478bd9Sstevel@tonic-gate di_link_next_by_node(di_node_t node, di_link_t link, uint_t endpoint)
34847c478bd9Sstevel@tonic-gate {
34857c478bd9Sstevel@tonic-gate struct di_all *di_all;
34867c478bd9Sstevel@tonic-gate
34877c478bd9Sstevel@tonic-gate /*
34887c478bd9Sstevel@tonic-gate * paranoid error checking
34897c478bd9Sstevel@tonic-gate */
34907c478bd9Sstevel@tonic-gate if ((node == DI_NODE_NIL) ||
34917c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) {
34927c478bd9Sstevel@tonic-gate errno = EINVAL;
34937c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
34947c478bd9Sstevel@tonic-gate }
34957c478bd9Sstevel@tonic-gate
34967c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)node - DI_NODE(node)->self);
34977c478bd9Sstevel@tonic-gate
34987c478bd9Sstevel@tonic-gate if (endpoint == DI_LINK_SRC) {
34997c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) {
3500f00128d8SToomas Soome if (DI_NODE(node)->src_links != 0)
35017c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35027c478bd9Sstevel@tonic-gate DI_NODE(node)->src_links));
35037c478bd9Sstevel@tonic-gate } else {
3504f00128d8SToomas Soome if (DI_LINK(link)->src_node_next != 0)
35057c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35067c478bd9Sstevel@tonic-gate DI_LINK(link)->src_node_next));
35077c478bd9Sstevel@tonic-gate }
35087c478bd9Sstevel@tonic-gate } else {
35097c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) {
3510f00128d8SToomas Soome if (DI_NODE(node)->tgt_links != 0)
35117c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35127c478bd9Sstevel@tonic-gate DI_NODE(node)->tgt_links));
35137c478bd9Sstevel@tonic-gate } else {
3514f00128d8SToomas Soome if (DI_LINK(link)->tgt_node_next != 0)
35157c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35167c478bd9Sstevel@tonic-gate DI_LINK(link)->tgt_node_next));
35177c478bd9Sstevel@tonic-gate }
35187c478bd9Sstevel@tonic-gate }
35197c478bd9Sstevel@tonic-gate
35207c478bd9Sstevel@tonic-gate if (DINFOLYR & DI_ALL(di_all)->command)
35217c478bd9Sstevel@tonic-gate errno = ENXIO;
35227c478bd9Sstevel@tonic-gate else
35237c478bd9Sstevel@tonic-gate errno = ENOTSUP;
35247c478bd9Sstevel@tonic-gate
35257c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
35267c478bd9Sstevel@tonic-gate }
35277c478bd9Sstevel@tonic-gate
35287c478bd9Sstevel@tonic-gate di_link_t
di_link_next_by_lnode(di_lnode_t lnode,di_link_t link,uint_t endpoint)35297c478bd9Sstevel@tonic-gate di_link_next_by_lnode(di_lnode_t lnode, di_link_t link, uint_t endpoint)
35307c478bd9Sstevel@tonic-gate {
35317c478bd9Sstevel@tonic-gate struct di_all *di_all;
35327c478bd9Sstevel@tonic-gate
35337c478bd9Sstevel@tonic-gate /*
35347c478bd9Sstevel@tonic-gate * paranoid error checking
35357c478bd9Sstevel@tonic-gate */
35367c478bd9Sstevel@tonic-gate if ((lnode == DI_LNODE_NIL) ||
35377c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) {
35387c478bd9Sstevel@tonic-gate errno = EINVAL;
35397c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
35407c478bd9Sstevel@tonic-gate }
35417c478bd9Sstevel@tonic-gate
35427c478bd9Sstevel@tonic-gate di_all = DI_ALL((caddr_t)lnode - DI_LNODE(lnode)->self);
35437c478bd9Sstevel@tonic-gate
35447c478bd9Sstevel@tonic-gate if (endpoint == DI_LINK_SRC) {
35457c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) {
3546f00128d8SToomas Soome if (DI_LNODE(lnode)->link_out == 0)
35477c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
35487c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35497c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->link_out));
35507c478bd9Sstevel@tonic-gate } else {
3551f00128d8SToomas Soome if (DI_LINK(link)->src_link_next == 0)
35527c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
35537c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35547c478bd9Sstevel@tonic-gate DI_LINK(link)->src_link_next));
35557c478bd9Sstevel@tonic-gate }
35567c478bd9Sstevel@tonic-gate } else {
35577c478bd9Sstevel@tonic-gate if (link == DI_LINK_NIL) {
3558f00128d8SToomas Soome if (DI_LNODE(lnode)->link_in == 0)
35597c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
35607c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35617c478bd9Sstevel@tonic-gate DI_LNODE(lnode)->link_in));
35627c478bd9Sstevel@tonic-gate } else {
3563f00128d8SToomas Soome if (DI_LINK(link)->tgt_link_next == 0)
35647c478bd9Sstevel@tonic-gate return (DI_LINK_NIL);
35657c478bd9Sstevel@tonic-gate return (DI_LINK((caddr_t)di_all +
35667c478bd9Sstevel@tonic-gate DI_LINK(link)->tgt_link_next));
35677c478bd9Sstevel@tonic-gate }
35687c478bd9Sstevel@tonic-gate }
35697c478bd9Sstevel@tonic-gate /* NOTREACHED */
35707c478bd9Sstevel@tonic-gate }
35717c478bd9Sstevel@tonic-gate
35727c478bd9Sstevel@tonic-gate /*
35737c478bd9Sstevel@tonic-gate * Internal library function:
35747c478bd9Sstevel@tonic-gate * Invoke callback for each link data on the link list of first node
35757c478bd9Sstevel@tonic-gate * on node_list headp, and place children of first node on the list.
35767c478bd9Sstevel@tonic-gate *
35777c478bd9Sstevel@tonic-gate * This is similar to walk_one_node, except we only walk in child
35787c478bd9Sstevel@tonic-gate * first mode.
35797c478bd9Sstevel@tonic-gate */
35807c478bd9Sstevel@tonic-gate static void
walk_one_link(struct node_list ** headp,uint_t ep,void * arg,int (* callback)(di_link_t link,void * arg))35817c478bd9Sstevel@tonic-gate walk_one_link(struct node_list **headp, uint_t ep,
35827c478bd9Sstevel@tonic-gate void *arg, int (*callback)(di_link_t link, void *arg))
35837c478bd9Sstevel@tonic-gate {
35847c478bd9Sstevel@tonic-gate int action = DI_WALK_CONTINUE;
35857c478bd9Sstevel@tonic-gate di_link_t link = DI_LINK_NIL;
35867c478bd9Sstevel@tonic-gate di_node_t node = (*headp)->node;
35877c478bd9Sstevel@tonic-gate
35887c478bd9Sstevel@tonic-gate while ((link = di_link_next_by_node(node, link, ep)) != DI_LINK_NIL) {
35897c478bd9Sstevel@tonic-gate action = callback(link, arg);
35907c478bd9Sstevel@tonic-gate if (action == DI_WALK_TERMINATE) {
35917c478bd9Sstevel@tonic-gate break;
35927c478bd9Sstevel@tonic-gate }
35937c478bd9Sstevel@tonic-gate }
35947c478bd9Sstevel@tonic-gate
35957c478bd9Sstevel@tonic-gate update_node_list(action, DI_WALK_LINKGEN, headp);
35967c478bd9Sstevel@tonic-gate }
35977c478bd9Sstevel@tonic-gate
35987c478bd9Sstevel@tonic-gate int
di_walk_link(di_node_t root,uint_t flag,uint_t endpoint,void * arg,int (* link_callback)(di_link_t link,void * arg))35997c478bd9Sstevel@tonic-gate di_walk_link(di_node_t root, uint_t flag, uint_t endpoint, void *arg,
36007c478bd9Sstevel@tonic-gate int (*link_callback)(di_link_t link, void *arg))
36017c478bd9Sstevel@tonic-gate {
36027c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */
36037c478bd9Sstevel@tonic-gate
36047c478bd9Sstevel@tonic-gate #ifdef DEBUG
3605602ca9eaScth char *devfspath = di_devfs_path(root);
36067c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "walking %s link data under %s\n",
3607602ca9eaScth (endpoint == DI_LINK_SRC) ? "src" : "tgt", devfspath));
3608602ca9eaScth di_devfs_path_free(devfspath);
36097c478bd9Sstevel@tonic-gate #endif
36107c478bd9Sstevel@tonic-gate
36117c478bd9Sstevel@tonic-gate /*
36127c478bd9Sstevel@tonic-gate * paranoid error checking
36137c478bd9Sstevel@tonic-gate */
36147c478bd9Sstevel@tonic-gate if ((root == DI_NODE_NIL) || (link_callback == NULL) || (flag != 0) ||
36157c478bd9Sstevel@tonic-gate ((endpoint != DI_LINK_SRC) && (endpoint != DI_LINK_TGT))) {
36167c478bd9Sstevel@tonic-gate errno = EINVAL;
36177c478bd9Sstevel@tonic-gate return (-1);
36187c478bd9Sstevel@tonic-gate }
36197c478bd9Sstevel@tonic-gate
36207c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) {
36217c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n"));
36227c478bd9Sstevel@tonic-gate return (-1);
36237c478bd9Sstevel@tonic-gate }
36247c478bd9Sstevel@tonic-gate
36257c478bd9Sstevel@tonic-gate head->next = NULL;
36267c478bd9Sstevel@tonic-gate head->node = root;
36277c478bd9Sstevel@tonic-gate
36287c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start link data walking from node %s\n",
36297c478bd9Sstevel@tonic-gate di_node_name(root)));
36307c478bd9Sstevel@tonic-gate
36317c478bd9Sstevel@tonic-gate while (head != NULL)
36327c478bd9Sstevel@tonic-gate walk_one_link(&head, endpoint, arg, link_callback);
36337c478bd9Sstevel@tonic-gate
36347c478bd9Sstevel@tonic-gate return (0);
36357c478bd9Sstevel@tonic-gate }
36367c478bd9Sstevel@tonic-gate
36377c478bd9Sstevel@tonic-gate /*
36387c478bd9Sstevel@tonic-gate * Internal library function:
36397c478bd9Sstevel@tonic-gate * Invoke callback for each link data on the link list of first node
36407c478bd9Sstevel@tonic-gate * on node_list headp, and place children of first node on the list.
36417c478bd9Sstevel@tonic-gate *
36427c478bd9Sstevel@tonic-gate * This is similar to walk_one_node, except we only walk in child
36437c478bd9Sstevel@tonic-gate * first mode.
36447c478bd9Sstevel@tonic-gate */
36457c478bd9Sstevel@tonic-gate static void
walk_one_lnode(struct node_list ** headp,void * arg,int (* callback)(di_lnode_t lnode,void * arg))36467c478bd9Sstevel@tonic-gate walk_one_lnode(struct node_list **headp, void *arg,
36477c478bd9Sstevel@tonic-gate int (*callback)(di_lnode_t lnode, void *arg))
36487c478bd9Sstevel@tonic-gate {
36497c478bd9Sstevel@tonic-gate int action = DI_WALK_CONTINUE;
36507c478bd9Sstevel@tonic-gate di_lnode_t lnode = DI_LNODE_NIL;
36517c478bd9Sstevel@tonic-gate di_node_t node = (*headp)->node;
36527c478bd9Sstevel@tonic-gate
36537c478bd9Sstevel@tonic-gate while ((lnode = di_lnode_next(node, lnode)) != DI_LNODE_NIL) {
36547c478bd9Sstevel@tonic-gate action = callback(lnode, arg);
36557c478bd9Sstevel@tonic-gate if (action == DI_WALK_TERMINATE) {
36567c478bd9Sstevel@tonic-gate break;
36577c478bd9Sstevel@tonic-gate }
36587c478bd9Sstevel@tonic-gate }
36597c478bd9Sstevel@tonic-gate
36607c478bd9Sstevel@tonic-gate update_node_list(action, DI_WALK_LINKGEN, headp);
36617c478bd9Sstevel@tonic-gate }
36627c478bd9Sstevel@tonic-gate
36637c478bd9Sstevel@tonic-gate int
di_walk_lnode(di_node_t root,uint_t flag,void * arg,int (* lnode_callback)(di_lnode_t lnode,void * arg))36647c478bd9Sstevel@tonic-gate di_walk_lnode(di_node_t root, uint_t flag, void *arg,
36657c478bd9Sstevel@tonic-gate int (*lnode_callback)(di_lnode_t lnode, void *arg))
36667c478bd9Sstevel@tonic-gate {
36677c478bd9Sstevel@tonic-gate struct node_list *head; /* node_list for tree walk */
36687c478bd9Sstevel@tonic-gate
36697c478bd9Sstevel@tonic-gate #ifdef DEBUG
3670602ca9eaScth char *devfspath = di_devfs_path(root);
3671602ca9eaScth DPRINTF((DI_INFO, "walking lnode data under %s\n", devfspath));
3672602ca9eaScth di_devfs_path_free(devfspath);
36737c478bd9Sstevel@tonic-gate #endif
36747c478bd9Sstevel@tonic-gate
36757c478bd9Sstevel@tonic-gate /*
36767c478bd9Sstevel@tonic-gate * paranoid error checking
36777c478bd9Sstevel@tonic-gate */
36787c478bd9Sstevel@tonic-gate if ((root == DI_NODE_NIL) || (lnode_callback == NULL) || (flag != 0)) {
36797c478bd9Sstevel@tonic-gate errno = EINVAL;
36807c478bd9Sstevel@tonic-gate return (-1);
36817c478bd9Sstevel@tonic-gate }
36827c478bd9Sstevel@tonic-gate
36837c478bd9Sstevel@tonic-gate if ((head = malloc(sizeof (struct node_list))) == NULL) {
36847c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "malloc of node_list failed\n"));
36857c478bd9Sstevel@tonic-gate return (-1);
36867c478bd9Sstevel@tonic-gate }
36877c478bd9Sstevel@tonic-gate
36887c478bd9Sstevel@tonic-gate head->next = NULL;
36897c478bd9Sstevel@tonic-gate head->node = root;
36907c478bd9Sstevel@tonic-gate
36917c478bd9Sstevel@tonic-gate DPRINTF((DI_INFO, "Start lnode data walking from node %s\n",
36927c478bd9Sstevel@tonic-gate di_node_name(root)));
36937c478bd9Sstevel@tonic-gate
36947c478bd9Sstevel@tonic-gate while (head != NULL)
36957c478bd9Sstevel@tonic-gate walk_one_lnode(&head, arg, lnode_callback);
36967c478bd9Sstevel@tonic-gate
36977c478bd9Sstevel@tonic-gate return (0);
36987c478bd9Sstevel@tonic-gate }
36997c478bd9Sstevel@tonic-gate
370094c894bbSVikram Hegde static char *
alias_to_curr(di_node_t anynode,char * devfspath,di_node_t * nodep)370194c894bbSVikram Hegde alias_to_curr(di_node_t anynode, char *devfspath, di_node_t *nodep)
370294c894bbSVikram Hegde {
370394c894bbSVikram Hegde caddr_t pa;
370494c894bbSVikram Hegde struct di_all *all;
370594c894bbSVikram Hegde struct di_alias *di_alias;
370694c894bbSVikram Hegde di_node_t node;
370794c894bbSVikram Hegde char *curr;
370894c894bbSVikram Hegde char *cp;
370994c894bbSVikram Hegde char *alias;
371094c894bbSVikram Hegde di_off_t off;
371194c894bbSVikram Hegde char buf[MAXPATHLEN];
371294c894bbSVikram Hegde
371394c894bbSVikram Hegde *nodep = NULL;
371494c894bbSVikram Hegde
37156c70e1f8SJerry Gilliam if (anynode == DI_NODE_NIL || devfspath == NULL)
37166c70e1f8SJerry Gilliam return (NULL);
371794c894bbSVikram Hegde
371894c894bbSVikram Hegde pa = (caddr_t)anynode - DI_NODE(anynode)->self;
371994c894bbSVikram Hegde all = DI_ALL(pa);
372094c894bbSVikram Hegde
372194c894bbSVikram Hegde di_alias = NULL;
372294c894bbSVikram Hegde for (off = all->aliases; off > 0; off = di_alias->next) {
372394c894bbSVikram Hegde di_alias = DI_ALIAS(pa + off);
372494c894bbSVikram Hegde alias = di_alias->alias;
372594c894bbSVikram Hegde if (strncmp(devfspath, alias, strlen(alias)) == 0) {
372694c894bbSVikram Hegde cp = devfspath + strlen(alias);
372794c894bbSVikram Hegde node = DI_NODE(pa + di_alias->curroff);
372894c894bbSVikram Hegde assert(node != DI_NODE_NIL);
372994c894bbSVikram Hegde if (*cp == '\0') {
373094c894bbSVikram Hegde *nodep = node;
373194c894bbSVikram Hegde return (NULL);
373294c894bbSVikram Hegde } else if (*cp == '/') {
373394c894bbSVikram Hegde curr = di_devfs_path(node);
373494c894bbSVikram Hegde (void) snprintf(buf, sizeof (buf), "%s%s",
373594c894bbSVikram Hegde curr, cp);
373694c894bbSVikram Hegde di_devfs_path_free(curr);
373794c894bbSVikram Hegde curr = strdup(buf);
373894c894bbSVikram Hegde return (curr);
373994c894bbSVikram Hegde }
374094c894bbSVikram Hegde }
374194c894bbSVikram Hegde }
374294c894bbSVikram Hegde
374394c894bbSVikram Hegde return (NULL);
374494c894bbSVikram Hegde }
374594c894bbSVikram Hegde
374694c894bbSVikram Hegde static di_node_t
di_lookup_node_impl(di_node_t root,char * devfspath)374794c894bbSVikram Hegde di_lookup_node_impl(di_node_t root, char *devfspath)
37487c478bd9Sstevel@tonic-gate {
37497c478bd9Sstevel@tonic-gate struct di_all *dap;
37507c478bd9Sstevel@tonic-gate di_node_t node;
3751602ca9eaScth char *copy, *slash, *pname, *paddr;
37527c478bd9Sstevel@tonic-gate
37537c478bd9Sstevel@tonic-gate /*
37547c478bd9Sstevel@tonic-gate * Path must be absolute and musn't have duplicate slashes
37557c478bd9Sstevel@tonic-gate */
3756602ca9eaScth if (*devfspath != '/' || strstr(devfspath, "//")) {
3757602ca9eaScth DPRINTF((DI_ERR, "Invalid path: %s\n", devfspath));
37587c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
37597c478bd9Sstevel@tonic-gate }
37607c478bd9Sstevel@tonic-gate
37617c478bd9Sstevel@tonic-gate if (root == DI_NODE_NIL) {
37627c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "root node is DI_NODE_NIL\n"));
37637c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
37647c478bd9Sstevel@tonic-gate }
37657c478bd9Sstevel@tonic-gate
37667c478bd9Sstevel@tonic-gate dap = DI_ALL((caddr_t)root - DI_NODE(root)->self);
37677c478bd9Sstevel@tonic-gate if (strcmp(dap->root_path, "/") != 0) {
37687c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "snapshot root not / : %s\n", dap->root_path));
37697c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
37707c478bd9Sstevel@tonic-gate }
37717c478bd9Sstevel@tonic-gate
3772602ca9eaScth if ((copy = strdup(devfspath)) == NULL) {
3773602ca9eaScth DPRINTF((DI_ERR, "strdup failed on: %s\n", devfspath));
37747c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
37757c478bd9Sstevel@tonic-gate }
37767c478bd9Sstevel@tonic-gate
37777c478bd9Sstevel@tonic-gate for (slash = copy, node = root; slash; ) {
37787c478bd9Sstevel@tonic-gate
37797c478bd9Sstevel@tonic-gate /*
3780602ca9eaScth * Handle devfspath = "/" case as well as trailing '/'
37817c478bd9Sstevel@tonic-gate */
37827c478bd9Sstevel@tonic-gate if (*(slash + 1) == '\0')
37837c478bd9Sstevel@tonic-gate break;
37847c478bd9Sstevel@tonic-gate
37857c478bd9Sstevel@tonic-gate /*
37867c478bd9Sstevel@tonic-gate * More path-components exist. Deal with the next one
37877c478bd9Sstevel@tonic-gate */
37887c478bd9Sstevel@tonic-gate pname = slash + 1;
37897c478bd9Sstevel@tonic-gate node = di_child_node(node);
37907c478bd9Sstevel@tonic-gate
37917c478bd9Sstevel@tonic-gate if (slash = strchr(pname, '/'))
37927c478bd9Sstevel@tonic-gate *slash = '\0';
37937c478bd9Sstevel@tonic-gate if (paddr = strchr(pname, '@'))
37947c478bd9Sstevel@tonic-gate *paddr++ = '\0';
37957c478bd9Sstevel@tonic-gate
37967c478bd9Sstevel@tonic-gate for (; node != DI_NODE_NIL; node = di_sibling_node(node)) {
37977c478bd9Sstevel@tonic-gate char *name, *baddr;
37987c478bd9Sstevel@tonic-gate
37997c478bd9Sstevel@tonic-gate name = di_node_name(node);
38007c478bd9Sstevel@tonic-gate baddr = di_bus_addr(node);
38017c478bd9Sstevel@tonic-gate
38027c478bd9Sstevel@tonic-gate if (strcmp(pname, name) != 0)
38037c478bd9Sstevel@tonic-gate continue;
38047c478bd9Sstevel@tonic-gate
38057c478bd9Sstevel@tonic-gate /*
38067c478bd9Sstevel@tonic-gate * Mappings between a "path-address" and bus-addr
38077c478bd9Sstevel@tonic-gate *
38087c478bd9Sstevel@tonic-gate * paddr baddr
38097c478bd9Sstevel@tonic-gate * ---------------------
38107c478bd9Sstevel@tonic-gate * NULL NULL
38117c478bd9Sstevel@tonic-gate * NULL ""
38127c478bd9Sstevel@tonic-gate * "" N/A (invalid paddr)
38137c478bd9Sstevel@tonic-gate */
38147c478bd9Sstevel@tonic-gate if (paddr && baddr && strcmp(paddr, baddr) == 0)
38157c478bd9Sstevel@tonic-gate break;
38167c478bd9Sstevel@tonic-gate if (paddr == NULL && (baddr == NULL || *baddr == '\0'))
38177c478bd9Sstevel@tonic-gate break;
38187c478bd9Sstevel@tonic-gate }
38197c478bd9Sstevel@tonic-gate
38207c478bd9Sstevel@tonic-gate /*
38217c478bd9Sstevel@tonic-gate * No nodes in the sibling list or there was no match
38227c478bd9Sstevel@tonic-gate */
38237c478bd9Sstevel@tonic-gate if (node == DI_NODE_NIL) {
38247c478bd9Sstevel@tonic-gate DPRINTF((DI_ERR, "%s@%s: no node\n", pname, paddr));
3825602ca9eaScth free(copy);
38267c478bd9Sstevel@tonic-gate return (DI_NODE_NIL);
38277c478bd9Sstevel@tonic-gate }
38287c478bd9Sstevel@tonic-gate }
38297c478bd9Sstevel@tonic-gate
38307c478bd9Sstevel@tonic-gate assert(node != DI_NODE_NIL);
3831602ca9eaScth free(copy);
38327c478bd9Sstevel@tonic-gate return (node);
38337c478bd9Sstevel@tonic-gate }
38347c478bd9Sstevel@tonic-gate
383594c894bbSVikram Hegde di_node_t
di_lookup_node(di_node_t root,char * devfspath)383694c894bbSVikram Hegde di_lookup_node(di_node_t root, char *devfspath)
383794c894bbSVikram Hegde {
383894c894bbSVikram Hegde di_node_t node;
383994c894bbSVikram Hegde char *curr;
384094c894bbSVikram Hegde
384194c894bbSVikram Hegde node = di_lookup_node_impl(root, devfspath);
384294c894bbSVikram Hegde if (node != DI_NODE_NIL) {
384394c894bbSVikram Hegde return (node);
384494c894bbSVikram Hegde }
384594c894bbSVikram Hegde
384694c894bbSVikram Hegde /* node is already set to DI_NODE_NIL */
384794c894bbSVikram Hegde curr = alias_to_curr(root, devfspath, &node);
384894c894bbSVikram Hegde if (curr == NULL) {
384994c894bbSVikram Hegde /* node may or may node be DI_NODE_NIL */
385094c894bbSVikram Hegde return (node);
385194c894bbSVikram Hegde }
385294c894bbSVikram Hegde
385394c894bbSVikram Hegde node = di_lookup_node_impl(root, curr);
385494c894bbSVikram Hegde
385594c894bbSVikram Hegde free(curr);
385694c894bbSVikram Hegde
385794c894bbSVikram Hegde return (node);
385894c894bbSVikram Hegde }
385994c894bbSVikram Hegde
386094c894bbSVikram Hegde char *
di_alias2curr(di_node_t anynode,char * alias)386194c894bbSVikram Hegde di_alias2curr(di_node_t anynode, char *alias)
386294c894bbSVikram Hegde {
386394c894bbSVikram Hegde di_node_t currnode = DI_NODE_NIL;
38646c70e1f8SJerry Gilliam char *curr;
386594c894bbSVikram Hegde
38666c70e1f8SJerry Gilliam if (anynode == DI_NODE_NIL || alias == NULL)
38676c70e1f8SJerry Gilliam return (NULL);
38686c70e1f8SJerry Gilliam
38696c70e1f8SJerry Gilliam curr = alias_to_curr(anynode, alias, &currnode);
387094c894bbSVikram Hegde if (curr == NULL && currnode != DI_NODE_NIL) {
387194c894bbSVikram Hegde return (di_devfs_path(currnode));
387294c894bbSVikram Hegde } else if (curr == NULL) {
387394c894bbSVikram Hegde return (strdup(alias));
387494c894bbSVikram Hegde }
387594c894bbSVikram Hegde
387694c894bbSVikram Hegde return (curr);
387794c894bbSVikram Hegde }
387894c894bbSVikram Hegde
3879602ca9eaScth di_path_t
di_lookup_path(di_node_t root,char * devfspath)3880602ca9eaScth di_lookup_path(di_node_t root, char *devfspath)
3881602ca9eaScth {
3882602ca9eaScth di_node_t phci_node;
3883602ca9eaScth di_path_t path = DI_PATH_NIL;
3884602ca9eaScth char *copy, *lastslash;
3885602ca9eaScth char *pname, *paddr;
3886602ca9eaScth char *path_name, *path_addr;
3887602ca9eaScth
3888602ca9eaScth if ((copy = strdup(devfspath)) == NULL) {
3889602ca9eaScth DPRINTF((DI_ERR, "strdup failed on: %s\n", devfspath));
3890602ca9eaScth return (DI_NODE_NIL);
3891602ca9eaScth }
3892602ca9eaScth
3893602ca9eaScth if ((lastslash = strrchr(copy, '/')) == NULL) {
3894602ca9eaScth DPRINTF((DI_ERR, "failed to find component: %s\n", devfspath));
3895602ca9eaScth goto out;
3896602ca9eaScth }
3897602ca9eaScth
3898602ca9eaScth /* stop at pHCI and find the node for the phci */
3899602ca9eaScth *lastslash = '\0';
3900602ca9eaScth phci_node = di_lookup_node(root, copy);
3901602ca9eaScth if (phci_node == NULL) {
3902602ca9eaScth DPRINTF((DI_ERR, "failed to find component: %s\n", devfspath));
3903602ca9eaScth goto out;
3904602ca9eaScth }
3905602ca9eaScth
3906602ca9eaScth /* set up pname and paddr for last component */
3907602ca9eaScth pname = lastslash + 1;
3908602ca9eaScth if ((paddr = strchr(pname, '@')) == NULL) {
3909602ca9eaScth DPRINTF((DI_ERR, "failed to find unit-addr: %s\n", devfspath));
3910602ca9eaScth goto out;
3911602ca9eaScth }
3912602ca9eaScth *paddr++ = '\0';
3913602ca9eaScth
3914602ca9eaScth /* walk paths below phci looking for match */
3915602ca9eaScth for (path = di_path_phci_next_path(phci_node, DI_PATH_NIL);
3916602ca9eaScth path != DI_PATH_NIL;
3917602ca9eaScth path = di_path_phci_next_path(phci_node, path)) {
3918602ca9eaScth
3919602ca9eaScth /* get name@addr of path */
3920602ca9eaScth path_name = di_path_node_name(path);
3921602ca9eaScth path_addr = di_path_bus_addr(path);
3922602ca9eaScth if ((path_name == NULL) || (path_addr == NULL))
3923602ca9eaScth continue;
3924602ca9eaScth
3925602ca9eaScth /* break on match */
3926602ca9eaScth if ((strcmp(pname, path_name) == 0) &&
3927602ca9eaScth (strcmp(paddr, path_addr) == 0))
3928602ca9eaScth break;
3929602ca9eaScth }
3930602ca9eaScth
3931602ca9eaScth out: free(copy);
3932602ca9eaScth return (path);
3933602ca9eaScth }
3934602ca9eaScth
39357c478bd9Sstevel@tonic-gate static char *
msglevel2str(di_debug_t msglevel)39367c478bd9Sstevel@tonic-gate msglevel2str(di_debug_t msglevel)
39377c478bd9Sstevel@tonic-gate {
39387c478bd9Sstevel@tonic-gate switch (msglevel) {
39397c478bd9Sstevel@tonic-gate case DI_ERR:
39407c478bd9Sstevel@tonic-gate return ("ERROR");
39417c478bd9Sstevel@tonic-gate case DI_INFO:
39427c478bd9Sstevel@tonic-gate return ("Info");
39437c478bd9Sstevel@tonic-gate case DI_TRACE:
39447c478bd9Sstevel@tonic-gate return ("Trace");
39457c478bd9Sstevel@tonic-gate case DI_TRACE1:
39467c478bd9Sstevel@tonic-gate return ("Trace1");
39477c478bd9Sstevel@tonic-gate case DI_TRACE2:
39487c478bd9Sstevel@tonic-gate return ("Trace2");
39497c478bd9Sstevel@tonic-gate default:
39507c478bd9Sstevel@tonic-gate return ("UNKNOWN");
39517c478bd9Sstevel@tonic-gate }
39527c478bd9Sstevel@tonic-gate }
39537c478bd9Sstevel@tonic-gate
39547c478bd9Sstevel@tonic-gate void
dprint(di_debug_t msglevel,const char * fmt,...)39557c478bd9Sstevel@tonic-gate dprint(di_debug_t msglevel, const char *fmt, ...)
39567c478bd9Sstevel@tonic-gate {
39577c478bd9Sstevel@tonic-gate va_list ap;
39587c478bd9Sstevel@tonic-gate char *estr;
39597c478bd9Sstevel@tonic-gate
39607c478bd9Sstevel@tonic-gate if (di_debug <= DI_QUIET)
39617c478bd9Sstevel@tonic-gate return;
39627c478bd9Sstevel@tonic-gate
39637c478bd9Sstevel@tonic-gate if (di_debug < msglevel)
39647c478bd9Sstevel@tonic-gate return;
39657c478bd9Sstevel@tonic-gate
39667c478bd9Sstevel@tonic-gate estr = msglevel2str(msglevel);
39677c478bd9Sstevel@tonic-gate
39687c478bd9Sstevel@tonic-gate assert(estr);
39697c478bd9Sstevel@tonic-gate
39707c478bd9Sstevel@tonic-gate va_start(ap, fmt);
39717c478bd9Sstevel@tonic-gate
39727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "libdevinfo[%lu]: %s: ",
39737c478bd9Sstevel@tonic-gate (ulong_t)getpid(), estr);
39747c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, fmt, ap);
39757c478bd9Sstevel@tonic-gate
39767c478bd9Sstevel@tonic-gate va_end(ap);
39777c478bd9Sstevel@tonic-gate }
39787c478bd9Sstevel@tonic-gate
39797c478bd9Sstevel@tonic-gate /* end of devinfo.c */
3980