예제 #1
0
/*
 * cvc_register()
 *	called from cvcredir to register it's queues.  cvc
 *	receives data from cn via the streamhead and sends it to cvcredir
 *	via pointers to cvcredir's queues.
 */
int
cvc_register(queue_t *q)
{
	int error = -1;

	if (cvcinput_q == NULL)
		cmn_err(CE_WARN, "cvc_register: register w/ no console open!");
	rw_enter(&cvclock, RW_WRITER);
	if (cvcoutput_q == NULL) {
		cvcoutput_q = RD(q);  /* Make sure its the upstream q */
		qprocson(cvcoutput_q);	/* must be done within cvclock */
		error = 0;
	} else {
		/*
		 * cmn_err will call us, so release lock.
		 */
		rw_exit(&cvclock);
		if (cvcoutput_q == q)
			cmn_err(CE_WARN, "cvc_register: duplicate q!");
		else
			cmn_err(CE_WARN, "cvc_register: nondup q = 0x%p",
			    q);
		return (error);
	}
	rw_exit(&cvclock);
	return (error);
}
예제 #2
0
파일: drcompat.c 프로젝트: andreiw/polaris
/* 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);
}
예제 #3
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);
}
예제 #4
0
/*ARGSUSED*/
static int
nca_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
{
	/* Reopen supported */
	if (q->q_ptr != NULL)
		return (0);

	/*
	 * NCA is not supported in non-global zones; we enforce this restriction
	 * here.
	 */
	if (credp != NULL && crgetzoneid(credp) != GLOBAL_ZONEID) {
		return (ENOTSUP);
	}

	if (! (sflag & MODOPEN)) {
		/* Device instance */
		RD(q)->q_ptr = (void *)B_TRUE;
		WR(q)->q_ptr = (void *)B_TRUE;
	} else {
		/* Modopen just pass through */
		RD(q)->q_ptr = (void *)B_FALSE;
		WR(q)->q_ptr = (void *)B_FALSE;
	}
	qprocson(q);
	return (0);
}
예제 #5
0
/*ARGSUSED*/
static int
sdp_gen_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
{
	qprocson(q);
	qenable(q);
	return (0);
}
예제 #6
0
파일: log.c 프로젝트: andreiw/polaris
/* 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);
}
예제 #7
0
static int
audio_stropen(queue_t *rq, dev_t *devp, int oflag, int sflag, cred_t *credp)
{
	int			rv;
	audio_client_t		*c;

	if (sflag != 0) {
		/* no direct clone or module opens */
		return (ENXIO);
	}

	/*
	 * Make sure its a STREAMS personality - only legacy Sun API uses
	 * STREAMS.
	 */
	switch (AUDIO_MN_TYPE_MASK & getminor(*devp)) {
	case AUDIO_MINOR_DEVAUDIO:
	case AUDIO_MINOR_DEVAUDIOCTL:
		break;
	default:
		return (ENOSTR);
	}

	if ((c = auimpl_client_create(*devp)) == NULL) {
		audio_dev_warn(NULL, "client create failed");
		return (ENXIO);
	}

	rq->q_ptr = WR(rq)->q_ptr = c;
	c->c_omode = oflag;
	c->c_pid = ddi_get_pid();
	c->c_cred = credp;
	c->c_rq = rq;
	c->c_wq = WR(rq);

	/*
	 * Call client/personality specific open handler.  Note that
	 * we "insist" that there is an open.  The personality layer
	 * will initialize/allocate any engines required.
	 *
	 * Hmm... do we need to pass in the cred?
	 */
	if ((rv = c->c_open(c, oflag)) != 0) {
		audio_dev_warn(c->c_dev, "open failed (rv %d)", rv);
		auimpl_client_destroy(c);
		return (rv);
	}

	/* we do device cloning! */
	*devp = makedevice(c->c_major, c->c_minor);

	qprocson(rq);

	/* now we can receive upcalls */
	auimpl_client_activate(c);

	atomic_inc_uint(&c->c_dev->d_serial);

	return (0);
}
예제 #8
0
/* ARGSUSED */
static int
wcmopen(queue_t *q, dev_t *dev, int flag, int sflag, cred_t *cred)
{
	if (sflag != MODOPEN)
		return (EINVAL);
	qprocson(q);
	return (0);
}
예제 #9
0
파일: zcons.c 프로젝트: pcd1193182/openzfs
/*ARGSUSED*/
static int
zc_master_open(zc_state_t *zcs,
    queue_t	*rqp,	/* pointer to the read side queue */
    dev_t	*devp,	/* pointer to stream tail's dev */
    int		oflag,	/* the user open(2) supplied flags */
    int		sflag,	/* open state flag */
    cred_t	*credp)	/* credentials */
{
	mblk_t *mop;
	struct stroptions *sop;

	/*
	 * Enforce exclusivity on the master side; the only consumer should
	 * be the zoneadmd for the zone.
	 */
	if ((zcs->zc_state & ZC_STATE_MOPEN) != 0)
		return (EBUSY);

	if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
		DBG("zc_master_open(): mop allocation failed\n");
		return (ENOMEM);
	}

	zcs->zc_state |= ZC_STATE_MOPEN;

	/*
	 * q_ptr stores driver private data; stash the soft state data on both
	 * read and write sides of the queue.
	 */
	WR(rqp)->q_ptr = rqp->q_ptr = zcs;
	qprocson(rqp);

	/*
	 * Following qprocson(), the master side is fully plumbed into the
	 * STREAM and may send/receive messages.  Setting zcs->zc_master_rdq
	 * will allow the slave to send messages to us (the master).
	 * This cannot occur before qprocson() because the master is not
	 * ready to process them until that point.
	 */
	zcs->zc_master_rdq = rqp;

	/*
	 * set up hi/lo water marks on stream head read queue and add
	 * controlling tty as needed.
	 */
	mop->b_datap->db_type = M_SETOPTS;
	mop->b_wptr += sizeof (struct stroptions);
	sop = (struct stroptions *)(void *)mop->b_rptr;
	if (oflag & FNOCTTY)
		sop->so_flags = SO_HIWAT | SO_LOWAT;
	else
		sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
	sop->so_hiwat = _TTY_BUFSIZ;
	sop->so_lowat = 256;
	putnext(rqp, mop);

	return (0);
}
/* ARGSUSED3 */
int
ip_helper_stream_setup(queue_t *q, dev_t *devp, int flag, int sflag,
    cred_t *credp, boolean_t isv6)
{
	major_t			maj;
	ip_helper_minfo_t	*ip_minfop;

	ASSERT((flag & ~(FKLYR)) == IP_HELPER_STR);

	ASSERT(RD(q) == q);

	ip_minfop = kmem_alloc(sizeof (ip_helper_minfo_t), KM_SLEEP);
	ASSERT(ip_minfop != NULL);

	ip_minfop->ip_minfo_dev = 0;
	ip_minfop->ip_minfo_arena = NULL;

	/*
	 * Clone the device, allocate minor device number
	 */
	if (ip_minor_arena_la != NULL)
		ip_minfop->ip_minfo_dev = inet_minor_alloc(ip_minor_arena_la);

	if (ip_minfop->ip_minfo_dev == 0) {
		/*
		 * numbers in the large arena are exhausted
		 * Try small arena.
		 * Or this is a 32 bit system, 32 bit systems do not have
		 * ip_minor_arena_la
		 */
		ip_minfop->ip_minfo_dev = inet_minor_alloc(ip_minor_arena_sa);
		if (ip_minfop->ip_minfo_dev == 0) {
			return (EBUSY);
		}
		ip_minfop->ip_minfo_arena = ip_minor_arena_sa;
	} else {
		ip_minfop->ip_minfo_arena = ip_minor_arena_la;
	}


	ASSERT(ip_minfop->ip_minfo_dev != 0);
	ASSERT(ip_minfop->ip_minfo_arena != NULL);

	RD(q)->q_ptr = WR(q)->q_ptr = ip_minfop;

	maj = getemajor(*devp);
	*devp = makedevice(maj, (ulong_t)(ip_minfop->ip_minfo_dev));

	q->q_qinfo = &ip_helper_stream_rinit;
	WR(q)->q_qinfo = &ip_helper_stream_winit;
	qprocson(q);
	return (0);
}
예제 #11
0
파일: zcons.c 프로젝트: andreiw/polaris
/*ARGSUSED*/
static int
zc_slave_open(zc_state_t *zcs,
    queue_t	*rqp,	/* pointer to the read side queue */
    dev_t	*devp,	/* pointer to stream tail's dev */
    int		oflag,	/* the user open(2) supplied flags */
    int		sflag,	/* open state flag */
    cred_t	*credp)	/* credentials */
{
	mblk_t *mop;
	struct stroptions *sop;

	/*
	 * The slave side can be opened as many times as needed.
	 */
	if ((zcs->zc_state & ZC_STATE_SOPEN) != 0) {
		ASSERT((rqp != NULL) && (WR(rqp)->q_ptr == zcs));
		return (0);
	}

	if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
		DBG("zc_slave_open(): mop allocation failed\n");
		return (ENOMEM);
	}

	zcs->zc_state |= ZC_STATE_SOPEN;

	/*
	 * q_ptr stores driver private data; stash the soft state data on both
	 * read and write sides of the queue.
	 */
	WR(rqp)->q_ptr = rqp->q_ptr = zcs;

	qprocson(rqp);

	/*
	 * Must follow qprocson(), since we aren't ready to process until then.
	 */
	zcs->zc_slave_rdq = rqp;

	/*
	 * set up hi/lo water marks on stream head read queue and add
	 * controlling tty as needed.
	 */
	mop->b_datap->db_type = M_SETOPTS;
	mop->b_wptr += sizeof (struct stroptions);
	sop = (struct stroptions *)mop->b_rptr;
	sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
	sop->so_hiwat = 512;
	sop->so_lowat = 256;
	putnext(rqp, mop);

	return (0);
}
예제 #12
0
파일: kb8042.c 프로젝트: andreiw/polaris
/*ARGSUSED2*/
static int
kb8042_open(queue_t *qp, dev_t *devp, int flag, int sflag, cred_t *credp)
{
	struct kb8042	*kb8042;
	int err;
	int initial_leds;
	int initial_led_mask;

	kb8042 = &Kdws;

	kb8042->w_dev = *devp;

	if (qp->q_ptr) {
		return (0);
	}
	qp->q_ptr = (caddr_t)kb8042;
	WR(qp)->q_ptr = qp->q_ptr;
	if (!kb8042->w_qp)
		kb8042->w_qp = qp;

	kb8042_get_initial_leds(kb8042, &initial_leds, &initial_led_mask);
	err = kbtrans_streams_init(qp, sflag, credp,
		(struct kbtrans_hardware *)kb8042, &kb8042_callbacks,
		&kb8042->hw_kbtrans,
		initial_leds, initial_led_mask);
	if (err != 0)
		return (err);

	kbtrans_streams_set_keyboard(kb8042->hw_kbtrans, KB_PC, &keyindex_pc);

	kb8042->polledio.cons_polledio_version = CONSPOLLEDIO_V1;
	kb8042->polledio.cons_polledio_argument =
		(cons_polledio_arg_t)kb8042;
	kb8042->polledio.cons_polledio_putchar = NULL;
	kb8042->polledio.cons_polledio_getchar =
		(int (*)(cons_polledio_arg_t))kb8042_polled_getchar;
	kb8042->polledio.cons_polledio_ischar =
		(boolean_t (*)(cons_polledio_arg_t))kb8042_polled_ischar;
	kb8042->polledio.cons_polledio_enter = NULL;
	kb8042->polledio.cons_polledio_exit = NULL;
	kb8042->polledio.cons_polledio_setled =
		(void (*)(cons_polledio_arg_t, int))kb8042_polled_setled;
	kb8042->polledio.cons_polledio_keycheck =
		(boolean_t (*)(cons_polledio_arg_t, int *,
		enum keystate *))kb8042_polled_keycheck;

	qprocson(qp);

	kbtrans_streams_enable(kb8042->hw_kbtrans);

	return (0);
}
예제 #13
0
/* ARGSUSED */
static int
cvc_open(register queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
{
	register int		unit = getminor(*devp);
	register int		err = DDI_SUCCESS;
	tty_common_t		*tty;
	cvc_t			*cp;

	if (unit != 0)
		return (ENXIO);

	if (q->q_ptr)
		return (0);

	cp = (cvc_t *)&cvc_common_tty;
	bzero((caddr_t)cp, sizeof (cvc_t));
	cp->cvc_wbufcid = 0;
	tty = &cp->cvc_tty;
	tty->t_readq = q;
	tty->t_writeq = WR(q);
	WR(q)->q_ptr = q->q_ptr = (caddr_t)cp;
	cvcinput_q = RD(q);		/* save for cvc_redir */
	qprocson(q);
	mutex_enter(&cvcmutex);
	input_ok = 1;

	/*
	 * Start the thread that handles input polling if it hasn't been started
	 * previously.
	 */
	if (!input_daemon_started) {
		input_daemon_started = 1;
		mutex_exit(&cvcmutex);

		cvc_input_daemon_thread = thread_create(NULL, 0,
		    cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri);
		CVC_DBG0(CVC_DBG_IOSRAM_RD, "Started input daemon");
	} else {
		mutex_exit(&cvcmutex);
	}

	/*
	 * Set the console window size.
	 */
	mutex_enter(&cvc_iosram_input_mutex);
	cvc_win_resize(FALSE);
	mutex_exit(&cvc_iosram_input_mutex);

	CVC_DBG0(CVC_DBG_OPEN, "Plumbed successfully");

	return (err);
}
예제 #14
0
파일: logi.c 프로젝트: andreiw/polaris
/*ARGSUSED2*/
static int
logiopen(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *cred_p)
{
	struct strmseinfo *logiptr;
	int unit;
	dev_info_t *dip;
#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:entered\n");
#endif
	if (((unit = LOGIUNIT(*devp)) >= LOGI_MAXUNIT) ||
		(dip = logiunits[unit]) == NULL)
		return (ENODEV);

	if (!mse_config.present)
		return (EIO);
	if ((logiptr = ddi_get_driver_private(dip)) == NULL)
		return (EIO);
	if (logiptr->state & M_OPEN)
		return (EBUSY);
	mutex_enter(&logiptr->lock);
	if (q->q_ptr != NULL) {
#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:already open\n");
#endif
		mutex_exit(&logiptr->lock);
		return (EBUSY);		/* already attached */
	}


	q->q_ptr = (caddr_t)logiptr;
	WR(q)->q_ptr = (caddr_t)logiptr;
	logiptr->rqp = q;
	logiptr->wqp = WR(q);
	qprocson(q);
#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:Enable interrupts ioaddr %x\n", BASE_IOA);
#endif
	control_port(0);	/* Enable interrupts */

#ifdef LOGI_DEBUG
	if (logi_debug)
		printf("logiopen:leaving\n");
#endif
	oldbuttons = 0;
	logiptr->state = M_OPEN;
	mutex_exit(&logiptr->lock);
	return (0);
}
예제 #15
0
/**
 * ptem_qopen - STREAMS module open routine
 * @q: read queue
 * @devp: number of device
 * @oflag: flags to open(2s) call
 * @sflag: STREAMS flag
 * @crp: credentials pointer
 *
 * When ptem is pushed successfully, it assigns this Stream as a controlling
 * terminal if one has not already been assigend by sending a M_SETOPTS
 * message to the Stream head with the SO_ISTTY flag set.  (The Stream head
 * determines whether the process already has a controlling tty.)  If,
 * however, the O_NOCTTY flag was set to open (and appears in oflag as
 * FNOCTTY), then no controlling tty should be assigned.  It is the job of the
 * Stream head to detect this too.
 *
 * When the module is pushed, if we are using old TTY semantics we need to
 * send SO_NDELON to the Stream head in an M_SETOPTS.  It is typical to change
 * the Stream head water marks and packet sizes using SO_MINPSZ, SO_MAXPSZ,
 * SO_HIWAT and SO_LOWAT in the M_SETOPTS.
 *
 * As we don't know (and can't query) the state of the Stream head, we need to
 * set several options that should be correct if the Stream head started in
 * the default state (which it might not have).  SO_MREADOFF should be set as
 * we default to canonical mode and do not want read notifications.  Also
 * RMSGN mode to SO_RDOPT for canonical mode (RNORM for non-canonical).
 * SO_NODELIM should probably be set, but see the discussion under
 * M_SETOPTS(9).  SO_WROFF should be set to zero.  We may or may not want to
 * set the SO_STRHOLD feature.  Do not set it for now and see if we can get a
 * performance gain from it.
 */
static streamscall int
ptem_qopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	if (q->q_ptr)
		return (0);	/* already open */
	if (sflag == MODOPEN && WR(q)->q_next != NULL) {
		struct stroptions *so;
		struct ptem *p;
		mblk_t *mp, *hp;

		if (!(hp = allocb(0, BPRI_WAITOK)))
			goto openfail;

		/* zero-length message block is good as it is */

		if (!(mp = allocb(sizeof(*so), BPRI_WAITOK))) {
			freeb(hp);
			goto openfail;
		}

		/* I don't really know what the point of this is, ldterm() will do this again.
		   Everything except the read options and SO_ISTTY the water marks and SO_READOPT
		   are defaults. */
		mp->b_datap->db_type = M_SETOPTS;
		so = (struct stroptions *) mp->b_rptr;
		mp->b_wptr += sizeof(*so);
		so->so_flags = SO_ISTTY;

		if (!(p = kmem_alloc(sizeof(*p), KM_SLEEP))) {
			freeb(mp);
			freeb(hp);
			goto openfail;
		}

		bzero(p, sizeof(*p));
		p->zero = hp;
		p->c.c_iflag = BRKINT | ICRNL | IXON | ISTRIP | IXANY;
		p->c.c_oflag = OPOST | ONLCR | TAB3;
		p->c.c_cflag = 0;
		p->c.c_lflag = ISIG | ICANON | ECHO | ECHOK;

		q->q_ptr = WR(q)->q_ptr = (void *) p;
		qprocson(q);

		putnext(q, mp);
		return (0);
	}
      openfail:
	return (OPENFAIL);
}
예제 #16
0
파일: dm2s.c 프로젝트: andreiw/polaris
/* ARGSUSED */
int
dm2s_open(queue_t *rq, dev_t *dev, int flag, int sflag, cred_t *cr)
{
	dm2s_t *dm2sp;
	int instance = getminor(*dev);
	int ret = 0;

	DPRINTF(DBG_DRV, ("dm2s_open: called\n"));
	if (sflag == CLONEOPEN)	{
		/* Clone open not supported */
		DPRINTF(DBG_WARN, ("dm2s_open: clone open not supported\n"));
		return (ENOTSUP);
	}

	if (rq->q_ptr != NULL) {
		DPRINTF(DBG_WARN, ("dm2s_open: already opened\n"));
		return (EBUSY);
	}

	if ((dm2sp = ddi_get_soft_state(dm2s_softstate, instance)) == NULL) {
		DPRINTF(DBG_WARN, ("dm2s_open: instance not found\n"));
		return (ENODEV);
	}

	mutex_enter(&dm2sp->ms_lock);
	if (dm2sp->ms_state & DM2S_OPENED) {
		/* Only one open supported */
		mutex_exit(&dm2sp->ms_lock);
		DPRINTF(DBG_WARN, ("dm2s_open: already opened\n"));
		return (EBUSY);
	}

	dm2sp->ms_state |= DM2S_OPENED;
	/* Initialize the mailbox. */
	if ((ret = dm2s_mbox_init(dm2sp)) != 0) {
		dm2sp->ms_state = 0;
		mutex_exit(&dm2sp->ms_lock);
		return (ret);
	}
	rq->q_ptr = WR(rq)->q_ptr = (void *)dm2sp;
	dm2sp->ms_rq = rq;
	dm2sp->ms_wq = WR(rq);
	mutex_exit(&dm2sp->ms_lock);

	if (ret == 0) {
		qprocson(rq);		/* now schedule our queue */
	}
	DPRINTF(DBG_DRV, ("dm2s_open: ret=%d\n", ret));
	return (ret);
}
예제 #17
0
파일: sad.c 프로젝트: andreiw/polaris
/* ARGSUSED */
static int
sadopen(
	queue_t *qp,	/* pointer to read queue */
	dev_t *devp,	/* major/minor device of stream */
	int flag,	/* file open flags */
	int sflag,	/* stream open flags */
	cred_t *credp)	/* user credentials */
{
	int i;

	if (sflag)		/* no longer called from clone driver */
		return (EINVAL);

	/*
	 * Both USRMIN and ADMMIN are clone interfaces.
	 */
	for (i = 0; i < sadcnt; i++)
		if (saddev[i].sa_qp == NULL)
			break;
	if (i >= sadcnt)		/* no such device */
		return (ENXIO);

	switch (getminor(*devp)) {
	case USRMIN:			/* mere mortal */
		saddev[i].sa_flags = 0;
		break;

	case ADMMIN:			/* privileged user */
		saddev[i].sa_flags = SADPRIV;
		break;

	default:
		return (EINVAL);
	}

	saddev[i].sa_qp = qp;
	qp->q_ptr = (caddr_t)&saddev[i];
	WR(qp)->q_ptr = (caddr_t)&saddev[i];

	/*
	 * NOTE: should the ADMMIN or USRMIN minors change
	 * then so should the offset of 2 below
	 * Both USRMIN and ADMMIN are clone interfaces and
	 * therefore their minor numbers (0 and 1) are reserved.
	 */
	*devp = makedevice(getemajor(*devp), i + 2);
	qprocson(qp);
	return (0);
}
예제 #18
0
    static int
dlpi_open( queue_t *q, dev_t *dev, int oflag, int sflag, cred_t *cred )
{
    struct atif_data	*aid;
    int			err = 0;

    if (( err = drv_priv( cred )) != 0 ) {
	return( err );
    }
    if (( aid = if_alloc( q )) == NULL ) {
	return( ENOMEM );
    }
    q->q_ptr = (void *)aid;

    qprocson( q );
    return( err );
}
예제 #19
0
/*ARGSUSED*/
int
connopen(queue_t *rqp, dev_t *devp, int flag, int sflag, cred_t *crp)
{
	int error = 0;
	vnode_t *streamvp;
	fifonode_t *streamfnp;

	if ((streamvp = strq2vp(rqp)) == NULL) {
		return (EINVAL);
	}

	/*
	 * CONNLD is only allowed to be pushed onto a "pipe" that has both
	 * of its ends open.
	 */
	if (streamvp->v_type != VFIFO) {
		error = EINVAL;
		goto out;
	}

	streamfnp = VTOF(streamvp);

	if (!(streamfnp->fn_flag & ISPIPE) ||
	    streamfnp->fn_dest->fn_open == 0) {
		error = EPIPE;
		goto out;
	}

	/*
	 * If this is the first time CONNLD was opened while on this stream,
	 * it is being pushed. Therefore, set a flag and return 0.
	 */
	if (rqp->q_ptr == 0) {
		if (streamfnp->fn_flag & FIFOCONNLD) {
			error = ENXIO;
			goto out;
		}
		rqp->q_ptr = (caddr_t)1;
		streamfnp->fn_flag |= FIFOCONNLD;
		qprocson(rqp);
	}
out:
	VN_RELE(streamvp);
	return (error);
}
예제 #20
0
/*
 *  -------------------------------------------------------------------------
 *
 *  OPEN and CLOSE
 *
 *  -------------------------------------------------------------------------
 */
STATIC streamscall int
srvmod_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	queue_t *wq;

	if (q->q_ptr != NULL) {
		return (0);	/* already open */
	}
	wq = WR(q);
	if (sflag == MODOPEN || wq->q_next != NULL) {
		/* inherit packet sizes of what we are pushed over */
		wq->q_minpsz = wq->q_next->q_minpsz;
		wq->q_maxpsz = wq->q_next->q_maxpsz;
		q->q_ptr = wq->q_ptr = q;	/* just set it to something */
		qprocson(q);
		return (0);
	}
	return (EIO);		/* can't be opened as driver */
}
예제 #21
0
/* 
 *  -------------------------------------------------------------------------
 *
 *  OPEN and CLOSE
 *
 *  -------------------------------------------------------------------------
 */
static streamscall int
pckt_qopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	if (q->q_ptr)
		return (0);	/* already open */
	if (sflag == MODOPEN && WR(q)->q_next != NULL) {
		struct pckt *p;

		if ((p = kmem_alloc(sizeof(*p), KM_SLEEP))) {
			bzero(p, sizeof(*p));
			p->flags = oflag;	/* to test later for data model */
			q->q_ptr = WR(q)->q_ptr = (void *) p;
			qprocson(q);
			return (0);
		}
		return (OPENFAIL);
	}
	return (OPENFAIL);	/* can't be opened as driver */
}
예제 #22
0
static streamscall __unlikely int
ch_qopen(queue_t *q, dev_t *devp, int oflags, int sflag, cred_t *crp)
{
	struct ch *ch;
	int err;

	if (!SAMESTR(_WR(q))) {
		strlog(modid, 0, 15, SL_ERROR, "%s: can only push on pipe or fifo", MOD_NAME);
		return (ENXIO);	/* can only be pushed on pipe or fifo */
	}
	if ((err = mi_open_comm(&ch_head, sizeof(*ch), q, devp, oflags, sflag, crp)))
		return (err);
	ch = CH_PRIV(q);
	bzero(ch, sizeof(*ch));
	ch->sid = atomic_add_return(&ch_numb, 1);
	/* FIXME initialize structure */
	qprocson(q);
	return (0);
}
예제 #23
0
/*ARGSUSED*/
static int
pfopen(queue_t *rq, dev_t *dev, int oflag, int sflag, cred_t *crp)
{
	struct epacketfilt	*pfp;

	ASSERT(rq);

	if (sflag != MODOPEN)
		return (EINVAL);

	if (rq->q_ptr)
		return (0);

	/*
	 * Allocate and initialize per-Stream structure.
	 */
	pfp = kmem_alloc(sizeof (struct epacketfilt), KM_SLEEP);
	rq->q_ptr = WR(rq)->q_ptr = (char *)pfp;

	qprocson(rq);

	return (0);
}
예제 #24
0
/* ARGSUSED */
static int
ptemopen(
	queue_t    *q,		/* pointer to the read side queue */
	dev_t   *devp,		/* pointer to stream tail's dev */
	int	oflag,		/* the user open(2) supplied flags */
	int	sflag,		/* open state flag */
	cred_t *credp)		/* credentials */
{
	struct ptem *ntp;	/* ptem entry for this PTEM module */
	mblk_t *mop;		/* an setopts mblk */
	struct stroptions *sop;
	struct termios *termiosp;
	int len;

	if (sflag != MODOPEN)
		return (EINVAL);

	if (q->q_ptr != NULL) {
		/* It's already attached. */
		return (0);
	}

	/*
	 * Allocate state structure.
	 */
	ntp = kmem_alloc(sizeof (*ntp), KM_SLEEP);

	/*
	 * Allocate a message block, used to pass the zero length message for
	 * "stty 0".
	 *
	 * NOTE: it's better to find out if such a message block can be
	 *	 allocated before it's needed than to not be able to
	 *	 deliver (for possible lack of buffers) when a hang-up
	 *	 occurs.
	 */
	if ((ntp->dack_ptr = allocb(4, BPRI_MED)) == NULL) {
		kmem_free(ntp, sizeof (*ntp));
		return (EAGAIN);
	}

	/*
	 * Initialize an M_SETOPTS message to set up hi/lo water marks on
	 * stream head read queue and add controlling tty if not set.
	 */
	mop = allocb(sizeof (struct stroptions), BPRI_MED);
	if (mop == NULL) {
		freemsg(ntp->dack_ptr);
		kmem_free(ntp, sizeof (*ntp));
		return (EAGAIN);
	}
	mop->b_datap->db_type = M_SETOPTS;
	mop->b_wptr += sizeof (struct stroptions);
	sop = (struct stroptions *)mop->b_rptr;
	sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
	sop->so_hiwat = 512;
	sop->so_lowat = 256;

	/*
	 * Cross-link.
	 */
	ntp->q_ptr = q;
	q->q_ptr = ntp;
	WR(q)->q_ptr = ntp;

	/*
	 * Get termios defaults.  These are stored as
	 * a property in the "options" node.
	 */
	if (ddi_getlongprop(DDI_DEV_T_ANY, ddi_root_node(), 0, "ttymodes",
	    (caddr_t)&termiosp, &len) == DDI_PROP_SUCCESS &&
	    len == sizeof (struct termios)) {

		ntp->cflags = termiosp->c_cflag;
		kmem_free(termiosp, len);
	} else {
		/*
		 * Gack!  Whine about it.
		 */
		cmn_err(CE_WARN, "ptem: Couldn't get ttymodes property!");
	}
	ntp->wsz.ws_row = 0;
	ntp->wsz.ws_col = 0;
	ntp->wsz.ws_xpixel = 0;
	ntp->wsz.ws_ypixel = 0;

	ntp->state = 0;

	/*
	 * Commit to the open and send the M_SETOPTS off to the stream head.
	 */
	qprocson(q);
	putnext(q, mop);

	return (0);
}
예제 #25
0
/*ARGSUSED*/
static int
parseopen(
	  queue_t *q,
	  dev_t *dev,
	  int flag,
	  int sflag,
	  cred_t *credp
	  )
{
	register parsestream_t *parse;
	static int notice = 0;
  
	pprintf(DD_OPEN, "parse: OPEN - q=%x\n", q); 
  
	if (sflag != MODOPEN)
	{			/* open only for modules */
		pprintf(DD_OPEN, "parse: OPEN - FAILED - not MODOPEN\n"); 
		return EIO;
	}

	if (q->q_ptr != (caddr_t)NULL)
	{
		pprintf(DD_OPEN, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n"); 
		return EBUSY;
	}

	q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP);
	if (q->q_ptr == (caddr_t)0)
	{
		return ENOMEM;
	}

	pprintf(DD_OPEN, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr); 
	WR(q)->q_ptr = q->q_ptr;
	pprintf(DD_OPEN, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q), WR(q)->q_ptr); 
  
	parse = (parsestream_t *) q->q_ptr;
	bzero((caddr_t)parse, sizeof(*parse));
	parse->parse_queue     = q;
	parse->parse_status    = PARSE_ENABLE;
	parse->parse_ppsclockev.tv.tv_sec  = 0;
	parse->parse_ppsclockev.tv.tv_usec = 0;
	parse->parse_ppsclockev.serial     = 0;

	qprocson(q);

	pprintf(DD_OPEN, "parse: OPEN - initializing io subsystem q=%x\n", q); 

	if (!parse_ioinit(&parse->parse_io))
	{
		/*
		 * ok guys - beat it
		 */
		qprocsoff(q);

		kmem_free((caddr_t)parse, sizeof(parsestream_t));

		return EIO;
	}

	pprintf(DD_OPEN, "parse: OPEN - initializing stream q=%x\n", q); 

	if (setup_stream(q, M_PARSE))
	{
		(void) init_linemon(q);	/* hook up PPS ISR routines if possible */
		pprintf(DD_OPEN, "parse: OPEN - SUCCEEDED\n"); 

		/*
		 * I know that you know the delete key, but you didn't write this
		 * code, did you ? - So, keep the message in here.
		 */
		if (!notice)
		{
		  cmn_err(CE_CONT, "?%s: Copyright (c) 1993-2005, Frank Kardel\n", modlstrmod.strmod_linkinfo);
			notice = 1;
		}

		return 0;
	}
	else
	{
		qprocsoff(q);

		kmem_free((caddr_t)parse, sizeof(parsestream_t));

		return EIO;
	}
}
예제 #26
0
/**
 * socksys_qopen - SOCKSYS driver STREAMS open routine
 * @q: read queue of opened Stream
 * @devp: pointer to device number opened
 * @oflag: flags to the open call
 * @sflag: STREAMS flag: DRVOPEN, MODOPEN or CLONEOPEN
 * @crp: pointer to opener's credentials
 */
STATIC streamscall int
socksys_qopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	int mindex = 0;
	int type = 0;
	major_t cmajor = getmajor(*devp);
	minor_t cminor = getminor(*devp);
	struct ssys **sp = &socksys_opens;
	unsigned long flags;

	if (q->q_ptr != NULL) {
		return (0);	/* already open */
	}
	if (sflag == MODOPEN || WR(q)->q_next) {
		ptrace(("%s: ERROR: cannot push as module\n", DRV_NAME));
		return (EIO);
	}
	/* Linux Fast-STREAMS always passes internal major device number (module id).  Note also,
	   however, that strconf-sh attempts to allocate module ids that are identical to the base
	   major device number anyway. */
	/* Linux Fast-STREAMS always passes internal major device numbers (module ids) */
	if (cmajor != DRV_ID)
		return (ENXIO);
	/* sorry, you cannot open by minor device */
	if (cminor > LAST_CMINOR) {
		return (ENXIO);
	}
	type = cminor;
#if 0
	if (sflag == CLONEOPEN)
#endif
		cminor = FREE_CMINOR;
	write_lock_str2(&socksys_lock, flags);
	for (; *sp; sp = &(*sp)->next) {
		if (cmajor != (*sp)->dev.cmajor)
			break;
		if (cmajor == (*sp)->dev.cmajor) {
			if (cminor < (*sp)->dev.cminor)
				break;
			if (cminor == (*sp)->dev.cminor) {
				if (++cminor >= NMINORS) {
					if (++mindex >= CMAJORS || !(cmajor = ssys_majors[mindex]))
						break;
					cminor = 0;	/* start next major */
				}
				continue;
			}
		}
	}
	if (mindex >= CMAJORS || !cmajor) {
		ptrace(("%s: ERROR: no device numbers available\n", DRV_NAME));
		write_unlock_str2(&socksys_lock, flags);
		return (ENXIO);
	}
	_printd(("%s: opened character device %d:%d\n", DRV_NAME, cmajor, cminor));
	*devp = makedevice(cmajor, cminor);
	if (!ssys_alloc_priv(q, sp, type, devp, crp)) {
		ptrace(("%s: ERROR: No memory\n", DRV_NAME));
		write_unlock_str2(&socksys_lock, flags);
		return (ENOMEM);
	}
	write_unlock_str2(&socksys_lock, flags);
	qprocson(q);
	return (0);
}
예제 #27
0
파일: spx.c 프로젝트: iHaD/openss7
/* 
 *  -------------------------------------------------------------------------
 *
 *  OPEN and CLOSE
 *
 *  -------------------------------------------------------------------------
 */
static streamscall int
spx_open(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *crp)
{
	struct spx *p, **pp = &spx_list;
	major_t cmajor = getmajor(*devp);
	minor_t cminor = getminor(*devp);

	if (q->q_ptr != NULL)
		return (0);	/* already open */
	if (sflag == MODOPEN || WR(q)->q_next)
		return (ENXIO);	/* can't open as module */
	if (!(p = kmem_alloc(sizeof(*p), KM_NOSLEEP)))	/* we could sleep */
		return (ENOMEM);	/* no memory */
	bzero(p, sizeof(*p));
	switch (sflag) {
	case CLONEOPEN:
		if (cminor < 1)
			cminor = 1;
	case DRVOPEN:
	{
		major_t dmajor = cmajor;

		if (cminor < 1)
			return (ENXIO);
		spin_lock(&spx_lock);
		for (; *pp && (dmajor = getmajor((*pp)->dev)) < cmajor; pp = &(*pp)->next) ;
		for (; *pp && dmajor == getmajor((*pp)->dev) &&
		     getminor(makedevice(cmajor, cminor)) != 0; pp = &(*pp)->next) {
			minor_t dminor = getminor((*pp)->dev);

			if (cminor < dminor)
				break;
			if (cminor == dminor) {
				if (sflag == CLONEOPEN)
					cminor++;
				else {
					spin_unlock(&spx_lock);
					kmem_free(p, sizeof(*p));
					return (EIO);	/* bad error */
				}
			}
		}
		if (getminor(makedevice(cmajor, cminor)) == 0) {
			spin_unlock(&spx_lock);
			kmem_free(p, sizeof(*p));
			return (EBUSY);	/* no minors left */
		}
		p->dev = *devp = makedevice(cmajor, cminor);
		p->init = 0;
		p->q = q;
		if ((p->next = *pp))
			p->next->prev = &p->next;
		p->prev = pp;
		*pp = p;
		q->q_ptr = OTHERQ(q)->q_ptr = p;
		spin_unlock(&spx_lock);
		qprocson(q);
		return (0);
	}
	}
	return (ENXIO);
}
예제 #28
0
파일: telmod.c 프로젝트: andreiw/polaris
/*ARGSUSED*/
static int
telmodopen(queue_t *q, dev_t *devp, int oflag, int sflag, cred_t *credp)
{
	struct telmod_info	*tmip;
	mblk_t *bp;
	union T_primitives *tp;
	int	error;

	if (sflag != MODOPEN)
		return (EINVAL);

	if (q->q_ptr != NULL) {
		/* It's already attached. */
		return (0);
	}
	/*
	 * Allocate state structure.
	 */
	tmip = kmem_zalloc(sizeof (*tmip), KM_SLEEP);

	/*
	 * Cross-link.
	 */
	q->q_ptr = tmip;
	WR(q)->q_ptr = tmip;

	noenable(q);
	tmip->flags |= TEL_STOPPED;
	qprocson(q);

	/*
	 * Since TCP operates in the TLI-inspired brain-dead fashion,
	 * the connection will revert to bound state if the connection
	 * is reset by the client.  We must send a T_UNBIND_REQ in
	 * that case so the port doesn't get "wedged" (preventing
	 * inetd from being able to restart the listener).  Allocate
	 * it here, so that we don't need to worry about allocb()
	 * failures later.
	 */
	while ((tmip->unbind_mp = allocb(sizeof (union T_primitives),
	    BPRI_HI)) == NULL) {
		bufcall_id_t id = qbufcall(q, sizeof (union T_primitives),
		    BPRI_HI, dummy_callback, NULL);
		if (!qwait_sig(q)) {
			qunbufcall(q, id);
			error = EINTR;
			goto fail;
		}
		qunbufcall(q, id);
	}
	tmip->unbind_mp->b_wptr = tmip->unbind_mp->b_rptr +
	    sizeof (struct T_unbind_req);
	tmip->unbind_mp->b_datap->db_type = M_PROTO;
	tp = (union T_primitives *)tmip->unbind_mp->b_rptr;
	tp->type = T_UNBIND_REQ;
	/*
	 * Send a M_PROTO msg of type T_DATA_REQ (this is unique for
	 * read queue since only write queue can get T_DATA_REQ).
	 * Readstream routine in telnet daemon will do a getmsg() till
	 * it receives this proto message
	 */
	while ((bp = allocb(sizeof (union T_primitives), BPRI_HI)) == NULL) {
		bufcall_id_t id = qbufcall(q, sizeof (union T_primitives),
		    BPRI_HI, dummy_callback, NULL);
		if (!qwait_sig(q)) {
			qunbufcall(q, id);
			error = EINTR;
			goto fail;
		}
		qunbufcall(q, id);
	}
	bp->b_datap->db_type = M_PROTO;
	bp->b_wptr = bp->b_rptr + sizeof (union T_primitives);
	tp = (union T_primitives *)bp->b_rptr;
	tp->type = T_DATA_REQ;
	tp->data_req.MORE_flag = 0;

	putnext(q, bp);
	return (0);

fail:
	qprocsoff(q);
	if (tmip->unbind_mp != NULL) {
		freemsg(tmip->unbind_mp);
	}
	kmem_free(tmip, sizeof (struct telmod_info));
	q->q_ptr = NULL;
	WR(q)->q_ptr = NULL;
	return (error);
}
예제 #29
0
파일: zcons.c 프로젝트: pcd1193182/openzfs
/*ARGSUSED*/
static int
zc_slave_open(zc_state_t *zcs,
    queue_t	*rqp,	/* pointer to the read side queue */
    dev_t	*devp,	/* pointer to stream tail's dev */
    int		oflag,	/* the user open(2) supplied flags */
    int		sflag,	/* open state flag */
    cred_t	*credp)	/* credentials */
{
	mblk_t *mop;
	struct stroptions *sop;
	major_t major;
	minor_t minor;
	minor_t lastminor;
	uint_t anchorindex;

	/*
	 * The slave side can be opened as many times as needed.
	 */
	if ((zcs->zc_state & ZC_STATE_SOPEN) != 0) {
		ASSERT((rqp != NULL) && (WR(rqp)->q_ptr == zcs));
		return (0);
	}

	/*
	 * Set up sad(7D) so that the necessary STREAMS modules will be in
	 * place.  A wrinkle is that 'ptem' must be anchored
	 * in place (see streamio(7i)) because we always want the console to
	 * have terminal semantics.
	 */
	minor = ddi_get_instance(zcs->zc_devinfo) << 1 | ZC_SLAVE_MINOR;
	major = ddi_driver_major(zcs->zc_devinfo);
	lastminor = 0;
	anchorindex = 1;
	if (kstr_autopush(SET_AUTOPUSH, &major, &minor, &lastminor,
	    &anchorindex, zcons_mods) != 0) {
		DBG("zc_slave_open(): kstr_autopush() failed\n");
		return (EIO);
	}

	if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
		DBG("zc_slave_open(): mop allocation failed\n");
		return (ENOMEM);
	}

	zcs->zc_state |= ZC_STATE_SOPEN;

	/*
	 * q_ptr stores driver private data; stash the soft state data on both
	 * read and write sides of the queue.
	 */
	WR(rqp)->q_ptr = rqp->q_ptr = zcs;

	qprocson(rqp);

	/*
	 * Must follow qprocson(), since we aren't ready to process until then.
	 */
	zcs->zc_slave_rdq = rqp;

	/*
	 * set up hi/lo water marks on stream head read queue and add
	 * controlling tty as needed.
	 */
	mop->b_datap->db_type = M_SETOPTS;
	mop->b_wptr += sizeof (struct stroptions);
	sop = (struct stroptions *)(void *)mop->b_rptr;
	sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
	sop->so_hiwat = _TTY_BUFSIZ;
	sop->so_lowat = 256;
	putnext(rqp, mop);

	return (0);
}
예제 #30
0
static streamscall int
ll_qopen(queue_t *q, dev_t *devp, int oflags, int sflag, cred_t *crp)
{
	struct priv *p;
	struct ll *llw;
	struct ll *llr;
	int err;

	if (q->q_ptr != NULL)
		return (0);	/* already open */
	if ((err = mi_open_comm(&ll_opens, sizeof(*p), q, devp, oflags, sflag, crp)))
		return (err);

	p = PRIV(q);
	llw = &p->w_priv;
	llr = &p->r_priv;

	/* initialize private structure */
	llw->priv = p;
	llw->ll = llr;
	llw->oq = q;
	llw->state = CD_DISABLED;
	llw->oldstate = CD_DISABLED;

	llw->proto.info.cd_primitive = CD_INFO_ACK;
	llw->proto.info.cd_state = CD_DISABLED;
	llw->proto.info.cd_max_sdu = STRMAXPSZ;
	llw->proto.info.cd_min_sdu = STRMINPSZ;
	llw->proto.info.cd_class = CD_HDLC;
	llw->proto.info.cd_duplex = CD_FULLDUPLEX;
	llw->proto.info.cd_output_style = CD_UNACKEDOUTPUT;
	llw->proto.info.cd_features = (CD_CANREAD | CD_AUTOALLOW);
	llw->proto.info.cd_addr_length = 0;
	llw->proto.info.cd_ppa_style = CD_STYLE1;

	llw->sigs = CD_DSR;
	llw->alen = 0;

	llr->priv = p;
	llr->ll = llw;
	llr->oq = WR(q);
	llr->state = CD_DISABLED;
	llr->oldstate = CD_DISABLED;

	llr->proto.info.cd_primitive = CD_INFO_ACK;
	llr->proto.info.cd_state = CD_DISABLED;
	llr->proto.info.cd_max_sdu = STRMAXPSZ;
	llr->proto.info.cd_min_sdu = STRMINPSZ;
	llr->proto.info.cd_class = CD_HDLC;
	llr->proto.info.cd_duplex = CD_FULLDUPLEX;
	llr->proto.info.cd_output_style = CD_UNACKEDOUTPUT;
	llr->proto.info.cd_features = (CD_CANREAD | CD_AUTOALLOW);
	llr->proto.info.cd_addr_length = 0;
	llr->proto.info.cd_ppa_style = CD_STYLE1;

	llr->sigs = CD_DSR;
	llr->alen = 0;

	qprocson(q);
	return (0);
}