示例#1
0
文件: msg.c 项目: leadingtheway/Jix
int
sendrecv(int function, struct msg *m, int dest)
{
    struct msg mbuf;
    char iobuf[BUFLEN];
    int ret;
    
    ret = -1;

    assert((dest >= 0 && dest < NPROC) ||
           (function == RECV && dest == ANY));
    assert(dest == ANY || ptable[dest].state != UNUSED);

    m->source = current - ptable;
    assert(m->source != dest);
     // mbuf is in kernel address space;

    if (function == SEND) {

        mbuf = *m;
        ret = sendmsg(&mbuf, dest);

    } else if (function == RECV) {

        ret = recvmsg(&mbuf, dest);
        *m = mbuf;

    } else if (function == BOTH) {

        mbuf = *m;
        mcopyin(iobuf, &mbuf, m);
        if ( (ret = sendmsg(&mbuf, dest)) != 0)
            return ret;
        ret = recvmsg(&mbuf, dest);
        mcopyout(&mbuf, m);
        *m = mbuf;

    }

    return ret;
}
示例#2
0
/*
 * Message must be of type M_IOCTL or M_IOCDATA for this routine to be called.
 */
static void
ptioc(queue_t *q, mblk_t *mp, int qside)
{
	struct ptem *tp;
	struct iocblk *iocp;
	struct winsize *wb;
	struct jwinsize *jwb;
	mblk_t *tmp;
	mblk_t *pckt_msgp;	/* message sent to the PCKT module */
	int error;

	iocp = (struct iocblk *)mp->b_rptr;
	tp = (struct ptem *)q->q_ptr;

	switch (iocp->ioc_cmd) {

	case JWINSIZE:
		/*
		 * For compatibility:  If all zeros, NAK the message for dumb
		 * terminals.
		 */
		if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
		    (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
			miocnak(q, mp, 0, EINVAL);
			return;
		}

		tmp = allocb(sizeof (struct jwinsize), BPRI_MED);
		if (tmp == NULL) {
			miocnak(q, mp, 0, EAGAIN);
			return;
		}

		if (iocp->ioc_count == TRANSPARENT)
			mcopyout(mp, NULL, sizeof (struct jwinsize), NULL, tmp);
		else
			mioc2ack(mp, tmp, sizeof (struct jwinsize), 0);

		jwb = (struct jwinsize *)mp->b_cont->b_rptr;
		jwb->bytesx = tp->wsz.ws_col;
		jwb->bytesy = tp->wsz.ws_row;
		jwb->bitsx = tp->wsz.ws_xpixel;
		jwb->bitsy = tp->wsz.ws_ypixel;

		qreply(q, mp);
		return;

	case TIOCGWINSZ:
		/*
		 * If all zeros NAK the message for dumb terminals.
		 */
		if ((tp->wsz.ws_row == 0) && (tp->wsz.ws_col == 0) &&
		    (tp->wsz.ws_xpixel == 0) && (tp->wsz.ws_ypixel == 0)) {
			miocnak(q, mp, 0, EINVAL);
			return;
		}

		tmp = allocb(sizeof (struct winsize), BPRI_MED);
		if (tmp == NULL) {
			miocnak(q, mp, 0, EAGAIN);
			return;
		}

		mioc2ack(mp, tmp, sizeof (struct winsize), 0);

		wb = (struct winsize *)mp->b_cont->b_rptr;
		wb->ws_row = tp->wsz.ws_row;
		wb->ws_col = tp->wsz.ws_col;
		wb->ws_xpixel = tp->wsz.ws_xpixel;
		wb->ws_ypixel = tp->wsz.ws_ypixel;

		qreply(q, mp);
		return;

	case TIOCSWINSZ:
		error = miocpullup(mp, sizeof (struct winsize));
		if (error != 0) {
			miocnak(q, mp, 0, error);
			return;
		}

		wb = (struct winsize *)mp->b_cont->b_rptr;
		/*
		 * Send a SIGWINCH signal if the row/col information has
		 * changed.
		 */
		if ((tp->wsz.ws_row != wb->ws_row) ||
		    (tp->wsz.ws_col != wb->ws_col) ||
		    (tp->wsz.ws_xpixel != wb->ws_xpixel) ||
		    (tp->wsz.ws_ypixel != wb->ws_xpixel)) {
			/*
			 * SIGWINCH is always sent upstream.
			 */
			if (qside == WRSIDE)
				(void) putnextctl1(RD(q), M_SIG, SIGWINCH);
			else if (qside == RDSIDE)
				(void) putnextctl1(q, M_SIG, SIGWINCH);
			/*
			 * Message may have come in as an M_IOCDATA; pass it
			 * to the master side as an M_IOCTL.
			 */
			mp->b_datap->db_type = M_IOCTL;
			if (qside == WRSIDE) {
				/*
				 * Need a copy of this message to pass on to
				 * the PCKT module, only if the M_IOCTL
				 * orginated from the slave side.
				 */
				if ((pckt_msgp = copymsg(mp)) == NULL) {
					miocnak(q, mp, 0, EAGAIN);
					return;
				}
				putnext(q, pckt_msgp);
			}
			tp->wsz.ws_row = wb->ws_row;
			tp->wsz.ws_col = wb->ws_col;
			tp->wsz.ws_xpixel = wb->ws_xpixel;
			tp->wsz.ws_ypixel = wb->ws_ypixel;
		}

		mioc2ack(mp, NULL, 0, 0);
		qreply(q, mp);
		return;

	case TIOCSIGNAL: {
		/*
		 * This ioctl can emanate from the master side in remote
		 * mode only.
		 */
		int	sig;

		if (DB_TYPE(mp) == M_IOCTL && iocp->ioc_count != TRANSPARENT) {
			error = miocpullup(mp, sizeof (int));
			if (error != 0) {
				miocnak(q, mp, 0, error);
				return;
			}
		}

		if (DB_TYPE(mp) == M_IOCDATA || iocp->ioc_count != TRANSPARENT)
			sig = *(int *)mp->b_cont->b_rptr;
		else
			sig = (int)*(intptr_t *)mp->b_cont->b_rptr;

		if (sig < 1 || sig >= NSIG) {
			miocnak(q, mp, 0, EINVAL);
			return;
		}

		/*
		 * Send an M_PCSIG message up the slave's read side and
		 * respond back to the master with an ACK or NAK as
		 * appropriate.
		 */
		if (putnextctl1(q, M_PCSIG, sig) == 0) {
			miocnak(q, mp, 0, EAGAIN);
			return;
		}

		mioc2ack(mp, NULL, 0, 0);
		qreply(q, mp);
		return;
	    }

	case TIOCREMOTE: {
		int	onoff;
		mblk_t	*mctlp;

		if (DB_TYPE(mp) == M_IOCTL) {
			error = miocpullup(mp, sizeof (int));
			if (error != 0) {
				miocnak(q, mp, 0, error);
				return;
			}
		}

		onoff = *(int *)mp->b_cont->b_rptr;

		/*
		 * Send M_CTL up using the iocblk format.
		 */
		mctlp = mkiocb(onoff ? MC_NO_CANON : MC_DO_CANON);
		if (mctlp == NULL) {
			miocnak(q, mp, 0, EAGAIN);
			return;
		}
		mctlp->b_datap->db_type = M_CTL;
		putnext(q, mctlp);

		/*
		 * ACK the ioctl.
		 */
		mioc2ack(mp, NULL, 0, 0);
		qreply(q, mp);

		/*
		 * Record state change.
		 */
		if (onoff)
			tp->state |= REMOTEMODE;
		else
			tp->state &= ~REMOTEMODE;
		return;
	    }

	default:
		putnext(q, mp);
		return;
	}
}
示例#3
0
文件: sad.c 项目: andreiw/polaris
/*
 * apush_iocdata() -
 * Handle the M_IOCDATA messages associated with
 * the autopush feature.
 */
static void
apush_iocdata(
	queue_t *qp,	/* pointer to write queue */
	mblk_t *mp)	/* message pointer */
{
	int i, ret;
	struct copyresp *csp;
	struct strapush *sap;
	struct autopush *ap;
	struct saddev *sadp;
	uint_t size;

	csp = (struct copyresp *)mp->b_rptr;
	if (csp->cp_rval) {	/* if there was an error */
		freemsg(mp);
		return;
	}
	if (mp->b_cont)
		/* sap needed only if mp->b_cont is set */
		sap = (struct strapush *)mp->b_cont->b_rptr;
	switch (SAD_CMD(csp->cp_cmd)) {
	case SAD_CMD(SAD_SAP):
		switch ((long)csp->cp_private) {
		case GETSTRUCT:
			switch (sap->sap_cmd) {
			case SAP_ONE:
			case SAP_RANGE:
			case SAP_ALL:
				if ((sap->sap_npush == 0) ||
				    (sap->sap_npush > MAXAPUSH) ||
				    (sap->sap_npush > nstrpush)) {

					/* invalid number of modules to push */

					miocnak(qp, mp, 0, EINVAL);
					break;
				}
				if (ret = valid_major(sap->sap_major)) {
					miocnak(qp, mp, 0, ret);
					break;
				}
				if ((sap->sap_cmd == SAP_RANGE) &&
				    (sap->sap_lastminor <= sap->sap_minor)) {

					/* bad range */

					miocnak(qp, mp, 0, ERANGE);
					break;
				}

				/*
				 * Validate that the specified list of
				 * modules exist.
				 */
				for (i = 0; i < sap->sap_npush; i++) {
					sap->sap_list[i][FMNAMESZ] = '\0';
					if (fmodsw_find(sap->sap_list[i],
					    FMODSW_LOAD) == NULL) {
						miocnak(qp, mp, 0, EINVAL);
						return;
					}
				}

				mutex_enter(&sad_lock);
				if (ap_hfind(sap->sap_major, sap->sap_minor,
				    sap->sap_lastminor, sap->sap_cmd)) {
					mutex_exit(&sad_lock);

					/* already configured */

					miocnak(qp, mp, 0, EEXIST);
					break;
				}
				if ((ap = ap_alloc()) == NULL) {
					mutex_exit(&sad_lock);

					/* no autopush structures */

					miocnak(qp, mp, 0, ENOSR);
					break;
				}
				ap->ap_cnt++;
				ap->ap_common = sap->sap_common;
				if (SAD_VER(csp->cp_cmd) > 0)
					ap->ap_anchor = sap->sap_anchor;
				else
					ap->ap_anchor = 0;
				for (i = 0; i < ap->ap_npush; i++)
					(void) strcpy(ap->ap_list[i],
					    sap->sap_list[i]);
				ap_hadd(ap);
				mutex_exit(&sad_lock);
				miocack(qp, mp, 0, 0);
				break;

			case SAP_CLEAR:
				if (ret = valid_major(sap->sap_major)) {
					miocnak(qp, mp, 0, ret);
					break;
				}
				mutex_enter(&sad_lock);
				if ((ap = ap_hfind(sap->sap_major,
				    sap->sap_minor, sap->sap_lastminor,
				    sap->sap_cmd)) == NULL) {
					mutex_exit(&sad_lock);

					/* not configured */

					miocnak(qp, mp, 0, ENODEV);
					break;
				}
				if ((ap->ap_type == SAP_RANGE) &&
				    (sap->sap_minor != ap->ap_minor)) {
					mutex_exit(&sad_lock);

					/* starting minors do not match */

					miocnak(qp, mp, 0, ERANGE);
					break;
				}
				if ((ap->ap_type == SAP_ALL) &&
				    (sap->sap_minor != 0)) {
					mutex_exit(&sad_lock);

					/* SAP_ALL must have minor == 0 */

					miocnak(qp, mp, 0, EINVAL);
					break;
				}
				ap_hrmv(ap);
				if (--(ap->ap_cnt) <= 0)
					ap_free(ap);
				mutex_exit(&sad_lock);
				miocack(qp, mp, 0, 0);
				break;

			default:
				miocnak(qp, mp, 0, EINVAL);
				break;
			} /* switch (sap_cmd) */
			break;

		default:
			cmn_err(CE_WARN,
			    "apush_iocdata: cp_private bad in SAD_SAP: %p",
			    (void *)csp->cp_private);
			freemsg(mp);
			break;
		} /* switch (cp_private) */
		break;

	case SAD_CMD(SAD_GAP):
		switch ((long)csp->cp_private) {

		case GETSTRUCT: {
			if (ret = valid_major(sap->sap_major)) {
				miocnak(qp, mp, 0, ret);
				break;
			}
			mutex_enter(&sad_lock);
			if ((ap = ap_hfind(sap->sap_major, sap->sap_minor,
			    sap->sap_lastminor, SAP_ONE)) == NULL) {
				mutex_exit(&sad_lock);

				/* not configured */

				miocnak(qp, mp, 0, ENODEV);
				break;
			}

			sap->sap_common = ap->ap_common;
			if (SAD_VER(csp->cp_cmd) > 0)
				sap->sap_anchor = ap->ap_anchor;
			for (i = 0; i < ap->ap_npush; i++)
				(void) strcpy(sap->sap_list[i], ap->ap_list[i]);
			for (; i < MAXAPUSH; i++)
				bzero(sap->sap_list[i], FMNAMESZ + 1);
			mutex_exit(&sad_lock);

			if (SAD_VER(csp->cp_cmd) == 1)
				size = STRAPUSH_V1_LEN;
			else
				size = STRAPUSH_V0_LEN;

			sadp = (struct saddev *)qp->q_ptr;
			mcopyout(mp, (void *)GETRESULT, size, sadp->sa_addr,
			    NULL);
			qreply(qp, mp);
			break;
			}
		case GETRESULT:
			miocack(qp, mp, 0, 0);
			break;

		default:
			cmn_err(CE_WARN,
			    "apush_iocdata: cp_private bad case SAD_GAP: %p",
			    (void *)csp->cp_private);
			freemsg(mp);
			break;
		} /* switch (cp_private) */
		break;

	default:	/* can't happen */
		ASSERT(0);
		freemsg(mp);
		break;
	} /* switch (cp_cmd) */
}