示例#1
0
文件: telmod.c 项目: andreiw/polaris
/*ARGSUSED*/
static int
telmodclose(queue_t *q, int flag, cred_t *credp)
{
	struct telmod_info   *tmip = (struct telmod_info *)q->q_ptr;
	mblk_t	*mp;

	/*
	 * Flush any write-side data downstream.  Ignoring flow
	 * control at this point is known to be safe because the
	 * M_HANGUP below poisons the stream such that no modules can
	 * be pushed again.
	 */
	while (mp = getq(WR(q)))
		putnext(WR(q), mp);

	/* Poison the stream head so that we can't be pushed again. */
	(void) putnextctl(q, M_HANGUP);

	qprocsoff(q);
	if (tmip->wbufcid) {
		qunbufcall(q, tmip->wbufcid);
		tmip->wbufcid = 0;
	}
	if (tmip->rbufcid) {
		qunbufcall(q, tmip->rbufcid);
		tmip->rbufcid = 0;
	}
	if (tmip->wtimoutid) {
		(void) quntimeout(q, tmip->wtimoutid);
		tmip->wtimoutid = 0;
	}
	if (tmip->rtimoutid) {
		(void) quntimeout(q, tmip->rtimoutid);
		tmip->rtimoutid = 0;
	}
	if (tmip->unbind_mp != NULL) {
		freemsg(tmip->unbind_mp);
	}

	kmem_free(q->q_ptr, sizeof (struct telmod_info));
	q->q_ptr = WR(q)->q_ptr = NULL;
	return (0);
}
示例#2
0
文件: dm2s.c 项目: andreiw/polaris
/* ARGSUSED */
int
dm2s_close(queue_t *rq, int flag, cred_t *cred)
{
	dm2s_t *dm2sp = (dm2s_t *)rq->q_ptr;

	DPRINTF(DBG_DRV, ("dm2s_close: called\n"));
	if (dm2sp == NULL) {
		/* Already closed once */
		return (ENODEV);
	}

	/* Close the lower layer first */
	mutex_enter(&dm2sp->ms_lock);
	(void) scf_mb_flush(dm2sp->ms_target, dm2sp->ms_key, MB_FLUSH_ALL);
	dm2s_mbox_fini(dm2sp);
	mutex_exit(&dm2sp->ms_lock);

	/*
	 * Now we can assume that no asynchronous callbacks exist.
	 * Poison the stream head so that we can't be pushed again.
	 */
	(void) putnextctl(rq, M_HANGUP);
	qprocsoff(rq);
	if (dm2sp->ms_rbufcid != 0) {
		qunbufcall(rq, dm2sp->ms_rbufcid);
		dm2sp->ms_rbufcid = 0;
	}
	if (dm2sp->ms_rq_timeoutid != 0) {
		DTRACE_PROBE1(dm2s_rqtimeout__cancel, dm2s_t, dm2sp);
		(void) quntimeout(dm2sp->ms_rq, dm2sp->ms_rq_timeoutid);
		dm2sp->ms_rq_timeoutid = 0;
	}
	if (dm2sp->ms_wq_timeoutid != 0) {
		DTRACE_PROBE1(dm2s_wqtimeout__cancel, dm2s_t, dm2sp);
		(void) quntimeout(dm2sp->ms_wq, dm2sp->ms_wq_timeoutid);
		dm2sp->ms_wq_timeoutid = 0;
	}
	/*
	 * Now we can really mark it closed.
	 */
	mutex_enter(&dm2sp->ms_lock);
	dm2sp->ms_rq = dm2sp->ms_wq = NULL;
	dm2sp->ms_state &= ~DM2S_OPENED;
	mutex_exit(&dm2sp->ms_lock);

	rq->q_ptr = WR(rq)->q_ptr = NULL;
	(void) qassociate(rq, -1);
	DPRINTF(DBG_DRV, ("dm2s_close: successfully closed\n"));
	return (0);
}
示例#3
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);
}
/*ARGSUSED*/
static int
mouse8042_close(queue_t *q, int flag, cred_t *cred_p)
{
	struct mouse_state *state;
	minor_t	minor;

	state = (struct mouse_state *)q->q_ptr;

	/*
	 * Disable queue processing now, so that another reset cannot get in
	 * after we wait for the current reset (if any) to complete.
	 */
	qprocsoff(q);

	mutex_enter(&state->reset_mutex);
	while (state->reset_state != MSE_RESET_IDLE) {
		/*
		 * Waiting for the previous reset to finish is
		 * non-interruptible.  Some upper-level clients
		 * cannot deal with EINTR and will not close the
		 * STREAM properly, resulting in failure to reopen it
		 * within the same process.
		 */
		cv_wait(&state->reset_cv, &state->reset_mutex);
	}

	if (state->reset_tid != 0) {
		(void) quntimeout(q, state->reset_tid);
		state->reset_tid = 0;
	}

	if (state->reply_mp != NULL) {
		freemsg(state->reply_mp);
		state->reply_mp = NULL;
	}

	if (state->reset_ack_mp != NULL) {
		freemsg(state->reset_ack_mp);
		state->reset_ack_mp = NULL;
	}

	mutex_exit(&state->reset_mutex);

	mutex_enter(&state->ms_mutex);

	if (state->bc_id != 0) {
		(void) qunbufcall(q, state->bc_id);
		state->bc_id = 0;
	}

	q->q_ptr = NULL;
	WR(q)->q_ptr = NULL;
	state->ms_rqp = NULL;
	state->ms_wqp = NULL;

	state->ms_opened = B_FALSE;

	minor = state->ms_minor;

	mutex_exit(&state->ms_mutex);

	if (!MOUSE8042_INTERNAL_OPEN(minor)) {
		/*
		 * Closing physical PS/2 mouse
		 *
		 * Link it back to virtual mouse, and
		 * mouse8042_open will be called as a result
		 * of the consconfig_link call.  Do NOT try
		 * this if the mouse is about to be detached!
		 *
		 * If linking back fails, this specific mouse
		 * will not be available underneath the virtual
		 * mouse, and can only be accessed via physical
		 * open.
		 */
		consconfig_link(ddi_driver_major(mouse8042_dip),
		    MOUSE8042_INTERNAL_MINOR(minor));
	}

	return (0);
}