Ejemplo n.º 1
0
static int
m3ua_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
{
	m3ua_t *m3ua, **m3p = &m3ua_devices;
	int cmajor = getmajor(*devp);
	int cminor = getmajor(*devp);

	trace();
	if (q->q_ptr != NULL)
		return (0);

	if (sflag == MODOPEN || WR(q)->q_next)
		return EIO;

	if (!cminor) {
		if (!m3ua_ctrlq)
			m3ua_ctrlq = q;
		else
			sflag = CLONEOPEN;
	}

	if (sflag == CLONEOPEN)
		cminor = 1;

	for (; cminor <= NMINORS && *m3p; m3p = &(*m3p)->next) {
		int dminor = getminor((*m3p)->devnum);

		if (cminor < dminor)
			break;
		if (cminor == dminor) {
			if (sflag == CLONEOPEN) {
				cminor++;
				continue;
			}
			return EIO;
		}
	}
	if (cminor > M3UA_MINOR)
		return ENXIO;

	*devp = makedevice(cmajor, cminor);

	if (!(m3ua = kmalloc(sizeof(*m3ua), GFP_KERNEL)))
		return ENOMEM;

	bzero(m3ua, sizeof(*m3ua));

	q->q_ptr = WR(q)->q_ptr;
	m3ua->rq = RD(q);
	m3ua->wq = WR(q);

	m3ua->state = FIXME;
	m3ua->devnum = *devp;

	return (0);
}
Ejemplo n.º 2
0
static int
vnode_match(vnode_t *v1, vnode_t *v2, cred_t *cr)
{
	vattr_t	v1attr, v2attr;

	/*
	 * If we have a device file, check to see if is a cloned open of the
	 * same device.  For self-cloning devices, the major numbers will match.
	 * For devices cloned through the 'clone' driver, the minor number of
	 * the source device will be the same as the major number of the cloned
	 * device.
	 */
	if ((v1->v_type == VCHR || v1->v_type == VBLK) &&
	    v1->v_type == v2->v_type) {
		if ((spec_is_selfclone(v1) || spec_is_selfclone(v2)) &&
		    getmajor(v1->v_rdev) == getmajor(v2->v_rdev))
			return (1);

		if (spec_is_clone(v1) &&
		    getmajor(v1->v_rdev) == getminor(v2->v_rdev))
			return (1);

		if (spec_is_clone(v2) &&
		    getmajor(v2->v_rdev) == getminor(v1->v_rdev))
			return (1);
	}

	v1attr.va_mask = v2attr.va_mask = AT_TYPE;

	/*
	 * This check for symbolic links handles the pseudo-symlinks in procfs.
	 * These particular links have v_type of VDIR, but the attributes have a
	 * type of VLNK.  We need to avoid these links because otherwise if we
	 * are currently in '/proc/self/fd', then '/proc/self/cwd' will compare
	 * as the same vnode.
	 */
	if (VOP_GETATTR(v1, &v1attr, 0, cr, NULL) != 0 ||
	    VOP_GETATTR(v2, &v2attr, 0, cr, NULL) != 0 ||
	    v1attr.va_type == VLNK || v2attr.va_type == VLNK)
		return (0);

	v1attr.va_mask = v2attr.va_mask = AT_TYPE | AT_FSID | AT_NODEID;

	if (VOP_GETATTR(v1, &v1attr, ATTR_REAL, cr, NULL) != 0 ||
	    VOP_GETATTR(v2, &v2attr, ATTR_REAL, cr, NULL) != 0)
		return (0);

	return (v1attr.va_fsid == v2attr.va_fsid &&
	    v1attr.va_nodeid == v2attr.va_nodeid);
}
Ejemplo n.º 3
0
/*ARGSUSED*/
static int
ipmi_open(dev_t *devp, int flag, int otyp, cred_t *cred)
{
	minor_t minor;
	ipmi_device_t *dev;

	if (ipmi_attached == B_FALSE)
		return (ENXIO);

	if (ipmi_found == B_FALSE)
		return (ENODEV);

	/* exclusive opens are not supported */
	if (flag & FEXCL)
		return (ENOTSUP);

	if ((minor = (minor_t)id_alloc_nosleep(minor_ids)) == 0)
		return (ENODEV);

	/* Initialize the per file descriptor data. */
	dev = kmem_zalloc(sizeof (ipmi_device_t), KM_SLEEP);

	dev->ipmi_pollhead = kmem_zalloc(sizeof (pollhead_t), KM_SLEEP);

	TAILQ_INIT(&dev->ipmi_completed_requests);
	dev->ipmi_address = IPMI_BMC_SLAVE_ADDR;
	dev->ipmi_lun = IPMI_BMC_SMS_LUN;
	*devp = makedevice(getmajor(*devp), minor);
	dev->ipmi_dev = *devp;

	list_insert_head(&dev_list, dev);

	return (0);
}
Ejemplo n.º 4
0
/* ARGSUSED1 */
static int
dropen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	struct drstate *dsp;

	if (sflag != MODOPEN) {	/* must be a pushed module */
		return (EINVAL);
	}

	if (secpolicy_net_rawaccess(crp) != 0) {
		return (EPERM);
	}

	if (q->q_ptr != NULL) {
		return (0);	/* already open */
	}

	dsp = kmem_zalloc(sizeof (*dsp), KM_SLEEP);
	dsp->dr_major = getmajor(*devp);
	mutex_init(&dsp->dr_lock, NULL, MUTEX_DEFAULT, NULL);
	q->q_ptr = OTHERQ(q)->q_ptr = dsp;
	qprocson(q);
	ddi_assoc_queue_with_devi(q, NULL);
	return (0);
}
Ejemplo n.º 5
0
/*
 * Create the "mac" kstat.  The "mac" kstat is comprised of three kinds of
 * statistics: statistics maintained by the mac module itself, generic mac
 * statistics maintained by the driver, and MAC-type specific statistics
 * also maintained by the driver.
 */
void
mac_driver_stat_create(mac_impl_t *mip)
{
	kstat_t		*ksp;
	kstat_named_t	*knp;
	uint_t		count;
	major_t		major = getmajor(mip->mi_phy_dev);

	count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount;
	ksp = kstat_create_zone((const char *)ddi_major_to_name(major),
	    getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME,
	    MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0, getzoneid());
	if (ksp == NULL)
		return;

	ksp->ks_update = i_mac_driver_stat_update;
	ksp->ks_private = mip;
	mip->mi_ksp = ksp;
	mip->mi_kstat_count = count;

	knp = (kstat_named_t *)ksp->ks_data;
	i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT);
	knp += MAC_MOD_NKSTAT;
	i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT);
	if (mip->mi_type->mt_statcount > 0) {
		knp += MAC_NKSTAT;
		i_mac_kstat_init(knp, mip->mi_type->mt_stats,
		    mip->mi_type->mt_statcount);
	}

	kstat_install(ksp);
}
Ejemplo n.º 6
0
 /* There are two minors 0 is the /dev/sad/admin driver and 1 is the /dev/sad/user driver.
    Permission for access to the /dev/sad/admin minor is performed by filesystem permission on the
    character device and a check on open. */
static streamscall int
sad_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	major_t major = getmajor(*devp);
	minor_t minor = getminor(*devp);

	if (q->q_ptr)
		return (0);	/* already open */
	switch (sflag) {
	case CLONEOPEN:
		minor = 1;
		if (sads[minor].assigned != 0)
			break;
	case DRVOPEN:
		if (minor != 0 && minor != 1)
			break;
#ifdef HAVE_KMEMB_STRUCT_CRED_UID_VAL
		if (minor == 0 && crp->cr_uid.val != 0 && crp->cr_ruid.val != 0)
			return (-EACCES);
#else
		if (minor == 0 && crp->cr_uid != 0 && crp->cr_ruid != 0)
			return (-EACCES);
#endif
		*devp = makedevice(major, minor);
		sads[minor].assigned |= 1;
		q->q_ptr = WR(q)->q_ptr = &sads[minor];
		qprocson(q);
		return (0);
	}
	return (-ENXIO);
}
Ejemplo n.º 7
0
/*ARGSUSED1*/
static int
ds1287_open(dev_t *devp, int flags, int otyp, cred_t *credp)
{
	struct ds1287 *softsp;
	int clone;

	if (otyp != OTYP_CHR)
		return (EINVAL);

	if ((softsp = ddi_get_soft_state(ds1287_state, instance)) ==
	    NULL)
		return (ENXIO);

	mutex_enter(&softsp->ds1287_mutex);
	for (clone = 1; clone < DS1287_MAX_CLONE; clone++)
		if (!softsp->clones[clone])
			break;

	if (clone == DS1287_MAX_CLONE) {
		cmn_err(CE_WARN, "ds1287_open: No more allocation left "
		    "to clone a minor.");
		mutex_exit(&softsp->ds1287_mutex);
		return (ENXIO);
	}

	*devp = makedevice(getmajor(*devp), (instance << 8) + clone);
	softsp->clones[clone] = 1;
	mutex_exit(&softsp->ds1287_mutex);

	return (0);
}
Ejemplo n.º 8
0
/*
 * Returns held device policy for the specific device node.
 * Note devfs_devpolicy returns with a hold on the policy.
 */
devplcy_t *
devpolicy_find(vnode_t *vp)
{
	dev_t dev = vp->v_rdev;
	vtype_t spec = vp->v_type;
	major_t maj = getmajor(dev);
	int i;
	devplcy_t *res;

	if (maj == clone_major)
		maj = getminor(dev);

	rw_enter(&policyrw, RW_READER);

	i = devpolicyent_bymajor(maj);

	if (i != -1) {
		res = match_policy(devpolicy[i].t_ent, dev, spec);
		dphold(res);
	} else if (devfs_devpolicy(vp, &res) != 0) {
		res = NETWORK_DRV(maj) ? netpolicy : dfltpolicy;
		dphold(res);
	}

	rw_exit(&policyrw);

	return (res);
}
Ejemplo n.º 9
0
void
wscnprobe(struct consdev *cp)
{
	extern int getmajor(void *);	/* conf.c */
	int major;

	major = getmajor(wsdisplayopen);
	if (major < 0)
		return;

#if NGPX > 0
	FRAMEBUFFER_PROBE(gpx);
#endif
#if NLCG > 0
	FRAMEBUFFER_PROBE(lcg);
#endif
#if NLCSPX > 0
	FRAMEBUFFER_PROBE(lcspx);
#endif
#if NSMG > 0
	FRAMEBUFFER_PROBE(smg);
#endif
	return;

found:
	cp->cn_pri = CN_INTERNAL;
	cp->cn_dev = makedev(major, 0);
}
Ejemplo n.º 10
0
/* ARGSUSED */
static int
log_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cr)
{
	log_t *lp;
	minor_t minor;

	if (sflag & (MODOPEN | CLONEOPEN))
		return (ENXIO);

	switch (minor = getminor(*devp)) {
	case LOG_CONSMIN:		/* clone open of /dev/conslog */
		if (flag & FREAD)
			return (EINVAL);	/* write-only device */
		if (q->q_ptr)
			return (0);
		break;

	case LOG_LOGMIN:		/* clone open of /dev/log */
		break;

	default:
		return (ENXIO);
	}

	lp = log_alloc(minor);
	if (lp == NULL)
		return (ENXIO);
	*devp = makedevice(getmajor(*devp), lp->log_minor);
	q->q_ptr = lp;
	WR(q)->q_ptr = lp;
	lp->log_inuse = 1;
	qprocson(q);

	return (0);
}
Ejemplo n.º 11
0
void check_promisc(int fildes, dl_promiscon_req_t * promiscon)
{
    char *device;
    file_t *file;
    cred_t *cred;
    dev_t rdev;

    if (promiscon->dl_primitive == DL_PROMISCON_REQ &&
        promiscon->dl_level == DL_PROMISC_PHYS) {

        file = getf(fildes);

        if (!file)
            return;

        rdev = file->f_vnode->v_rdev;
        device = ddi_major_to_name(getmajor(rdev));
        cred = ddi_get_cred();

        log_msg(CE_WARN, "Promiscuous mode enabled on interface %s",
                device ? device : "unknown");

        releasef(fildes);
    }

    return;
}
Ejemplo n.º 12
0
STATIC streamscall int
spm_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
{
	int cmajor = getmajor(*devp);
	int cminor = getminor(*devp);
	spm_t *s, **sp = &spm_list;

	(void) crp;
	MOD_INC_USE_COUNT;	/* keep module from unloading in our face */
	if (q->q_ptr != NULL) {
		MOD_DEC_USE_COUNT;
		return (0);	/* already open */
	}
	if (sflag == DRVOPEN || WR(q)->q_next == NULL) {
		ptrace(("spm: ERROR: Can't open as driver\n"));
		MOD_DEC_USE_COUNT;
		return (EIO);
	}
	for (; *sp && (*sp)->cmajor < cmajor; sp = &(*sp)->next) ;
	for (; *sp && (*sp)->cmajor == cmajor && (*sp)->cminor < cminor; sp = &(*sp)->next) ;
	if (*sp && (*sp)->cmajor == cmajor && (*sp)->cminor == cminor) {
		ptrace(("spm: ERROR: Multiple push\n"));
		MOD_DEC_USE_COUNT;
		return (ENXIO);
	}
	printd(("spm: Pushed module for char device %d:%d\n", cmajor, cminor));
	if (!(s = spm_alloc_priv(q, sp, cmajor, cminor))) {
		ptrace(("spm: ERROR: No cache memory\n"));
		MOD_DEC_USE_COUNT;
		return (ENOMEM);
	}
	return (0);
}
Ejemplo n.º 13
0
static streamscall int
zap_qopen(queue_t *q, dev_t *devp, int oflags, int sflag, cred_t *crp)
{
	major_t cmajor = getmajor(*devp);
	minor_t cminor = getminor(*devp);
	struct zt_chan *chan;
	int err;

	if (q->q_ptr != NULL)
		return (0);	/* already open */
	if (sflag == DRVOPEN && cmajor == CMAJOR_0) {
		if (cminor == 0) {
			/* explicit open of control device */
		} else if (cminor == 253) {
			/* special timining device */
		} else if (cminor == 254) {
		} else if (cminor == 255) {
		} else if (cminor < ZT_MAX_CHANNELS) {
			chan = &chans[cminor];
		} else
			goto enxio;
	} else if (sflag == CLONEOPEN && cmajor == CMAJOR_0) {
		if ((cminor == 255 && !(chan = zt_alloc_pseudo())) || cminor != 255)
			goto enxio;
	} else
		goto enxio;
	*devp = makedevice(cmajor, chan->channo);
	if ((err = zt_specchan_open(NULL, qstream(q)->sd_file, chan->channo, 1)))
		return (err < 0 ? -err : err);
	q->q_ptr = WR(q)->q_ptr = (void *) chan;
	return (0);
      enxio:
	return (ENXIO);
}
Ejemplo n.º 14
0
/*
 * Returns -1 or the instance number of the given dev_t as
 * interpreted by the device driver.  The code may load the driver
 * but it does not attach any instances.
 *
 * Instance is supposed to be a int but drivers have assumed that
 * the pointer was a pointer to "void *" instead of a pointer to
 * "int *" so we now explicitly pass a pointer to "void *" and then
 * cast the result to an int when returning the value.
 */
int
dev_to_instance(dev_t dev)
{
	major_t		major = getmajor(dev);
	struct dev_ops	*ops;
	void		*vinstance;
	int		error;

	/* verify that the driver is loaded */
	if ((ops = mod_hold_dev_by_major(major)) == NULL)
		return (-1);
	ASSERT(CB_DRV_INSTALLED(ops));

	/* verify that it supports the getinfo(9E) entry point */
	if (ops->devo_getinfo == NULL) {
		mod_rele_dev_by_major(major);
		return (-1);
	}

	/* ask the driver to extract the instance number from the devt */
	error = (*ops->devo_getinfo)(NULL, DDI_INFO_DEVT2INSTANCE,
	    (void *)dev, &vinstance);

	/* release the driver */
	mod_rele_dev_by_major(major);

	if (error != DDI_SUCCESS)
		return (-1);

	return ((int)(uintptr_t)vinstance);
}
Ejemplo n.º 15
0
/*
 * Leaf driver entry points. The following [cb]dev_* functions are *not* part
 * of the DDI, please use functions defined in <sys/sunldi.h> and driver_lyr.c.
 */
int
dev_open(dev_t *devp, int flag, int type, struct cred *cred)
{
	struct cb_ops   *cb;

	cb = devopsp[getmajor(*devp)]->devo_cb_ops;
	return ((*cb->cb_open)(devp, flag, type, cred));
}
Ejemplo n.º 16
0
int
dev_close(dev_t dev, int flag, int type, struct cred *cred)
{
	struct cb_ops   *cb;

	cb = (devopsp[getmajor(dev)])->devo_cb_ops;
	return ((*cb->cb_close)(dev, flag, type, cred));
}
Ejemplo n.º 17
0
static void
zvol_size_changed(zvol_state_t *zv, dev_t dev)
{
	dev = makedevice(getmajor(dev), zv->zv_minor);

	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
	    "Size", zv->zv_volsize) == DDI_SUCCESS);
	VERIFY(ddi_prop_update_int64(dev, zfs_dip,
	    "Nblocks", lbtodb(zv->zv_volsize)) == DDI_SUCCESS);
}
Ejemplo n.º 18
0
/**
 * User context entry points
 *
 * @remarks fFlags are the flags passed to open() or to ldi_open_by_name.  In
 *          the latter case the FKLYR flag is added to indicate that the caller
 *          is a kernel component rather than user land.
 */
static int vgdrvSolarisOpen(dev_t *pDev, int fFlags, int fType, cred_t *pCred)
{
    int                 rc;
    PVBOXGUESTSESSION   pSession = NULL;

    LogFlow(("vgdrvSolarisOpen:\n"));

    /*
     * Verify we are being opened as a character device.
     */
    if (fType != OTYP_CHR)
        return EINVAL;

    vboxguest_state_t *pState = NULL;
    unsigned iOpenInstance;
    for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
    {
        if (    !ddi_get_soft_state(g_pvgdrvSolarisState, iOpenInstance) /* faster */
            &&  ddi_soft_state_zalloc(g_pvgdrvSolarisState, iOpenInstance) == DDI_SUCCESS)
        {
            pState = ddi_get_soft_state(g_pvgdrvSolarisState, iOpenInstance);
            break;
        }
    }
    if (!pState)
    {
        Log(("vgdrvSolarisOpen: too many open instances."));
        return ENXIO;
    }

    /*
     * Create a new session.
     */
    if (!(fFlags & FKLYR))
        rc = VGDrvCommonCreateUserSession(&g_DevExt, &pSession);
    else
        rc = VGDrvCommonCreateKernelSession(&g_DevExt, &pSession);
    if (RT_SUCCESS(rc))
    {
        if (!(fFlags & FKLYR))
            pState->pvProcRef = proc_ref();
        else
            pState->pvProcRef = NULL;
        pState->pSession = pSession;
        *pDev = makedevice(getmajor(*pDev), iOpenInstance);
        Log(("vgdrvSolarisOpen: pSession=%p pState=%p pid=%d\n", pSession, pState, (int)RTProcSelf()));
        return 0;
    }

    /* Failed, clean up. */
    ddi_soft_state_free(g_pvgdrvSolarisState, iOpenInstance);

    LogRel((DEVICE_NAME "::Open: VGDrvCommonCreateUserSession failed. rc=%d\n", rc));
    return EFAULT;
}
Ejemplo n.º 19
0
/*
 * Get a physical device name, and maybe load and attach
 * the driver.
 *
 * XXX	Need better checking of whether or not a device
 *	actually exists if the user typed in a pathname.
 *
 * XXX	Are we sure we want to expose users to this sort
 *	of physical namespace gobbledygook (now there's
 *	a word to conjure with..)
 *
 * XXX	Note that on an OBP machine, we can easily ask the
 *	prom and pretty-print some plausible set of bootable
 *	devices.  We can also user the prom to verify any
 *	such device.  Later tim.. later.
 */
static int
getphysdev(char *askfor, char *name, size_t namelen)
{
	static char fmt[] = "Enter physical name of %s device\n[%s]: ";
	dev_t dev;
	static char defaultpath[BO_MAXOBJNAME];

	/*
	 * Establish 'default' values - we get the root device from
	 * boot, and we infer the swap device is the same but with
	 * a 'b' on the end instead of an 'a'.  A first stab at
	 * ease-of-use ..
	 */
	if (strcmp(askfor, "root") == 0) {
		if (get_bootpath_prop(defaultpath) == -1)
			boothowto |= RB_ASKNAME | RB_VERBOSE;
	} else {
		(void) strcpy(defaultpath, rootfs.bo_name);
		defaultpath[strlen(defaultpath) - 1] = 'b';
	}

retry:
	if (boothowto & RB_ASKNAME) {
		printf(fmt, askfor, defaultpath);
		console_gets(name, namelen);
	}
	if (*name == '\0')
		(void) strcpy(name, defaultpath);

	if (strcmp(askfor, "swap") == 0)   {

		/*
		 * Try to load and install the swap device driver.
		 */
		dev = ddi_pathname_to_dev_t(name);

		if (dev == (dev_t)-1)  {
			printf("Not a supported device for swap.\n");
			boothowto |= RB_ASKNAME | RB_VERBOSE;
			goto retry;
		}

		/*
		 * Ensure that we're not trying to swap on the floppy.
		 */
		if (strncmp(ddi_major_to_name(getmajor(dev)), "fd", 2) == 0) {
			printf("Too dangerous to swap on the floppy\n");
			if (boothowto & RB_ASKNAME)
				goto retry;
			return (-1);
		}
	}

	return (0);
}
Ejemplo n.º 20
0
/*ARGSUSED1*/
static int
kcpc_open(dev_t *dev, int flags, int otyp, cred_t *cr)
{
	processorid_t	cpuid;
	int		error;

	ASSERT(pcbe_ops != NULL);

	if ((error = secpolicy_cpc_cpu(cr)) != 0)
		return (error);
	if (getminor(*dev) != KCPC_MINOR_SHARED)
		return (ENXIO);
	if ((cpuid = curthread->t_bind_cpu) == PBIND_NONE)
		return (EINVAL);
	if (cpuid > max_cpuid)
		return (EINVAL);

	rw_enter(&kcpc_cpuctx_lock, RW_WRITER);
	if (++kcpc_cpuctx == 1) {
		ASSERT(kcpc_cpumap == NULL);

		/*
		 * Bail out if DTrace is already using the counters.
		 */
		if (dtrace_cpc_in_use) {
			kcpc_cpuctx--;
			rw_exit(&kcpc_cpuctx_lock);
			return (EAGAIN);
		}
		kcpc_cpumap = kmem_zalloc(BT_SIZEOFMAP(max_cpuid + 1),
		    KM_SLEEP);
		/*
		 * When this device is open for processor-based contexts,
		 * no further lwp-based contexts can be created.
		 *
		 * Since this is the first open, ensure that all existing
		 * contexts are invalidated.
		 */
		kcpc_invalidate_all();
	} else if (BT_TEST(kcpc_cpumap, cpuid)) {
		kcpc_cpuctx--;
		rw_exit(&kcpc_cpuctx_lock);
		return (EAGAIN);
	} else if (kcpc_hw_cpu_hook(cpuid, kcpc_cpumap) != 0) {
		kcpc_cpuctx--;
		rw_exit(&kcpc_cpuctx_lock);
		return (EACCES);
	}
	BT_SET(kcpc_cpumap, cpuid);
	rw_exit(&kcpc_cpuctx_lock);

	*dev = makedevice(getmajor(*dev), (minor_t)cpuid);

	return (0);
}
Ejemplo n.º 21
0
/* ARGSUSED */
static int
evtchndrv_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
	struct evtsoftdata *ep;
	minor_t minor = getminor(*devp);

	if (otyp == OTYP_BLK)
		return (ENXIO);

	/*
	 * only allow open on minor = 0 - the clone device
	 */
	if (minor != 0)
		return (ENXIO);

	/*
	 * find a free slot and grab it
	 */
	mutex_enter(&evtchndrv_clone_tab_mutex);
	for (minor = 1; minor < evtchndrv_nclones; minor++) {
		if (evtchndrv_clone_tab[minor] == 0) {
			evtchndrv_clone_tab[minor] = 1;
			break;
		}
	}
	mutex_exit(&evtchndrv_clone_tab_mutex);
	if (minor == evtchndrv_nclones)
		return (EAGAIN);

	/* Allocate softstate structure */
	if (ddi_soft_state_zalloc(evtchndrv_statep,
	    EVTCHNDRV_MINOR2INST(minor)) != DDI_SUCCESS) {
		mutex_enter(&evtchndrv_clone_tab_mutex);
		evtchndrv_clone_tab[minor] = 0;
		mutex_exit(&evtchndrv_clone_tab_mutex);
		return (EAGAIN);
	}
	ep = EVTCHNDRV_INST2SOFTS(EVTCHNDRV_MINOR2INST(minor));

	/* ... and init it */
	ep->dip = evtchndrv_dip;

	cv_init(&ep->evtchn_wait, NULL, CV_DEFAULT, NULL);
	mutex_init(&ep->evtchn_lock, NULL, MUTEX_DEFAULT, NULL);

	ep->ring = kmem_alloc(PAGESIZE, KM_SLEEP);

	/* clone driver */
	*devp = makedevice(getmajor(*devp), minor);

	return (0);
}
Ejemplo n.º 22
0
int streamscall
ip2xinet_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
{
	mblk_t *bp;
	minor_t minor;
	struct stroptions *sop;

	/* already open */
	if (sflag != CLONEOPEN)
		return ENXIO;

	spin_lock(&ip2xinet_lock);

	/* Can only open one time */
	if (ip2xinet_numopen) {
		spin_unlock(&ip2xinet_lock);
		return ENXIO;
	} else
		ip2xinet_numopen = 1;

	if (q->q_count != 0)
		printk("ip2x level:q_count is %lu", (ulong) q->q_count);

	/* Set up the flow control parameters and send them up to the stream head.  */
	minor = getminor(*devp);
	if ((bp = allocb(sizeof(struct stroptions), BPRI_LO)) == NULL) {
		spin_unlock(&ip2xinet_lock);
		printk("%s: allocb failed", __FUNCTION__);
		return ENOMEM;
	}

	ip2xinet_status.myminor = minor;
	ip2xinet_status.ip2x_dlstate = DL_UNATTACHED;

	/* These are dummy to keep track of the fact the device is open */
	q->q_ptr = (char *) &ip2xinet_numopen;
	WR(q)->q_ptr = (char *) &ip2xinet_numopen;

	spin_unlock(&ip2xinet_lock);

	bp->b_datap->db_type = M_SETOPTS;
	bp->b_wptr += sizeof(struct stroptions);

	sop = (struct stroptions *) bp->b_rptr;
	sop->so_flags = SO_HIWAT | SO_LOWAT;
	sop->so_hiwat = ip2xinet_minfo.mi_hiwat;
	sop->so_lowat = ip2xinet_minfo.mi_lowat;
	putnext(q, bp);

	*devp = makedevice(getmajor(*devp), 0);
	return 0;
}
Ejemplo n.º 23
0
/*
 * Helper for SMBIOC_DUP_DEV
 * Duplicate state from the FD @arg ("from") onto
 * the FD for this device instance.
 */
int
smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags)
{
	file_t *fp = NULL;
	vnode_t *vp;
	smb_dev_t *from_sdp;
	dev_t dev;
	int32_t ufd;
	int err;

	/* Should be no VC */
	if (sdp->sd_vc != NULL)
		return (EISCONN);

	/*
	 * Get from_sdp (what we will duplicate)
	 */
	if (ddi_copyin((void *) arg, &ufd, sizeof (ufd), flags))
		return (EFAULT);
	if ((fp = getf(ufd)) == NULL)
		return (EBADF);
	/* rele fp below */
	vp = fp->f_vnode;
	dev = vp->v_rdev;
	if (dev == 0 || dev == NODEV ||
	    getmajor(dev) != nsmb_major) {
		err = EINVAL;
		goto out;
	}
	from_sdp = ddi_get_soft_state(statep, getminor(dev));
	if (from_sdp == NULL) {
		err = EINVAL;
		goto out;
	}

	/*
	 * Duplicate VC and share references onto this FD.
	 */
	if ((sdp->sd_vc = from_sdp->sd_vc) != NULL)
		smb_vc_hold(sdp->sd_vc);
	if ((sdp->sd_share = from_sdp->sd_share) != NULL)
		smb_share_hold(sdp->sd_share);
	sdp->sd_level = from_sdp->sd_level;
	err = 0;

out:
	if (fp)
		releasef(ufd);
	return (err);
}
Ejemplo n.º 24
0
static int
audio_close(dev_t dev, int flag, int otyp, cred_t *credp)
{
	audio_client_t	*c;
	audio_dev_t	*d;

	_NOTE(ARGUNUSED(flag));
	_NOTE(ARGUNUSED(credp));
	_NOTE(ARGUNUSED(otyp));

	if ((c = auclnt_hold_by_devt(dev)) == NULL) {
		audio_dev_warn(NULL, "close on bogus devt %x,%x",
		    getmajor(dev), getminor(dev));
		return (ENXIO);
	}

	/* we don't want any upcalls anymore */
	auimpl_client_deactivate(c);

	/*
	 * Pick up any data sitting around in input buffers.  This
	 * avoids leaving record data stuck in queues.
	 */
	if (c->c_istream.s_engine != NULL)
		audio_engine_produce(c->c_istream.s_engine);

	/* get a local hold on the device */
	d = c->c_dev;
	auimpl_dev_hold(c->c_dev);

	/*
	 * NB: This must be done before c->c_close, since it calls
	 * auclnt_close which will block waiting for the refence count
	 * to drop to zero.
	 */
	auclnt_release(c);

	/* Call personality specific close handler */
	c->c_close(c);

	auimpl_client_destroy(c);

	/* notify peers that a change has occurred */
	atomic_inc_uint(&d->d_serial);

	/* now we can drop the release we had on the device */
	auimpl_dev_release(d);

	return (0);
}
Ejemplo n.º 25
0
/* ARGSUSED */
static int
cryptoadm_open(dev_t *devp, int flag, int otyp, cred_t *credp)
{
	if (otyp != OTYP_CHR || cryptoadm_dip == NULL)
		return (ENXIO);

	/* exclusive opens are not supported */
	if (flag & FEXCL)
		return (ENOTSUP);

	*devp = makedevice(getmajor(*devp), 0);

	kcf_sched_start();

	return (0);
}
Ejemplo n.º 26
0
/*ARGSUSED*/
int
snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	snode_cbdata_t sd;
	struct snode snode;
	uintptr_t major = 0, dev = 0;

	sd.sd_major = -1;
	sd.sd_minor = -1;
	sd.sd_verbose = !(flags & DCMD_PIPE_OUT);

	if (mdb_getopts(argc, argv,
	    'm', MDB_OPT_UINTPTR, &major,
	    'd', MDB_OPT_UINTPTR, &dev, NULL) != argc)
		return (DCMD_USAGE);

	if (dev != 0) {
		sd.sd_major = getmajor(dev);
		sd.sd_minor = getminor(dev);
	}

	if (major != 0)
		sd.sd_major = major;

	if (DCMD_HDRSPEC(flags) && !(flags & DCMD_PIPE_OUT)) {
		mdb_printf("%<u>%?s %?s %6s %16s %-15s%</u>\n",
		    "ADDR", "VNODE", "COUNT", "DEV", "FLAG");
	}

	if (!(flags & DCMD_ADDRSPEC)) {
		if (mdb_walk("snode", (mdb_walk_cb_t)snode_cb, &sd) == -1) {
			mdb_warn("can't walk snodes");
			return (DCMD_ERR);
		}
		return (DCMD_OK);
	}

	if (mdb_vread(&snode, sizeof (snode), addr) == -1) {
		mdb_warn("failed to read snode structure at %p", addr);
		return (DCMD_ERR);
	}

	snode_cb(addr, &snode, &sd);

	return (DCMD_OK);
}
Ejemplo n.º 27
0
/*ARGSUSED3*/
int
dev2snode(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
{
	snode_cbdata_t sd;

	if (!(flags & DCMD_ADDRSPEC) || argc != 0)
		return (DCMD_USAGE);

	sd.sd_major = getmajor(addr);
	sd.sd_minor = getminor(addr);
	sd.sd_verbose = 0;

	if (mdb_pwalk("snode", (mdb_walk_cb_t)snode_cb, &sd, 0) != 0)
		return (DCMD_ERR);

	return (DCMD_OK);
}
Ejemplo n.º 28
0
/*
 * Helper used by smbfs_mount
 */
int
smb_dev2share(int fd, struct smb_share **sspp)
{
	file_t *fp = NULL;
	vnode_t *vp;
	smb_dev_t *sdp;
	smb_share_t *ssp;
	dev_t dev;
	int err;

	if ((fp = getf(fd)) == NULL)
		return (EBADF);
	/* rele fp below */

	vp = fp->f_vnode;
	dev = vp->v_rdev;
	if (dev == 0 || dev == NODEV ||
	    getmajor(dev) != nsmb_major) {
		err = EINVAL;
		goto out;
	}

	sdp = ddi_get_soft_state(statep, getminor(dev));
	if (sdp == NULL) {
		err = EINVAL;
		goto out;
	}

	ssp = sdp->sd_share;
	if (ssp == NULL) {
		err = ENOTCONN;
		goto out;
	}

	/*
	 * Our caller gains a ref. to this share.
	 */
	*sspp = ssp;
	smb_share_hold(ssp);
	err = 0;

out:
	if (fp)
		releasef(fd);
	return (err);
}
Ejemplo n.º 29
0
/*ARGSUSED*/
static int
opromopen(dev_t *devp, int flag, int otyp, cred_t *credp)
{
	int m;
	struct oprom_state *st = oprom_state;

	if (getminor(*devp) != 0)
		return (ENXIO);

	mutex_enter(&oprom_lock);
	for (m = 0; m < MAX_OPENS; m++)
		if (st->already_open)
			st++;
		else {
			st->already_open = 1;
			/*
			 * It's ours.
			 */
			st->current_id = (pnode_t)0;
			ASSERT(st->snapshot == NULL && st->size == 0);
			ASSERT(st->ioc_state == IOC_IDLE);
			break;
		}
	mutex_exit(&oprom_lock);

	if (m == MAX_OPENS)  {
		/*
		 * "Thank you for calling, but all our lines are
		 * busy at the moment.."
		 *
		 * We could get sophisticated here, and go into a
		 * sleep-retry loop .. but hey, I just can't see
		 * that many processes sitting in this driver.
		 *
		 * (And if it does become possible, then we should
		 * change the interface so that the 'state' is held
		 * external to the driver)
		 */
		return (EAGAIN);
	}

	*devp = makedevice(getmajor(*devp), (minor_t)m);

	return (0);
}
Ejemplo n.º 30
0
static int VBoxUSBMonSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred)
{
    vboxusbmon_state_t *pState = NULL;
    unsigned iOpenInstance;

    LogFunc((DEVICE_NAME ": VBoxUSBMonSolarisOpen\n"));

    /*
     * Verify we are being opened as a character device.
     */
    if (fType != OTYP_CHR)
        return EINVAL;

    /*
     * Verify that we're called after attach.
     */
    if (!g_pDip)
    {
        LogRel((DEVICE_NAME ": VBoxUSBMonSolarisOpen: Invalid state for opening\n"));
        return ENXIO;
    }

    for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++)
    {
        if (    !ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance) /* faster */
            &&  ddi_soft_state_zalloc(g_pVBoxUSBMonSolarisState, iOpenInstance) == DDI_SUCCESS)
        {
            pState = ddi_get_soft_state(g_pVBoxUSBMonSolarisState, iOpenInstance);
            break;
        }
    }
    if (!pState)
    {
        LogRel((DEVICE_NAME ": VBoxUSBMonSolarisOpen: Too many open instances"));
        return ENXIO;
    }

    pState->Process = RTProcSelf();
    *pDev = makedevice(getmajor(*pDev), iOpenInstance);

    NOREF(fFlag);
    NOREF(pCred);

    return 0;
}