int
mp_find_cpu(dev_info_t *dip, void *arg)
{
    extern int get_portid_ddi(dev_info_t *, dev_info_t **);
    struct mp_find_cpu_arg *target = (struct mp_find_cpu_arg *)arg;
    char *type;
    int rv = DDI_WALK_CONTINUE;
    int cpuid;

    if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
                               "device_type", &type))
        return (DDI_WALK_CONTINUE);

    if (strcmp(type, "cpu") != 0)
        goto out;

    cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
                             DDI_PROP_DONTPASS, "cpuid", -1);

    if (cpuid == -1)
        cpuid = get_portid_ddi(dip, NULL);
    if (cpuid != target->cpuid)
        goto out;

    /* Found it */
    rv = DDI_WALK_TERMINATE;
    target->dip = dip;

out:
    ddi_prop_free(type);
    return (rv);
}
int
mp_find_cpu(dev_info_t *dip, void *arg)
{
	struct mp_find_cpu_arg *target = (struct mp_find_cpu_arg *)arg;
	char	*type;
	int	rv = DDI_WALK_CONTINUE;
	int	cpuid;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "device_type", &type))
		return (DDI_WALK_CONTINUE);

	if (strcmp(type, "cpu") != 0)
		goto out;

	cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
	    DDI_PROP_DONTPASS, "reg", -1);

	if (cpuid == -1) {
		cmn_err(CE_PANIC, "reg prop not found in cpu node");
	}

	cpuid = PROM_CFGHDL_TO_CPUID(cpuid);

	if (cpuid != target->cpuid)
		goto out;

	/* Found it */
	rv = DDI_WALK_TERMINATE;
	target->dip = dip;

out:
	ddi_prop_free(type);
	return (rv);
}
Exemple #3
0
int
_init(void)
{
	int	err;
	char tty_irq_param[9] = "ttyX-irq";
	char *tty_irq;
	int i;

	if ((err = mod_install(&modlinkage)) != 0)
		return (err);

	/* Check if any tty irqs are overridden by eeprom config */
	for (i = 0; i < num_BIOS_serial; i++) {
		tty_irq_param[3] = 'a' + i;
		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
		    DDI_PROP_DONTPASS, tty_irq_param, &tty_irq)
		    == DDI_PROP_SUCCESS) {
			long data;

			if (ddi_strtol(tty_irq, NULL, 0, &data) == 0) {
				asy_intrs[i] = (int)data;
				asy_intr_override |= 1<<i;
			}

			ddi_prop_free(tty_irq);
		}
	}

	impl_bus_add_probe(isa_enumerate);
	return (0);
}
Exemple #4
0
char *
spa_get_bootprop(char *propname)
{
	char *value;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, propname, &value) != DDI_SUCCESS)
		return (NULL);
	return (value);
}
Exemple #5
0
/*ARGSUSED*/
static int
fipe_search_ioat_dev(dev_info_t *dip, void *arg)
{
	char *unit;
	struct fipe_pci_ioat_id *id;
	int i, max, venid, devid, subvenid, subsysid;

	/* Query PCI id properties. */
	venid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "vendor-id", 0xffffffff);
	if (venid == 0xffffffff) {
		return (DDI_WALK_CONTINUE);
	}
	devid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "device-id", 0xffffffff);
	if (devid == 0xffffffff) {
		return (DDI_WALK_CONTINUE);
	}
	subvenid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "subsystem-vendor-id", 0xffffffff);
	if (subvenid == 0xffffffff) {
		return (DDI_WALK_CONTINUE);
	}
	subsysid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "subsystem-id", 0xffffffff);
	if (subvenid == 0xffffffff) {
		return (DDI_WALK_CONTINUE);
	}
	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "unit-address", &unit) != DDI_PROP_SUCCESS) {
		return (DDI_WALK_CONTINUE);
	}

	max = sizeof (fipe_pci_ioat_ids) / sizeof (fipe_pci_ioat_ids[0]);
	for (i = 0; i < max; i++) {
		id = &fipe_pci_ioat_ids[i];
		if ((id->venid == 0xffffu || id->venid == venid) &&
		    (id->devid == 0xffffu || id->devid == devid) &&
		    (id->subvenid == 0xffffu || id->subvenid == subvenid) &&
		    (id->subsysid == 0xffffu || id->subsysid == subsysid) &&
		    (id->unitaddr == NULL || strcmp(id->unitaddr, unit) == 0)) {
			break;
		}
	}
	ddi_prop_free(unit);
	if (i >= max) {
		return (DDI_WALK_CONTINUE);
	}

	/* Found IOAT device, hold one reference count. */
	ndi_hold_devi(dip);
	fipe_ioat_ctrl.ioat_dev_info = dip;

	return (DDI_WALK_TERMINATE);
}
/*
 * Check's if this child is a PCI device.
 * Child is a PCI device if:
 * parent has a dev_type of "pci"
 * -and-
 * child does not have a dev_type of "pciex"
 *
 * If the parent is not of dev_type "pci", then assume it is "pciex" and all
 * children should support using PCIe style MMCFG access.
 *
 * If parent's dev_type is "pci" and child is "pciex", then also enable using
 * PCIe style MMCFG access.  This covers the case where NPE is "pci" and a PCIe
 * RP is beneath.
 */
boolean_t
npe_child_is_pci(dev_info_t *dip) {
	char *dev_type;
	boolean_t parent_is_pci, child_is_pciex;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(dip),
	    DDI_PROP_DONTPASS, "device_type", &dev_type) ==
	    DDI_PROP_SUCCESS) {
		parent_is_pci = (strcmp(dev_type, "pci") == 0);
		ddi_prop_free(dev_type);
	} else {
		parent_is_pci = B_FALSE;
	}

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "device_type", &dev_type) == DDI_PROP_SUCCESS) {
		child_is_pciex = (strcmp(dev_type, "pciex") == 0);
		ddi_prop_free(dev_type);
	} else {
		child_is_pciex = B_FALSE;
	}

	return (parent_is_pci && !child_is_pciex);
}
Exemple #7
0
/*
 * sets master_ops_debug flag from propertyu passed by the boot
 */
static void
set_master_ops_debug_flags()
{
	char *prop;
	long flags;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "master_ops_debug", &prop) == DDI_PROP_SUCCESS) {
		long data;
		if (ddi_strtol(prop, NULL, 0, &data) == 0) {
			master_ops_debug = (unsigned long)data;
			e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(),
			    "master_ops_debug");
			e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(),
			    "master_ops_debug", data);
		}
		ddi_prop_free(prop);
	}
}
Exemple #8
0
static int
name_child(dev_info_t *child, char *name, int namelen)
{
	char *unitaddr;

	ddi_set_parent_data(child, NULL);

	name[0] = '\0';
	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
	    ACPIDEV_PROP_NAME_UNIT_ADDR, &unitaddr) == DDI_SUCCESS) {
		(void) strlcpy(name, unitaddr, namelen);
		ddi_prop_free(unitaddr);
	} else {
		ACPINEX_DEBUG(CE_NOTE, "!acpinex: failed to lookup child "
		    "unit-address prop for %p.", (void *)child);
	}

	return (DDI_SUCCESS);
}
Exemple #9
0
/*
 * Get boot property value for fastreboot_onpanic.
 *
 * NOTE: If fastreboot_onpanic is set to non-zero in /etc/system,
 * new setting passed in via "-B fastreboot_onpanic" is ignored.
 * This order of precedence is to enable developers debugging panics
 * that occur early in boot to utilize Fast Reboot on panic.
 */
static void
fastboot_get_bootprop(void)
{
	int		val = 0xaa, len, ret;
	dev_info_t	*devi;
	char		*propstr = NULL;

	devi = ddi_root_node();

	ret = ddi_prop_lookup_string(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
	    FASTREBOOT_ONPANIC, &propstr);

	if (ret == DDI_PROP_SUCCESS) {
		if (FASTREBOOT_ONPANIC_NOTSET(propstr))
			val = 0;
		else if (FASTREBOOT_ONPANIC_ISSET(propstr))
			val = UA_FASTREBOOT_ONPANIC;

		/*
		 * Only set fastreboot_onpanic to the value passed in
		 * if it's not already set to non-zero, and the value
		 * has indeed been passed in via command line.
		 */
		if (!fastreboot_onpanic && val != 0xaa)
			fastreboot_onpanic = val;
		ddi_prop_free(propstr);
	} else if (ret != DDI_PROP_NOT_FOUND && ret != DDI_PROP_UNDEFINED) {
		cmn_err(CE_NOTE, "!%s value is invalid, will be ignored",
		    FASTREBOOT_ONPANIC);
	}

	len = sizeof (fastreboot_onpanic_cmdline);
	ret = ddi_getlongprop_buf(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
	    FASTREBOOT_ONPANIC_CMDLINE, fastreboot_onpanic_cmdline, &len);

	if (ret == DDI_PROP_BUF_TOO_SMALL)
		cmn_err(CE_NOTE, "!%s value is too long, will be ignored",
		    FASTREBOOT_ONPANIC_CMDLINE);
}
Exemple #10
0
static int
console_type()
{
	static int boot_console = CONS_INVALID;

	char *cons;
	dev_info_t *root;

	if (boot_console != CONS_INVALID)
		return (boot_console);

#if defined(__xpv)
	if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) {
		boot_console = CONS_HYPERVISOR;
		return (boot_console);
	}
#endif /* __xpv */

	/*
	 * console is defined by "console" property, with
	 * fallback on the old "input-device" property.
	 * If "input-device" is not defined either, also check "output-device".
	 */
	boot_console = CONS_SCREEN;	/* default is screen/kb */
	root = ddi_root_node();
	if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
	    DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) ||
	    (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
	    DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) ||
	    (ddi_prop_lookup_string(DDI_DEV_T_ANY, root,
	    DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) {
		if (strcmp(cons, "ttya") == 0) {
			boot_console = CONS_TTYA;
		} else if (strcmp(cons, "ttyb") == 0) {
			boot_console = CONS_TTYB;
		} else if (strcmp(cons, "usb-serial") == 0) {
			(void) i_ddi_attach_hw_nodes("ehci");
			(void) i_ddi_attach_hw_nodes("uhci");
			(void) i_ddi_attach_hw_nodes("ohci");
			/*
			 * USB device enumerate asynchronously.
			 * Wait 2 seconds for USB serial devices to attach.
			 */
			delay(drv_usectohz(2000000));
			boot_console = CONS_USBSER;
#if defined(__xpv)
		} else if (strcmp(cons, "hypervisor") == 0) {
			boot_console = CONS_HYPERVISOR;
#endif /* __xpv */
		}
		ddi_prop_free(cons);
	}

	/*
	 * If the console is configured to use a framebuffer but none
	 * could be found, fallback to "ttya" since it's likely to exist
	 * and it matches longstanding behavior on SPARC.
	 */
	if (boot_console == CONS_SCREEN && plat_fbpath() == NULL)
		boot_console = CONS_TTYA;

	return (boot_console);
}
Exemple #11
0
/*
 * The VGA device could be under a subtractive PCI bridge on some systems.
 * Though the PCI_BCNF_BCNTRL_VGA_ENABLE bit is not set on such subtractive
 * PCI bridge, the subtractive PCI bridge can forward VGA access if no other
 * agent claims the access.
 * The vga_enable element in param acts as a flag, if not set, ignore the
 * checking for the PCI_BCNF_BCNTRL_VGA_ENABLE bit of the PCI bridge during
 * the search.
 */
static int
find_fb_dev(dev_info_t *dip, void *param)
{
	struct find_fb_dev_param *p = param;
	char *dev_type;
	dev_info_t *pdip;
	char *parent_type;

	if (dip == ddi_root_node())
		return (DDI_WALK_CONTINUE);

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
	    "device_type", &dev_type) != DDI_SUCCESS)
		return (DDI_WALK_PRUNECHILD);

	if ((strcmp(dev_type, "isa") == 0) || (strcmp(dev_type, "eisa") == 0)) {
		ddi_prop_free(dev_type);
		return (DDI_WALK_CONTINUE);
	}

	if ((strcmp(dev_type, "pci") == 0) ||
	    (strcmp(dev_type, "pciex") == 0)) {
		ddi_acc_handle_t pci_conf;
		uint16_t data16;
		char *nodename;

		ddi_prop_free(dev_type);

		if (!p->vga_enable)
			return (DDI_WALK_CONTINUE);

		nodename = ddi_node_name(dip);

		/*
		 * If the node is not a PCI-to-PCI bridge, continue traversing
		 * (it could be the root node), otherwise, check for the
		 * VGAEnable bit to be set in the Bridge Control Register.
		 */
		if (strcmp(nodename, "pci") == 0) {
			if (is_pci_bridge(dip) == B_FALSE)
				return (DDI_WALK_CONTINUE);
		}

		if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		data16 = pci_config_get16(pci_conf, PCI_BCNF_BCNTRL);
		pci_config_teardown(&pci_conf);

		if (data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)
			return (DDI_WALK_CONTINUE);

		return (DDI_WALK_PRUNECHILD);
	}

	if (strcmp(dev_type, "display") != 0) {
		ddi_prop_free(dev_type);
		return (DDI_WALK_CONTINUE);
	}

	ddi_prop_free(dev_type);

	if ((pdip = ddi_get_parent(dip)) == NULL)
		return (DDI_WALK_PRUNECHILD);

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip, DDI_PROP_DONTPASS,
	    "device_type", &parent_type) != DDI_SUCCESS)
		return (DDI_WALK_PRUNECHILD);

	if ((strcmp(parent_type, "isa") == 0) ||
	    (strcmp(parent_type, "eisa") == 0)) {
		p->found_dip = dip;
		ddi_prop_free(parent_type);
		return (DDI_WALK_TERMINATE);
	}

	if ((strcmp(parent_type, "pci") == 0) ||
	    (strcmp(parent_type, "pciex") == 0)) {
		ddi_acc_handle_t pci_conf;
		uint16_t data16;

		ddi_prop_free(parent_type);

		if (i_ddi_attach_node_hierarchy(dip) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		if (pci_config_setup(dip, &pci_conf) != DDI_SUCCESS)
			return (DDI_WALK_PRUNECHILD);

		data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
		pci_config_teardown(&pci_conf);

		if (!(data16 & PCI_COMM_IO))
			return (DDI_WALK_PRUNECHILD);

		p->found_dip = dip;
		return (DDI_WALK_TERMINATE);
	}

	ddi_prop_free(parent_type);
	return (DDI_WALK_PRUNECHILD);
}
Exemple #12
0
static int
zfs_vfs_mount(struct mount *mp, vnode_t devvp, user_addr_t data, vfs_context_t context)
{
	char	*osname = NULL;
	size_t  osnamelen = 0;
	int		error = 0;
	int		canwrite;
	/*
	 * Get the objset name (the "special" mount argument).
	 * The filesystem that we mount as root is defined in the
	 * "zfs-bootfs" property. 
	 */
	if (data) {
		user_addr_t fspec = USER_ADDR_NULL;
#ifndef __APPLE__
		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
		    DDI_PROP_DONTPASS, "zfs-bootfs", &zfs_bootpath) !=
		    DDI_SUCCESS)
			return (EIO);

		error = parse_bootpath(zfs_bootpath, rootfs.bo_name);
		ddi_prop_free(zfs_bootpath);
#endif
		osname = kmem_alloc(MAXPATHLEN, KM_SLEEP);

		if (vfs_context_is64bit(context)) {
			if ( (error = copyin(data, (caddr_t)&fspec, sizeof(fspec))) )
				goto out;	
		} else {
#ifdef ZFS_LEOPARD_ONLY
			char *tmp;
#else
			user32_addr_t tmp;
#endif
			if ( (error = copyin(data, (caddr_t)&tmp, sizeof(tmp))) )
				goto out;	
			/* munge into LP64 addr */
			fspec = CAST_USER_ADDR_T(tmp);
		}
		if ( (error = copyinstr(fspec, osname, MAXPATHLEN, &osnamelen)) )
			goto out;
	}

#if 0
	if (mvp->v_type != VDIR)
		return (ENOTDIR);

	mutex_enter(&mvp->v_lock);
	if ((uap->flags & MS_REMOUNT) == 0 &&
	    (uap->flags & MS_OVERLAY) == 0 &&
	    (mvp->v_count != 1 || (mvp->v_flag & VROOT))) {
		mutex_exit(&mvp->v_lock);
		return (EBUSY);
	}
	mutex_exit(&mvp->v_lock);

	/*
	 * ZFS does not support passing unparsed data in via MS_DATA.
	 * Users should use the MS_OPTIONSTR interface; this means
	 * that all option parsing is already done and the options struct
	 * can be interrogated.
	 */
	if ((uap->flags & MS_DATA) && uap->datalen > 0)
		return (EINVAL);

	/*
	 * Get the objset name (the "special" mount argument).
	 */
	if (error = pn_get(uap->spec, fromspace, &spn))
		return (error);

	osname = spn.pn_path;
#endif
	/*
	 * Check for mount privilege?
	 *
	 * If we don't have privilege then see if
	 * we have local permission to allow it
	 */
#ifndef __APPLE__
	error = secpolicy_fs_mount(cr, mvp, vfsp);
	if (error) {
		error = dsl_deleg_access(osname, ZFS_DELEG_PERM_MOUNT, cr);
		if (error == 0) {
			vattr_t		vattr;

			/*
			 * Make sure user is the owner of the mount point
			 * or has sufficient privileges.
			 */

			vattr.va_mask = AT_UID;

			if (error = VOP_GETATTR(mvp, &vattr, 0, cr)) {
				goto out;
			}

			if (error = secpolicy_vnode_owner(cr, vattr.va_uid)) {
				goto out;
			}

			if (error = VOP_ACCESS(mvp, VWRITE, 0, cr)) {
				goto out;
			}

			secpolicy_fs_mount_clearopts(cr, vfsp);
		} else {
			goto out;
		}
	}
#endif

	error = zfs_domount(mp, 0, osname, context);
	if (error)
		printf("zfs_vfs_mount: error %d\n", error);
	if (error == 0) {
		zfsvfs_t *zfsvfs = NULL;

		/* Make the Finder treat sub file systems just like a folder */
		if (strpbrk(osname, "/"))
			vfs_setflags(mp, (u_int64_t)((unsigned int)MNT_DONTBROWSE));

		/* Indicate to VFS that we support ACLs. */
		vfs_setextendedsecurity(mp);

		/* Advisory locking should be handled at the VFS layer */
		vfs_setlocklocal(mp);

		/*
		 * Mac OS X needs a file system modify time
		 *
		 * We use the mtime of the "com.apple.system.mtime" 
		 * extended attribute, which is associated with the
		 * file system root directory.
		 *
		 * Here we need to take a ref on z_mtime_vp to keep it around.
		 * If the attribute isn't there, attempt to create it.
		 */
		zfsvfs = vfs_fsprivate(mp);
		if (zfsvfs->z_mtime_vp == NULL) {
			struct vnode * rvp;
			struct vnode *xdvp = NULLVP;
			struct vnode *xvp = NULLVP;
			znode_t *rootzp;
			timestruc_t modify_time;
			cred_t  *cr;
			timestruc_t  now;
			int flag;
			int result;

			if (zfs_zget(zfsvfs, zfsvfs->z_root, &rootzp) != 0) {
				goto out;
			}
			rvp = ZTOV(rootzp);
			cr = (cred_t *)vfs_context_ucred(context);

			/* Grab the hidden attribute directory vnode. */
			result = zfs_get_xattrdir(rootzp, &xdvp, cr, CREATE_XATTR_DIR);
			vnode_put(rvp);	/* all done with root vnode */
			rvp = NULL;
			if (result) {
				goto out;
			}

			/*
			 * HACK - workaround missing vnode_setnoflush() KPI...
			 *
			 * We tag zfsvfs so that zfs_attach_vnode() can then set
			 * vnfs_marksystem when the vnode gets created.
			 */
			zfsvfs->z_last_unmount_time = 0xBADC0DE;
			zfsvfs->z_last_mtime_synced = VTOZ(xdvp)->z_id;
			flag = vfs_isrdonly(mp) ? 0 : ZEXISTS;
			/* Lookup or create the named attribute. */
			if ( zfs_obtain_xattr(VTOZ(xdvp), ZFS_MTIME_XATTR,
			                          S_IRUSR | S_IWUSR, cr, &xvp,
			                          flag) ) {
					zfsvfs->z_last_unmount_time = 0;
					zfsvfs->z_last_mtime_synced = 0;
					vnode_put(xdvp);
					goto out;
				}
				gethrestime(&now);
			ZFS_TIME_ENCODE(&now, VTOZ(xvp)->z_phys->zp_mtime);
			vnode_put(xdvp);
			vnode_ref(xvp);

			zfsvfs->z_mtime_vp = xvp;
			ZFS_TIME_DECODE(&modify_time, VTOZ(xvp)->z_phys->zp_mtime);
			zfsvfs->z_last_unmount_time = modify_time.tv_sec;
			zfsvfs->z_last_mtime_synced = modify_time.tv_sec;

			/*
			 * Keep this referenced vnode from impeding an unmount.
			 *
			 * XXX vnode_setnoflush() is MIA from KPI (see workaround above).
			 */
#if 0
			vnode_setnoflush(xvp);
#endif
			vnode_put(xvp);
		}
	}
out:
	if (osname) {
		kmem_free(osname, MAXPATHLEN);
	}
	return (error);
}
Exemple #13
0
/*ARGSUSED*/
static int
ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	dev_info_t *root = ddi_root_node();
	int instance;
	ppb_devstate_t *ppb;
	dev_info_t *pdip;
	ddi_acc_handle_t config_handle;
	char *bus;
	int ret;

	switch (cmd) {
	case DDI_ATTACH:

		/*
		 * Make sure the "device_type" property exists.
		 */
		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
		    "device_type", "pci");

		/*
		 * Allocate and get soft state structure.
		 */
		instance = ddi_get_instance(devi);
		if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
			return (DDI_FAILURE);
		ppb = ddi_get_soft_state(ppb_state, instance);
		ppb->dip = devi;

		/*
		 * don't enable ereports if immediate child of npe
		 */
		if (strcmp(ddi_driver_name(ddi_get_parent(devi)), "npe") == 0)
			ppb->ppb_fmcap = DDI_FM_ERRCB_CAPABLE |
			    DDI_FM_ACCCHK_CAPABLE | DDI_FM_DMACHK_CAPABLE;
		else
			ppb->ppb_fmcap = DDI_FM_EREPORT_CAPABLE |
			    DDI_FM_ERRCB_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
			    DDI_FM_DMACHK_CAPABLE;

		ddi_fm_init(devi, &ppb->ppb_fmcap, &ppb->ppb_fm_ibc);
		mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL);
		mutex_init(&ppb->ppb_err_mutex, NULL, MUTEX_DRIVER,
		    (void *)ppb->ppb_fm_ibc);
		mutex_init(&ppb->ppb_peek_poke_mutex, NULL, MUTEX_DRIVER,
		    (void *)ppb->ppb_fm_ibc);

		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
		    DDI_FM_EREPORT_CAPABLE))
			pci_ereport_setup(devi);
		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
			ddi_fm_handler_register(devi, ppb_fm_callback, NULL);

		if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
			if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
				ddi_fm_handler_unregister(devi);
			if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
			    DDI_FM_EREPORT_CAPABLE))
				pci_ereport_teardown(devi);
			ddi_fm_fini(devi);
			ddi_soft_state_free(ppb_state, instance);
			return (DDI_FAILURE);
		}

		ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO;
		for (pdip = ddi_get_parent(devi); pdip && (pdip != root) &&
		    (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
		    pdip = ddi_get_parent(pdip)) {
			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
			    DDI_PROP_DONTPASS, "device_type", &bus) !=
			    DDI_PROP_SUCCESS)
				break;

			if (strcmp(bus, "pciex") == 0)
				ppb->parent_bus =
				    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;

			ddi_prop_free(bus);
		}

		if (ppb_support_ht_msimap == 1)
			(void) ppb_ht_msimap_set(config_handle,
			    HT_MSIMAP_ENABLE);
		else if (ppb_support_ht_msimap == -1)
			(void) ppb_ht_msimap_set(config_handle,
			    HT_MSIMAP_DISABLE);

		pci_config_teardown(&config_handle);

		/*
		 * Initialize hotplug support on this bus.
		 */
		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
			ret = pcie_init(devi, NULL);
		else
			ret = pcihp_init(devi);

		if (ret != DDI_SUCCESS) {
			cmn_err(CE_WARN,
			    "pci: Failed to setup hotplug framework");
			(void) ppb_detach(devi, DDI_DETACH);
			return (ret);
		}

		ddi_report_dev(devi);
		return (DDI_SUCCESS);

	case DDI_RESUME:

		/*
		 * Get the soft state structure for the bridge.
		 */
		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
		ppb_restore_config_regs(ppb);
		return (DDI_SUCCESS);

	default:
		break;
	}
	return (DDI_FAILURE);
}
Exemple #14
0
/* register callback to mdeg */
static int
i_vldc_mdeg_register(vldc_t *vldcp)
{
	mdeg_prop_spec_t *pspecp;
	mdeg_node_spec_t *inst_specp;
	mdeg_handle_t	mdeg_hdl;
	size_t		templatesz;
	int		inst;
	char		*name;
	size_t		namesz;
	char		*nameprop;
	int		rv;

	/* get the unique vldc instance assigned by the LDom manager */
	inst = ddi_prop_get_int(DDI_DEV_T_ANY, vldcp->dip,
	    DDI_PROP_DONTPASS, "reg", -1);
	if (inst == -1) {
		cmn_err(CE_NOTE, "?vldc%d has no 'reg' property",
		    ddi_get_instance(vldcp->dip));
		return (DDI_FAILURE);
	}

	/* get the name of the vldc instance */
	rv = ddi_prop_lookup_string(DDI_DEV_T_ANY, vldcp->dip,
	    DDI_PROP_DONTPASS, "name", &nameprop);
	if (rv != DDI_PROP_SUCCESS) {
		cmn_err(CE_NOTE, "?vldc%d has no 'name' property",
		    ddi_get_instance(vldcp->dip));
		return (DDI_FAILURE);
	}

	D1("i_vldc_mdeg_register: name=%s, instance=%d\n", nameprop, inst);

	/*
	 * Allocate and initialize a per-instance copy
	 * of the global property spec array that will
	 * uniquely identify this vldc instance.
	 */
	templatesz = sizeof (vldc_prop_template);
	pspecp = kmem_alloc(templatesz, KM_SLEEP);

	bcopy(vldc_prop_template, pspecp, templatesz);

	/* copy in the name property */
	namesz = strlen(nameprop) + 1;
	name = kmem_alloc(namesz, KM_SLEEP);

	bcopy(nameprop, name, namesz);
	VLDC_SET_MDEG_PROP_NAME(pspecp, name);
	ddi_prop_free(nameprop);

	/* copy in the instance property */
	VLDC_SET_MDEG_PROP_INST(pspecp, inst);

	/* initialize the complete prop spec structure */
	inst_specp = kmem_alloc(sizeof (mdeg_node_spec_t), KM_SLEEP);
	inst_specp->namep = "virtual-device";
	inst_specp->specp = pspecp;

	/* perform the registration */
	rv = mdeg_register(inst_specp, &vport_match, i_vldc_mdeg_cb,
	    vldcp, &mdeg_hdl);

	if (rv != MDEG_SUCCESS) {
		cmn_err(CE_NOTE, "?i_vldc_mdeg_register: mdeg_register "
		    "failed, err = %d", rv);
		kmem_free(name, namesz);
		kmem_free(pspecp, templatesz);
		kmem_free(inst_specp, sizeof (mdeg_node_spec_t));
		return (DDI_FAILURE);
	}

	/* save off data that will be needed later */
	vldcp->inst_spec = inst_specp;
	vldcp->mdeg_hdl = mdeg_hdl;

	return (DDI_SUCCESS);
}
int
gfxp_vgatext_attach(dev_info_t *devi, ddi_attach_cmd_t cmd,
	gfxp_vgatext_softc_ptr_t ptr)
{
	struct vgatext_softc *softc = (struct vgatext_softc *)ptr;
	int	unit = ddi_get_instance(devi);
	int	error;
	char	*parent_type = NULL;
	int	reg_rnumber;
	off_t	reg_offset;
	off_t	mem_offset;
	char	*cons;
	int pci_pcie_bus = 0;
	int value;

	switch (cmd) {
	case DDI_ATTACH:
		break;

	case DDI_RESUME:
		vgatext_resume(softc);
		return (DDI_SUCCESS);

	default:
		return (DDI_FAILURE);
	}

	/* DDI_ATTACH */

	softc->devi = devi; /* Copy and init DEVI */

	softc->polledio.arg = (struct vis_polledio_arg *)softc;
	softc->polledio.display = vgatext_polled_display;
	softc->polledio.copy = vgatext_polled_copy;
	softc->polledio.cursor = vgatext_polled_cursor;

	mutex_init(&(softc->lock), NULL, MUTEX_DRIVER, NULL);

	error = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_get_parent(devi),
	    DDI_PROP_DONTPASS, "device_type", &parent_type);
	if (error != DDI_SUCCESS) {
		cmn_err(CE_WARN, MYNAME ": can't determine parent type.");
		goto fail;
	}

	/* Not enable AGP and DRM by default */
	if (STREQ(parent_type, "isa") || STREQ(parent_type, "eisa")) {
		reg_rnumber = vgatext_get_isa_reg_index(devi, 1, VGA_REG_ADDR,
		    &reg_offset);
		if (reg_rnumber < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for registers");
			error = DDI_FAILURE;
			goto fail;
		}
		softc->fb_regno = vgatext_get_isa_reg_index(devi, 0,
		    VGA_MEM_ADDR, &mem_offset);
		if (softc->fb_regno < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for memory");
			error = DDI_FAILURE;
			goto fail;
		}
	} else if (STREQ(parent_type, "pci") || STREQ(parent_type, "pciex")) {
		pci_pcie_bus = 1;
		reg_rnumber = vgatext_get_pci_reg_index(devi,
		    PCI_REG_ADDR_M|PCI_REG_REL_M,
		    PCI_ADDR_IO|PCI_RELOCAT_B, VGA_REG_ADDR,
		    &reg_offset);
		if (reg_rnumber < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for registers");
			error = DDI_FAILURE;
			goto fail;
		}
		softc->fb_regno = vgatext_get_pci_reg_index(devi,
		    PCI_REG_ADDR_M|PCI_REG_REL_M,
		    PCI_ADDR_MEM32|PCI_RELOCAT_B, VGA_MEM_ADDR,
		    &mem_offset);
		if (softc->fb_regno < 0) {
			cmn_err(CE_WARN,
			    MYNAME
			    ": can't find reg entry for memory");
			error = DDI_FAILURE;
			goto fail;
		}
	} else {
		cmn_err(CE_WARN, MYNAME ": unknown parent type \"%s\".",
		    parent_type);
		error = DDI_FAILURE;
		goto fail;
	}
	ddi_prop_free(parent_type);
	parent_type = NULL;

	error = ddi_regs_map_setup(devi, reg_rnumber,
	    (caddr_t *)&softc->regs.addr, reg_offset, VGA_REG_SIZE,
	    &dev_attr, &softc->regs.handle);
	if (error != DDI_SUCCESS)
		goto fail;
	softc->regs.mapped = B_TRUE;

	softc->fb_size = VGA_MEM_SIZE;

	error = ddi_regs_map_setup(devi, softc->fb_regno,
	    (caddr_t *)&softc->fb.addr,
	    mem_offset, softc->fb_size,
	    &dev_attr, &softc->fb.handle);
	if (error != DDI_SUCCESS)
		goto fail;
	softc->fb.mapped = B_TRUE;

	if (ddi_get8(softc->regs.handle,
	    softc->regs.addr + VGA_MISC_R) & VGA_MISC_IOA_SEL)
		softc->text_base = (caddr_t)softc->fb.addr + VGA_COLOR_BASE;
	else
		softc->text_base = (caddr_t)softc->fb.addr + VGA_MONO_BASE;

	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) {
		if (strcmp(cons, "graphics") == 0) {
			happyface_boot = 1;
			vgatext_silent = 1;
			softc->current_base = softc->shadow;
		} else {
			softc->current_base = softc->text_base;
		}
		ddi_prop_free(cons);
	} else {
		softc->current_base = softc->text_base;
	}

	error = ddi_prop_create(makedevice(DDI_MAJOR_T_UNKNOWN, unit),
	    devi, DDI_PROP_CANSLEEP, DDI_KERNEL_IOCTL, NULL, 0);
	if (error != DDI_SUCCESS)
		goto fail;

	gfxp_check_for_console(devi, softc, pci_pcie_bus);

	value = GFXP_IS_CONSOLE(softc) ? 1 : 0;
	if (ddi_prop_update_int(DDI_DEV_T_NONE, devi,
	    "primary-controller", value) != DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    "Can not %s primary-controller "
		    "property for driver", value ? "set" : "clear");
	}

	/* only do this if not in graphics mode */
	if ((vgatext_silent == 0) && (GFXP_IS_CONSOLE(softc))) {
		vgatext_init(softc);
		vgatext_save_colormap(softc);
	}

	return (DDI_SUCCESS);

fail:
	if (parent_type != NULL)
		ddi_prop_free(parent_type);
	(void) gfxp_vgatext_detach(devi, DDI_DETACH, (void *)softc);
	return (error);
}
Exemple #16
0
/*
 * Process acpi-user-options property  if present
 */
static void
acpica_process_user_options()
{
	static int processed = 0;
	int acpi_user_options;
	char *acpi_prop;

	/*
	 * return if acpi-user-options has already been processed
	 */
	if (processed)
		return;
	else
		processed = 1;

	/* converts acpi-user-options from type string to int, if any */
	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "acpi-user-options", &acpi_prop) ==
	    DDI_PROP_SUCCESS) {
		long data;
		int ret;
		ret = ddi_strtol(acpi_prop, NULL, 0, &data);
		if (ret == 0) {
			e_ddi_prop_remove(DDI_DEV_T_NONE, ddi_root_node(),
			    "acpi-user-options");
			e_ddi_prop_update_int(DDI_DEV_T_NONE, ddi_root_node(),
			    "acpi-user-options", data);
		}
		ddi_prop_free(acpi_prop);
	}

	/*
	 * fetch the optional options property
	 */
	acpi_user_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(),
	    DDI_PROP_DONTPASS, "acpi-user-options", 0);

	/*
	 * Note that 'off' has precedence over 'on'
	 * Also note - all cases of ACPI_OUSER_MASK
	 * provided here, no default: case is present
	 */
	switch (acpi_user_options & ACPI_OUSER_MASK) {
	case ACPI_OUSER_DFLT:
		acpica_enable = acpica_check_bios_date(1999, 1, 1);
		break;
	case ACPI_OUSER_ON:
		acpica_enable = TRUE;
		break;
	case ACPI_OUSER_OFF:
	case ACPI_OUSER_OFF | ACPI_OUSER_ON:
		acpica_enable = FALSE;
		break;
	}

	acpi_init_level = ACPI_FULL_INITIALIZATION;

	/*
	 * special test here; may be generalized in the
	 * future - test for a machines that are known to
	 * work only in legacy mode, and set OUSER_LEGACY if
	 * we're on one
	 */
	if (acpica_metro_old_bios())
		acpi_user_options |= ACPI_OUSER_LEGACY;

	/*
	 * If legacy mode is specified, set initialization
	 * options to avoid entering ACPI mode and hooking SCI
	 * - basically try to act like legacy acpi_intp
	 */
	if ((acpi_user_options & ACPI_OUSER_LEGACY) != 0)
		acpi_init_level |= (ACPI_NO_ACPI_ENABLE | ACPI_NO_HANDLER_INIT);

	/*
	 * modify default ACPI CA debug output level for non-DEBUG builds
	 * (to avoid BIOS debug chatter in /var/adm/messages)
	 */
	if (acpica_muzzle_debug_output)
		AcpiDbgLevel = 0;
}
static void
gfxp_check_for_console(dev_info_t *devi, struct vgatext_softc *softc,
	int pci_pcie_bus)
{
	ddi_acc_handle_t pci_conf;
	dev_info_t *pdevi;
	uint16_t data16;

	/*
	 * Based on Section 11.3, "PCI Display Subsystem Initialization",
	 * of the 1.1 PCI-to-PCI Bridge Architecture Specification
	 * determine if this is the boot console device.  First, see
	 * if the SBIOS has turned on PCI I/O for this device.  Then if
	 * this is PCI/PCI-E, verify the parent bridge has VGAEnable set.
	 */

	if (pci_config_setup(devi, &pci_conf) != DDI_SUCCESS) {
		cmn_err(CE_WARN,
		    MYNAME
		    ": can't get PCI conf handle");
		return;
	}

	data16 = pci_config_get16(pci_conf, PCI_CONF_COMM);
	if (data16 & PCI_COMM_IO)
		softc->flags |= GFXP_FLAG_CONSOLE;

	pci_config_teardown(&pci_conf);

	/* If IO not enabled or ISA/EISA, just return */
	if (!(softc->flags & GFXP_FLAG_CONSOLE) || !pci_pcie_bus)
		return;

	/*
	 * Check for VGA Enable in the Bridge Control register for all
	 * PCI/PCIEX parents.  If not set all the way up the chain,
	 * this cannot be the boot console.
	 */

	pdevi = ddi_get_parent(devi);
	while (pdevi) {
		int	error;
		ddi_acc_handle_t ppci_conf;
		char	*parent_type = NULL;

		error = ddi_prop_lookup_string(DDI_DEV_T_ANY, pdevi,
		    DDI_PROP_DONTPASS, "device_type", &parent_type);
		if (error != DDI_SUCCESS) {
			return;
		}

		/* Verify still on the PCI/PCIEX parent tree */
		if (!STREQ(parent_type, "pci") &&
		    !STREQ(parent_type, "pciex")) {
			ddi_prop_free(parent_type);
			return;
		}

		ddi_prop_free(parent_type);
		parent_type = NULL;

		if (pci_config_setup(pdevi, &ppci_conf) != DDI_SUCCESS) {
			/* No registers on root node, done with check */
			return;
		}

		data16 = pci_config_get16(ppci_conf, PCI_BCNF_BCNTRL);
		pci_config_teardown(&ppci_conf);

		if (!(data16 & PCI_BCNF_BCNTRL_VGA_ENABLE)) {
			softc->flags &= ~GFXP_FLAG_CONSOLE;
			return;
		}

		pdevi = ddi_get_parent(pdevi);
	}
}
Exemple #18
0
/*ARGSUSED*/
static int
ppb_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
{
	dev_info_t *root = ddi_root_node();
	int instance;
	ppb_devstate_t *ppb;
	dev_info_t *pdip;
	ddi_acc_handle_t config_handle;
	char *bus;

	switch (cmd) {
	case DDI_ATTACH:

		/*
		 * Make sure the "device_type" property exists.
		 */
		(void) ddi_prop_update_string(DDI_DEV_T_NONE, devi,
		    "device_type", "pci");

		/*
		 * Allocate and get soft state structure.
		 */
		instance = ddi_get_instance(devi);
		if (ddi_soft_state_zalloc(ppb_state, instance) != DDI_SUCCESS)
			return (DDI_FAILURE);
		ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state, instance);
		ppb->dip = devi;
		mutex_init(&ppb->ppb_mutex, NULL, MUTEX_DRIVER, NULL);
		ppb->ppb_soft_state = PCI_SOFT_STATE_CLOSED;
		if (pci_config_setup(devi, &config_handle) != DDI_SUCCESS) {
			mutex_destroy(&ppb->ppb_mutex);
			ddi_soft_state_free(ppb_state, instance);
			return (DDI_FAILURE);
		}
		ppb_pwr_setup(ppb, devi);

		if (PM_CAPABLE(ppb->ppb_pwr_p)) {
			mutex_enter(&ppb->ppb_pwr_p->pwr_mutex);

			/*
			 * Before reading config registers, make sure power is
			 * on, and remains on.
			 */
			ppb->ppb_pwr_p->pwr_fp++;

			pci_pwr_change(ppb->ppb_pwr_p,
			    ppb->ppb_pwr_p->current_lvl,
			    pci_pwr_new_lvl(ppb->ppb_pwr_p));
		}

		ppb->ppb_cache_line_size =
		    pci_config_get8(config_handle, PCI_CONF_CACHE_LINESZ);
		ppb->ppb_latency_timer =
		    pci_config_get8(config_handle, PCI_CONF_LATENCY_TIMER);

		/*
		 * Check whether the "ranges" property is present.
		 * Otherwise create the ranges property by reading
		 * the configuration registers
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
		    "ranges") == 0) {
			ppb_create_ranges_prop(devi, config_handle);
		}

		pci_config_teardown(&config_handle);

		if (PM_CAPABLE(ppb->ppb_pwr_p)) {
			ppb->ppb_pwr_p->pwr_fp--;

			pci_pwr_change(ppb->ppb_pwr_p,
			    ppb->ppb_pwr_p->current_lvl,
			    pci_pwr_new_lvl(ppb->ppb_pwr_p));

			mutex_exit(&ppb->ppb_pwr_p->pwr_mutex);
		}

		ppb->parent_bus = PCIE_PCIECAP_DEV_TYPE_PCI_PSEUDO;
		for (pdip = ddi_get_parent(ppb->dip); pdip && (pdip != root) &&
		    (ppb->parent_bus != PCIE_PCIECAP_DEV_TYPE_PCIE_DEV);
		    pdip = ddi_get_parent(pdip)) {
			if (ddi_prop_lookup_string(DDI_DEV_T_ANY, pdip,
			    DDI_PROP_DONTPASS, "device_type", &bus) !=
			    DDI_PROP_SUCCESS)
				break;

			if (strcmp(bus, "pciex") == 0)
				ppb->parent_bus =
				    PCIE_PCIECAP_DEV_TYPE_PCIE_DEV;

			ddi_prop_free(bus);
		}

		/*
		 * Initialize hotplug support on this bus.
		 */
		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
			if (pcie_init(devi, NULL) != DDI_SUCCESS) {
				(void) ppb_detach(devi, DDI_DETACH);
				return (DDI_FAILURE);
			}
		else
			ppb_init_hotplug(ppb);

		DEBUG1(DBG_ATTACH, devi,
		    "ppb_attach(): this nexus %s hotplug slots\n",
		    ppb->hotplug_capable == B_TRUE ? "has":"has no");

		ppb_fm_init(ppb);
		ddi_report_dev(devi);

		return (DDI_SUCCESS);

	case DDI_RESUME:
		/*
		 * Get the soft state structure for the bridge.
		 */
		ppb = (ppb_devstate_t *)
		    ddi_get_soft_state(ppb_state, ddi_get_instance(devi));

		pci_pwr_resume(devi, ppb->ppb_pwr_p);

		return (DDI_SUCCESS);
	}
	return (DDI_FAILURE);
}
Exemple #19
0
static int
gen_create_minor_nodes(dev_info_t *devi, struct dstate *dstatep)
{
	int rval = DDI_SUCCESS;
	char *node_name;

	node_name = ddi_node_name(devi);

	if (strcmp(node_name, "disk_chan") == 0) {
		rval = gen_create_mn_disk_chan(devi);
	} else if (strcmp(node_name, "disk_wwn") == 0) {
		rval = gen_create_mn_disk_wwn(devi);
	} else if (strcmp(node_name, "disk_cdrom") == 0) {
		rval = gen_create_mn_disk_cdrom(devi);
	} else if (strcmp(node_name, "disk_fd") == 0) {
		rval = gen_create_mn_disk_fd(devi);
	} else if (strcmp(node_name, "cgtwenty") == 0) {
		rval = gen_create_display(devi);
	} else if (strcmp(node_name, "genzs") == 0) {
		rval = gen_create_serial(devi);
	} else if (strcmp(node_name, "net") == 0) {
		rval = gen_create_net(devi);
	} else {
		int instance = ddi_get_instance(devi);
		char *node_type;

		/*
		 * Solaris may directly hang the node_type off the minor node
		 * (without making a copy).  Since we free the node_type
		 * property below we need to make a private copy to pass
		 * to ddi_create_minor_node to avoid devinfo snapshot panics.
		 * We store a pointer to our copy in dstate and free it in
		 * gen_detach after the minor nodes have been deleted by
		 * ddi_remove_minor_node.
		 */
		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, devi,
		    DDI_PROP_DONTPASS, "node-type", &node_type) != 0) {
			cmn_err(CE_WARN, "couldn't get node-type\n");
			return (DDI_FAILURE);
		}
		if (node_type) {
			dstatep->node_type = kmem_alloc(
			    strlen(node_type) + 1, KM_SLEEP);
			(void) strcpy(dstatep->node_type, node_type);
		}
		ddi_prop_free(node_type);

		/* the minor name is the same as the node name */
		if (ddi_create_minor_node(devi, node_name, S_IFCHR,
		    (INST_TO_MINOR(instance)), dstatep->node_type, NULL) !=
		    DDI_SUCCESS) {
			if (dstatep->node_type) {
				kmem_free(dstatep->node_type,
				    strlen(dstatep->node_type) + 1);
				dstatep->node_type = NULL;
			}
			return (DDI_FAILURE);
		}
		return (DDI_SUCCESS);
	}

	if (rval != DDI_SUCCESS) {
		ddi_prop_remove_all(devi);
		ddi_remove_minor_node(devi, NULL);
	}

	return (rval);
}
Exemple #20
0
/*
 * Per-instance initialization.  Suspend/resume not supported.
 */
static int
iospc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	iospc_t *iospc_p;
	int instance = ddi_get_instance(dip);
	char *ptr;

	IOSPC_DBG2("iospc: iospc_attach: enter\n");
	switch (cmd) {
	case DDI_RESUME:
	case DDI_ATTACH:
		/* Initialize one-time kstat structures. */
		mutex_enter(&iospc_mutex);
		if (!iospc_kstat_inited) {
			if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip,
			    0, "compatible", &ptr)) != DDI_PROP_SUCCESS)
				goto bad_property;

			if ((strcmp(ptr, "SUNW,ktios-pr") == 0) ||
			    (strcmp(ptr, "SUNW,rfios-pr") == 0)) {
				iospc_leaf_grps = rfios_bind_group();
			} else {
				ddi_prop_free(ptr);
				goto bad_property;
			}

			ddi_prop_free(ptr);

			if (iospc_kstat_init() != DDI_SUCCESS)
				goto bad_kstat_init;

			iospc_kstat_inited++;
		}
		mutex_exit(&iospc_mutex);

		if (ddi_soft_state_zalloc(iospc_state_p, instance) !=
		    DDI_SUCCESS) {
			goto bad_softstate;
		}

		iospc_p = (iospc_t *)ddi_get_soft_state(iospc_state_p,
		    instance);

		iospc_p->iospc_dip = dip;

		/* Set up kstats. */

		if (iospc_kstat_attach(iospc_p) != DDI_SUCCESS)
			goto bad_kstat_attach;

		IOSPC_DBG2("iospc: iospc_attach: exit SUCCESS\n");

		return (DDI_SUCCESS);

bad_kstat_attach:
		(void) ddi_soft_state_free(iospc_state_p, instance);
bad_softstate:
		iospc_kstat_fini();
bad_kstat_init:
bad_property:
		mutex_enter(&iospc_mutex);
		IOSPC_DBG2("iospc: iospc_attach: exit FAILURE\n");
		return (DDI_FAILURE);

	default:
		return (DDI_FAILURE);
	}
}
Exemple #21
0
/*
 * cnex_find_chan_dip -- Find the dip of a device that is corresponding
 * 	to the specific channel. Below are the details on how the dip
 *	is derived.
 *
 *	- In the MD, the cfg-handle is expected to be unique for
 *	  virtual-device nodes that have the same 'name' property value.
 *	  This value is expected to be the same as that of "reg" property
 *	  of the corresponding OBP device node.
 *
 *	- The value of the 'name' property of a virtual-device node
 *	  in the MD is expected to be the same for the corresponding
 *	  OBP device node.
 *
 *	- Find the virtual-device node corresponding to a channel-endpoint
 *	  by walking backwards. Then obtain the values for the 'name' and
 *	  'cfg-handle' properties.
 *
 *	- Walk all the children of the cnex, find a matching dip which
 *	  has the same 'name' and 'reg' property values.
 *
 *	- The channels that have no corresponding device driver are
 *	  treated as if they  correspond to the cnex driver,
 *	  that is, return cnex dip for them. This means, the
 *	  cnex acts as an umbrella device driver. Note, this is
 *	  for 'intrstat' statistics purposes only. As a result of this,
 *	  the 'intrstat' shows cnex as the device that is servicing the
 *	  interrupts corresponding to these channels.
 *
 *	  For now, only one such case is known, that is, the channels that
 *	  are used by the "domain-services".
 */
static dev_info_t *
cnex_find_chan_dip(dev_info_t *dip, uint64_t chan_id,
    md_t *mdp, mde_cookie_t mde)
{
	int listsz;
	int num_nodes;
	int num_devs;
	uint64_t cfghdl;
	char *md_name;
	mde_cookie_t *listp;
	dev_info_t *cdip = NULL;

	num_nodes = md_node_count(mdp);
	ASSERT(num_nodes > 0);
	listsz = num_nodes * sizeof (mde_cookie_t);
	listp = (mde_cookie_t *)kmem_zalloc(listsz, KM_SLEEP);

	num_devs = md_scan_dag(mdp, mde, md_find_name(mdp, "virtual-device"),
	    md_find_name(mdp, "back"), listp);
	ASSERT(num_devs <= 1);
	if (num_devs <= 0) {
		DWARN("cnex_find_chan_dip:channel(0x%llx): "
		    "No virtual-device found\n", chan_id);
		goto fdip_exit;
	}
	if (md_get_prop_str(mdp, listp[0], "name", &md_name) != 0) {
		DWARN("cnex_find_chan_dip:channel(0x%llx): "
		    "name property not found\n", chan_id);
		goto fdip_exit;
	}

	D1("cnex_find_chan_dip: channel(0x%llx): virtual-device "
	    "name property value = %s\n", chan_id, md_name);

	if (md_get_prop_val(mdp, listp[0], "cfg-handle", &cfghdl) != 0) {
		DWARN("cnex_find_chan_dip:channel(0x%llx): virtual-device's "
		    "cfg-handle property not found\n", chan_id);
		goto fdip_exit;
	}

	D1("cnex_find_chan_dip:channel(0x%llx): virtual-device cfg-handle "
	    " property value = 0x%x\n", chan_id, cfghdl);

	for (cdip = ddi_get_child(dip); cdip != NULL;
	    cdip = ddi_get_next_sibling(cdip)) {

		int *cnex_regspec;
		uint32_t reglen;
		char	*dev_name;

		if (ddi_prop_lookup_string(DDI_DEV_T_ANY, cdip,
		    DDI_PROP_DONTPASS, "name",
		    &dev_name) != DDI_PROP_SUCCESS) {
			DWARN("cnex_find_chan_dip: name property not"
			    " found for dip(0x%p)\n", cdip);
			continue;
		}
		if (strcmp(md_name, dev_name) != 0) {
			ddi_prop_free(dev_name);
			continue;
		}
		ddi_prop_free(dev_name);
		if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, cdip,
		    DDI_PROP_DONTPASS, "reg",
		    &cnex_regspec, &reglen) != DDI_SUCCESS) {
			DWARN("cnex_find_chan_dip: reg property not"
			    " found for dip(0x%p)\n", cdip);
			continue;
		}
		if (*cnex_regspec == cfghdl) {
			D1("cnex_find_chan_dip:channel(0x%llx): found "
			    "dip(0x%p) drvname=%s\n", chan_id, cdip,
			    ddi_driver_name(cdip));
			ddi_prop_free(cnex_regspec);
			break;
		}
		ddi_prop_free(cnex_regspec);
	}

fdip_exit:
	if (cdip == NULL) {
		/*
		 * If a virtual-device node exists but no dip found,
		 * then for now print a DEBUG error message only.
		 */
		if (num_devs > 0) {
			DERR("cnex_find_chan_dip:channel(0x%llx): "
			    "No device found\n", chan_id);
		}

		/* If no dip was found, return cnex device's dip. */
		cdip = dip;
	}

	kmem_free(listp, listsz);
	D1("cnex_find_chan_dip:channel(0x%llx): returning dip=0x%p\n",
	    chan_id, cdip);
	return (cdip);
}