Example #1
0
/*
 * xVM virtual block device
 *
 * VBDs are enumerated into xenstore by xend and named using
 * the linux dev_t values for 'hd' and 'xvd' devices.  Linux
 * dev_t's are 16-bit values.  The upper 8 bits identify the major #
 * of the device (hd, xvd) and the lower 8 bits the instance and partition
 *
 * For PV guests, VBDs are named by the virt-tools using
 * the form xvd[a-p][1-15].  The corresponding Solaris /dev/dsk name
 * created by this generator will be c0t[0-15]d[0-15]sN,
 * were the target (t) value represents [a-p] and the
 * disk (d) value is either 0 (e.g. xvda) or contains the partition
 * information if it has been specified [1-15] (e.g. xvda1)
 *
 * For PV guests using the legacy naming (0, 1, 2, ...)
 * the Solaris disk names created will be c0d[0..767]sN
 * The Solaris version of virt-install based on virtinst.101
 * named PV disks as sequential integers.  With virtinst.300_1 and
 * beyond, the virt-* tools will no longer create legacy disk
 * names.
 */
static int
disk_callback_xvmd(di_minor_t minor, di_node_t node)
{
#define	HD_BASE (3 << 8)
#define	XVBDMAJ 202

	char *addr;
	char disk[16];
	uint_t targ;
	uint_t lun = 0;
	uint_t fmaj;

	addr = di_bus_addr(node);
	targ = strtol(addr, (char **)NULL, 10);
	fmaj = targ >> 8;

	/* legacy device address */
	if (targ < HD_BASE)
		(void) snprintf(disk, sizeof (disk),  "d%d", targ);
	/* PV VBD */
	else if (fmaj == XVBDMAJ) {
		lun = targ & 0xf;
		targ = (targ & 0xff) >> 4;
		(void) snprintf(disk, sizeof (disk), "t%dd%d", targ, lun);
	/* HVM device names are generated using the standard generator */
	} else {
Example #2
0
static int
find_fru_node(di_node_t node, void *arg)
{
	frutree_locnode_t *locp = NULL;
	char	*char_di_bus_addr = NULL;
	int	busaddr = 0;
	int	di_busaddr = 0;
	char bus_addr[PICL_PROPNAMELEN_MAX];
	frutree_devinfo_t *devinfo = NULL;

	devinfo = *(frutree_devinfo_t **)arg;
	locp = *(frutree_locnode_t **)devinfo->arg;

	if (devinfo->rnode == node) {
		return (DI_WALK_CONTINUE);
	}

	char_di_bus_addr = di_bus_addr(node);
	if (char_di_bus_addr == NULL) {
		return (DI_WALK_PRUNECHILD);
	}

	if (ptree_get_propval_by_name(locp->locnodeh, PICL_PROP_BUS_ADDR,
		bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) {
		return (DI_WALK_PRUNECHILD);
	}

	if (strstr(bus_addr, ",") != NULL) {
		/* bus addr is of type 1,0 */
		if (strcmp(bus_addr, char_di_bus_addr) == 0) {
			devinfo->retval = PICL_SUCCESS;
			return (DI_WALK_TERMINATE);
		} else {
			return (DI_WALK_PRUNECHILD);
		}
	} else { /* bus addr is of type 0x */

		/* check if the values are same */
		errno = 0;
		busaddr = strtol(bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_PRUNECHILD);
		}

		errno = 0;
		di_busaddr = strtol(char_di_bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_PRUNECHILD);
		}

		if (di_busaddr == busaddr) {
			devinfo->retval = PICL_SUCCESS;
			return (DI_WALK_TERMINATE);
		} else {
			return (DI_WALK_PRUNECHILD);
		}
	}
}
Example #3
0
did_t *
split_bus_address(did_hash_t *dhash, di_node_t dp, uint_t baseaddr,
    uint_t bussep, int minbrd, int maxbrd, int *brd, int *br, int *bus,
    di_prom_handle_t promtree, topo_mod_t *mod)
{
	uint_t bc, ac;
	char *comma;
	char *bac;
	char *ba;
	int e;

	if ((ba = di_bus_addr(dp)) == NULL ||
	    (bac = topo_mod_strdup(mod, ba)) == NULL)
		return (NULL);

	topo_mod_dprintf(mod,
	    "Transcribing %s into board, bus, etc.\n", bac);

	if ((comma = strchr(bac, ',')) == NULL) {
		topo_mod_strfree(mod, bac);
		return (NULL);
	}
	*comma = '\0';
	bc = strtonum(mod, bac, &e);
	*comma = ',';
	if (e < 0) {
		topo_mod_dprintf(mod,
		    "Trouble interpreting %s before comma.\n", bac);
		topo_mod_strfree(mod, bac);
		return (NULL);
	}
	ac = strtonum(mod, comma + 1, &e);
	if (e < 0) {
		topo_mod_dprintf(mod,
		    "Trouble interpreting %s after comma.\n", bac);
		topo_mod_strfree(mod, bac);
		return (NULL);
	}
	topo_mod_strfree(mod, bac);

	*brd = ((bc - baseaddr) / bussep) + minbrd;
	*br = (bc - baseaddr) % bussep;
	*bus = ((ac == IOB_BUSADDR1) ? 0 : 1);
	if (*brd < minbrd || *brd > maxbrd || (*br != 0 && *br != 1) ||
	    (ac != IOB_BUSADDR1 && ac != IOB_BUSADDR2)) {
		topo_mod_dprintf(mod, "Trouble with transcription\n");
		topo_mod_dprintf(mod, "brd=%d br=%d bus=%d bc=%x ac=%x\n",
		    *brd, *br, *bus, bc, ac);
		return (NULL);
	}
	return (did_create(dhash, dp, *brd, *br, NO_RC, *bus, promtree));
}
Example #4
0
static int
disk_callback_nchan(di_minor_t minor, di_node_t node)
{
	char *addr;
	char disk[10];
	uint_t lun;

	addr = di_bus_addr(node);
	(void) sscanf(addr, "%X", &lun);
	(void) sprintf(disk, "d%d", lun);
	disk_common(minor, node, disk, 0);
	return (DEVFSADM_CONTINUE);

}
Example #5
0
static int
sunos_add_devices(di_devlink_t link, void *arg)
{
	struct devlink_cbarg	*largs = (struct devlink_cbarg *)arg;
	struct node_args	*nargs;
	di_node_t		myself, pnode;
	uint64_t		session_id = 0;
	uint16_t		bdf = 0;
	struct libusb_device	*dev;
	sunos_dev_priv_t	*devpriv;
	const char		*path, *newpath;
	int			 n, i;
	int			*addr_prop;
	uint8_t			bus_number = 0;

	nargs = (struct node_args *)largs->nargs;
	myself = largs->myself;
	if (nargs->last_ugenpath) {
		/* the same node's links */
		return (DI_WALK_CONTINUE);
	}

	/*
	 * Construct session ID.
	 * session ID = ...parent hub addr|hub addr|dev addr.
	 */
	pnode = myself;
	i = 0;
	while (pnode != DI_NODE_NIL) {
		if (di_prop_exists(DDI_DEV_T_ANY, pnode, "root-hub") == 1) {
			/* walk to root */
			uint32_t *regbuf = NULL;
			uint32_t reg;

			n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode, "reg",
			    (int **)&regbuf);
			reg = regbuf[0];
			bdf = (PCI_REG_BUS_G(reg) << 8) |
			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);
			session_id |= (bdf << i * 8);

			/* same as 'unit-address' property */
			bus_number =
			    (PCI_REG_DEV_G(reg) << 3) | PCI_REG_FUNC_G(reg);

			usbi_dbg("device bus address=%s:%x",
			    di_bus_addr(pnode), bus_number);

			break;
		}

		/* usb_addr */
		n = di_prop_lookup_ints(DDI_DEV_T_ANY, pnode,
		    "assigned-address", &addr_prop);
		if ((n != 1) || (addr_prop[0] == 0)) {
			usbi_dbg("cannot get valid usb_addr");

			return (DI_WALK_CONTINUE);
		}

		session_id |= ((addr_prop[0] & 0xff) << i * 8);
		if (++i > 7)
			break;

		pnode = di_parent_node(pnode);
	}

	path = di_devlink_path(link);
	dev = usbi_get_device_by_session_id(nargs->ctx, session_id);
	if (dev == NULL) {
		dev = usbi_alloc_device(nargs->ctx, session_id);
		if (dev == NULL) {
			usbi_dbg("can't alloc device");

			return (DI_WALK_TERMINATE);
		}
		devpriv = (sunos_dev_priv_t *)dev->os_priv;
		if ((newpath = strrchr(path, '/')) == NULL) {
			libusb_unref_device(dev);

			return (DI_WALK_TERMINATE);
		}
		devpriv->ugenpath = strndup(path, strlen(path) -
		    strlen(newpath));
		dev->bus_number = bus_number;

		if (sunos_fill_in_dev_info(myself, dev) != LIBUSB_SUCCESS) {
			libusb_unref_device(dev);

			return (DI_WALK_TERMINATE);
		}
		if (usbi_sanitize_device(dev) < 0) {
			libusb_unref_device(dev);
			usbi_dbg("sanatize failed: ");
			return (DI_WALK_TERMINATE);
		}
	} else {
		usbi_dbg("Dev %s exists", path);
	}

	devpriv = (sunos_dev_priv_t *)dev->os_priv;
	if (nargs->last_ugenpath == NULL) {
		/* first device */
		nargs->last_ugenpath = devpriv->ugenpath;

		if (discovered_devs_append(*(nargs->discdevs), dev) == NULL) {
			usbi_dbg("cannot append device");
		}

		/*
		 * we alloc and hence ref this dev. We don't need to ref it
		 * hereafter. Front end or app should take care of their ref.
		 */
		libusb_unref_device(dev);
	}

	usbi_dbg("Device %s %s id=0x%llx, devcount:%d, bdf=%x",
	    devpriv->ugenpath, path, (uint64_t)session_id,
	    (*nargs->discdevs)->len, bdf);

	return (DI_WALK_CONTINUE);
}
static int solarisWalkDeviceNode(di_node_t Node, void *pvArg)
{
    PUSBDEVICELIST pList = (PUSBDEVICELIST)pvArg;
    AssertPtrReturn(pList, DI_WALK_TERMINATE);

    /*
     * Check if it's a USB device in the first place.
     */
    bool fUSBDevice = false;
    char *pszCompatNames = NULL;
    int cCompatNames = di_compatible_names(Node, &pszCompatNames);
    for (int i = 0; i < cCompatNames; i++, pszCompatNames += strlen(pszCompatNames) + 1)
        if (!strncmp(pszCompatNames, "usb", 3))
        {
            fUSBDevice = true;
            break;
        }

    if (!fUSBDevice)
        return DI_WALK_CONTINUE;

    /*
     * Check if it's a device node or interface.
     */
    int *pInt = NULL;
    char *pStr = NULL;
    int rc = DI_WALK_CONTINUE;
    if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "interface", &pInt) < 0)
    {
        /* It's a device node. */
        char *pszDevicePath = di_devfs_path(Node);
        PUSBDEVICE pCur = (PUSBDEVICE)RTMemAllocZ(sizeof(*pCur));
        if (!pCur)
        {
            LogRel(("USBService: failed to allocate %d bytes for PUSBDEVICE.\n", sizeof(*pCur)));
            return DI_WALK_TERMINATE;
        }

        bool fValidDevice = false;
        do
        {
            AssertBreak(pszDevicePath);

            char *pszDriverName = di_driver_name(Node);

            /*
             * Skip hubs
             */
            if (   pszDriverName
                && !strcmp(pszDriverName, "hubd"))
            {
                break;
            }

            /*
             * Mandatory.
             * snv_85 and above have usb-dev-descriptor node properties, but older one's do not.
             * So if we cannot obtain the entire device descriptor, we try falling back to the
             * individual properties (those must not fail, if it does we drop the device).
             */
            uchar_t *pDevData = NULL;
            int cbProp = di_prop_lookup_bytes(DDI_DEV_T_ANY, Node, "usb-dev-descriptor", &pDevData);
            if (   cbProp > 0
                && pDevData)
            {
                usb_dev_descr_t *pDeviceDescriptor = (usb_dev_descr_t *)pDevData;
                pCur->bDeviceClass = pDeviceDescriptor->bDeviceClass;
                pCur->bDeviceSubClass = pDeviceDescriptor->bDeviceSubClass;
                pCur->bDeviceProtocol = pDeviceDescriptor->bDeviceProtocol;
                pCur->idVendor = pDeviceDescriptor->idVendor;
                pCur->idProduct = pDeviceDescriptor->idProduct;
                pCur->bcdDevice = pDeviceDescriptor->bcdDevice;
                pCur->bcdUSB = pDeviceDescriptor->bcdUSB;
                pCur->bNumConfigurations = pDeviceDescriptor->bNumConfigurations;
                pCur->fPartialDescriptor = false;
            }
            else
            {
                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-vendor-id", &pInt) > 0);
                pCur->idVendor = (uint16_t)*pInt;

                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-product-id", &pInt) > 0);
                pCur->idProduct = (uint16_t)*pInt;

                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-revision-id", &pInt) > 0);
                pCur->bcdDevice = (uint16_t)*pInt;

                AssertBreak(di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "usb-release", &pInt) > 0);
                pCur->bcdUSB = (uint16_t)*pInt;

                pCur->fPartialDescriptor = true;
            }

            char *pszPortAddr = di_bus_addr(Node);
            if (pszPortAddr)
                pCur->bPort = RTStrToUInt8(pszPortAddr);     /* Bus & Port are mixed up (kernel driver/userland) */
            else
                pCur->bPort = 0;

            char pathBuf[PATH_MAX];
            RTStrPrintf(pathBuf, sizeof(pathBuf), "%s", pszDevicePath);
            RTPathStripFilename(pathBuf);

            char szBuf[PATH_MAX + 48];
            RTStrPrintf(szBuf, sizeof(szBuf), "%#x:%#x:%d:%s", pCur->idVendor, pCur->idProduct, pCur->bcdDevice, pathBuf);
            pCur->pszAddress = RTStrDup(szBuf);

            pCur->pszDevicePath = RTStrDup(pszDevicePath);
            AssertBreak(pCur->pszDevicePath);

            /*
             * Optional (some devices don't have all these)
             */
            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-product-name", &pStr) > 0)
                pCur->pszProduct = RTStrDup(pStr);

            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-vendor-name", &pStr) > 0)
                pCur->pszManufacturer = RTStrDup(pStr);

            if (di_prop_lookup_strings(DDI_DEV_T_ANY, Node, "usb-serialno", &pStr) > 0)
                pCur->pszSerialNumber = RTStrDup(pStr);

            if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "low-speed", &pInt) >= 0)
                pCur->enmSpeed = USBDEVICESPEED_LOW;
            else if (di_prop_lookup_ints(DDI_DEV_T_ANY, Node, "high-speed", &pInt) >= 0)
                pCur->enmSpeed = USBDEVICESPEED_HIGH;
            else
                pCur->enmSpeed = USBDEVICESPEED_FULL;

            /* Determine state of the USB device. */
            pCur->enmState = solarisDetermineUSBDeviceState(pCur, Node);

            /*
             * Valid device, add it to the list.
             */
            fValidDevice = true;
            pCur->pPrev = pList->pTail;
            if (pList->pTail)
                pList->pTail = pList->pTail->pNext = pCur;
            else
                pList->pTail = pList->pHead = pCur;

            rc = DI_WALK_CONTINUE;
        } while(0);

        di_devfs_path_free(pszDevicePath);
        if (!fValidDevice)
            solarisFreeUSBDevice(pCur);
    }
    return rc;
}
Example #7
0
/*
 * initializes the port driver and instance fields based on libdevinfo
 */
picl_errno_t
get_port_info(frutree_portnode_t *portp)
{
	picl_errno_t rc;
	di_node_t rnode, curr, peer;
	char devfs_path[PICL_PROPNAMELEN_MAX];
	char bus_addr[PICL_PROPNAMELEN_MAX];
	char *di_busaddr = NULL, *di_drv = NULL;
	int di_int_busaddr, int_busaddr;

	if ((rc = ptree_get_propval_by_name(portp->portnodeh,
		PICL_PROP_DEVFS_PATH, devfs_path,
		sizeof (devfs_path))) != PICL_SUCCESS) {
		return (rc);
	}

	if (ptree_get_propval_by_name(portp->portnodeh, PICL_PROP_BUS_ADDR,
		bus_addr, sizeof (bus_addr)) != PICL_SUCCESS) {
		return (rc);
	}

	rnode = di_init(devfs_path, DINFOCPYALL);
	if (rnode == DI_NODE_NIL) {
		return (PICL_FAILURE);
	}

	peer = di_child_node(rnode);
	while (peer != DI_NODE_NIL) {
		curr = peer;
		peer = di_sibling_node(curr);

		di_busaddr = di_bus_addr(curr);
		if (di_busaddr == NULL) {
			continue;
		}

		/* compare the bus_addr */
		if (strstr(bus_addr, ",") != NULL) {
			/* bus addr is of type 1,0 */
			if (strcmp(bus_addr, di_busaddr) != 0) {
				continue;
			}
		} else { /* bus addr is of type 0x */
			errno = 0;
			int_busaddr = strtol(bus_addr, (char **)NULL, 16);
			if (errno != 0) {
				continue;
			}

			errno = 0;
			di_int_busaddr = strtol(di_busaddr, (char **)NULL, 16);
			if (errno != 0) {
				continue;
			}

			if (di_int_busaddr != int_busaddr) {
				continue;
			}
		}
		di_drv = di_driver_name(curr);
		if (di_drv == NULL) {
			di_fini(rnode);
			return (PICL_FAILURE);
		}
		/* initialize the driver name and instance number */
		(void) strncpy(portp->driver, di_drv, sizeof (portp->driver));
		portp->instance = di_instance(curr);
		di_fini(rnode);
		return (PICL_SUCCESS);
	}
	di_fini(rnode);
	return (PICL_NODENOTFOUND);
}
Example #8
0
static int
walk_tree(di_node_t node, void *arg)
{
	char	*path = NULL;
	char	*bus_addr = NULL;
	char	*char_di_bus_addr = NULL;
	int	busaddr = 0;
	int	di_busaddr = 0;
	char 	*node_name = NULL;
	frutree_devinfo_t *devinfo;
	frutree_frunode_t *frup = NULL;

	devinfo = *(frutree_devinfo_t **)arg;
	frup = (frutree_frunode_t *)devinfo->arg;
	if (frup == NULL) {
		return (DI_WALK_TERMINATE);
	}

	if (devinfo->rnode == node) {	/* skip the root node */
		return (DI_WALK_CONTINUE);
	}
	bus_addr = devinfo->bus_addr;

	char_di_bus_addr = di_bus_addr(node);
	if (char_di_bus_addr == NULL) {
		/*
		 * look for reg property
		 * This applies to only cPCI devices
		 */
		if (strstr(bus_addr, ",") != NULL) {
			/* bus addr is of type 1,0 */
			/* we dont handle this case yet */
			return (DI_WALK_PRUNECHILD);
		}
		di_busaddr = get_reg_dev(node);
		if (di_busaddr == -1) {
			/* reg prop not found */
			return (DI_WALK_PRUNECHILD);
		}

		/* check if the bus addresses are same */
		errno = 0;
		busaddr = strtol(bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_TERMINATE);
		}
		if (di_busaddr != busaddr) {
			return (DI_WALK_PRUNECHILD);
		}

		/* build the fru path name */
		/* parent_path/nodename@bus_addr */
		node_name = di_node_name(node);
		if (node_name == NULL) {
			return (DI_WALK_TERMINATE);
		}
		(void) snprintf(devinfo->path, sizeof (devinfo->path),
			"%s/%s@%s", frup->fru_path, node_name, bus_addr);
		return (DI_WALK_TERMINATE);
	}

	if (strstr(bus_addr, ",") != NULL) { /* bus addr is of type 1,0 */
		if (strcmp(bus_addr, char_di_bus_addr) != 0) {
			return (DI_WALK_PRUNECHILD);
		}
	} else { /* bus addr is of type 0x */

		/* check if the values are same */
		errno = 0;
		busaddr = strtol(bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_TERMINATE);
		}

		errno = 0;
		di_busaddr = strtol(char_di_bus_addr, (char **)NULL, 16);
		if (errno != 0) {
			return (DI_WALK_TERMINATE);
		}

		if (di_busaddr != busaddr) {
			return (DI_WALK_PRUNECHILD);
		}
	}

	/* node found */
	path = di_devfs_path(node);
	(void) strncpy(devinfo->path, path, sizeof (devinfo->path));
	di_devfs_path_free(path);
	return (DI_WALK_TERMINATE);
}
Example #9
0
/*
 * probe for port nodes
 */
static int
probe_tree(di_node_t node, void *arg)
{
	char *nodetype = NULL;
	char *devfs_path = NULL;
	char *bus_addr = NULL;
	char *drv_name = NULL;
	plist_t *listptr = NULL;
	port_info_t *port_info = NULL;
	frutree_port_type_t port_type = UNKNOWN_PORT;
	di_minor_t minor = DI_MINOR_NIL;

	if (arg == NULL) {
		return (DI_WALK_TERMINATE);
	}
	listptr = (plist_t *)arg;

	while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) {
		nodetype = di_minor_nodetype(minor);
		if (nodetype == NULL) {
			continue;
		}

		if (strcmp(nodetype, DDI_NT_NET) == 0) {
			port_type = NETWORK_PORT;
		} else if (strcmp(nodetype, DDI_NT_PARALLEL) == 0) {
			port_type = PARALLEL_PORT;
		} else if ((strcmp(nodetype, DDI_NT_SERIAL) == 0) ||
			(strcmp(nodetype, DDI_NT_SERIAL_MB) == 0) ||
			(strcmp(nodetype, DDI_NT_SERIAL_DO) == 0) ||
			(strcmp(nodetype, DDI_NT_SERIAL_MB_DO) == 0)) {
			port_type = SERIAL_PORT;
		} else {
			continue;
		}

		/* found port node */
		devfs_path = di_devfs_path(node);
		if (devfs_path == NULL) {
			continue;
		}

		bus_addr = di_bus_addr(node);
		drv_name = di_driver_name(node);

		if ((bus_addr == NULL) || (drv_name == NULL)) {
			di_devfs_path_free(devfs_path);
			continue;
		}

		port_info = malloc(sizeof (port_info_t));
		if (port_info == NULL) {
			di_devfs_path_free(devfs_path);
			return (PICL_NOSPACE);
		}

		(void) strncpy(port_info->devfs_path, devfs_path,
			sizeof (port_info->devfs_path));
		(void) strncpy(port_info->bus_addr, bus_addr,
			sizeof (port_info->bus_addr));
		(void) strncpy(port_info->drv_name, drv_name,
			sizeof (port_info->drv_name));
		port_info->type = port_type;
		port_info->instance = di_instance(node);
		port_info->geo_addr = -1;
		port_info->next = NULL;

		switch (port_type) {
		case NETWORK_PORT:
			listptr->n_network++;
			break;
		case SERIAL_PORT:
			listptr->n_serial++;
			break;
		case PARALLEL_PORT:
			listptr->n_parallel++;
			break;
		}

		/* add to the list */
		if (listptr->first == NULL) {	/* 1st node */
			listptr->first = port_info;
			listptr->last = NULL;
		} else if (listptr->last != NULL) { /* last node */
			listptr->last->next = port_info;
			listptr->last = port_info;
		} else {			/* 2nd node */
			listptr->first->next = port_info;
			listptr->last = port_info;
		}
		di_devfs_path_free(devfs_path);
		return (DI_WALK_CONTINUE);
	}
	return (DI_WALK_CONTINUE);
}
Example #10
0
/*
 * This function is identical to the one in the picldevtree plugin.
 * Unfortunately we can't just reuse that code.
 */
static void
add_devinfo_props(picl_nodehdl_t nodeh, di_node_t di_node)
{
	int			instance;
	char			*di_val;
	di_prop_t		di_prop;
	int			di_ptype;
	ptree_propinfo_t	propinfo;

	instance = di_instance(di_node);
	(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
	    PICL_PTYPE_INT, PICL_READ, sizeof (instance), PICL_PROP_INSTANCE,
	    NULL, NULL);
	(void) ptree_create_and_add_prop(nodeh, &propinfo, &instance, NULL);

	di_val = di_bus_addr(di_node);
	if (di_val) {
		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
		    PICL_PROP_BUS_ADDR, NULL, NULL);
		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
		    NULL);
	}

	di_val = di_binding_name(di_node);
	if (di_val) {
		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
		    PICL_PROP_BINDING_NAME, NULL, NULL);
		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
		    NULL);
	}

	di_val = di_driver_name(di_node);
	if (di_val) {
		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
		    PICL_PROP_DRIVER_NAME, NULL, NULL);
		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
		    NULL);
	}

	di_val = di_devfs_path(di_node);
	if (di_val) {
		(void) ptree_init_propinfo(&propinfo, PTREE_PROPINFO_VERSION,
		    PICL_PTYPE_CHARSTRING, PICL_READ, strlen(di_val) + 1,
		    PICL_PROP_DEVFS_PATH, NULL, NULL);
		(void) ptree_create_and_add_prop(nodeh, &propinfo, di_val,
		    NULL);
		di_devfs_path_free(di_val);
	}

	for (di_prop = di_prop_next(di_node, DI_PROP_NIL);
	    di_prop != DI_PROP_NIL;
	    di_prop = di_prop_next(di_node, di_prop)) {

		di_val = di_prop_name(di_prop);
		di_ptype = di_prop_type(di_prop);
		switch (di_ptype) {
		case DI_PROP_TYPE_BOOLEAN:
			(void) ptree_init_propinfo(&propinfo,
			    PTREE_PROPINFO_VERSION, PICL_PTYPE_VOID,
			    PICL_READ, (size_t)0, di_val, NULL, NULL);
			(void) ptree_create_and_add_prop(nodeh, &propinfo,
			    NULL, NULL);
			break;
		case DI_PROP_TYPE_INT: {
			int	*idata;
			int	len;

			len = di_prop_ints(di_prop, &idata);
			if (len < 0)
				/* Recieved error, so ignore prop */
				break;

			if (len == 1)
				(void) ptree_init_propinfo(&propinfo,
				    PTREE_PROPINFO_VERSION, PICL_PTYPE_INT,
				    PICL_READ, len * sizeof (int), di_val,
				    NULL, NULL);
			else
				(void) ptree_init_propinfo(&propinfo,
				    PTREE_PROPINFO_VERSION,
				    PICL_PTYPE_BYTEARRAY, PICL_READ,
				    len * sizeof (int), di_val,
				    NULL, NULL);

			(void) ptree_create_and_add_prop(nodeh, &propinfo,
			    idata, NULL);
		}
		break;
		case DI_PROP_TYPE_STRING: {
			char	*sdata;
			int	len;

			len = di_prop_strings(di_prop, &sdata);
			if (len < 0)
				break;

			if (len == 1) {
				(void) ptree_init_propinfo(&propinfo,
				    PTREE_PROPINFO_VERSION,
				    PICL_PTYPE_CHARSTRING, PICL_READ,
				    strlen(sdata) + 1, di_val,
				    NULL, NULL);
				(void) ptree_create_and_add_prop(nodeh,
				    &propinfo, sdata, NULL);
			} else {
				(void) add_string_list_prop(nodeh, di_val,
				    sdata, len);
			}
		}
		break;
		case DI_PROP_TYPE_BYTE: {
			int		len;
			unsigned char *bdata;

			len = di_prop_bytes(di_prop, &bdata);
			if (len < 0)
				break;
			(void) ptree_init_propinfo(&propinfo,
			    PTREE_PROPINFO_VERSION, PICL_PTYPE_BYTEARRAY,
			    PICL_READ, len, di_val, NULL, NULL);
			(void) ptree_create_and_add_prop(nodeh, &propinfo,
			    bdata, NULL);
		}
		break;
		case DI_PROP_TYPE_UNKNOWN:
			break;
		case DI_PROP_TYPE_UNDEF_IT:
			break;
		default:
			break;
		}
	}
}