Example #1
0
/*
 * cvc_ioctl()
 *	handle normal console ioctls.
 */
static void
cvc_ioctl(register queue_t *q, register mblk_t *mp)
{
	register cvc_t			*cp = q->q_ptr;
	int				datasize;
	int				error = 0;

	/*
	 * Let ttycommon_ioctl take the first shot at processing the ioctl.  If
	 * it fails because it can't allocate memory, schedule processing of the
	 * ioctl later when a proper buffer is available.  The mblk that
	 * couldn't be processed will have been stored in the tty structure by
	 * ttycommon_ioctl.
	 */
	datasize = ttycommon_ioctl(&cp->cvc_tty, q, mp, &error);
	if (datasize != 0) {
		if (cp->cvc_wbufcid) {
			unbufcall(cp->cvc_wbufcid);
		}
		cp->cvc_wbufcid = bufcall(datasize, BPRI_HI, cvc_reioctl, cp);
		return;
	}

	/*
	 * ttycommon_ioctl didn't do anything, but there's nothing we really
	 * support either with the exception of TCSBRK, which is supported
	 * only to appear a bit more like a serial device for software that
	 * expects TCSBRK to work.
	 */
	if (error != 0) {
		struct iocblk *iocp = (struct iocblk *)mp->b_rptr;

		if (iocp->ioc_cmd == TCSBRK) {
			miocack(q, mp, 0, 0);
		} else {
			miocnak(q, mp, 0, EINVAL);
		}
	} else {
		qreply(q, mp);
	}
}
Example #2
0
static int
pckt_r_msg(queue_t *q, mblk_t *mp)
{
	mblk_t *bp, *fp;
	struct pckt *p = PCKT_PRIV(q);

	switch (mp->b_datap->db_type) {
	case M_FLUSH:
		/* The pseudo-terminal device, pty(4), slave side reverses the sense of the
		   M_FLUSH(9) flush bits so that they can be used directly by the master side
		   Stream head. This is similar to the pipemod(4) module. To provide an
		   encapsulated message that contains flush bits that are exactly as they were
		   issued by the user of the slave side of the pty(4), pckt reverses the FLUSHR and 
		   FLUSHW bits before packetizing the M_FLUSH(9) message. Also, because every
		   Stream must respond to M_FLUSH(9) by flushing queues, pckt also passes the
		   M_FLUSH(9) message to the Stream head. However, to preserve packetized messages
		   that may be sitting on the Stream head read queue, the read side is not flushed
		   and the FLUSHR bit in any M_FLUSH(9) message passed to the Stream head will be
		   cleared. The result is as follows, depending on the value of the M_FLUSH(9)
		   bits: FLUSHR: The bits are set to FLUSHW and the message is packetized. No
		   M_FLUSH(9) message is sent to the Stream head. FLUSHW: The bits are set to
		   FLUSHR and the message is packetized. An M_FLUSH(9) message is sent to the
		   Stream head containing the FLUSHW flag. FLUSHRW: The bits are set to FLUSHRW and 
		   the message is packetized. An M_FLUSH(9) message is sent to the Stream head
		   containing only the FLUSHW flag.  */
		if (!(bp = allocb(1, BPRI_MED)))
			goto bufcall;
		if ((mp->b_rptr[0] & FLUSHW)) {
			if (!(fp = copyb(mp))) {
				freeb(bp);
				goto bufcall;
			}
			fp->b_rptr[0] &= ~FLUSHR;
			putnext(q, fp);
		} else {
			fp = NULL;
		}
		switch (mp->b_rptr[0] & (FLUSHR | FLUSHW)) {
		case FLUSHR:
			mp->b_rptr[0] &= ~FLUSHR;
			mp->b_rptr[0] |= FLUSHW;
			break;
		case FLUSHW:
			mp->b_rptr[0] &= ~FLUSHW;
			mp->b_rptr[0] |= FLUSHR;
			break;
		}
		goto finish_it;
	case M_IOCTL:
		/* The M_IOCTL(9) message is packetized as normal on 32-bit systems. On 64-bit
		   systems, where the user process that pushed the pckt module on the master side
		   of the pseudo-terminal, pty(4), device is a 32-bit process, the iocblk(9)
		   structure contained in the message block is transformed by the pckt module into
		   a 32-bit representation of the iocblk(9) structure (struct iocblk32) before
		   being packetized.  */
		if ((p->flags & FILP32)) {
			struct iocblk *ioc;
			struct iocblk32 ioc32 = { 0, };

			/* Need to convert from native to ILP32. */
			if ((bp = allocb(1, BPRI_MED)) == NULL)
				goto bufcall;
			ioc = (typeof(ioc)) mp->b_rptr;
			ioc32.ioc_cmd32 = ioc->ioc_cmd;
			ioc32.ioc_cr32 = (uint32_t) (long) ioc->ioc_cr;
			ioc32.ioc_id32 = ioc->ioc_id;
			ioc32.ioc_count32 = ioc->ioc_count;
			ioc32.ioc_error32 = ioc->ioc_error;
			ioc32.ioc_rval32 = ioc->ioc_rval;
			ioc32.ioc_filler32[0] = ioc->ioc_filler[0];
			ioc32.ioc_filler32[1] = ioc->ioc_filler[1];
			ioc32.ioc_filler32[2] = ioc->ioc_filler[2];
			ioc32.ioc_filler32[3] = ioc->ioc_filler[3];
			mp->b_wptr = mp->b_wptr - sizeof(*ioc) + sizeof(ioc32);
			*(struct iocblk32 *) mp->b_rptr = ioc32;
			goto finish_it;
		}
		goto pass_it;
	case M_READ:
		/* The M_READ(9) message is packetized as normal on 32-bit systems.  On 64-bit
		   systems, where the user process that pushed the pckt module on the master side
		   of the pseudo-terminal, pty(4), device is a 32-bit process, the size_t count
		   contained in the message block is transformed by the pckt module into a 32-bit
		   representation of the size_t (size32_t) before being packetized.  */
		if ((p->flags & FILP32)) {
			uint32_t size32;

			/* Need to convert from native to ILP32. */
			if ((bp = allocb(1, BPRI_MED)) == NULL)
				goto bufcall;
			size32 = *(size_t *) mp->b_rptr;
			*(uint32_t *) mp->b_rptr = size32;
			mp->b_wptr = mp->b_wptr - sizeof(size_t) + sizeof(uint32_t);
			goto finish_it;
		}
		goto pass_it;
	case M_PROTO:
	case M_PCPROTO:
	case M_STOP:
	case M_STOPI:
	case M_START:
	case M_STARTI:
	case M_DATA:
	      pass_it:
		/* Problem: UnixWare says 4 bytes.  Solaris says 1 byte.  The user must determine
		   the size and alignment of the message type by the length of the control part.
		   We'll go with 1 byte.  On little endian it should line up. */
		if ((bp = allocb(1, BPRI_MED))) {
		      finish_it:
			bp->b_datap->db_type = M_PROTO;
			bp->b_wptr[0] = mp->b_datap->db_type;
			bp->b_wptr++;
			mp->b_datap->db_type = M_DATA;
			bp->b_cont = mp;
			putnext(q, bp);
			return (1);
		}
	      bufcall:
		noenable(q);
		if (!(p->bufcall = bufcall(1, BPRI_MED, pckt_enable, (long) q)))
			qenable(q);	/* spin through service procedure */
		return (0);
	default:
		putnext(q, mp);
		return (1);
	}
}
Example #3
0
/*
 * bufcall request
 *
 * Requires Lock (( M: Mandatory, P: Prohibited, A: Allowed ))
 *  -. uinst_t->lock   : M [RW_READER]
 *  -. uinst_t->u_lock : A
 *  -. uinst_t->l_lock : P
 *  -. uinst_t->c_lock : P
 */
void
oplmsu_cmn_bufcall(queue_t *q, mblk_t *mp, size_t size, int rw_flag)
{

	ASSERT(RW_READ_HELD(&oplmsu_uinst->lock));

	if (rw_flag == MSU_WRITE_SIDE) {
		ctrl_t	*ctrl;

		putbq(q, mp);

		mutex_enter(&oplmsu_uinst->c_lock);
		ctrl = (ctrl_t *)q->q_ptr;
		if (ctrl->wbuf_id != 0) {
			mutex_exit(&oplmsu_uinst->c_lock);
			return;
		}

		ctrl->wbuftbl->q = q;
		ctrl->wbuftbl->rw_flag = rw_flag;
		ctrl->wbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb,
		    (void *)ctrl->wbuftbl);

		if (ctrl->wbuf_id == 0) {
			if (ctrl->wtout_id != 0) {
				mutex_exit(&oplmsu_uinst->c_lock);
				return;
			}

			ctrl->wtout_id = timeout(oplmsu_cmn_bufcb,
			    (void *)ctrl->wbuftbl, drv_usectohz(MSU_TM_500MS));
		}
		mutex_exit(&oplmsu_uinst->c_lock);
	} else if (rw_flag == MSU_READ_SIDE) {
		lpath_t	*lpath;
		mblk_t	*wrk_msg;

		mutex_enter(&oplmsu_uinst->l_lock);
		lpath = (lpath_t *)q->q_ptr;
		if (mp->b_datap->db_type >= QPCTL) {
			if (lpath->first_lpri_hi == NULL) {
				lpath->last_lpri_hi = mp;
				mp->b_next = NULL;
			} else {
				wrk_msg = lpath->first_lpri_hi;
				wrk_msg->b_prev = mp;
				mp->b_next = wrk_msg;
			}
			mp->b_prev = NULL;
			lpath->first_lpri_hi = mp;
		} else {
			putbq(q, mp);
		}

		if (lpath->rbuf_id != 0) {
			mutex_exit(&oplmsu_uinst->l_lock);
			return;
		}

		lpath->rbuftbl->q = q;
		lpath->rbuftbl->rw_flag = rw_flag;
		lpath->rbuf_id = bufcall(size, BPRI_LO, oplmsu_cmn_bufcb,
		    (void *)lpath->rbuftbl);

		if (lpath->rbuf_id == 0) {
			if (lpath->rtout_id != 0) {
				mutex_exit(&oplmsu_uinst->l_lock);
				return;
			}

			lpath->rtout_id = timeout(oplmsu_cmn_bufcb,
			    (void *)lpath->rbuftbl, drv_usectohz(MSU_TM_500MS));
		}
		mutex_exit(&oplmsu_uinst->l_lock);
	}
}